teamai-cli 0.24.0-beta.2 → 0.24.0-beta.3
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 +1 -0
- package/README.zh-CN.md +1 -0
- package/dist/index.js +110 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -91,6 +91,7 @@ Once initialized, every AI session automatically pulls the latest skills / rules
|
|
|
91
91
|
<tr><td>Hermes</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td></tr>
|
|
92
92
|
<tr><td>DeepSeek Harness</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td></tr>
|
|
93
93
|
<tr><td>Qoder</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td></tr>
|
|
94
|
+
<tr><td>ZCode</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td></tr>
|
|
94
95
|
</tbody>
|
|
95
96
|
</table>
|
|
96
97
|
|
package/README.zh-CN.md
CHANGED
|
@@ -91,6 +91,7 @@ teamai init https://github.com/yourorg/yourrepo --scope user
|
|
|
91
91
|
<tr><td>Hermes</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td></tr>
|
|
92
92
|
<tr><td>DeepSeek Harness</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">—</td><td align="center">—</td><td align="center">—</td></tr>
|
|
93
93
|
<tr><td>Qoder</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td></tr>
|
|
94
|
+
<tr><td>ZCode</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">—</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td><td align="center">✓</td></tr>
|
|
94
95
|
</tbody>
|
|
95
96
|
</table>
|
|
96
97
|
|
package/dist/index.js
CHANGED
|
@@ -868,6 +868,17 @@ var init_types = __esm({
|
|
|
868
868
|
mcp: ".qoder/settings.json",
|
|
869
869
|
mcpProject: ".qoder/settings.json"
|
|
870
870
|
},
|
|
871
|
+
// ZCode: user-level config lives at ~/.zcode/cli/config.json (a shared file
|
|
872
|
+
// that also carries plugin state — reconcile must merge, never replace).
|
|
873
|
+
// Hooks are Claude-shaped but nested under `hooks.events` and gated by
|
|
874
|
+
// `hooks.enabled` (config-file hooks are disabled by default; the writer
|
|
875
|
+
// must force it on). Subagents deploy to ~/.zcode/agents/ as Claude-style
|
|
876
|
+
// Markdown (the CLI also reads <project>/.zcode/agents/ per workspace).
|
|
877
|
+
// User-scope MCP mirrors Claude's shape (`mcpServers` key) in
|
|
878
|
+
// ~/.agents/mcp.json; project scope writes `mcp.servers` inside
|
|
879
|
+
// .zcode/config.json (a different key), which the Claude writer cannot
|
|
880
|
+
// emit — so no mcpProject. ZCode has no user-level rules dir convention.
|
|
881
|
+
zcode: { skills: ".zcode/skills", agents: ".zcode/agents", settings: ".zcode/cli/config.json", mcp: ".agents/mcp.json" },
|
|
871
882
|
codebuddy: { skills: ".codebuddy/skills", rules: ".codebuddy/rules", settings: ".codebuddy/settings.json", claudemd: ".codebuddy/CODEBUDDY.md", agents: ".codebuddy/agents", mcp: ".codebuddy/mcp.json", mcpProject: ".codebuddy/mcp.json" },
|
|
872
883
|
openclaw: { skills: ".openclaw/skills", rules: ".openclaw/rules", claudemd: ".openclaw/workspace/AGENTS.md" },
|
|
873
884
|
hermes: { skills: ".hermes/skills", claudemd: "AGENTS.md" },
|
|
@@ -1240,13 +1251,17 @@ function getDispatchCommand(event, tool, matcher, binPath) {
|
|
|
1240
1251
|
const matcherArg = matcher && matcher !== "*" ? ` --matcher ${matcher}` : "";
|
|
1241
1252
|
return `bash -lc "${bin} hook-dispatch ${event} --tool ${tool}${matcherArg} 2>/dev/null" || true`;
|
|
1242
1253
|
}
|
|
1254
|
+
function getRawDispatchCommand(event, tool, matcher) {
|
|
1255
|
+
const matcherArg = matcher && matcher !== "*" ? ` --matcher ${matcher}` : "";
|
|
1256
|
+
return `teamai hook-dispatch ${event} --tool ${tool}${matcherArg}`;
|
|
1257
|
+
}
|
|
1243
1258
|
function getWrapperDispatchCommand(event, tool, matcher) {
|
|
1244
1259
|
const matcherArg = matcher && matcher !== "*" ? ` --matcher ${matcher}` : "";
|
|
1245
1260
|
return `PATH="$HOME/${TEAMAI_BIN_DIR}:$PATH" teamai hook-dispatch ${event} --tool ${tool}${matcherArg} 2>/dev/null || true`;
|
|
1246
1261
|
}
|
|
1247
1262
|
function builtinHookDefs(tool) {
|
|
1248
|
-
const withTimeout3 = tool === "cursor" || tool === "workbuddy" || tool === "codebuddy";
|
|
1249
|
-
const buildCommand = WRAPPER_TOOLS.has(tool) ? getWrapperDispatchCommand : getDispatchCommand;
|
|
1263
|
+
const withTimeout3 = tool === "cursor" || tool === "workbuddy" || tool === "codebuddy" || tool === "zcode";
|
|
1264
|
+
const buildCommand = tool === "zcode" ? getRawDispatchCommand : WRAPPER_TOOLS.has(tool) ? getWrapperDispatchCommand : getDispatchCommand;
|
|
1250
1265
|
return BUILTIN_HOOK_SPECS.map((spec) => ({
|
|
1251
1266
|
source: "builtin",
|
|
1252
1267
|
key: spec.key,
|
|
@@ -2186,6 +2201,7 @@ import path12 from "path";
|
|
|
2186
2201
|
import { realpathSync } from "fs";
|
|
2187
2202
|
function detectFormat(tool) {
|
|
2188
2203
|
if (CODEX_TOOLS.has(tool)) return "codex";
|
|
2204
|
+
if (ZCODE_TOOLS.has(tool)) return "zcode";
|
|
2189
2205
|
return CURSOR_TOOLS.has(tool) ? "cursor" : "claude";
|
|
2190
2206
|
}
|
|
2191
2207
|
function isCodexTrustGatedTool(tool) {
|
|
@@ -2273,6 +2289,27 @@ function toCodexEntry(def) {
|
|
|
2273
2289
|
if (def.matcher && def.matcher !== "*") entry.matcher = def.matcher;
|
|
2274
2290
|
return entry;
|
|
2275
2291
|
}
|
|
2292
|
+
function toZcodeEntry(def) {
|
|
2293
|
+
const entry = {
|
|
2294
|
+
type: "process",
|
|
2295
|
+
command: "bash",
|
|
2296
|
+
// Stored verbatim: the shell payload must equal `def.command` exactly so
|
|
2297
|
+
// managed-entry detection and the managed-hooks manifest share one command
|
|
2298
|
+
// representation (the same invariant the Codex format keeps). teamai
|
|
2299
|
+
// hook-dispatch is silent and failure-tolerant on its success paths, so no
|
|
2300
|
+
// shell redirection is layered on top of the payload.
|
|
2301
|
+
args: ["-lc", def.command],
|
|
2302
|
+
...def.timeout !== void 0 ? { timeoutMs: def.timeout * 1e3 } : {}
|
|
2303
|
+
};
|
|
2304
|
+
const group = { hooks: [entry] };
|
|
2305
|
+
if (def.matcher && def.matcher !== "*") group.matcher = def.matcher;
|
|
2306
|
+
return group;
|
|
2307
|
+
}
|
|
2308
|
+
function zcodeEntryCommand(entry) {
|
|
2309
|
+
const hook = entry.hooks?.[0];
|
|
2310
|
+
if (hook?.command === "bash" && hook.args?.[0] === "-lc") return hook.args[1] ?? "";
|
|
2311
|
+
return hook?.command ?? "";
|
|
2312
|
+
}
|
|
2276
2313
|
function desiredEventOrder(defs, mapEvent) {
|
|
2277
2314
|
const seen = /* @__PURE__ */ new Set();
|
|
2278
2315
|
const order = [];
|
|
@@ -2412,6 +2449,42 @@ async function reconcileCodexFormat(hooksPath, tool, teamDefs, opts, priorTeamCo
|
|
|
2412
2449
|
log.debug(`teamai hooks already up-to-date in ${hooksPath}`);
|
|
2413
2450
|
}
|
|
2414
2451
|
}
|
|
2452
|
+
async function reconcileZcodeFormat(settingsPath, tool, teamDefs, opts, priorTeamCommands) {
|
|
2453
|
+
const expanded = expandHome(settingsPath);
|
|
2454
|
+
await ensureDir(path12.dirname(expanded));
|
|
2455
|
+
const cfg = await readJson(expanded) ?? {};
|
|
2456
|
+
if (!cfg.hooks) cfg.hooks = {};
|
|
2457
|
+
let changed = false;
|
|
2458
|
+
if (!opts.removeAll && cfg.hooks.enabled !== true) {
|
|
2459
|
+
cfg.hooks.enabled = true;
|
|
2460
|
+
changed = true;
|
|
2461
|
+
}
|
|
2462
|
+
if (!cfg.hooks.events) cfg.hooks.events = {};
|
|
2463
|
+
const isManaged = (entry) => {
|
|
2464
|
+
const cmd = zcodeEntryCommand(entry);
|
|
2465
|
+
return TEAMAI_COMMAND_MARKERS.some((marker) => cmd.includes(marker)) || priorTeamCommands.has(cmd);
|
|
2466
|
+
};
|
|
2467
|
+
const defs = opts.removeAll ? [] : desiredDefs(tool, teamDefs, opts.builtinOverride);
|
|
2468
|
+
const eventOrder = desiredEventOrder(defs, (e) => e);
|
|
2469
|
+
const eventsMap = cfg.hooks.events;
|
|
2470
|
+
const events = [...eventOrder, ...Object.keys(eventsMap).filter((e) => !eventOrder.includes(e))];
|
|
2471
|
+
for (const event of events) {
|
|
2472
|
+
const existing = eventsMap[event] ?? [];
|
|
2473
|
+
const untouched = existing.filter((e) => !isManaged(e));
|
|
2474
|
+
const desiredEntries = defs.filter((d) => d.event === event).map(toZcodeEntry);
|
|
2475
|
+
const newArr = [...untouched, ...desiredEntries];
|
|
2476
|
+
if (JSON.stringify(existing) !== JSON.stringify(newArr)) {
|
|
2477
|
+
eventsMap[event] = newArr;
|
|
2478
|
+
changed = true;
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
if (changed) {
|
|
2482
|
+
await writeJson(expanded, cfg);
|
|
2483
|
+
log.success(`${opts.removeAll ? "Removed" : "Updated"} teamai hooks in ${settingsPath}`);
|
|
2484
|
+
} else {
|
|
2485
|
+
log.debug(`teamai hooks already up-to-date in ${settingsPath}`);
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2415
2488
|
function isAgentHookSupportedTool(tool) {
|
|
2416
2489
|
return !CURSOR_TOOLS.has(tool);
|
|
2417
2490
|
}
|
|
@@ -2529,6 +2602,8 @@ async function reconcileHooks(settingsPath, tool, teamDefs = [], opts = {}) {
|
|
|
2529
2602
|
await reconcileCursorFormat(settingsPath, tool, scopedDefs, opts, priorTeamCommands);
|
|
2530
2603
|
} else if (format === "codex") {
|
|
2531
2604
|
await reconcileCodexFormat(settingsPath, tool, scopedDefs, opts, priorTeamCommands);
|
|
2605
|
+
} else if (format === "zcode") {
|
|
2606
|
+
await reconcileZcodeFormat(settingsPath, tool, scopedDefs, opts, priorTeamCommands);
|
|
2532
2607
|
} else {
|
|
2533
2608
|
await reconcileClaudeFormat(settingsPath, tool, scopedDefs, {
|
|
2534
2609
|
...opts,
|
|
@@ -2588,6 +2663,18 @@ async function getHookStatus(settingsPath, tool) {
|
|
|
2588
2663
|
});
|
|
2589
2664
|
return present2 ? "installed" : "missing";
|
|
2590
2665
|
}
|
|
2666
|
+
if (format === "zcode") {
|
|
2667
|
+
const cfg = await readJson(expanded);
|
|
2668
|
+
const eventsMap = cfg?.hooks?.events;
|
|
2669
|
+
if (!eventsMap) return "missing";
|
|
2670
|
+
const present2 = defs.every((def) => {
|
|
2671
|
+
const want = toZcodeEntry(def);
|
|
2672
|
+
const wantCmd = zcodeEntryCommand(want);
|
|
2673
|
+
const entries = eventsMap[def.event] ?? [];
|
|
2674
|
+
return entries.some((e) => e.matcher === want.matcher && zcodeEntryCommand(e) === wantCmd);
|
|
2675
|
+
});
|
|
2676
|
+
return present2 ? "installed" : "missing";
|
|
2677
|
+
}
|
|
2591
2678
|
const settings = await readJson(expanded);
|
|
2592
2679
|
if (!settings?.hooks) return "missing";
|
|
2593
2680
|
const present = defs.every((def) => {
|
|
@@ -2619,6 +2706,17 @@ async function hasTeamaiHooks(settingsPath, tool, manifestPath) {
|
|
|
2619
2706
|
})
|
|
2620
2707
|
);
|
|
2621
2708
|
}
|
|
2709
|
+
if (format === "zcode") {
|
|
2710
|
+
const j = await readJson(expanded);
|
|
2711
|
+
const eventsMap = j?.hooks?.events;
|
|
2712
|
+
if (!eventsMap) return false;
|
|
2713
|
+
return Object.values(eventsMap).some(
|
|
2714
|
+
(entries) => (entries ?? []).some((e) => {
|
|
2715
|
+
const cmd = zcodeEntryCommand(e);
|
|
2716
|
+
return TEAMAI_COMMAND_MARKERS.some((m) => cmd.includes(m)) || priorTeamCommands.has(cmd);
|
|
2717
|
+
})
|
|
2718
|
+
);
|
|
2719
|
+
}
|
|
2622
2720
|
const s = await readJson(expanded);
|
|
2623
2721
|
if (!s?.hooks) return false;
|
|
2624
2722
|
return Object.values(s.hooks).some(
|
|
@@ -2792,7 +2890,7 @@ async function reconcileTeamHooksForConfig(teamConfig, localConfig, opts = {}) {
|
|
|
2792
2890
|
await sweepLegacyProjectHooks(teamConfig.toolPaths, localConfig);
|
|
2793
2891
|
return teamDefs;
|
|
2794
2892
|
}
|
|
2795
|
-
var OPENCLAW_TOOLS, TEAMAI_HOOK_SUBCOMMANDS, TEAMAI_LEGACY_HOOK_SUBCOMMANDS, CLAUDE_TO_CURSOR_EVENTS, CURSOR_TOOLS, CODEX_TOOLS, CODEX_TRUST_GATE_TOOLS, TEAMAI_COMMAND_MARKERS, AGENT_HOOK_EVENTS;
|
|
2893
|
+
var OPENCLAW_TOOLS, TEAMAI_HOOK_SUBCOMMANDS, TEAMAI_LEGACY_HOOK_SUBCOMMANDS, CLAUDE_TO_CURSOR_EVENTS, CURSOR_TOOLS, CODEX_TOOLS, ZCODE_TOOLS, CODEX_TRUST_GATE_TOOLS, TEAMAI_COMMAND_MARKERS, AGENT_HOOK_EVENTS;
|
|
2796
2894
|
var init_hooks2 = __esm({
|
|
2797
2895
|
"src/hooks.ts"() {
|
|
2798
2896
|
"use strict";
|
|
@@ -2814,6 +2912,7 @@ var init_hooks2 = __esm({
|
|
|
2814
2912
|
};
|
|
2815
2913
|
CURSOR_TOOLS = /* @__PURE__ */ new Set(["cursor"]);
|
|
2816
2914
|
CODEX_TOOLS = /* @__PURE__ */ new Set(["codex", "codex-internal", "tcodex"]);
|
|
2915
|
+
ZCODE_TOOLS = /* @__PURE__ */ new Set(["zcode"]);
|
|
2817
2916
|
CODEX_TRUST_GATE_TOOLS = /* @__PURE__ */ new Set(["codex"]);
|
|
2818
2917
|
TEAMAI_COMMAND_MARKERS = [
|
|
2819
2918
|
"teamai pull",
|
|
@@ -7769,7 +7868,7 @@ var CLAUDE_TOOLS, CURSOR_TOOLS2, CODEX_TOOLS2, BUDDY_TOOLS, OPENCODE_TOOLS, MCP_
|
|
|
7769
7868
|
var init_mcp_format = __esm({
|
|
7770
7869
|
"src/resources/mcp-format.ts"() {
|
|
7771
7870
|
"use strict";
|
|
7772
|
-
CLAUDE_TOOLS = /* @__PURE__ */ new Set(["claude", "claude-internal", "tclaude", "qoder"]);
|
|
7871
|
+
CLAUDE_TOOLS = /* @__PURE__ */ new Set(["claude", "claude-internal", "tclaude", "qoder", "zcode"]);
|
|
7773
7872
|
CURSOR_TOOLS2 = /* @__PURE__ */ new Set(["cursor"]);
|
|
7774
7873
|
CODEX_TOOLS2 = /* @__PURE__ */ new Set(["codex", "codex-internal", "tcodex"]);
|
|
7775
7874
|
BUDDY_TOOLS = /* @__PURE__ */ new Set(["codebuddy", "workbuddy"]);
|
|
@@ -12720,6 +12819,8 @@ function renderForTool(spec, tool) {
|
|
|
12720
12819
|
return renderForJoycode(spec);
|
|
12721
12820
|
case "qoder":
|
|
12722
12821
|
return renderForClaude(spec);
|
|
12822
|
+
case "zcode":
|
|
12823
|
+
return renderForClaude(spec);
|
|
12723
12824
|
case "opencode":
|
|
12724
12825
|
return renderForOpencode(spec);
|
|
12725
12826
|
}
|
|
@@ -12739,6 +12840,7 @@ var init_agent_format = __esm({
|
|
|
12739
12840
|
"cursor",
|
|
12740
12841
|
"joycode",
|
|
12741
12842
|
"qoder",
|
|
12843
|
+
"zcode",
|
|
12742
12844
|
"opencode"
|
|
12743
12845
|
];
|
|
12744
12846
|
COMMON_CLAUDE_FIELDS = /* @__PURE__ */ new Set(["name", "description", "model", "tools"]);
|
|
@@ -12942,6 +13044,8 @@ function reverseByTool(tool, filePath, content) {
|
|
|
12942
13044
|
return reverseFromJoycode(filePath, content);
|
|
12943
13045
|
case "qoder":
|
|
12944
13046
|
return reverseFromClaude(filePath, content);
|
|
13047
|
+
case "zcode":
|
|
13048
|
+
return reverseFromClaude(filePath, content);
|
|
12945
13049
|
case "opencode":
|
|
12946
13050
|
return reverseFromOpencode(filePath, content);
|
|
12947
13051
|
}
|
|
@@ -14645,6 +14749,7 @@ var init_known_agents = __esm({
|
|
|
14645
14749
|
{ id: "trae", displayName: "Trae", category: "coding", skillsPath: ".trae/skills" },
|
|
14646
14750
|
{ id: "trae-cn", displayName: "Trae CN", category: "coding", skillsPath: ".trae-cn/skills" },
|
|
14647
14751
|
{ id: "windsurf", displayName: "Windsurf", category: "coding", skillsPath: ".windsurf/skills" },
|
|
14752
|
+
{ id: "zcode", displayName: "ZCode", category: "coding", skillsPath: ".zcode/skills" },
|
|
14648
14753
|
// Lobster family
|
|
14649
14754
|
{ id: "openclaw", displayName: "OpenClaw", category: "lobster", skillsPath: ".openclaw/skills" },
|
|
14650
14755
|
{ id: "qclaw", displayName: "QClaw", category: "lobster", skillsPath: ".qclaw/skills" },
|
|
@@ -21162,6 +21267,7 @@ async function resolveTargets(teamConfig, localConfig) {
|
|
|
21162
21267
|
for (const [tool, paths] of Object.entries(scopedToolPaths(teamConfig, localConfig))) {
|
|
21163
21268
|
if (disabled.has(tool)) continue;
|
|
21164
21269
|
if (whitelist && !whitelist.includes(tool)) continue;
|
|
21270
|
+
if (tool === "zcode") continue;
|
|
21165
21271
|
const family = familyOf(tool);
|
|
21166
21272
|
const probe = paths.settings ?? paths.skills ?? paths.agents;
|
|
21167
21273
|
if (!probe) continue;
|