cognova 0.2.18 → 0.2.20

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cognova-prod",
3
- "version": "0.2.17",
3
+ "version": "0.2.19",
4
4
  "type": "module",
5
5
  "private": true,
6
6
  "dependencies": {
@@ -11,7 +11,7 @@ import os
11
11
  import subprocess
12
12
  import sys
13
13
  from pathlib import Path
14
- from typing import Any
14
+ from typing import Any, Optional
15
15
 
16
16
  API_BASE = os.environ.get('COGNOVA_API_URL', 'http://localhost:3000')
17
17
 
@@ -59,8 +59,8 @@ if not API_TOKEN and os.environ.get('DEBUG'):
59
59
  def api_request(
60
60
  method: str,
61
61
  endpoint: str,
62
- data: dict | None = None,
63
- params: dict | None = None
62
+ data: Optional[dict] = None,
63
+ params: Optional[dict] = None
64
64
  ) -> tuple[bool, Any]:
65
65
  """
66
66
  Make an API request to Cognova.
@@ -123,7 +123,7 @@ def api_request(
123
123
  return False, str(e)
124
124
 
125
125
 
126
- def get(endpoint: str, params: dict | None = None) -> tuple[bool, Any]:
126
+ def get(endpoint: str, params: Optional[dict] = None) -> tuple[bool, Any]:
127
127
  """GET request helper."""
128
128
  return api_request("GET", endpoint, params=params)
129
129
 
@@ -14,6 +14,7 @@ import argparse
14
14
  import re
15
15
  import sys
16
16
  from pathlib import Path
17
+ from typing import Optional
17
18
 
18
19
  sys.path.insert(0, str(Path(__file__).parent.parent / '_lib'))
19
20
 
@@ -26,7 +27,7 @@ def validate_color(color: str) -> bool:
26
27
  return bool(re.match(r'^#[0-9A-Fa-f]{6}$', color))
27
28
 
28
29
 
29
- def find_project_by_id(id_prefix: str) -> str | None:
30
+ def find_project_by_id(id_prefix: str) -> Optional[str]:
30
31
  """Find a project by ID prefix."""
31
32
  ok, projects = get('/projects')
32
33
  if not ok:
@@ -115,6 +115,7 @@ python3 ~/.claude/skills/<name>/<name>.py <command> [options]
115
115
  import argparse
116
116
  import sys
117
117
  from pathlib import Path
118
+ from typing import Optional # Use Optional[T] instead of T | None for Python 3.9 compatibility
118
119
 
119
120
  def main():
120
121
  parser = argparse.ArgumentParser(description='Skill Name')
@@ -126,6 +127,12 @@ if __name__ == '__main__':
126
127
  main()
127
128
  ```
128
129
 
130
+ **Python 3.9 Compatibility:**
131
+ - Skills must work with Python 3.9+ (macOS ships with 3.9.6)
132
+ - Use `Optional[T]` instead of `T | None` for type hints
133
+ - Import `Optional` from `typing` module
134
+ - Avoid `match` statements and other Python 3.10+ features
135
+
129
136
  ### 5. Accessing Secrets & API Keys
130
137
 
131
138
  **NEVER hardcode API keys, tokens, or sensitive values in skills.**
@@ -14,6 +14,7 @@ import argparse
14
14
  import sys
15
15
  from datetime import datetime, timedelta
16
16
  from pathlib import Path
17
+ from typing import Optional
17
18
 
18
19
  sys.path.insert(0, str(Path(__file__).parent.parent / '_lib'))
19
20
 
@@ -21,7 +22,7 @@ from api import get, post, put, delete
21
22
  from output import success, error, info, format_task
22
23
 
23
24
 
24
- def parse_date(date_str: str) -> str | None:
25
+ def parse_date(date_str: str) -> Optional[str]:
25
26
  """Parse natural language date to ISO format."""
26
27
  if not date_str:
27
28
  return None
@@ -53,7 +54,7 @@ def parse_date(date_str: str) -> str | None:
53
54
  return date_str
54
55
 
55
56
 
56
- def find_project(name: str) -> dict | None:
57
+ def find_project(name: str) -> Optional[dict]:
57
58
  """Search for a project by name."""
58
59
  ok, projects = get('/projects')
59
60
  if not ok:
@@ -77,7 +78,7 @@ def find_project(name: str) -> dict | None:
77
78
  return None
78
79
 
79
80
 
80
- def find_task_by_id(id_prefix: str) -> str | None:
81
+ def find_task_by_id(id_prefix: str) -> Optional[str]:
81
82
  """Find a task by ID prefix."""
82
83
  ok, tasks = get('/tasks', {'includeDeleted': 'false'})
83
84
  if not ok: