perplexity-web-mcp-cli 0.11.2__tar.gz → 0.12.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 (42) hide show
  1. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/PKG-INFO +1 -1
  2. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/pyproject.toml +1 -1
  3. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/main.py +1 -1
  4. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/skill.py +63 -39
  5. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/README.md +0 -0
  6. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/__init__.py +0 -0
  7. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/api/__init__.py +0 -0
  8. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/api/responses.py +0 -0
  9. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/api/server.py +0 -0
  10. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/api/session_manager.py +0 -0
  11. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/api/tool_calling.py +0 -0
  12. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/__init__.py +0 -0
  13. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/ai_doc.py +0 -0
  14. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/auth.py +0 -0
  15. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/doctor.py +0 -0
  16. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/hack.py +0 -0
  17. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/cli/setup.py +0 -0
  18. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/config.py +0 -0
  19. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/constants.py +0 -0
  20. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/core.py +0 -0
  21. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/council.py +0 -0
  22. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/data/SKILL.md +0 -0
  23. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/data/references/api-endpoints.md +0 -0
  24. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/data/references/mcp-tools.md +0 -0
  25. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/data/references/models.md +0 -0
  26. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/enums.py +0 -0
  27. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/exceptions.py +0 -0
  28. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/http.py +0 -0
  29. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/limits.py +0 -0
  30. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/logging.py +0 -0
  31. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/mcp/__init__.py +0 -0
  32. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/mcp/__main__.py +0 -0
  33. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/mcp/server.py +0 -0
  34. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/models.py +0 -0
  35. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/py.typed +0 -0
  36. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/rate_limits.py +0 -0
  37. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/resilience.py +0 -0
  38. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/router.py +0 -0
  39. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/sessions.py +0 -0
  40. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/shared.py +0 -0
  41. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/token_store.py +0 -0
  42. {perplexity_web_mcp_cli-0.11.2 → perplexity_web_mcp_cli-0.12.0}/src/perplexity_web_mcp/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: perplexity-web-mcp-cli
3
- Version: 0.11.2
3
+ Version: 0.12.0
4
4
  Summary: CLI, MCP server, and Anthropic/OpenAI API-compatible interface for Perplexity AI.
5
5
  Keywords: perplexity,ai,mcp,anthropic,api,client
6
6
  Author: Jacob BD
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "perplexity-web-mcp-cli"
3
- version = "0.11.2"
3
+ version = "0.12.0"
4
4
  description = "CLI, MCP server, and Anthropic/OpenAI API-compatible interface for Perplexity AI."
5
5
  authors = [{ name = "Jacob BD" }]
6
6
  license = "MIT"
@@ -230,7 +230,7 @@ def _cmd_research_impl(query, source, json_output):
230
230
 
231
231
  # ── Council ────────────────────────────────────────────────────────────────
232
232
 
233
- COUNCIL_MODEL_NAMES = ("gpt54", "gpt55", "claude_sonnet", "claude_opus", "gemini_pro", "nemotron")
233
+ COUNCIL_MODEL_NAMES = tuple(n for n in MODEL_NAMES if n not in {"auto", "sonar", "deep_research"})
234
234
 
235
235
 
236
236
  @cli.command()
@@ -6,8 +6,9 @@ to the appropriate location for each supported AI platform.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
- from dataclasses import dataclass
9
+ from dataclasses import dataclass, field
10
10
  from importlib import metadata
11
+ import os
11
12
  from pathlib import Path
12
13
  import re
13
14
  import shutil
@@ -17,6 +18,11 @@ import sys
17
18
  SKILL_DIR_NAME = "perplexity-web-mcp"
18
19
 
19
20
 
21
+ def _hermes_home() -> Path:
22
+ """Resolve the Hermes root directory, respecting $HERMES_HOME."""
23
+ return Path(os.environ.get("HERMES_HOME", Path.home() / ".hermes"))
24
+
25
+
20
26
  @dataclass(frozen=True)
21
27
  class SkillTarget:
22
28
  """A platform that supports Agent Skills."""
@@ -25,72 +31,95 @@ class SkillTarget:
25
31
  description: str
26
32
  user_dir: Path
27
33
  project_dir: str
34
+ binary: str | None = None
35
+ root_dirs: list[Path] = field(default_factory=list)
28
36
  frontmatter_extras: dict[str, str] | None = None
29
37
 
30
38
 
31
- def _home() -> Path:
32
- return Path.home()
33
-
34
-
35
39
  def _get_targets() -> list[SkillTarget]:
36
40
  """Return the list of platforms that support skills."""
37
- home = _home()
41
+ home = Path.home()
42
+ hm_root = _hermes_home()
38
43
  return [
39
44
  SkillTarget(
40
45
  name="claude-code",
41
46
  description="Claude Code CLI and Desktop",
42
47
  user_dir=home / ".claude" / "skills",
43
48
  project_dir=".claude/skills",
49
+ binary="claude",
50
+ root_dirs=[home / ".claude"],
44
51
  ),
45
52
  SkillTarget(
46
53
  name="cursor",
47
54
  description="Cursor AI editor",
48
55
  user_dir=home / ".cursor" / "skills",
49
56
  project_dir=".cursor/skills",
57
+ binary="cursor",
58
+ root_dirs=[home / ".cursor"],
50
59
  ),
51
60
  SkillTarget(
52
61
  name="codex",
53
62
  description="OpenAI Codex CLI",
54
63
  user_dir=home / ".agents" / "skills",
55
64
  project_dir=".agents/skills",
65
+ binary="codex",
66
+ root_dirs=[home / ".codex", home / ".agents"],
56
67
  ),
57
68
  SkillTarget(
58
69
  name="opencode",
59
70
  description="OpenCode AI assistant",
60
71
  user_dir=home / ".config" / "opencode" / "skills",
61
72
  project_dir=".opencode/skills",
73
+ binary="opencode",
74
+ root_dirs=[home / ".config" / "opencode"],
62
75
  ),
63
76
  SkillTarget(
64
77
  name="gemini-cli",
65
78
  description="Google Gemini CLI",
66
79
  user_dir=home / ".agents" / "skills",
67
80
  project_dir=".agents/skills",
81
+ binary="gemini",
82
+ root_dirs=[home / ".agents", home / ".gemini"],
68
83
  ),
69
84
  SkillTarget(
70
85
  name="antigravity",
71
86
  description="Google Antigravity IDE",
72
87
  user_dir=home / ".gemini" / "antigravity" / "skills",
73
88
  project_dir=".agent/skills",
89
+ root_dirs=[home / ".gemini" / "antigravity"],
74
90
  ),
75
91
  SkillTarget(
76
92
  name="cline",
77
93
  description="Cline CLI terminal agent",
78
94
  user_dir=home / ".cline" / "skills",
79
95
  project_dir=".cline/skills",
96
+ binary="cline",
97
+ root_dirs=[home / ".cline"],
80
98
  ),
81
99
  SkillTarget(
82
100
  name="openclaw",
83
101
  description="OpenClaw AI agent framework",
84
102
  user_dir=home / ".openclaw" / "workspace" / "skills",
85
103
  project_dir=".openclaw/workspace/skills",
104
+ binary="openclaw",
105
+ root_dirs=[home / ".openclaw"],
86
106
  ),
87
107
  SkillTarget(
88
108
  name="alef-agent",
89
109
  description="Alef Agent AI framework",
90
110
  user_dir=home / ".alef-agent" / "workspace" / "skills",
91
111
  project_dir=".alef-agent/workspace/skills",
112
+ root_dirs=[home / ".alef-agent"],
92
113
  frontmatter_extras={"type": "tool", "status": "approved"},
93
114
  ),
115
+ SkillTarget(
116
+ name="hermes",
117
+ description="Hermes Agent (NousResearch)",
118
+ user_dir=hm_root / "skills",
119
+ project_dir=".hermes/skills",
120
+ binary="hermes",
121
+ root_dirs=[hm_root],
122
+ ),
94
123
  SkillTarget(
95
124
  name="other",
96
125
  description="Export all formats for manual install",
@@ -100,33 +129,17 @@ def _get_targets() -> list[SkillTarget]:
100
129
  ]
101
130
 
102
131
 
103
- def _is_tool_detected(target: SkillTarget) -> bool:
104
- """Check if a tool appears to be installed on this system.
105
-
106
- Looks for the tool's config directory (parent of its skills dir) and
107
- verifies the tool itself created content there -- not just our own
108
- ``skills/`` subdirectory from a previous install.
132
+ def _is_tool_installed(target: SkillTarget) -> bool:
133
+ """Detect whether a tool is actually installed on this system.
109
134
 
110
- Special case: Codex and Gemini CLI both use ``~/.agents/`` which is a
111
- shared cross-tool directory, so we check for their respective binaries
112
- (``codex`` / ``gemini``) in PATH instead.
135
+ Checks two signals (either is sufficient):
136
+ 1. Binary on PATH (e.g. ``claude``, ``cursor``, ``opencode``, ``hermes``)
137
+ 2. Tool's root config directory exists (e.g. ``~/.claude``, ``~/.cursor``)
113
138
  """
114
- # Codex and Gemini CLI: check for binary since ~/.agents/ is a shared directory
115
- if target.name == "codex":
116
- return shutil.which("codex") is not None
117
- if target.name == "gemini-cli":
118
- return shutil.which("gemini") is not None
119
-
120
- config_root = target.user_dir.parent
121
- if not config_root.is_dir():
122
- return False
123
- try:
124
- for child in config_root.iterdir():
125
- if child.name != "skills":
126
- return True
127
- except OSError:
128
- return False
129
- return False
139
+ if target.binary and shutil.which(target.binary):
140
+ return True
141
+
142
+ return any(root_dir.is_dir() for root_dir in target.root_dirs)
130
143
 
131
144
 
132
145
  def _find_skill_source() -> Path | None:
@@ -163,10 +176,16 @@ def _get_installed_version(target_dir: Path) -> str | None:
163
176
  return None
164
177
  try:
165
178
  text = skill_file.read_text(encoding="utf-8")
166
- for line in text.split("\n"):
167
- line = line.strip()
168
- if line.startswith("version:"):
169
- return line.split(":", 1)[1].strip().strip('"').strip("'")
179
+ in_frontmatter = False
180
+ for raw_line in text.split("\n"):
181
+ stripped = raw_line.strip()
182
+ if stripped == "---":
183
+ if not in_frontmatter:
184
+ in_frontmatter = True
185
+ continue
186
+ break # closing --- reached
187
+ if stripped.startswith("version:"):
188
+ return stripped.split(":", 1)[1].strip().strip('"').strip("'")
170
189
  except OSError:
171
190
  pass
172
191
  return None
@@ -304,6 +323,11 @@ cp -r {SKILL_DIR_NAME} ~/.openclaw/workspace/skills/
304
323
  cp -r {SKILL_DIR_NAME} ~/.alef-agent/workspace/skills/
305
324
  ```
306
325
 
326
+ ### Hermes Agent
327
+ ```bash
328
+ cp -r {SKILL_DIR_NAME} ~/.hermes/skills/
329
+ ```
330
+
307
331
  ## Automated Installation
308
332
 
309
333
  Instead of manual copying, you can use:
@@ -311,7 +335,7 @@ Instead of manual copying, you can use:
311
335
  pwm skill install <tool>
312
336
  ```
313
337
 
314
- Where `<tool>` is: claude-code, cursor, codex, opencode, gemini-cli, antigravity, cline, openclaw, alef-agent.
338
+ Where `<tool>` is: claude-code, cursor, codex, opencode, gemini-cli, antigravity, cline, openclaw, alef-agent, hermes.
315
339
  """
316
340
 
317
341
  (export_dir / "README.md").write_text(readme_content)
@@ -336,14 +360,14 @@ def _install_all(targets: list[SkillTarget], current_version: str) -> int:
336
360
  for t in targets:
337
361
  if t.name == "other":
338
362
  continue
339
- if _is_tool_detected(t):
363
+ if _is_tool_installed(t):
340
364
  detected.append(t)
341
365
  else:
342
366
  not_detected.append(t.name)
343
367
 
344
368
  if not detected:
345
369
  print(" No supported tools detected on this system.")
346
- print(f" Looked for: {', '.join(t.name for t in targets)}")
370
+ print(" (No binary on PATH and no config directory found for any tool)")
347
371
  return 0
348
372
 
349
373
  installed: list[str] = []
@@ -405,7 +429,7 @@ def cmd_skill(args: list[str]) -> int:
405
429
  " pwm skill show Display the skill content\n"
406
430
  " pwm skill update Update all outdated skills\n"
407
431
  "\n"
408
- "Tools: claude-code, cursor, codex, opencode, gemini-cli, antigravity, cline, openclaw, alef-agent, other, all\n"
432
+ "Tools: claude-code, cursor, codex, opencode, gemini-cli, antigravity, cline, openclaw, alef-agent, hermes, other, all\n"
409
433
  "\n"
410
434
  "Examples:\n"
411
435
  " pwm skill list\n"