netra-zen 1.0.9__py3-none-any.whl → 1.0.11__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.
scripts/bump_version.py CHANGED
@@ -1,138 +1,138 @@
1
- #!/usr/bin/env python3
2
- """
3
- Version bump utility for Zen Orchestrator.
4
- Updates version in all relevant files.
5
-
6
- Usage:
7
- python scripts/bump_version.py patch # 1.0.0 -> 1.0.1
8
- python scripts/bump_version.py minor # 1.0.0 -> 1.1.0
9
- python scripts/bump_version.py major # 1.0.0 -> 2.0.0
10
- python scripts/bump_version.py 1.2.3 # Set specific version
11
- """
12
-
13
- import re
14
- import sys
15
- from pathlib import Path
16
- from typing import Tuple
17
-
18
-
19
- def parse_version(version_str: str) -> Tuple[int, int, int]:
20
- """Parse version string to tuple of integers."""
21
- match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', version_str)
22
- if not match:
23
- raise ValueError(f"Invalid version format: {version_str}")
24
- return tuple(map(int, match.groups()))
25
-
26
-
27
- def format_version(version_tuple: Tuple[int, int, int]) -> str:
28
- """Format version tuple to string."""
29
- return '.'.join(map(str, version_tuple))
30
-
31
-
32
- def get_current_version() -> str:
33
- """Get current version from __init__.py."""
34
- init_file = Path(__file__).parent.parent / "__init__.py"
35
- content = init_file.read_text()
36
- match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content)
37
- if not match:
38
- raise ValueError("Could not find version in __init__.py")
39
- return match.group(1)
40
-
41
-
42
- def bump_version(current: str, bump_type: str) -> str:
43
- """Bump version based on type."""
44
- if re.match(r'^\d+\.\d+\.\d+$', bump_type):
45
- # Specific version provided
46
- return bump_type
47
-
48
- major, minor, patch = parse_version(current)
49
-
50
- if bump_type == 'major':
51
- return format_version((major + 1, 0, 0))
52
- elif bump_type == 'minor':
53
- return format_version((major, minor + 1, 0))
54
- elif bump_type == 'patch':
55
- return format_version((major, minor, patch + 1))
56
- else:
57
- raise ValueError(f"Invalid bump type: {bump_type}")
58
-
59
-
60
- def update_file(file_path: Path, old_version: str, new_version: str, patterns: list):
61
- """Update version in a file using specified patterns."""
62
- if not file_path.exists():
63
- print(f" ⚠️ {file_path} does not exist, skipping...")
64
- return
65
-
66
- content = file_path.read_text()
67
- original_content = content
68
-
69
- for pattern in patterns:
70
- old_pattern = pattern.format(version=old_version)
71
- new_pattern = pattern.format(version=new_version)
72
- content = content.replace(old_pattern, new_pattern)
73
-
74
- if content != original_content:
75
- file_path.write_text(content)
76
- print(f" ✅ Updated {file_path}")
77
- else:
78
- print(f" ℹ️ No changes in {file_path}")
79
-
80
-
81
- def main():
82
- """Main function."""
83
- if len(sys.argv) != 2:
84
- print(__doc__)
85
- sys.exit(1)
86
-
87
- bump_type = sys.argv[1]
88
-
89
- # Get current version
90
- try:
91
- current = get_current_version()
92
- print(f"Current version: {current}")
93
- except Exception as e:
94
- print(f"Error getting current version: {e}")
95
- sys.exit(1)
96
-
97
- # Calculate new version
98
- try:
99
- new = bump_version(current, bump_type)
100
- print(f"New version: {new}")
101
- except Exception as e:
102
- print(f"Error calculating new version: {e}")
103
- sys.exit(1)
104
-
105
- # Update files
106
- base_path = Path(__file__).parent.parent
107
-
108
- files_to_update = [
109
- (
110
- base_path / "__init__.py",
111
- ['__version__ = "{version}"']
112
- ),
113
- (
114
- base_path / "setup.py",
115
- ['version="{version}"']
116
- ),
117
- (
118
- base_path / "pyproject.toml",
119
- ['version = "{version}"']
120
- ),
121
- ]
122
-
123
- print("\nUpdating files:")
124
- for file_path, patterns in files_to_update:
125
- update_file(file_path, current, new, patterns)
126
-
127
- print(f"\n✨ Version bumped from {current} to {new}")
128
- print("\nNext steps:")
129
- print(f" 1. Update CHANGELOG.md with changes for v{new}")
130
- print(f" 2. Commit: git commit -am 'Bump version to {new}'")
131
- print(f" 3. Tag: git tag -a v{new} -m 'Release version {new}'")
132
- print(f" 4. Push: git push origin main --tags")
133
- print(f" 5. Build: python -m build")
134
- print(f" 6. Upload: python -m twine upload dist/*")
135
-
136
-
137
- if __name__ == "__main__":
1
+ #!/usr/bin/env python3
2
+ """
3
+ Version bump utility for Zen Orchestrator.
4
+ Updates version in all relevant files.
5
+
6
+ Usage:
7
+ python scripts/bump_version.py patch # 1.0.0 -> 1.0.1
8
+ python scripts/bump_version.py minor # 1.0.0 -> 1.1.0
9
+ python scripts/bump_version.py major # 1.0.0 -> 2.0.0
10
+ python scripts/bump_version.py 1.2.3 # Set specific version
11
+ """
12
+
13
+ import re
14
+ import sys
15
+ from pathlib import Path
16
+ from typing import Tuple
17
+
18
+
19
+ def parse_version(version_str: str) -> Tuple[int, int, int]:
20
+ """Parse version string to tuple of integers."""
21
+ match = re.match(r'^(\d+)\.(\d+)\.(\d+)$', version_str)
22
+ if not match:
23
+ raise ValueError(f"Invalid version format: {version_str}")
24
+ return tuple(map(int, match.groups()))
25
+
26
+
27
+ def format_version(version_tuple: Tuple[int, int, int]) -> str:
28
+ """Format version tuple to string."""
29
+ return '.'.join(map(str, version_tuple))
30
+
31
+
32
+ def get_current_version() -> str:
33
+ """Get current version from __init__.py."""
34
+ init_file = Path(__file__).parent.parent / "__init__.py"
35
+ content = init_file.read_text()
36
+ match = re.search(r'__version__\s*=\s*["\']([^"\']+)["\']', content)
37
+ if not match:
38
+ raise ValueError("Could not find version in __init__.py")
39
+ return match.group(1)
40
+
41
+
42
+ def bump_version(current: str, bump_type: str) -> str:
43
+ """Bump version based on type."""
44
+ if re.match(r'^\d+\.\d+\.\d+$', bump_type):
45
+ # Specific version provided
46
+ return bump_type
47
+
48
+ major, minor, patch = parse_version(current)
49
+
50
+ if bump_type == 'major':
51
+ return format_version((major + 1, 0, 0))
52
+ elif bump_type == 'minor':
53
+ return format_version((major, minor + 1, 0))
54
+ elif bump_type == 'patch':
55
+ return format_version((major, minor, patch + 1))
56
+ else:
57
+ raise ValueError(f"Invalid bump type: {bump_type}")
58
+
59
+
60
+ def update_file(file_path: Path, old_version: str, new_version: str, patterns: list):
61
+ """Update version in a file using specified patterns."""
62
+ if not file_path.exists():
63
+ print(f" ⚠️ {file_path} does not exist, skipping...")
64
+ return
65
+
66
+ content = file_path.read_text()
67
+ original_content = content
68
+
69
+ for pattern in patterns:
70
+ old_pattern = pattern.format(version=old_version)
71
+ new_pattern = pattern.format(version=new_version)
72
+ content = content.replace(old_pattern, new_pattern)
73
+
74
+ if content != original_content:
75
+ file_path.write_text(content)
76
+ print(f" ✅ Updated {file_path}")
77
+ else:
78
+ print(f" ℹ️ No changes in {file_path}")
79
+
80
+
81
+ def main():
82
+ """Main function."""
83
+ if len(sys.argv) != 2:
84
+ print(__doc__)
85
+ sys.exit(1)
86
+
87
+ bump_type = sys.argv[1]
88
+
89
+ # Get current version
90
+ try:
91
+ current = get_current_version()
92
+ print(f"Current version: {current}")
93
+ except Exception as e:
94
+ print(f"Error getting current version: {e}")
95
+ sys.exit(1)
96
+
97
+ # Calculate new version
98
+ try:
99
+ new = bump_version(current, bump_type)
100
+ print(f"New version: {new}")
101
+ except Exception as e:
102
+ print(f"Error calculating new version: {e}")
103
+ sys.exit(1)
104
+
105
+ # Update files
106
+ base_path = Path(__file__).parent.parent
107
+
108
+ files_to_update = [
109
+ (
110
+ base_path / "__init__.py",
111
+ ['__version__ = "{version}"']
112
+ ),
113
+ (
114
+ base_path / "setup.py",
115
+ ['version="{version}"']
116
+ ),
117
+ (
118
+ base_path / "pyproject.toml",
119
+ ['version = "{version}"']
120
+ ),
121
+ ]
122
+
123
+ print("\nUpdating files:")
124
+ for file_path, patterns in files_to_update:
125
+ update_file(file_path, current, new, patterns)
126
+
127
+ print(f"\n✨ Version bumped from {current} to {new}")
128
+ print("\nNext steps:")
129
+ print(f" 1. Update CHANGELOG.md with changes for v{new}")
130
+ print(f" 2. Commit: git commit -am 'Bump version to {new}'")
131
+ print(f" 3. Tag: git tag -a v{new} -m 'Release version {new}'")
132
+ print(f" 4. Push: git push origin main --tags")
133
+ print(f" 5. Build: python -m build")
134
+ print(f" 6. Upload: python -m twine upload dist/*")
135
+
136
+
137
+ if __name__ == "__main__":
138
138
  main()
@@ -1,144 +1,146 @@
1
- #!/usr/bin/env python3
2
- """
3
- Demonstration of log collection from .claude/Projects
4
-
5
- This script shows how the zen --apex --send-logs functionality works
6
- """
7
- import sys
8
- from pathlib import Path
9
- import json
10
-
11
- # Add parent to path for imports
12
- sys.path.insert(0, str(Path(__file__).parent.parent))
13
-
14
- from scripts.agent_logs import collect_recent_logs
15
-
16
-
17
- def demo_log_collection():
18
- """Demonstrate log collection with various scenarios"""
19
-
20
- print("=" * 60)
21
- print("Zen Apex Log Collection Demo")
22
- print("=" * 60)
23
- print()
24
-
25
- # Check if .claude/Projects exists
26
- claude_path = Path.home() / ".claude" / "Projects"
27
-
28
- if not claude_path.exists():
29
- print("❌ .claude/Projects does not exist")
30
- print(f" Expected location: {claude_path}")
31
- print()
32
- print("Creating test directory...")
33
- claude_path.mkdir(parents=True, exist_ok=True)
34
- test_project = claude_path / "demo-project"
35
- test_project.mkdir(exist_ok=True)
36
-
37
- # Create sample log
38
- sample_log = {
39
- "type": "demo_event",
40
- "timestamp": "2025-01-08T12:00:00",
41
- "message": "This is a demo log entry",
42
- "data": {"key": "value"}
43
- }
44
- (test_project / "demo-session.jsonl").write_text(json.dumps(sample_log) + "\n")
45
- print(f"✅ Created demo project at {test_project}")
46
- print()
47
-
48
- # Scenario 1: Collect with defaults
49
- print("Scenario 1: Collect logs with defaults (limit=5, auto-detect project)")
50
- print("-" * 60)
51
- logs = collect_recent_logs(limit=5)
52
-
53
- if logs:
54
- print(f"✅ Collected {len(logs)} log entries")
55
- print(f" Total entries: {len(logs)}")
56
- print()
57
- print(" Sample entry (first):")
58
- print(f" {json.dumps(logs[0], indent=4)}")
59
- else:
60
- print("⚠️ No logs found")
61
- print(" Tip: Run Claude Code with some commands to generate logs")
62
- print()
63
-
64
- # Scenario 2: List available projects
65
- print("Scenario 2: List available projects")
66
- print("-" * 60)
67
- if claude_path.exists():
68
- projects = [p for p in claude_path.iterdir() if p.is_dir()]
69
- if projects:
70
- print(f"Found {len(projects)} project(s):")
71
- for proj in sorted(projects, key=lambda p: p.stat().st_mtime, reverse=True):
72
- jsonl_count = len(list(proj.glob("*.jsonl")))
73
- mtime = proj.stat().st_mtime
74
- from datetime import datetime
75
- mtime_str = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
76
- marker = " ← most recent" if proj == projects[0] else ""
77
- print(f" • {proj.name}: {jsonl_count} .jsonl files (modified: {mtime_str}){marker}")
78
- else:
79
- print(" No projects found")
80
- print()
81
-
82
- # Scenario 3: Collect from specific project
83
- if claude_path.exists():
84
- projects = [p for p in claude_path.iterdir() if p.is_dir()]
85
- if projects:
86
- specific_project = projects[0].name
87
- print(f"Scenario 3: Collect from specific project '{specific_project}'")
88
- print("-" * 60)
89
- logs = collect_recent_logs(limit=3, project_name=specific_project)
90
- if logs:
91
- print(f"✅ Collected {len(logs)} entries from '{specific_project}'")
92
- print(f" Entry types: {[log.get('type', 'unknown') for log in logs[:3]]}")
93
- else:
94
- print(f"⚠️ No logs in '{specific_project}'")
95
- print()
96
-
97
- # Scenario 4: Show what would be sent with --send-logs
98
- print("Scenario 4: What gets sent with 'zen --apex --send-logs --message \"..\"'")
99
- print("-" * 60)
100
- logs = collect_recent_logs(limit=5)
101
- if logs:
102
- payload_preview = {
103
- "type": "user_message",
104
- "payload": {
105
- "content": "your message here",
106
- "run_id": "cli_20250108_120000_12345",
107
- "thread_id": "cli_thread_abc123def456",
108
- "timestamp": "2025-01-08T12:00:00",
109
- "jsonl_logs": logs # This is what gets attached
110
- }
111
- }
112
- print("Payload structure:")
113
- print(json.dumps(payload_preview, indent=2)[:500] + "...")
114
- print()
115
- print(f"✅ {len(logs)} log entries would be attached to the message")
116
- else:
117
- print("⚠️ No logs would be attached (none found)")
118
- print()
119
-
120
- # Summary
121
- print("=" * 60)
122
- print("Summary")
123
- print("=" * 60)
124
- print()
125
- print("To use log forwarding with zen --apex:")
126
- print()
127
- print(" # Basic usage (attaches last 5 log files)")
128
- print(" zen --apex --send-logs --message \"analyze these sessions\"")
129
- print()
130
- print(" # Custom number of logs")
131
- print(" zen --apex --send-logs --logs-count 10 --message \"review last 10\"")
132
- print()
133
- print(" # Specific project")
134
- if claude_path.exists() and list(claude_path.iterdir()):
135
- first_project = list(p for p in claude_path.iterdir() if p.is_dir())[0].name
136
- print(f" zen --apex --send-logs --logs-project {first_project} --message \"...\"")
137
- else:
138
- print(" zen --apex --send-logs --logs-project PROJECT_NAME --message \"...\"")
139
- print()
140
- print("=" * 60)
141
-
142
-
143
- if __name__ == "__main__":
144
- demo_log_collection()
1
+ #!/usr/bin/env python3
2
+ """
3
+ Demonstration of log collection from .claude/Projects
4
+
5
+ This script shows how the zen --apex --send-logs functionality works
6
+ """
7
+ import sys
8
+ from pathlib import Path
9
+ import json
10
+
11
+ # Add parent to path for imports
12
+ sys.path.insert(0, str(Path(__file__).parent.parent))
13
+
14
+ from scripts.agent_logs import collect_recent_logs
15
+
16
+
17
+ def demo_log_collection():
18
+ """Demonstrate log collection with various scenarios"""
19
+
20
+ print("=" * 60)
21
+ print("Zen Apex Log Collection Demo")
22
+ print("=" * 60)
23
+ print()
24
+
25
+ # Check if .claude/Projects exists
26
+ claude_path = Path.home() / ".claude" / "Projects"
27
+
28
+ if not claude_path.exists():
29
+ print("❌ .claude/Projects does not exist")
30
+ print(f" Expected location: {claude_path}")
31
+ print()
32
+ print("Creating test directory...")
33
+ claude_path.mkdir(parents=True, exist_ok=True)
34
+ test_project = claude_path / "demo-project"
35
+ test_project.mkdir(exist_ok=True)
36
+
37
+ # Create sample log
38
+ sample_log = {
39
+ "type": "demo_event",
40
+ "timestamp": "2025-01-08T12:00:00",
41
+ "message": "This is a demo log entry",
42
+ "data": {"key": "value"}
43
+ }
44
+ (test_project / "demo-session.jsonl").write_text(json.dumps(sample_log) + "\n")
45
+ print(f"✅ Created demo project at {test_project}")
46
+ print()
47
+
48
+ # Scenario 1: Collect with defaults
49
+ print("Scenario 1: Collect logs with defaults (limit=1, auto-detect project)")
50
+ print("-" * 60)
51
+ logs = collect_recent_logs(limit=1)
52
+
53
+ if logs:
54
+ print(f"✅ Collected {len(logs)} log entries")
55
+ print(f" Total entries: {len(logs)}")
56
+ print()
57
+ print(" Sample entry (first):")
58
+ print(f" {json.dumps(logs[0], indent=4)}")
59
+ else:
60
+ print("⚠️ No logs found")
61
+ print(" Tip: Run Claude Code with some commands to generate logs")
62
+ print()
63
+
64
+ # Scenario 2: List available projects
65
+ print("Scenario 2: List available projects")
66
+ print("-" * 60)
67
+ if claude_path.exists():
68
+ projects = [p for p in claude_path.iterdir() if p.is_dir()]
69
+ if projects:
70
+ print(f"Found {len(projects)} project(s):")
71
+ for proj in sorted(projects, key=lambda p: p.stat().st_mtime, reverse=True):
72
+ jsonl_count = len(list(proj.glob("*.jsonl")))
73
+ mtime = proj.stat().st_mtime
74
+ from datetime import datetime
75
+ mtime_str = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S")
76
+ marker = " ← most recent" if proj == projects[0] else ""
77
+ print(f" • {proj.name}: {jsonl_count} .jsonl files (modified: {mtime_str}){marker}")
78
+ else:
79
+ print(" No projects found")
80
+ print()
81
+
82
+ # Scenario 3: Collect from specific project
83
+ if claude_path.exists():
84
+ projects = [p for p in claude_path.iterdir() if p.is_dir()]
85
+ if projects:
86
+ specific_project = projects[0].name
87
+ print(f"Scenario 3: Collect from specific project '{specific_project}'")
88
+ print("-" * 60)
89
+ logs = collect_recent_logs(limit=3, project_name=specific_project)
90
+ if logs:
91
+ print(f"✅ Collected {len(logs)} entries from '{specific_project}'")
92
+ print(f" Entry types: {[log.get('type', 'unknown') for log in logs[:3]]}")
93
+ else:
94
+ print(f"⚠️ No logs in '{specific_project}'")
95
+ print()
96
+
97
+ # Scenario 4: Show what would be sent with --send-logs
98
+ print("Scenario 4: What gets sent with 'zen --apex --send-logs --message \"..\"'")
99
+ print("-" * 60)
100
+ logs = collect_recent_logs(limit=1)
101
+ if logs:
102
+ payload_preview = {
103
+ "type": "user_message",
104
+ "payload": {
105
+ "content": "your message here",
106
+ "run_id": "cli_20250108_120000_12345",
107
+ "thread_id": "cli_thread_abc123def456",
108
+ "timestamp": "2025-01-08T12:00:00",
109
+ "jsonl_logs": logs # This is what gets attached
110
+ }
111
+ }
112
+ print("Payload structure:")
113
+ print(json.dumps(payload_preview, indent=2)[:500] + "...")
114
+ print()
115
+ print(f"✅ {len(logs)} log entries would be attached to the message")
116
+ else:
117
+ print("⚠️ No logs would be attached (none found)")
118
+ print()
119
+
120
+ # Summary
121
+ print("=" * 60)
122
+ print("Summary")
123
+ print("=" * 60)
124
+ print()
125
+ print("To use log forwarding with zen --apex:")
126
+ print()
127
+ print(" # Basic usage (default: 1 log file for best results)")
128
+ print(" zen --apex --send-logs --message \"analyze these sessions\"")
129
+ print()
130
+ print(" # Custom number of logs (default: 1 for best results)")
131
+ print(" zen --apex --send-logs --message \"review recent log\" (analyzes 1 file)")
132
+ print(" # Multiple files (use with caution - keep payload under 1MB)")
133
+ print(" zen --apex --send-logs --logs-count 2 --message \"review last 2\"")
134
+ print()
135
+ print(" # Specific project")
136
+ if claude_path.exists() and list(claude_path.iterdir()):
137
+ first_project = list(p for p in claude_path.iterdir() if p.is_dir())[0].name
138
+ print(f" zen --apex --send-logs --logs-project {first_project} --message \"...\"")
139
+ else:
140
+ print(" zen --apex --send-logs --logs-project PROJECT_NAME --message \"...\"")
141
+ print()
142
+ print("=" * 60)
143
+
144
+
145
+ if __name__ == "__main__":
146
+ demo_log_collection()