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.
Files changed (82) hide show
  1. axion/__init__.py +3 -0
  2. axion/api/__init__.py +0 -0
  3. axion/api/anthropic.py +460 -0
  4. axion/api/client.py +259 -0
  5. axion/api/error.py +161 -0
  6. axion/api/ollama.py +597 -0
  7. axion/api/openai_compat.py +805 -0
  8. axion/api/openai_responses.py +627 -0
  9. axion/api/prompt_cache.py +31 -0
  10. axion/api/sse.py +98 -0
  11. axion/api/types.py +451 -0
  12. axion/cli/__init__.py +0 -0
  13. axion/cli/init_cmd.py +50 -0
  14. axion/cli/input.py +290 -0
  15. axion/cli/main.py +2953 -0
  16. axion/cli/render.py +489 -0
  17. axion/cli/tui.py +766 -0
  18. axion/commands/__init__.py +0 -0
  19. axion/commands/handlers/__init__.py +0 -0
  20. axion/commands/handlers/agents.py +51 -0
  21. axion/commands/handlers/builtin_commands.py +367 -0
  22. axion/commands/handlers/mcp.py +59 -0
  23. axion/commands/handlers/models.py +75 -0
  24. axion/commands/handlers/plugins.py +55 -0
  25. axion/commands/handlers/skills.py +61 -0
  26. axion/commands/parsing.py +317 -0
  27. axion/commands/registry.py +166 -0
  28. axion/compat_harness/__init__.py +0 -0
  29. axion/compat_harness/extractor.py +145 -0
  30. axion/plugins/__init__.py +0 -0
  31. axion/plugins/hooks.py +22 -0
  32. axion/plugins/manager.py +391 -0
  33. axion/plugins/manifest.py +270 -0
  34. axion/runtime/__init__.py +0 -0
  35. axion/runtime/bash.py +388 -0
  36. axion/runtime/bootstrap.py +39 -0
  37. axion/runtime/claude_subscription.py +300 -0
  38. axion/runtime/compact.py +233 -0
  39. axion/runtime/config.py +397 -0
  40. axion/runtime/conversation.py +1073 -0
  41. axion/runtime/file_ops.py +613 -0
  42. axion/runtime/git.py +213 -0
  43. axion/runtime/hooks.py +235 -0
  44. axion/runtime/image.py +212 -0
  45. axion/runtime/lanes.py +282 -0
  46. axion/runtime/lsp.py +425 -0
  47. axion/runtime/mcp/__init__.py +0 -0
  48. axion/runtime/mcp/client.py +76 -0
  49. axion/runtime/mcp/lifecycle.py +96 -0
  50. axion/runtime/mcp/stdio.py +318 -0
  51. axion/runtime/mcp/tool_bridge.py +79 -0
  52. axion/runtime/memory.py +196 -0
  53. axion/runtime/oauth.py +329 -0
  54. axion/runtime/openai_subscription.py +346 -0
  55. axion/runtime/permissions.py +247 -0
  56. axion/runtime/plan_mode.py +96 -0
  57. axion/runtime/policy_engine.py +259 -0
  58. axion/runtime/prompt.py +586 -0
  59. axion/runtime/recovery.py +261 -0
  60. axion/runtime/remote.py +28 -0
  61. axion/runtime/sandbox.py +68 -0
  62. axion/runtime/scheduler.py +231 -0
  63. axion/runtime/session.py +365 -0
  64. axion/runtime/sharing.py +159 -0
  65. axion/runtime/skills.py +124 -0
  66. axion/runtime/tasks.py +258 -0
  67. axion/runtime/usage.py +241 -0
  68. axion/runtime/workers.py +186 -0
  69. axion/telemetry/__init__.py +0 -0
  70. axion/telemetry/events.py +67 -0
  71. axion/telemetry/profile.py +49 -0
  72. axion/telemetry/sink.py +60 -0
  73. axion/telemetry/tracer.py +95 -0
  74. axion/tools/__init__.py +0 -0
  75. axion/tools/lane_completion.py +33 -0
  76. axion/tools/registry.py +853 -0
  77. axion/tools/tool_search.py +226 -0
  78. axion_code-1.0.0.dist-info/METADATA +709 -0
  79. axion_code-1.0.0.dist-info/RECORD +82 -0
  80. axion_code-1.0.0.dist-info/WHEEL +4 -0
  81. axion_code-1.0.0.dist-info/entry_points.txt +2 -0
  82. 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
@@ -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)
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
+ )