coze_lab 0.1.14 → 0.1.15
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.
- package/README.md +11 -0
- package/index.js +12 -2
- package/package.json +7 -2
- package/scripts/claude-code/cozeloop_hook.py +41 -4
- package/scripts/codex/cozeloop_hook.py +41 -4
package/README.md
CHANGED
|
@@ -8,6 +8,9 @@ Configure local AI agents (Claude Code, Codex, OpenClaw) to report traces to Coz
|
|
|
8
8
|
# First-time setup — triggers browser OAuth authorization
|
|
9
9
|
npx coze_lab --agent=<type>
|
|
10
10
|
|
|
11
|
+
# Cloud setup for a managed agent
|
|
12
|
+
npx coze_lab --cloud --agent-id=<agentId>
|
|
13
|
+
|
|
11
14
|
# Auth-only commands (no agent configuration)
|
|
12
15
|
npx coze_lab --login # Device Code login only
|
|
13
16
|
npx coze_lab --status # Show current authorization status
|
|
@@ -20,6 +23,9 @@ npx coze_lab --logout # Clear cached credentials
|
|
|
20
23
|
| Parameter | Required | Values / Effect |
|
|
21
24
|
|-----------|----------|-----------------|
|
|
22
25
|
| `--agent` | ✓ (for setup) | `claude-code`, `codex`, `openclaw` |
|
|
26
|
+
| `--agent-id` | — | Resolve `~/.coze/agents/<agentId>/config.json` and write per-agent config |
|
|
27
|
+
| `--cloud` | — | Cloud mode: read token from env and emit `COZE_LAB_RESULT=...` |
|
|
28
|
+
| `--codex-home` | — | Override Codex config home for non-cloud/custom runs |
|
|
23
29
|
| `--login` | — | Run the Device Code login flow only |
|
|
24
30
|
| `--status` | — | Print local token status (valid / expiring / expired) |
|
|
25
31
|
| `--refresh` | — | Force-refresh the access token via `refresh_token` |
|
|
@@ -50,6 +56,11 @@ npx coze_lab --logout # Clear cached credentials
|
|
|
50
56
|
| `codex` | `~/.codex/hooks/cozeloop_hook.py` | `~/.codex/hooks.json` | `~/.codex/hooks/cozeloop.env` |
|
|
51
57
|
| `openclaw` | — (Node.js plugin) | `~/.openclaw/openclaw.json` | inline in config |
|
|
52
58
|
|
|
59
|
+
For cloud Codex with `--cloud --agent-id=<agentId>`, Codex hooks are written to
|
|
60
|
+
`~/.coze/agents/<agentId>/codex-home` by default. The directory is created if it
|
|
61
|
+
does not already exist, so callers do not need to pass `--codex-home` for the
|
|
62
|
+
standard coze-bridge layout.
|
|
63
|
+
|
|
53
64
|
## Token lifecycle
|
|
54
65
|
|
|
55
66
|
OAuth tokens are stored in `~/.cozeloop/credentials.json` (mode 600).
|
package/index.js
CHANGED
|
@@ -4618,6 +4618,13 @@ function writeCodexHook(token, workspaceId, pythonCmd, codexHome, cloud) {
|
|
|
4618
4618
|
return { hookScript, envFile, hooksJson };
|
|
4619
4619
|
}
|
|
4620
4620
|
|
|
4621
|
+
function resolveCodexHome(args) {
|
|
4622
|
+
if (args.cloud && args.agentId) {
|
|
4623
|
+
return path.join(os.homedir(), '.coze', 'agents', args.agentId, 'codex-home');
|
|
4624
|
+
}
|
|
4625
|
+
return args['codex-home'] || process.env.CODEX_HOME || undefined;
|
|
4626
|
+
}
|
|
4627
|
+
|
|
4621
4628
|
// writeOpenClawHook 配置 OpenClaw 的 cozeloop-trace 插件(全局装在 ~/.openclaw)。
|
|
4622
4629
|
// agentId 非空时并入 plugins.entries[...].config.traceAgentIds allowlist —— 插件运行时
|
|
4623
4630
|
// 用 resolveAgentIdFromHookCtx 取当前 agentId,仅 allowlist 内的 agent 才上报 trace。
|
|
@@ -5290,8 +5297,11 @@ async function main() {
|
|
|
5290
5297
|
}
|
|
5291
5298
|
written = writeClaudeCodeHook(token, WORKSPACE_ID, pythonCmd, args.agentId ? agentWorkspace : undefined, args.cloud);
|
|
5292
5299
|
} else if (agent === 'codex') {
|
|
5293
|
-
|
|
5294
|
-
|
|
5300
|
+
const codexHome = resolveCodexHome(args);
|
|
5301
|
+
if (args.cloud && args.agentId && codexHome && !fs.existsSync(codexHome)) {
|
|
5302
|
+
ensureDir(codexHome);
|
|
5303
|
+
info(`已创建云端 Codex 配置目录: ${codexHome}`);
|
|
5304
|
+
}
|
|
5295
5305
|
if (codexHome) info(`Codex 配置目录: ${codexHome}`);
|
|
5296
5306
|
written = writeCodexHook(token, WORKSPACE_ID, pythonCmd, codexHome, args.cloud);
|
|
5297
5307
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coze_lab",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Configure local AI agents (Claude Code, Codex, OpenClaw) to report traces to CozeLoop",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cozeloop",
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"index.js",
|
|
19
|
-
"scripts/"
|
|
19
|
+
"scripts/claude-code/cozeloop_hook.py",
|
|
20
|
+
"scripts/codex/cozeloop_hook.py",
|
|
21
|
+
"scripts/shared/cozeloop_refresh.py",
|
|
22
|
+
"scripts/openclaw/dist/",
|
|
23
|
+
"scripts/openclaw/openclaw.plugin.json",
|
|
24
|
+
"scripts/openclaw/package.json"
|
|
20
25
|
],
|
|
21
26
|
"engines": {
|
|
22
27
|
"node": ">=18"
|
|
@@ -29,15 +29,53 @@ from pathlib import Path
|
|
|
29
29
|
from typing import Optional, List, Dict, Any
|
|
30
30
|
|
|
31
31
|
# --- SDK Import ---
|
|
32
|
-
|
|
32
|
+
def _ensure_cozeloop_sdk():
|
|
33
|
+
try:
|
|
34
|
+
import cozeloop # noqa: F401
|
|
35
|
+
return True
|
|
36
|
+
except ImportError:
|
|
37
|
+
pass
|
|
38
|
+
import subprocess
|
|
39
|
+
import importlib
|
|
40
|
+
import site
|
|
41
|
+
attempts = (
|
|
42
|
+
["--quiet", "--disable-pip-version-check", "cozeloop"],
|
|
43
|
+
["--quiet", "--disable-pip-version-check", "--break-system-packages", "cozeloop"],
|
|
44
|
+
["--quiet", "--disable-pip-version-check", "--break-system-packages", "--user", "cozeloop"],
|
|
45
|
+
)
|
|
46
|
+
for extra in attempts:
|
|
47
|
+
try:
|
|
48
|
+
subprocess.run(
|
|
49
|
+
[sys.executable, "-m", "pip", "install", *extra],
|
|
50
|
+
timeout=180, check=True,
|
|
51
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
52
|
+
)
|
|
53
|
+
except Exception:
|
|
54
|
+
continue
|
|
55
|
+
try:
|
|
56
|
+
importlib.reload(site)
|
|
57
|
+
user_site = site.getusersitepackages()
|
|
58
|
+
for p in ([user_site] if isinstance(user_site, str) else list(user_site)):
|
|
59
|
+
if p and p not in sys.path:
|
|
60
|
+
sys.path.insert(0, p)
|
|
61
|
+
importlib.invalidate_caches()
|
|
62
|
+
import cozeloop # noqa: F401
|
|
63
|
+
print("[CozeLoop] cozeloop SDK auto-installed at runtime.", file=sys.stderr)
|
|
64
|
+
return True
|
|
65
|
+
except ImportError:
|
|
66
|
+
continue
|
|
67
|
+
return False
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
if _ensure_cozeloop_sdk():
|
|
33
71
|
import cozeloop
|
|
34
72
|
from cozeloop.spec.tracespec import (
|
|
35
73
|
Runtime, ModelInput, ModelMessage, ModelToolChoice,
|
|
36
74
|
ModelOutput, ModelChoice, ModelToolCall, ModelToolCallFunction,
|
|
37
75
|
ModelMessagePart, ModelMessagePartType
|
|
38
76
|
)
|
|
39
|
-
|
|
40
|
-
print("Error: cozeloop SDK not found
|
|
77
|
+
else:
|
|
78
|
+
print("Error: cozeloop SDK not found and auto-install failed. Try: pip install cozeloop", file=sys.stderr)
|
|
41
79
|
sys.exit(1)
|
|
42
80
|
|
|
43
81
|
# --- Configuration ---
|
|
@@ -1412,4 +1450,3 @@ if __name__ == "__main__":
|
|
|
1412
1450
|
main()
|
|
1413
1451
|
|
|
1414
1452
|
|
|
1415
|
-
|
|
@@ -202,15 +202,53 @@ def get_fresh_token():
|
|
|
202
202
|
# -------------------------------------------------------------------------
|
|
203
203
|
|
|
204
204
|
# --- SDK Import ---
|
|
205
|
-
|
|
205
|
+
def _ensure_cozeloop_sdk():
|
|
206
|
+
try:
|
|
207
|
+
import cozeloop # noqa: F401
|
|
208
|
+
return True
|
|
209
|
+
except ImportError:
|
|
210
|
+
pass
|
|
211
|
+
import subprocess
|
|
212
|
+
import importlib
|
|
213
|
+
import site
|
|
214
|
+
attempts = (
|
|
215
|
+
["--quiet", "--disable-pip-version-check", "cozeloop"],
|
|
216
|
+
["--quiet", "--disable-pip-version-check", "--break-system-packages", "cozeloop"],
|
|
217
|
+
["--quiet", "--disable-pip-version-check", "--break-system-packages", "--user", "cozeloop"],
|
|
218
|
+
)
|
|
219
|
+
for extra in attempts:
|
|
220
|
+
try:
|
|
221
|
+
subprocess.run(
|
|
222
|
+
[sys.executable, "-m", "pip", "install", *extra],
|
|
223
|
+
timeout=180, check=True,
|
|
224
|
+
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
|
|
225
|
+
)
|
|
226
|
+
except Exception:
|
|
227
|
+
continue
|
|
228
|
+
try:
|
|
229
|
+
importlib.reload(site)
|
|
230
|
+
user_site = site.getusersitepackages()
|
|
231
|
+
for p in ([user_site] if isinstance(user_site, str) else list(user_site)):
|
|
232
|
+
if p and p not in sys.path:
|
|
233
|
+
sys.path.insert(0, p)
|
|
234
|
+
importlib.invalidate_caches()
|
|
235
|
+
import cozeloop # noqa: F401
|
|
236
|
+
print("[CozeLoop] cozeloop SDK auto-installed at runtime.", file=sys.stderr)
|
|
237
|
+
return True
|
|
238
|
+
except ImportError:
|
|
239
|
+
continue
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
if _ensure_cozeloop_sdk():
|
|
206
244
|
import cozeloop
|
|
207
245
|
from cozeloop.spec.tracespec import (
|
|
208
246
|
Runtime, ModelInput, ModelMessage, ModelToolChoice,
|
|
209
247
|
ModelOutput, ModelChoice, ModelToolCall, ModelToolCallFunction,
|
|
210
248
|
ModelMessagePart, ModelMessagePartType
|
|
211
249
|
)
|
|
212
|
-
|
|
213
|
-
print("Error: cozeloop SDK not found
|
|
250
|
+
else:
|
|
251
|
+
print("Error: cozeloop SDK not found and auto-install failed. Try: pip install cozeloop", file=sys.stderr)
|
|
214
252
|
sys.exit(1)
|
|
215
253
|
|
|
216
254
|
# --- Configuration ---
|
|
@@ -1120,4 +1158,3 @@ def main():
|
|
|
1120
1158
|
|
|
1121
1159
|
if __name__ == "__main__":
|
|
1122
1160
|
main()
|
|
1123
|
-
|