@kairyou/agent-tools 0.16.0 → 0.17.1
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 +3 -3
- package/README.zh-CN.md +3 -3
- package/{integrations → capabilities}/vision/mcp-server.mjs +1 -1
- package/dist/log/hook.mjs +2 -2
- package/dist/log/opencode-plugin.mjs +1 -1
- package/dist/statusline/claude-statusline.mjs +2 -2
- package/dist/usage/cli.mjs +4 -4
- package/dist/usage/codex-hook.mjs +1 -1
- package/dist/usage/core.mjs +11 -11
- package/dist/usage/opencode-plugin.mjs +1 -1
- package/dist/usage/opencode-tui.mjs +1 -1
- package/dist/vision/cli.mjs +13 -13
- package/dist/vision/mcp-server.mjs +12 -12
- package/docs/en/repository-structure.md +2 -2
- package/docs/zh-CN/repository-structure.md +2 -2
- package/package.json +3 -3
- package/scripts/build.mjs +13 -13
- package/scripts/install.mjs +13 -13
- /package/{integrations → capabilities}/log/hook.mjs +0 -0
- /package/{integrations → capabilities}/log/opencode-plugin.mjs +0 -0
- /package/{integrations → capabilities}/statusline/claude-statusline.mjs +0 -0
- /package/{integrations → capabilities}/usage/cli.mjs +0 -0
- /package/{integrations → capabilities}/usage/codex-hook.mjs +0 -0
- /package/{integrations → capabilities}/usage/core.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/cache.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/config.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/context.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/format.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/http.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/routes.mjs +0 -0
- /package/{integrations → capabilities}/usage/lib/urls.mjs +0 -0
- /package/{integrations → capabilities}/usage/opencode-plugin.mjs +0 -0
- /package/{integrations → capabilities}/usage/opencode-tui.mjs +0 -0
- /package/{integrations → capabilities}/usage/routes/.gitkeep +0 -0
- /package/{integrations → capabilities}/usage/skills/at-usage/SKILL.md +0 -0
- /package/{integrations → capabilities}/vision/lib/cli.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/config.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/errors.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/image-source.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/inspect.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/providers/anthropic-compatible.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/providers/openai-compatible.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/providers/shared.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/rate-limit.mjs +0 -0
- /package/{integrations → capabilities}/vision/lib/redact.mjs +0 -0
- /package/{integrations → capabilities}/vision/skills/at-vision/SKILL.md +0 -0
- /package/skills/{integrations → systems}/at-zentao/SKILL.md +0 -0
- /package/skills/{integrations → systems}/at-zentao/scripts/zentao-cli.mjs +0 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Tools
|
|
2
2
|
|
|
3
|
-
Reusable Agent Skills, plus
|
|
3
|
+
Reusable Agent Skills, plus runtime capabilities (statusline, provider usage, vision) for Codex, Claude Code, and opencode.
|
|
4
4
|
|
|
5
5
|
Requires Node.js >= 22.
|
|
6
6
|
|
|
@@ -71,7 +71,7 @@ Usage:
|
|
|
71
71
|
|
|
72
72
|
Config: `~/.agent-tools/config.jsonc` → `"zentao": { "url", "account", "password" }`. The password can be entered directly or referenced with `"password": { "env": "ZENTAO_PASSWORD" }`; never paste credentials or tokens into chat.
|
|
73
73
|
|
|
74
|
-
##
|
|
74
|
+
## Capabilities
|
|
75
75
|
|
|
76
76
|
Runtime capabilities, installed per agent:
|
|
77
77
|
|
|
@@ -80,7 +80,7 @@ npx -y @kairyou/agent-tools@latest <capability> -a <agent...>
|
|
|
80
80
|
# npx -y github:kairyou/agent-tools <capability> -a <agent...> # Or the latest code from GitHub (needs Git)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
`--dry-run` previews, `--uninstall`
|
|
83
|
+
`--dry-run` previews, `--uninstall` removes the capability from the agent, and
|
|
84
84
|
re-running the install command updates. The installer only touches config
|
|
85
85
|
entries it wrote itself, and `config.jsonc` updates only add missing default
|
|
86
86
|
keys without touching your edits or comments.
|
package/README.zh-CN.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md)
|
|
4
4
|
|
|
5
|
-
可复用的 Agent Skills,
|
|
5
|
+
可复用的 Agent Skills, 以及适用于 Codex, Claude Code 与 opencode 的 runtime capabilities: statusline, provider usage 与跨模型识图.
|
|
6
6
|
|
|
7
7
|
需要 Node.js >= 22.
|
|
8
8
|
|
|
@@ -71,7 +71,7 @@ npx -y skills@latest add kairyou/agent-tools --skill at-zentao -g -y
|
|
|
71
71
|
|
|
72
72
|
配置: `~/.agent-tools/config.jsonc` → `"zentao": { "url", "account", "password" }`. 密码可以直接填写, 也可以使用 `"password": { "env": "ZENTAO_PASSWORD" }` 引用环境变量; 不要在对话中粘贴凭据或 token.
|
|
73
73
|
|
|
74
|
-
##
|
|
74
|
+
## Capabilities
|
|
75
75
|
|
|
76
76
|
Runtime capability, 按 agent 选装:
|
|
77
77
|
|
|
@@ -80,7 +80,7 @@ npx -y @kairyou/agent-tools@latest <capability> -a <agent...>
|
|
|
80
80
|
# npx -y github:kairyou/agent-tools <capability> -a <agent...> # 或用 GitHub 上的最新代码(需 Git)
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
-
`--dry-run` 预览, `--uninstall`
|
|
83
|
+
`--dry-run` 预览, `--uninstall` 移除对应 capability, 重新执行安装命令即为更新.
|
|
84
84
|
安装器只改动自己写入的配置项, 更新 `config.jsonc` 时只补充缺失的默认键,
|
|
85
85
|
不会动你的修改和注释.
|
|
86
86
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Vision MCP stdio server. Thin shell over ./lib: registers the
|
|
3
3
|
// inspect_image tool, translates results/errors, and nothing else. Launched by
|
|
4
|
-
// hosts as `agent-tools mcp-vision` (or `node
|
|
4
|
+
// hosts as `agent-tools mcp-vision` (or `node capabilities/vision/mcp-server.mjs`).
|
|
5
5
|
|
|
6
6
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
7
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
package/dist/log/hook.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// capabilities/log/hook.mjs
|
|
4
4
|
import { spawnSync } from "node:child_process";
|
|
5
5
|
import fs from "node:fs/promises";
|
|
6
6
|
import os from "node:os";
|
|
@@ -865,7 +865,7 @@ var ParseErrorCode;
|
|
|
865
865
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
866
866
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
867
867
|
|
|
868
|
-
//
|
|
868
|
+
// capabilities/log/hook.mjs
|
|
869
869
|
var MAX_SNAPSHOT_BYTES = 512 * 1024;
|
|
870
870
|
var MIN_RESULT_SUMMARY_LENGTH = 24;
|
|
871
871
|
var DAILY_ITEM_TARGET_CHARS = 160;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// capabilities/statusline/claude-statusline.mjs
|
|
4
4
|
import { execFileSync, spawn } from "node:child_process";
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import { basename, dirname, join } from "node:path";
|
|
@@ -865,7 +865,7 @@ var ParseErrorCode;
|
|
|
865
865
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
866
866
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
867
867
|
|
|
868
|
-
//
|
|
868
|
+
// capabilities/statusline/claude-statusline.mjs
|
|
869
869
|
var SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
|
|
870
870
|
var AGENT_TOOLS_HOME = process.env.AGENT_TOOLS_HOME || join(SCRIPT_DIR, "..", "..");
|
|
871
871
|
var DEFAULT_CONFIG_FILE = join(AGENT_TOOLS_HOME, "config.jsonc");
|
package/dist/usage/cli.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// capabilities/usage/cli.mjs
|
|
4
4
|
import { queryAgentProviderUsage } from "./core.mjs";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// capabilities/usage/lib/config.mjs
|
|
7
7
|
import { readFile, writeFile, mkdir, open, stat } from "node:fs/promises";
|
|
8
8
|
import { existsSync } from "node:fs";
|
|
9
9
|
import { dirname, join } from "node:path";
|
|
@@ -868,7 +868,7 @@ var ParseErrorCode;
|
|
|
868
868
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
869
869
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
870
870
|
|
|
871
|
-
//
|
|
871
|
+
// capabilities/usage/lib/config.mjs
|
|
872
872
|
var CODEX_HOME = process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
873
873
|
var AGENT_TOOLS_HOME = process.env.AGENT_TOOLS_HOME || join(homedir(), ".agent-tools");
|
|
874
874
|
var AUTH_PATH = join(CODEX_HOME, "auth.json");
|
|
@@ -931,7 +931,7 @@ async function debugLog(event) {
|
|
|
931
931
|
}
|
|
932
932
|
var HOOK_SNAPSHOT_MAX_AGE_MS = 10 * 6e4;
|
|
933
933
|
|
|
934
|
-
//
|
|
934
|
+
// capabilities/usage/cli.mjs
|
|
935
935
|
function parseAgent(argv) {
|
|
936
936
|
for (let index = 0; index < argv.length; index += 1) {
|
|
937
937
|
const arg = argv[index];
|
package/dist/usage/core.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
//
|
|
3
|
+
// capabilities/usage/core.mjs
|
|
4
4
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "node:url";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// capabilities/usage/lib/config.mjs
|
|
8
8
|
import { readFile, writeFile, mkdir, open, stat } from "node:fs/promises";
|
|
9
9
|
import { existsSync } from "node:fs";
|
|
10
10
|
import { dirname, join } from "node:path";
|
|
@@ -869,7 +869,7 @@ var ParseErrorCode;
|
|
|
869
869
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
870
870
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
871
871
|
|
|
872
|
-
//
|
|
872
|
+
// capabilities/usage/lib/config.mjs
|
|
873
873
|
var CODEX_HOME = process.env.CODEX_HOME || join(homedir(), ".codex");
|
|
874
874
|
var AGENT_TOOLS_HOME = process.env.AGENT_TOOLS_HOME || join(homedir(), ".agent-tools");
|
|
875
875
|
var AUTH_PATH = join(CODEX_HOME, "auth.json");
|
|
@@ -954,7 +954,7 @@ async function newApiQuotaScale() {
|
|
|
954
954
|
return Number.isFinite(scale) && scale > 0 ? scale : 0;
|
|
955
955
|
}
|
|
956
956
|
|
|
957
|
-
//
|
|
957
|
+
// capabilities/usage/lib/urls.mjs
|
|
958
958
|
function isOfficialBaseUrl(baseUrl) {
|
|
959
959
|
if (!baseUrl) return true;
|
|
960
960
|
const clean = baseUrl.replace(/\/+$/, "");
|
|
@@ -994,7 +994,7 @@ function hostIncludes(baseUrl, value) {
|
|
|
994
994
|
}
|
|
995
995
|
}
|
|
996
996
|
|
|
997
|
-
//
|
|
997
|
+
// capabilities/usage/lib/cache.mjs
|
|
998
998
|
import { writeFile as writeFile2, mkdir as mkdir2, open as open2, unlink, rename, stat as stat2, utimes } from "node:fs/promises";
|
|
999
999
|
import { createHash, randomUUID } from "node:crypto";
|
|
1000
1000
|
import { dirname as dirname2, join as join2 } from "node:path";
|
|
@@ -1142,12 +1142,12 @@ async function acquireWriteLock({ timeoutMs = 500, staleMs = 5e3 } = {}) {
|
|
|
1142
1142
|
return null;
|
|
1143
1143
|
}
|
|
1144
1144
|
|
|
1145
|
-
//
|
|
1145
|
+
// capabilities/usage/lib/routes.mjs
|
|
1146
1146
|
import { readdir } from "node:fs/promises";
|
|
1147
1147
|
import { basename, extname, isAbsolute, join as join3 } from "node:path";
|
|
1148
1148
|
import { pathToFileURL } from "node:url";
|
|
1149
1149
|
|
|
1150
|
-
//
|
|
1150
|
+
// capabilities/usage/lib/http.mjs
|
|
1151
1151
|
import { createContext, runInContext } from "node:vm";
|
|
1152
1152
|
var DEFAULT_REQUEST_TIMEOUT_MS = 1e4;
|
|
1153
1153
|
var SHIELD_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36";
|
|
@@ -1307,7 +1307,7 @@ async function requestJson(url, options = {}) {
|
|
|
1307
1307
|
throw new Error(`${name} unavailable`);
|
|
1308
1308
|
}
|
|
1309
1309
|
|
|
1310
|
-
//
|
|
1310
|
+
// capabilities/usage/lib/format.mjs
|
|
1311
1311
|
var ONE_API_HARD_LIMIT_SENTINEL_USD = 1e6;
|
|
1312
1312
|
var RESET_TIME_FIELDS = Object.freeze({
|
|
1313
1313
|
// Sub2API rate-limit entries returned alongside quota usage.
|
|
@@ -1591,7 +1591,7 @@ function formatUsageLine(root) {
|
|
|
1591
1591
|
return parts.join(" | ");
|
|
1592
1592
|
}
|
|
1593
1593
|
|
|
1594
|
-
//
|
|
1594
|
+
// capabilities/usage/lib/routes.mjs
|
|
1595
1595
|
async function subscriptionUrl(baseUrl) {
|
|
1596
1596
|
const clean = baseUrl.replace(/\/+$/, "");
|
|
1597
1597
|
const url = clean.endsWith("/v1") ? `${clean}/usage` : `${clean}/v1/usage`;
|
|
@@ -1834,7 +1834,7 @@ async function orderedUsageRoutes(context) {
|
|
|
1834
1834
|
return [cached.route, ...routeIds.filter((id) => id !== cached.route)].map((id) => registry[id]).filter(Boolean);
|
|
1835
1835
|
}
|
|
1836
1836
|
|
|
1837
|
-
//
|
|
1837
|
+
// capabilities/usage/lib/context.mjs
|
|
1838
1838
|
import { existsSync as existsSync2 } from "node:fs";
|
|
1839
1839
|
function stripInlineComment(value) {
|
|
1840
1840
|
let inSingle = false;
|
|
@@ -1938,7 +1938,7 @@ function normalizeUsageContext(input) {
|
|
|
1938
1938
|
};
|
|
1939
1939
|
}
|
|
1940
1940
|
|
|
1941
|
-
//
|
|
1941
|
+
// capabilities/usage/core.mjs
|
|
1942
1942
|
function parseArgs(argv) {
|
|
1943
1943
|
const opts = { mode: "hook", agent: "codex", silent: false };
|
|
1944
1944
|
let modeSet = false;
|
package/dist/vision/cli.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
//
|
|
1
|
+
// capabilities/vision/lib/cli.mjs
|
|
2
2
|
import fs4 from "node:fs";
|
|
3
3
|
import path5 from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// capabilities/vision/lib/inspect.mjs
|
|
7
7
|
import crypto3 from "node:crypto";
|
|
8
8
|
import path4 from "node:path";
|
|
9
9
|
|
|
10
|
-
//
|
|
10
|
+
// capabilities/vision/lib/config.mjs
|
|
11
11
|
import fs from "node:fs";
|
|
12
12
|
import os from "node:os";
|
|
13
13
|
import path from "node:path";
|
|
@@ -871,7 +871,7 @@ var ParseErrorCode;
|
|
|
871
871
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
872
872
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
873
873
|
|
|
874
|
-
//
|
|
874
|
+
// capabilities/vision/lib/errors.mjs
|
|
875
875
|
var ERROR_CODES = Object.freeze({
|
|
876
876
|
CONFIG: "config_error",
|
|
877
877
|
INPUT: "input_error",
|
|
@@ -899,7 +899,7 @@ function toVisionError(err, fallbackCode = ERROR_CODES.PROVIDER_HTTP) {
|
|
|
899
899
|
return new VisionError(fallbackCode, message, { cause: err });
|
|
900
900
|
}
|
|
901
901
|
|
|
902
|
-
//
|
|
902
|
+
// capabilities/vision/lib/config.mjs
|
|
903
903
|
var PROVIDERS = Object.freeze(["openai-compatible", "anthropic-compatible"]);
|
|
904
904
|
var CONFIG_DEFAULTS = Object.freeze({
|
|
905
905
|
timeoutMs: 3e4,
|
|
@@ -1037,7 +1037,7 @@ function loadVisionConfig({ file, env = process.env } = {}) {
|
|
|
1037
1037
|
};
|
|
1038
1038
|
}
|
|
1039
1039
|
|
|
1040
|
-
//
|
|
1040
|
+
// capabilities/vision/lib/image-source.mjs
|
|
1041
1041
|
import fs2 from "node:fs";
|
|
1042
1042
|
import os2 from "node:os";
|
|
1043
1043
|
import path2 from "node:path";
|
|
@@ -1285,7 +1285,7 @@ async function loadImageSource(source, { maxImageBytes, timeoutMs, fetchImpl } =
|
|
|
1285
1285
|
throw new VisionError(ERROR_CODES.INPUT, `Unsupported image_source.type: ${JSON.stringify(source.type)}`);
|
|
1286
1286
|
}
|
|
1287
1287
|
|
|
1288
|
-
//
|
|
1288
|
+
// capabilities/vision/lib/rate-limit.mjs
|
|
1289
1289
|
import crypto from "node:crypto";
|
|
1290
1290
|
import fs3 from "node:fs";
|
|
1291
1291
|
import path3 from "node:path";
|
|
@@ -1442,7 +1442,7 @@ function createLimiter(config, now = Date.now, { stateFile = null } = {}) {
|
|
|
1442
1442
|
return stateFile ? createSharedLimiter(config, now, stateFile) : createProcessLimiter(config, now);
|
|
1443
1443
|
}
|
|
1444
1444
|
|
|
1445
|
-
//
|
|
1445
|
+
// capabilities/vision/lib/redact.mjs
|
|
1446
1446
|
var MASK = "***";
|
|
1447
1447
|
function redactSecrets(text, secrets) {
|
|
1448
1448
|
if (typeof text !== "string" || text.length === 0) return text;
|
|
@@ -1454,7 +1454,7 @@ function redactSecrets(text, secrets) {
|
|
|
1454
1454
|
return out;
|
|
1455
1455
|
}
|
|
1456
1456
|
|
|
1457
|
-
//
|
|
1457
|
+
// capabilities/vision/lib/providers/shared.mjs
|
|
1458
1458
|
import crypto2 from "node:crypto";
|
|
1459
1459
|
async function* encodeBase64(readable) {
|
|
1460
1460
|
let carry = Buffer.alloc(0);
|
|
@@ -1667,7 +1667,7 @@ async function postJson({ url, headers, body, timeoutMs, fetchImpl, providerLabe
|
|
|
1667
1667
|
}
|
|
1668
1668
|
}
|
|
1669
1669
|
|
|
1670
|
-
//
|
|
1670
|
+
// capabilities/vision/lib/providers/anthropic-compatible.mjs
|
|
1671
1671
|
function messagesUrl(baseUrl) {
|
|
1672
1672
|
return baseUrl.endsWith("/v1") ? `${baseUrl}/messages` : `${baseUrl}/v1/messages`;
|
|
1673
1673
|
}
|
|
@@ -1718,7 +1718,7 @@ async function inspectWithAnthropicCompatible({ config, image, questions, fetchI
|
|
|
1718
1718
|
return normalizeAnswers(text, questions);
|
|
1719
1719
|
}
|
|
1720
1720
|
|
|
1721
|
-
//
|
|
1721
|
+
// capabilities/vision/lib/providers/openai-compatible.mjs
|
|
1722
1722
|
function replyText2(json) {
|
|
1723
1723
|
const message = json?.choices?.[0]?.message;
|
|
1724
1724
|
if (typeof message?.content === "string") return message.content;
|
|
@@ -1765,7 +1765,7 @@ async function inspectWithOpenAICompatible({ config, image, questions, fetchImpl
|
|
|
1765
1765
|
return normalizeAnswers(text, questions);
|
|
1766
1766
|
}
|
|
1767
1767
|
|
|
1768
|
-
//
|
|
1768
|
+
// capabilities/vision/lib/inspect.mjs
|
|
1769
1769
|
var PROVIDER_IMPL = {
|
|
1770
1770
|
"openai-compatible": inspectWithOpenAICompatible,
|
|
1771
1771
|
"anthropic-compatible": inspectWithAnthropicCompatible
|
|
@@ -1849,7 +1849,7 @@ function createVisionService({ config, fetchImpl, now, limiterStateFile } = {})
|
|
|
1849
1849
|
return { config: resolved, inspect };
|
|
1850
1850
|
}
|
|
1851
1851
|
|
|
1852
|
-
//
|
|
1852
|
+
// capabilities/vision/lib/cli.mjs
|
|
1853
1853
|
function printHelp() {
|
|
1854
1854
|
const lines = [];
|
|
1855
1855
|
for (const line of fs4.readFileSync(fileURLToPath(import.meta.url), "utf8").split("\n")) {
|
|
@@ -30952,11 +30952,11 @@ var StdioServerTransport = class {
|
|
|
30952
30952
|
}
|
|
30953
30953
|
};
|
|
30954
30954
|
|
|
30955
|
-
//
|
|
30955
|
+
// capabilities/vision/lib/inspect.mjs
|
|
30956
30956
|
import crypto3 from "node:crypto";
|
|
30957
30957
|
import path4 from "node:path";
|
|
30958
30958
|
|
|
30959
|
-
//
|
|
30959
|
+
// capabilities/vision/lib/config.mjs
|
|
30960
30960
|
import fs from "node:fs";
|
|
30961
30961
|
import os from "node:os";
|
|
30962
30962
|
import path from "node:path";
|
|
@@ -31820,7 +31820,7 @@ var ParseErrorCode;
|
|
|
31820
31820
|
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
31821
31821
|
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
31822
31822
|
|
|
31823
|
-
//
|
|
31823
|
+
// capabilities/vision/lib/errors.mjs
|
|
31824
31824
|
var ERROR_CODES = Object.freeze({
|
|
31825
31825
|
CONFIG: "config_error",
|
|
31826
31826
|
INPUT: "input_error",
|
|
@@ -31848,7 +31848,7 @@ function toVisionError(err, fallbackCode = ERROR_CODES.PROVIDER_HTTP) {
|
|
|
31848
31848
|
return new VisionError(fallbackCode, message, { cause: err });
|
|
31849
31849
|
}
|
|
31850
31850
|
|
|
31851
|
-
//
|
|
31851
|
+
// capabilities/vision/lib/config.mjs
|
|
31852
31852
|
var PROVIDERS = Object.freeze(["openai-compatible", "anthropic-compatible"]);
|
|
31853
31853
|
var CONFIG_DEFAULTS = Object.freeze({
|
|
31854
31854
|
timeoutMs: 3e4,
|
|
@@ -31986,7 +31986,7 @@ function loadVisionConfig({ file: file2, env = process.env } = {}) {
|
|
|
31986
31986
|
};
|
|
31987
31987
|
}
|
|
31988
31988
|
|
|
31989
|
-
//
|
|
31989
|
+
// capabilities/vision/lib/image-source.mjs
|
|
31990
31990
|
import fs2 from "node:fs";
|
|
31991
31991
|
import os2 from "node:os";
|
|
31992
31992
|
import path2 from "node:path";
|
|
@@ -32234,7 +32234,7 @@ async function loadImageSource(source, { maxImageBytes, timeoutMs, fetchImpl } =
|
|
|
32234
32234
|
throw new VisionError(ERROR_CODES.INPUT, `Unsupported image_source.type: ${JSON.stringify(source.type)}`);
|
|
32235
32235
|
}
|
|
32236
32236
|
|
|
32237
|
-
//
|
|
32237
|
+
// capabilities/vision/lib/rate-limit.mjs
|
|
32238
32238
|
import crypto from "node:crypto";
|
|
32239
32239
|
import fs3 from "node:fs";
|
|
32240
32240
|
import path3 from "node:path";
|
|
@@ -32391,7 +32391,7 @@ function createLimiter(config2, now = Date.now, { stateFile = null } = {}) {
|
|
|
32391
32391
|
return stateFile ? createSharedLimiter(config2, now, stateFile) : createProcessLimiter(config2, now);
|
|
32392
32392
|
}
|
|
32393
32393
|
|
|
32394
|
-
//
|
|
32394
|
+
// capabilities/vision/lib/redact.mjs
|
|
32395
32395
|
var MASK = "***";
|
|
32396
32396
|
function redactSecrets(text, secrets) {
|
|
32397
32397
|
if (typeof text !== "string" || text.length === 0) return text;
|
|
@@ -32403,7 +32403,7 @@ function redactSecrets(text, secrets) {
|
|
|
32403
32403
|
return out;
|
|
32404
32404
|
}
|
|
32405
32405
|
|
|
32406
|
-
//
|
|
32406
|
+
// capabilities/vision/lib/providers/shared.mjs
|
|
32407
32407
|
import crypto2 from "node:crypto";
|
|
32408
32408
|
async function* encodeBase64(readable) {
|
|
32409
32409
|
let carry = Buffer.alloc(0);
|
|
@@ -32616,7 +32616,7 @@ async function postJson({ url: url2, headers, body, timeoutMs, fetchImpl, provid
|
|
|
32616
32616
|
}
|
|
32617
32617
|
}
|
|
32618
32618
|
|
|
32619
|
-
//
|
|
32619
|
+
// capabilities/vision/lib/providers/anthropic-compatible.mjs
|
|
32620
32620
|
function messagesUrl(baseUrl) {
|
|
32621
32621
|
return baseUrl.endsWith("/v1") ? `${baseUrl}/messages` : `${baseUrl}/v1/messages`;
|
|
32622
32622
|
}
|
|
@@ -32667,7 +32667,7 @@ async function inspectWithAnthropicCompatible({ config: config2, image, question
|
|
|
32667
32667
|
return normalizeAnswers(text, questions);
|
|
32668
32668
|
}
|
|
32669
32669
|
|
|
32670
|
-
//
|
|
32670
|
+
// capabilities/vision/lib/providers/openai-compatible.mjs
|
|
32671
32671
|
function replyText2(json2) {
|
|
32672
32672
|
const message = json2?.choices?.[0]?.message;
|
|
32673
32673
|
if (typeof message?.content === "string") return message.content;
|
|
@@ -32714,7 +32714,7 @@ async function inspectWithOpenAICompatible({ config: config2, image, questions,
|
|
|
32714
32714
|
return normalizeAnswers(text, questions);
|
|
32715
32715
|
}
|
|
32716
32716
|
|
|
32717
|
-
//
|
|
32717
|
+
// capabilities/vision/lib/inspect.mjs
|
|
32718
32718
|
var PROVIDER_IMPL = {
|
|
32719
32719
|
"openai-compatible": inspectWithOpenAICompatible,
|
|
32720
32720
|
"anthropic-compatible": inspectWithAnthropicCompatible
|
|
@@ -32798,7 +32798,7 @@ function createVisionService({ config: config2, fetchImpl, now, limiterStateFile
|
|
|
32798
32798
|
return { config: resolved, inspect };
|
|
32799
32799
|
}
|
|
32800
32800
|
|
|
32801
|
-
//
|
|
32801
|
+
// capabilities/vision/mcp-server.mjs
|
|
32802
32802
|
var TOOL_DESCRIPTION = [
|
|
32803
32803
|
"Use the configured vision model when the user's task depends on visible content and only a local image path or http(s) URL is available, direct inspection failed, or the user explicitly requested the provider.",
|
|
32804
32804
|
"If the prompt already contains actual image content or a host image viewer returned it, inspect that content directly; a bare path or URL without a visual task is not a reason to call this.",
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
agent-tools/
|
|
5
5
|
├── .claude-plugin/ # Claude Code/plugin ecosystem manifest.
|
|
6
6
|
├── .codex-plugin/ # Codex plugin manifest.
|
|
7
|
-
├──
|
|
7
|
+
├── capabilities/ # Runtime capabilities, one directory each.
|
|
8
8
|
│ ├── statusline/ # Agent status line: branch, model, usage.
|
|
9
9
|
│ ├── usage/ # Provider balance / quota display.
|
|
10
10
|
│ └── vision/ # Cross-model image understanding.
|
|
@@ -13,7 +13,7 @@ agent-tools/
|
|
|
13
13
|
│ │ ├── at-commit/ # Conventional Commit message skill.
|
|
14
14
|
│ │ ├── at-review/ # Review local or hosted changes for bugs and regressions.
|
|
15
15
|
│ │ └── at-simplify/ # Reduce complexity and duplication in changes.
|
|
16
|
-
│ └──
|
|
16
|
+
│ └── systems/ # Self-contained Skills for external systems.
|
|
17
17
|
│ └── at-zentao/ # Self-contained ZenTao workflow and secure API script.
|
|
18
18
|
├── docs/ # Advanced guides and contributor reference.
|
|
19
19
|
├── tools/ # Maintainer-only upstream sync and repository tooling.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
agent-tools/
|
|
5
5
|
├── .claude-plugin/ # Claude Code/plugin 生态的 manifest.
|
|
6
6
|
├── .codex-plugin/ # Codex plugin manifest.
|
|
7
|
-
├──
|
|
7
|
+
├── capabilities/ # Runtime capabilities, 一个一目录.
|
|
8
8
|
│ ├── statusline/ # Agent 状态栏: 分支, 模型, 用量.
|
|
9
9
|
│ ├── usage/ # Provider 余额/额度显示.
|
|
10
10
|
│ └── vision/ # 跨模型识图.
|
|
@@ -13,7 +13,7 @@ agent-tools/
|
|
|
13
13
|
│ │ ├── at-commit/ # 生成 Conventional Commits message.
|
|
14
14
|
│ │ ├── at-review/ # 审查本地或托管改动中的 bug 与回归风险.
|
|
15
15
|
│ │ └── at-simplify/ # 减少改动中的冗余和复杂度.
|
|
16
|
-
│ └──
|
|
16
|
+
│ └── systems/ # 面向外部系统的自包含 Skills.
|
|
17
17
|
│ └── at-zentao/ # 自包含的禅道工作流和安全 API 脚本.
|
|
18
18
|
├── docs/ # 高级指南和贡献者参考.
|
|
19
19
|
├── tools/ # 仅供维护者使用的上游同步和仓库工具.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kairyou/agent-tools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Reusable Agent Skills, plus
|
|
3
|
+
"version": "0.17.1",
|
|
4
|
+
"description": "Reusable Agent Skills, plus runtime capabilities (statusline, provider usage, vision) for Codex, Claude Code, and opencode.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"config.default.jsonc",
|
|
18
18
|
"docs/",
|
|
19
19
|
"dist/",
|
|
20
|
-
"
|
|
20
|
+
"capabilities/",
|
|
21
21
|
"scripts/",
|
|
22
22
|
"skills/"
|
|
23
23
|
],
|
package/scripts/build.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// Bundles everything that ships to ~/.agent-tools into dist/<capability>.
|
|
3
|
-
// Installed artifacts are always built output;
|
|
3
|
+
// Installed artifacts are always built output; capabilities/ holds the sources.
|
|
4
4
|
|
|
5
5
|
import fs from "node:fs";
|
|
6
6
|
import path from "node:path";
|
|
@@ -13,16 +13,16 @@ const DIST = path.join(ROOT, "dist");
|
|
|
13
13
|
const TARGETS = {
|
|
14
14
|
statusline: {
|
|
15
15
|
entryPoints: {
|
|
16
|
-
"claude-statusline": path.join(ROOT, "
|
|
16
|
+
"claude-statusline": path.join(ROOT, "capabilities", "statusline", "claude-statusline.mjs"),
|
|
17
17
|
},
|
|
18
18
|
},
|
|
19
19
|
usage: {
|
|
20
20
|
entryPoints: {
|
|
21
|
-
core: path.join(ROOT, "
|
|
22
|
-
cli: path.join(ROOT, "
|
|
23
|
-
"codex-hook": path.join(ROOT, "
|
|
24
|
-
"opencode-plugin": path.join(ROOT, "
|
|
25
|
-
"opencode-tui": path.join(ROOT, "
|
|
21
|
+
core: path.join(ROOT, "capabilities", "usage", "core.mjs"),
|
|
22
|
+
cli: path.join(ROOT, "capabilities", "usage", "cli.mjs"),
|
|
23
|
+
"codex-hook": path.join(ROOT, "capabilities", "usage", "codex-hook.mjs"),
|
|
24
|
+
"opencode-plugin": path.join(ROOT, "capabilities", "usage", "opencode-plugin.mjs"),
|
|
25
|
+
"opencode-tui": path.join(ROOT, "capabilities", "usage", "opencode-tui.mjs"),
|
|
26
26
|
},
|
|
27
27
|
// core.mjs detects "run as a script" via process.argv[1]; inlining it into
|
|
28
28
|
// the other entries would re-trigger that check inside their bundles, so it
|
|
@@ -31,21 +31,21 @@ const TARGETS = {
|
|
|
31
31
|
},
|
|
32
32
|
vision: {
|
|
33
33
|
entryPoints: {
|
|
34
|
-
"mcp-server": path.join(ROOT, "
|
|
35
|
-
cli: path.join(ROOT, "
|
|
34
|
+
"mcp-server": path.join(ROOT, "capabilities", "vision", "mcp-server.mjs"),
|
|
35
|
+
cli: path.join(ROOT, "capabilities", "vision", "lib", "cli.mjs"),
|
|
36
36
|
},
|
|
37
37
|
},
|
|
38
38
|
log: {
|
|
39
39
|
entryPoints: {
|
|
40
|
-
hook: path.join(ROOT, "
|
|
41
|
-
"opencode-plugin": path.join(ROOT, "
|
|
40
|
+
hook: path.join(ROOT, "capabilities", "log", "hook.mjs"),
|
|
41
|
+
"opencode-plugin": path.join(ROOT, "capabilities", "log", "opencode-plugin.mjs"),
|
|
42
42
|
},
|
|
43
43
|
},
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
-
// Repo-shipped usage routes (a fork can commit
|
|
46
|
+
// Repo-shipped usage routes (a fork can commit capabilities/usage/routes/*.mjs
|
|
47
47
|
// to distribute custom gateways to everyone who installs). Absent upstream.
|
|
48
|
-
const USAGE_ROUTES_DIR = path.join(ROOT, "
|
|
48
|
+
const USAGE_ROUTES_DIR = path.join(ROOT, "capabilities", "usage", "routes");
|
|
49
49
|
if (fs.existsSync(USAGE_ROUTES_DIR)) {
|
|
50
50
|
for (const file of fs.readdirSync(USAGE_ROUTES_DIR).filter((n) => n.endsWith(".mjs"))) {
|
|
51
51
|
TARGETS.usage.entryPoints[`routes/${file.slice(0, -4)}`] = path.join(USAGE_ROUTES_DIR, file);
|
package/scripts/install.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
// agent-tools installer: wires statusline / usage into each agent's config.
|
|
3
3
|
// Runtime-dependent skills are installed with their capability. Standalone
|
|
4
|
-
//
|
|
4
|
+
// Standalone skills are still handled by `npx skills add`.
|
|
5
5
|
//
|
|
6
6
|
// Capabilities (all global for now — they target the user-level config):
|
|
7
7
|
// statusline Claude Code statusLine script (claude only).
|
|
@@ -68,7 +68,7 @@ const PACKAGE_VERSION = (() => {
|
|
|
68
68
|
}
|
|
69
69
|
})();
|
|
70
70
|
// Everything copied into ~/.agent-tools is built output from dist/ (see
|
|
71
|
-
// scripts/build.mjs);
|
|
71
|
+
// scripts/build.mjs); capabilities/ holds the sources.
|
|
72
72
|
const SOURCE = {
|
|
73
73
|
logHook: path.join(REPO_ROOT, "dist", "log", "hook.mjs"),
|
|
74
74
|
logOpencodePlugin: path.join(REPO_ROOT, "dist", "log", "opencode-plugin.mjs"),
|
|
@@ -100,12 +100,12 @@ const AGENT_CAPS = {
|
|
|
100
100
|
};
|
|
101
101
|
const VISION_MCP_NAME = "agent-tools-vision";
|
|
102
102
|
const VISION_SKILL_NAME = "at-vision";
|
|
103
|
-
// The at-vision skill ships inside the vision capability dir (
|
|
103
|
+
// The at-vision skill ships inside the vision capability dir (capabilities/vision),
|
|
104
104
|
// not skills/: it is unusable without the MCP server, so it must not surface
|
|
105
105
|
// as an independently installable skill.
|
|
106
|
-
const VISION_SKILL_SRC = path.join(REPO_ROOT, "
|
|
106
|
+
const VISION_SKILL_SRC = path.join(REPO_ROOT, "capabilities", "vision", "skills", VISION_SKILL_NAME);
|
|
107
107
|
const USAGE_SKILL_NAME = "at-usage";
|
|
108
|
-
const USAGE_SKILL_SRC = path.join(REPO_ROOT, "
|
|
108
|
+
const USAGE_SKILL_SRC = path.join(REPO_ROOT, "capabilities", "usage", "skills", USAGE_SKILL_NAME);
|
|
109
109
|
const VISION_BUNDLED_MCP_SERVER = path.join(REPO_ROOT, "dist", "vision", "mcp-server.mjs");
|
|
110
110
|
const VISION_BUNDLED_CLI = path.join(REPO_ROOT, "dist", "vision", "cli.mjs");
|
|
111
111
|
const INSTALL_STATE_PATH = path.join(INSTALL_ROOT, "install-state.json");
|
|
@@ -292,7 +292,7 @@ function syncUsageRoutesDir(dryRun) {
|
|
|
292
292
|
function parseArgs(argv) {
|
|
293
293
|
const opts = {
|
|
294
294
|
agents: [],
|
|
295
|
-
|
|
295
|
+
capabilities: [],
|
|
296
296
|
settings: null,
|
|
297
297
|
codexHooks: null,
|
|
298
298
|
opencodeConfigDir: null,
|
|
@@ -343,15 +343,15 @@ function parseArgs(argv) {
|
|
|
343
343
|
console.error(`Unknown option: ${a}`);
|
|
344
344
|
process.exit(2);
|
|
345
345
|
}
|
|
346
|
-
opts.
|
|
346
|
+
opts.capabilities.push(a);
|
|
347
347
|
}
|
|
348
348
|
}
|
|
349
349
|
if (opts.agents.length === 0) opts.agents = ["claude"];
|
|
350
|
-
if (!opts.help && opts.
|
|
350
|
+
if (!opts.help && opts.capabilities.length === 0) {
|
|
351
351
|
console.error(`Missing capability (available: ${ALL_CAPS.join(", ")})`);
|
|
352
352
|
process.exit(2);
|
|
353
353
|
}
|
|
354
|
-
for (const name of opts.
|
|
354
|
+
for (const name of opts.capabilities) {
|
|
355
355
|
if (!ALL_CAPS.includes(name)) {
|
|
356
356
|
console.error(`Unknown capability: ${name} (available: ${ALL_CAPS.join(", ")})`);
|
|
357
357
|
process.exit(2);
|
|
@@ -361,14 +361,14 @@ function parseArgs(argv) {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
function wants(opts, cap) {
|
|
364
|
-
return opts.
|
|
364
|
+
return opts.capabilities.length === 0 || opts.capabilities.includes(cap);
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
function validateAgentCapabilities(opts) {
|
|
368
368
|
const invalid = [];
|
|
369
369
|
for (const agent of opts.agents) {
|
|
370
370
|
const supported = AGENT_CAPS[agent] || [];
|
|
371
|
-
for (const cap of opts.
|
|
371
|
+
for (const cap of opts.capabilities) {
|
|
372
372
|
if (!supported.includes(cap)) invalid.push(`${cap} -a ${agent}`);
|
|
373
373
|
}
|
|
374
374
|
}
|
|
@@ -1181,7 +1181,7 @@ function cleanupVisionRuntimeIfUnused(opts) {
|
|
|
1181
1181
|
try {
|
|
1182
1182
|
fs.rmdirSync(path.dirname(VISION_RATE_LIMIT_STATE));
|
|
1183
1183
|
} catch {
|
|
1184
|
-
// The shared cache directory may contain state for other
|
|
1184
|
+
// The shared cache directory may contain state for other capabilities.
|
|
1185
1185
|
}
|
|
1186
1186
|
}
|
|
1187
1187
|
console.log(` removed unused vision runtime ${VISION_RUNTIME_DIR}`);
|
|
@@ -1218,7 +1218,7 @@ function main() {
|
|
|
1218
1218
|
}
|
|
1219
1219
|
|
|
1220
1220
|
// Standalone vision commands dispatch before capability parsing so image
|
|
1221
|
-
// paths and questions are never mistaken for
|
|
1221
|
+
// paths and questions are never mistaken for capabilities.
|
|
1222
1222
|
const subcommand = process.argv[2];
|
|
1223
1223
|
if (subcommand === "inspect-image") {
|
|
1224
1224
|
const { runInspectImageCli } = await import(
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|