grokbot-kit 0.2.1__tar.gz → 0.2.2__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 (27) hide show
  1. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/PKG-INFO +1 -1
  2. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/pyproject.toml +1 -1
  3. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/pyproject.toml.orig +1 -1
  4. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/doctor.py +33 -2
  5. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/LICENSE +0 -0
  6. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/README.md +0 -0
  7. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/__init__.py +0 -0
  8. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/event.v1.json +0 -0
  9. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/opencode/grokbot-kit.ts +0 -0
  10. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/cli.py +0 -0
  11. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/config.py +0 -0
  12. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/deliver.py +0 -0
  13. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/emit.py +0 -0
  14. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/gc.py +0 -0
  15. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/launch.py +0 -0
  16. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/login.py +0 -0
  17. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/models.py +0 -0
  18. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/opencode_plugin.py +0 -0
  19. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/payload.py +0 -0
  20. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/redeliver.py +0 -0
  21. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/resolve.py +0 -0
  22. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/route.py +0 -0
  23. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/run.py +0 -0
  24. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/secret.py +0 -0
  25. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/setup.py +0 -0
  26. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/sinks.py +0 -0
  27. {grokbot_kit-0.2.1 → grokbot_kit-0.2.2}/src/grokbot_kit/terminal.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: grokbot-kit
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Grok Bot integration kit: delegate tasks to headless coding agents (opencode, Claude Code, Codex) and wake the right Grok Bot routine when they finish or need input.
5
5
  Author: Rodrigo Pasini
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "grokbot-kit"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  description = "Grok Bot integration kit: delegate tasks to headless coding agents (opencode, Claude Code, Codex) and wake the right Grok Bot routine when they finish or need input."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "grokbot-kit"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  description = "Grok Bot integration kit: delegate tasks to headless coding agents (opencode, Claude Code, Codex) and wake the right Grok Bot routine when they finish or need input."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -8,10 +8,11 @@ import subprocess
8
8
  import sys
9
9
  from typing import Any
10
10
 
11
- from grokbot_kit import config
11
+ from grokbot_kit import config, launch, opencode_plugin
12
12
  from grokbot_kit.launch import TOOLS
13
13
 
14
14
  TIERS = ("trivial", "standard", "complex")
15
+ PLUGIN_EXE_PREFIX = "const GROKBOT_KIT = "
15
16
  STATUS_ARGV = {"claude": ["auth", "status"], "codex": ["login", "status"], "opencode": ["auth", "list"]}
16
17
  COMMAND_TIMEOUT = 60
17
18
  SECRET_KEYS = ("url_secret", "key_secret", "token_secret", "webhook_secret")
@@ -41,6 +42,21 @@ def _opencode_logged_in(proc: subprocess.CompletedProcess[str]) -> bool:
41
42
  return False
42
43
 
43
44
 
45
+ def _plugin() -> dict[str, Any]:
46
+ """O plugin global do opencode e o executável que ele chama (door 24)."""
47
+ path = opencode_plugin.plugin_path()
48
+ exe = None
49
+ try:
50
+ for line in path.read_text(encoding="utf-8").splitlines():
51
+ if line.startswith(PLUGIN_EXE_PREFIX):
52
+ value = json.loads(line.removeprefix(PLUGIN_EXE_PREFIX))
53
+ exe = value if isinstance(value, str) else None
54
+ break
55
+ except (OSError, ValueError):
56
+ exe = None
57
+ return {"path": str(path), "exe": exe, "ok": exe == launch.kit_executable()}
58
+
59
+
44
60
  def _cli(tool: str, cli: dict[str, Any], default: str | None) -> dict[str, Any]:
45
61
  bin_path = os.path.expanduser(str(cli.get("bin", tool)))
46
62
  method = "api-key" if tool == "claude" and "api_key_secret" in cli else "subscription"
@@ -58,13 +74,16 @@ def _cli(tool: str, cli: dict[str, Any], default: str | None) -> dict[str, Any]:
58
74
  else:
59
75
  logged_in = status.returncode == 0
60
76
  tiers = cli.get("tiers", {})
61
- return {
77
+ entry = {
62
78
  "bin": bin_path,
63
79
  "version": (version.stdout.strip().splitlines() or [""])[0] if version and version.returncode == 0 else None,
64
80
  "default": tool == default,
65
81
  "login": {"command": " ".join([tool, *STATUS_ARGV[tool]]), "method": method, "logged_in": logged_in},
66
82
  "tiers": {tier: len(tiers.get(tier, [])) for tier in TIERS},
67
83
  }
84
+ if tool == "opencode":
85
+ entry["plugin"] = _plugin()
86
+ return entry
68
87
 
69
88
 
70
89
  def problems(out: dict[str, Any], facts: dict[str, Any]) -> list[str]:
@@ -85,6 +104,14 @@ def problems(out: dict[str, Any], facts: dict[str, Any]) -> list[str]:
85
104
  found.append(f"{cli['login']['command']} failed")
86
105
  elif not logged_in and tool != "opencode":
87
106
  found.append(f"{tool} is not logged in; run: grokbot-kit login {tool}")
107
+ plugin = cli.get("plugin")
108
+ if plugin and plugin["exe"] is None:
109
+ found.append(f"opencode plugin not found at {plugin['path']}; run: grokbot-kit install opencode")
110
+ elif plugin and not plugin["ok"]:
111
+ found.append(
112
+ f"opencode plugin at {plugin['path']} calls {plugin['exe']}, not {launch.kit_executable()}; "
113
+ "run: grokbot-kit install opencode"
114
+ )
88
115
  mode = facts.get("secrets_dir_mode")
89
116
  if mode is not None and mode != 0o700:
90
117
  found.append(
@@ -145,6 +172,10 @@ def _text(out: dict[str, Any]) -> str:
145
172
  default = " (default)" if cli["default"] else ""
146
173
  lines.append(f"{tool}{default}: {cli['version'] or 'version unknown'} at {cli['bin']}")
147
174
  lines.append(f" login: {state} ({login['method']}, {login['command']}); tiers: {tiers}")
175
+ if "plugin" in cli:
176
+ plugin = cli["plugin"]
177
+ plugin_state = "missing" if plugin["exe"] is None else "ok" if plugin["ok"] else "stale"
178
+ lines.append(f" plugin: {plugin_state} ({plugin['path']})")
148
179
  for target, sinks in out["routes"].items():
149
180
  lines.append(f"route {target}: {', '.join(sinks)}")
150
181
  for name, secret in out["secrets"].items():
File without changes
File without changes