grokbot-kit 0.2.0__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.0 → grokbot_kit-0.2.2}/PKG-INFO +32 -7
  2. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/README.md +31 -6
  3. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/pyproject.toml +1 -1
  4. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/pyproject.toml.orig +1 -1
  5. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/doctor.py +33 -2
  6. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/LICENSE +0 -0
  7. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/__init__.py +0 -0
  8. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/event.v1.json +0 -0
  9. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/opencode/grokbot-kit.ts +0 -0
  10. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/cli.py +0 -0
  11. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/config.py +0 -0
  12. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/deliver.py +0 -0
  13. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/emit.py +0 -0
  14. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/gc.py +0 -0
  15. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/launch.py +0 -0
  16. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/login.py +0 -0
  17. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/models.py +0 -0
  18. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/opencode_plugin.py +0 -0
  19. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/payload.py +0 -0
  20. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/redeliver.py +0 -0
  21. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/resolve.py +0 -0
  22. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/route.py +0 -0
  23. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/run.py +0 -0
  24. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/secret.py +0 -0
  25. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/setup.py +0 -0
  26. {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/sinks.py +0 -0
  27. {grokbot_kit-0.2.0 → 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.0
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
@@ -58,20 +58,45 @@ CLIs and their login, the default CLI, the model tiers and the routine that the
58
58
 
59
59
  ```text
60
60
  Install the grokbot-kit skill and set up grokbot-kit on this box:
61
- 1. Download https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/v0.2.0/skills/grokbot-kit/SKILL.md
61
+ 1. Download https://github.com/rodrigo-pasini/grokbot-kit/releases/latest/download/SKILL.md (follow redirects)
62
62
  to /home/box/agent-data/workflows/grokbot-kit/SKILL.md (create the directory).
63
63
  2. Read that skill and follow its "Setup (primeira vez)" section from start to finish, one step at a time,
64
64
  skipping what `grokbot-kit doctor --json` shows as already done. Use "mybot" as the name of this bot.
65
- 3. Never ask me for a secret (API key, routine URL or key) in the chat: tell me the `grokbot-kit secret set`
66
- command and I run it in a terminal on the box.
65
+ 3. Never ask me for a secret (API key, routine URL or key) in the chat: read it yourself from the routine
66
+ or ask me in a masked secret field, and pass it to `grokbot-kit secret set` on standard input.
67
67
  4. At the end, run `grokbot-kit doctor --json` and summarise the result and any problems.
68
68
  ```
69
69
 
70
- The skill asks you to create the routine in the Grok Bot panel, with a webhook trigger and the routine prompt it
71
- gives you. Copy the routine URL and key from the panel only into the box terminal, never into the chat or a
72
- screenshot. When the setup ends, ask for a small task, such as "rename the variables in x.py": the bot picks the
70
+ The bot creates the routine, with a webhook trigger and the routine prompt from the skill, or asks you to create it
71
+ in the Grok Bot panel. It reads the routine URL and key itself or asks for each one in a masked secret field, never
72
+ in the chat or a screenshot. When the setup ends, ask for a small task, such as "rename the variables in x.py": the bot picks the
73
73
  `trivial` tier and tells you so, and the result arrives through the routine.
74
74
 
75
+ <details>
76
+ <summary>Screenshots of a setup and a task (Grok Bot, in Portuguese)</summary>
77
+
78
+ **1. The message and the choice of CLIs**
79
+
80
+ ![1. The message and the choice of CLIs](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/01-pedido-e-clis.png)
81
+
82
+ **2. opencode installed, free models without login**
83
+
84
+ ![2. opencode installed, free models without login](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/02-login.png)
85
+
86
+ **3. Model tiers and the routine created by the bot**
87
+
88
+ ![3. Model tiers and the routine created by the bot](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/03-tiers-e-routine.png)
89
+
90
+ **4. Routine URL and key through the masked secret field**
91
+
92
+ ![4. Routine URL and key through the masked secret field](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/04-segredos.png)
93
+
94
+ **5. A task delegated to opencode, with the result back through the routine**
95
+
96
+ ![5. A task delegated to opencode, with the result back through the routine](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/05-tarefa.png)
97
+
98
+ </details>
99
+
75
100
  ### By hand
76
101
 
77
102
  ```sh
@@ -41,20 +41,45 @@ CLIs and their login, the default CLI, the model tiers and the routine that the
41
41
 
42
42
  ```text
43
43
  Install the grokbot-kit skill and set up grokbot-kit on this box:
44
- 1. Download https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/v0.2.0/skills/grokbot-kit/SKILL.md
44
+ 1. Download https://github.com/rodrigo-pasini/grokbot-kit/releases/latest/download/SKILL.md (follow redirects)
45
45
  to /home/box/agent-data/workflows/grokbot-kit/SKILL.md (create the directory).
46
46
  2. Read that skill and follow its "Setup (primeira vez)" section from start to finish, one step at a time,
47
47
  skipping what `grokbot-kit doctor --json` shows as already done. Use "mybot" as the name of this bot.
48
- 3. Never ask me for a secret (API key, routine URL or key) in the chat: tell me the `grokbot-kit secret set`
49
- command and I run it in a terminal on the box.
48
+ 3. Never ask me for a secret (API key, routine URL or key) in the chat: read it yourself from the routine
49
+ or ask me in a masked secret field, and pass it to `grokbot-kit secret set` on standard input.
50
50
  4. At the end, run `grokbot-kit doctor --json` and summarise the result and any problems.
51
51
  ```
52
52
 
53
- The skill asks you to create the routine in the Grok Bot panel, with a webhook trigger and the routine prompt it
54
- gives you. Copy the routine URL and key from the panel only into the box terminal, never into the chat or a
55
- screenshot. When the setup ends, ask for a small task, such as "rename the variables in x.py": the bot picks the
53
+ The bot creates the routine, with a webhook trigger and the routine prompt from the skill, or asks you to create it
54
+ in the Grok Bot panel. It reads the routine URL and key itself or asks for each one in a masked secret field, never
55
+ in the chat or a screenshot. When the setup ends, ask for a small task, such as "rename the variables in x.py": the bot picks the
56
56
  `trivial` tier and tells you so, and the result arrives through the routine.
57
57
 
58
+ <details>
59
+ <summary>Screenshots of a setup and a task (Grok Bot, in Portuguese)</summary>
60
+
61
+ **1. The message and the choice of CLIs**
62
+
63
+ ![1. The message and the choice of CLIs](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/01-pedido-e-clis.png)
64
+
65
+ **2. opencode installed, free models without login**
66
+
67
+ ![2. opencode installed, free models without login](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/02-login.png)
68
+
69
+ **3. Model tiers and the routine created by the bot**
70
+
71
+ ![3. Model tiers and the routine created by the bot](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/03-tiers-e-routine.png)
72
+
73
+ **4. Routine URL and key through the masked secret field**
74
+
75
+ ![4. Routine URL and key through the masked secret field](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/04-segredos.png)
76
+
77
+ **5. A task delegated to opencode, with the result back through the routine**
78
+
79
+ ![5. A task delegated to opencode, with the result back through the routine](https://raw.githubusercontent.com/rodrigo-pasini/grokbot-kit/main/docs/images/quickstart/05-tarefa.png)
80
+
81
+ </details>
82
+
58
83
  ### By hand
59
84
 
60
85
  ```sh
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "grokbot-kit"
3
- version = "0.2.0"
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.0"
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