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.
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/PKG-INFO +32 -7
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/README.md +31 -6
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/pyproject.toml +1 -1
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/pyproject.toml.orig +1 -1
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/doctor.py +33 -2
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/LICENSE +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/__init__.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/event.v1.json +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/assets/opencode/grokbot-kit.ts +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/cli.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/config.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/deliver.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/emit.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/gc.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/launch.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/login.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/models.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/opencode_plugin.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/payload.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/redeliver.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/resolve.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/route.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/run.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/secret.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/setup.py +0 -0
- {grokbot_kit-0.2.0 → grokbot_kit-0.2.2}/src/grokbot_kit/sinks.py +0 -0
- {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.
|
|
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://
|
|
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:
|
|
66
|
-
|
|
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
|
|
71
|
-
|
|
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
|
+

|
|
81
|
+
|
|
82
|
+
**2. opencode installed, free models without login**
|
|
83
|
+
|
|
84
|
+

|
|
85
|
+
|
|
86
|
+
**3. Model tiers and the routine created by the bot**
|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
**4. Routine URL and key through the masked secret field**
|
|
91
|
+
|
|
92
|
+

|
|
93
|
+
|
|
94
|
+
**5. A task delegated to opencode, with the result back through the routine**
|
|
95
|
+
|
|
96
|
+

|
|
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://
|
|
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:
|
|
49
|
-
|
|
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
|
|
54
|
-
|
|
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
|
+

|
|
64
|
+
|
|
65
|
+
**2. opencode installed, free models without login**
|
|
66
|
+
|
|
67
|
+

|
|
68
|
+
|
|
69
|
+
**3. Model tiers and the routine created by the bot**
|
|
70
|
+
|
|
71
|
+

|
|
72
|
+
|
|
73
|
+
**4. Routine URL and key through the masked secret field**
|
|
74
|
+
|
|
75
|
+

|
|
76
|
+
|
|
77
|
+
**5. A task delegated to opencode, with the result back through the routine**
|
|
78
|
+
|
|
79
|
+

|
|
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.
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|