sv-cli 0.4.0__tar.gz → 0.5.0__tar.gz

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 (78) hide show
  1. {sv_cli-0.4.0 → sv_cli-0.5.0}/AGENT.md +1 -1
  2. {sv_cli-0.4.0 → sv_cli-0.5.0}/PKG-INFO +2 -2
  3. {sv_cli-0.4.0 → sv_cli-0.5.0}/pyproject.toml +1 -1
  4. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/__init__.py +1 -1
  5. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/adapters.py +1 -1
  6. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/api_client.py +7 -2
  7. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/executor.py +2 -1
  8. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/main.py +14 -2
  9. {sv_cli-0.4.0 → sv_cli-0.5.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  10. {sv_cli-0.4.0 → sv_cli-0.5.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  11. {sv_cli-0.4.0 → sv_cli-0.5.0}/.github/workflows/publish.yml +0 -0
  12. {sv_cli-0.4.0 → sv_cli-0.5.0}/.github/workflows/release.yml +0 -0
  13. {sv_cli-0.4.0 → sv_cli-0.5.0}/.github/workflows/test.yml +0 -0
  14. {sv_cli-0.4.0 → sv_cli-0.5.0}/.gitignore +0 -0
  15. {sv_cli-0.4.0 → sv_cli-0.5.0}/CHANGELOG.md +0 -0
  16. {sv_cli-0.4.0 → sv_cli-0.5.0}/CODE_OF_CONDUCT.md +0 -0
  17. {sv_cli-0.4.0 → sv_cli-0.5.0}/CONTRIBUTING.md +0 -0
  18. {sv_cli-0.4.0 → sv_cli-0.5.0}/LICENSE +0 -0
  19. {sv_cli-0.4.0 → sv_cli-0.5.0}/PULL_REQUEST_TEMPLATE.md +0 -0
  20. {sv_cli-0.4.0 → sv_cli-0.5.0}/README.md +0 -0
  21. {sv_cli-0.4.0 → sv_cli-0.5.0}/SECURITY.md +0 -0
  22. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/agent-usage.md +0 -0
  23. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/api-definition-format.md +0 -0
  24. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/authentication.md +0 -0
  25. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/commands.md +0 -0
  26. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/examples.md +0 -0
  27. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/installation.md +0 -0
  28. {sv_cli-0.4.0 → sv_cli-0.5.0}/docs/troubleshooting.md +0 -0
  29. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/__init__.py +0 -0
  30. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/auth.py +0 -0
  31. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/better_keywords.py +0 -0
  32. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/call.py +0 -0
  33. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/config.py +0 -0
  34. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/content_quality.py +0 -0
  35. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/content_transformer.py +0 -0
  36. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/core_analysis.py +0 -0
  37. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/definitions.py +0 -0
  38. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/geo_audit.py +0 -0
  39. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/insight_igniter.py +0 -0
  40. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/marketplace_services.py +0 -0
  41. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/options.py +0 -0
  42. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/preliminary_audit.py +0 -0
  43. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/ranklens.py +0 -0
  44. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/seo_image.py +0 -0
  45. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/seo_mapping.py +0 -0
  46. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/seogpt.py +0 -0
  47. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/seogpt2.py +0 -0
  48. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/seogpt_compare.py +0 -0
  49. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/top_competitors.py +0 -0
  50. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/commands/topical_authority.py +0 -0
  51. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/config.py +0 -0
  52. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/definitions.py +0 -0
  53. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/errors.py +0 -0
  54. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/formatter.py +0 -0
  55. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/__init__.py +0 -0
  56. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/csv_renderer.py +0 -0
  57. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/json_renderer.py +0 -0
  58. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/markdown_renderer.py +0 -0
  59. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/table_renderer.py +0 -0
  60. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/renderers/text_renderer.py +0 -0
  61. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/resolver.py +0 -0
  62. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/schemas/__init__.py +0 -0
  63. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/schemas/api_response.py +0 -0
  64. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/schemas/config.py +0 -0
  65. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/schemas/tool_definition.py +0 -0
  66. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/tasks.py +0 -0
  67. {sv_cli-0.4.0 → sv_cli-0.5.0}/src/sv_cli/utils.py +0 -0
  68. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/fixtures/api_root.json +0 -0
  69. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/fixtures/better_keywords_response.json +0 -0
  70. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/fixtures/ranklens_definitions.json +0 -0
  71. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/fixtures/seogpt2_definitions.json +0 -0
  72. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/fixtures/seogpt_definitions.json +0 -0
  73. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_config.py +0 -0
  74. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_definitions.py +0 -0
  75. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_executor.py +0 -0
  76. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_formatter.py +0 -0
  77. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_help_filtering.py +0 -0
  78. {sv_cli-0.4.0 → sv_cli-0.5.0}/tests/test_resolver.py +0 -0
@@ -87,7 +87,7 @@ seogpt: generate, raw
87
87
  seogpt2: create-task, get-task-status, get-result, raw
88
88
  seogpt-compare: create-task, get-task-status, get-result, raw
89
89
  seo-mapping: create-task, get-task-status, get-result, raw
90
- topical-authority: topics, content, raw
90
+ topical-authority: topics, raw
91
91
  top-competitors: analyze, raw
92
92
  marketplace-services: search, raw
93
93
  content-quality: analyze, raw
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: sv-cli
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Open-source, definition-driven command-line client for SV AI API tools.
5
5
  Project-URL: Homepage, https://github.com/seovendorco/sv-cli
6
6
  Project-URL: Issues, https://github.com/seovendorco/sv-cli/issues
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sv-cli"
7
- version = "0.4.0"
7
+ version = "0.5.0"
8
8
  description = "Open-source, definition-driven command-line client for SV AI API tools."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """SV CLI package."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.4.0"
@@ -242,7 +242,7 @@ TOOL_ADAPTERS: dict[str, ToolAdapter] = {
242
242
  command="topical-authority",
243
243
  aliases=("topical",),
244
244
  default_action="topics",
245
- actions=("topics", "content", "raw"),
245
+ actions=("topics", "raw"),
246
246
  field_aliases=COMMON_FIELD_ALIASES,
247
247
  option_aliases={
248
248
  "modes": ("topicmode", "topic_mode", "mode", "modes"),
@@ -24,9 +24,13 @@ class APIResponse:
24
24
 
25
25
 
26
26
  class APIClient:
27
- def __init__(self, *, debug: bool = False, console: Console | None = None) -> None:
27
+ def __init__(self, *, debug: bool = False, console: Console | None = None, client_type: str | None = None) -> None:
28
28
  self.debug = debug
29
29
  self.console = console or Console(stderr=True)
30
+ # Identifies this process to the SV API as "cli" or "mcp" (X-SV-Client header)
31
+ # for usage tracking. None means the caller didn't specify one - the header is
32
+ # simply omitted, and the API buckets the call as generic "api" usage.
33
+ self.client_type = client_type
30
34
 
31
35
  def request_tool(
32
36
  self,
@@ -42,6 +46,7 @@ class APIClient:
42
46
  final_payload["k"] = api_key
43
47
 
44
48
  method = method.upper()
49
+ headers = {"X-SV-Client": self.client_type} if self.client_type else None
45
50
  if self.debug:
46
51
  parsed = urlparse(endpoint)
47
52
  shown_path = parsed.path or endpoint
@@ -50,7 +55,7 @@ class APIClient:
50
55
 
51
56
  started = time.perf_counter()
52
57
  try:
53
- with httpx.Client(timeout=timeout, follow_redirects=True) as client:
58
+ with httpx.Client(timeout=timeout, follow_redirects=True, headers=headers) as client:
54
59
  if method == "GET":
55
60
  response = client.get(endpoint, params=final_payload)
56
61
  elif method in {"POST", "PUT", "PATCH"}:
@@ -120,6 +120,7 @@ def execute_tool(
120
120
  raw_payload: dict[str, Any] | None = None,
121
121
  method: str = "POST",
122
122
  console: Console | None = None,
123
+ client_type: str | None = None,
123
124
  ) -> Any:
124
125
  console = console or Console()
125
126
  definitions = DefinitionsManager(runtime.base_url)
@@ -149,7 +150,7 @@ def execute_tool(
149
150
  non_interactive=runtime.non_interactive,
150
151
  )
151
152
 
152
- client = APIClient(debug=runtime.debug, console=Console(stderr=True))
153
+ client = APIClient(debug=runtime.debug, console=Console(stderr=True), client_type=client_type)
153
154
  response = client.request_tool(endpoint=str(endpoint), payload=payload, api_key=api_key, method=method)
154
155
  data = response.data
155
156
 
@@ -228,6 +228,7 @@ def run_tool_action(
228
228
  wait_options=wait_options,
229
229
  method=method,
230
230
  console=console,
231
+ client_type="cli",
231
232
  )
232
233
  except Exception as exc: # noqa: BLE001
233
234
  fail(exc)
@@ -597,7 +598,16 @@ def raw_call(
597
598
  runtime = runtime_from_ctx(ctx)
598
599
  # Raw calls intentionally bypass fuzzy matching. Users can pass exact API payloads.
599
600
  runtime.no_fuzzy = True
600
- execute_tool(tool_name=tool, action=None, params={}, runtime=runtime, raw_payload=payload, method=method, console=console)
601
+ execute_tool(
602
+ tool_name=tool,
603
+ action=None,
604
+ params={},
605
+ runtime=runtime,
606
+ raw_payload=payload,
607
+ method=method,
608
+ console=console,
609
+ client_type="cli",
610
+ )
601
611
  except Exception as exc: # noqa: BLE001
602
612
  fail(exc)
603
613
 
@@ -617,7 +627,7 @@ def task_call(ctx: typer.Context, task_id: str, action: str, tool: str | None) -
617
627
  non_interactive=runtime.non_interactive,
618
628
  )
619
629
  payload = status_payload(task_id) if action == "status" else result_payload(task_id)
620
- data = APIClient(debug=runtime.debug, console=err_console).request_tool(
630
+ data = APIClient(debug=runtime.debug, console=err_console, client_type="cli").request_tool(
621
631
  endpoint=str(entry.get("endpoint")), payload=payload, api_key=api_key
622
632
  ).data
623
633
  print_output(console, data, runtime.output_format, runtime.output)
@@ -945,6 +955,7 @@ def make_tool_app(adapter: ToolAdapter) -> typer.Typer:
945
955
  runtime=runtime,
946
956
  wait_options=wait_options,
947
957
  console=console,
958
+ client_type="cli",
948
959
  )
949
960
  except Exception as exc: # noqa: BLE001
950
961
  fail(exc)
@@ -977,6 +988,7 @@ def make_tool_app(adapter: ToolAdapter) -> typer.Typer:
977
988
  raw_payload=payload,
978
989
  method=method,
979
990
  console=console,
991
+ client_type="cli",
980
992
  )
981
993
  except Exception as exc: # noqa: BLE001
982
994
  fail(exc)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes