@kairyou/agent-tools 0.2.0 → 0.3.0
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 +75 -95
- package/README.zh-CN.md +71 -92
- package/dist/vision/cli.mjs +13 -13
- package/dist/vision/mcp-server.mjs +12 -12
- package/{statusline/claude/statusline.mjs → integrations/statusline/claude-statusline.mjs} +3 -1
- package/integrations/usage/cli.mjs +27 -0
- package/{hooks/codex/usage-hook.mjs → integrations/usage/codex-hook.mjs} +1 -1
- package/{lib/usage.mjs → integrations/usage/core.mjs} +4 -0
- package/{plugins/opencode/usage-plugin.mjs → integrations/usage/opencode-plugin.mjs} +1 -1
- package/integrations/usage/skills/at-usage/SKILL.md +16 -0
- package/{plugins → integrations}/vision/mcp-server.mjs +4 -4
- package/package.json +5 -9
- package/scripts/build-vision.mjs +2 -2
- package/scripts/install.mjs +122 -88
- package/scripts/release.mjs +75 -5
- package/hooks/claude/.gitkeep +0 -1
- package/hooks/codex/.gitkeep +0 -1
- package/hooks/common/.gitkeep +0 -1
- package/hooks/opencode/.gitkeep +0 -1
- package/statusline/.gitkeep +0 -1
- package/statusline/codex/.gitkeep +0 -1
- /package/{plugins/opencode/usage-tui.mjs → integrations/usage/opencode-tui.mjs} +0 -0
- /package/{lib/vision → integrations/vision/lib}/cli.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/config.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/errors.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/image-source.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/inspect.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/providers/anthropic-compatible.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/providers/openai-compatible.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/providers/shared.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/rate-limit.mjs +0 -0
- /package/{lib/vision → integrations/vision/lib}/redact.mjs +0 -0
- /package/{plugins → integrations}/vision/skills/at-vision/SKILL.md +0 -0
|
@@ -30952,11 +30952,11 @@ var StdioServerTransport = class {
|
|
|
30952
30952
|
}
|
|
30953
30953
|
};
|
|
30954
30954
|
|
|
30955
|
-
//
|
|
30955
|
+
// integrations/vision/lib/inspect.mjs
|
|
30956
30956
|
import crypto3 from "node:crypto";
|
|
30957
30957
|
import path4 from "node:path";
|
|
30958
30958
|
|
|
30959
|
-
//
|
|
30959
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/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
|
+
// integrations/vision/mcp-server.mjs
|
|
32802
32802
|
var TOOL_DESCRIPTION = [
|
|
32803
32803
|
"This is a callable MCP tool, not an MCP resource. Invoke it directly; never use list_mcp_resources or read_mcp_resource, and never treat inspect_image as a resource URI.",
|
|
32804
32804
|
"Ask a vision model factual questions about one image (local file path or http(s) URL).",
|
|
@@ -20,7 +20,9 @@ const AGENT_TOOLS_HOME = process.env.AGENT_TOOLS_HOME || join(SCRIPT_DIR, "..",
|
|
|
20
20
|
const DEFAULT_CONFIG_FILE = join(AGENT_TOOLS_HOME, "config.jsonc");
|
|
21
21
|
const SNAPSHOT_FILE = join(AGENT_TOOLS_HOME, "cache", "usage-snapshot.json");
|
|
22
22
|
const REFRESH_STATE_FILE = join(AGENT_TOOLS_HOME, "cache", "usage-refresh-state.json");
|
|
23
|
-
|
|
23
|
+
// Cross-integration dependency: statusline renders provider usage via the
|
|
24
|
+
// usage integration's query engine.
|
|
25
|
+
const USAGE_RUNTIME = join(AGENT_TOOLS_HOME, "integrations", "usage", "core.mjs");
|
|
24
26
|
const DEFAULT_SNAPSHOT_TTL_MS = 60_000;
|
|
25
27
|
const DEFAULT_REFRESH_COOLDOWN_MS = 30_000;
|
|
26
28
|
const DEFAULT_FAILURE_BACKOFF_MS = 120_000;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Local CLI used by the managed at-usage skills.
|
|
3
|
+
|
|
4
|
+
import { queryAgentProviderUsage } from "./core.mjs";
|
|
5
|
+
|
|
6
|
+
function parseAgent(argv) {
|
|
7
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
8
|
+
const arg = argv[index];
|
|
9
|
+
if (arg === "--agent" && argv[index + 1]) return argv[index + 1];
|
|
10
|
+
if (arg.startsWith("--agent=")) return arg.slice("--agent=".length);
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const agent = parseAgent(process.argv.slice(2));
|
|
16
|
+
if (agent !== "claude" && agent !== "codex") {
|
|
17
|
+
process.stderr.write(agent ? `Unsupported agent: ${agent}\n` : "Missing --agent <claude|codex>\n");
|
|
18
|
+
process.exitCode = 2;
|
|
19
|
+
} else {
|
|
20
|
+
try {
|
|
21
|
+
const result = await queryAgentProviderUsage(agent);
|
|
22
|
+
if (result?.text) process.stdout.write(`${result.text}\n`);
|
|
23
|
+
} catch {
|
|
24
|
+
// Usage is informational. Leave stdout empty so the skill can report the
|
|
25
|
+
// provider as unavailable without exposing endpoint or credential details.
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -11,7 +11,7 @@ import { fileURLToPath } from "node:url";
|
|
|
11
11
|
|
|
12
12
|
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
13
13
|
const AGENT_TOOLS_HOME = process.env.AGENT_TOOLS_HOME || path.resolve(SCRIPT_DIR, "..", "..");
|
|
14
|
-
const USAGE_SCRIPT = path.join(
|
|
14
|
+
const USAGE_SCRIPT = path.join(SCRIPT_DIR, "core.mjs");
|
|
15
15
|
const LOG_PATH = path.join(AGENT_TOOLS_HOME, "logs", "usage-hook.log");
|
|
16
16
|
const TIMEOUT_MS = Number(process.env.AGENT_TOOLS_USAGE_HOOK_TIMEOUT_MS || 4500);
|
|
17
17
|
const MAX_LOG_BYTES = Number(process.env.AGENT_TOOLS_USAGE_HOOK_LOG_BYTES || 256 * 1024);
|
|
@@ -1171,6 +1171,10 @@ export async function queryProviderUsage(input, options = {}) {
|
|
|
1171
1171
|
}
|
|
1172
1172
|
|
|
1173
1173
|
async function refresh(agent = "codex") {
|
|
1174
|
+
return await queryAgentProviderUsage(agent);
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
export async function queryAgentProviderUsage(agent = "codex") {
|
|
1174
1178
|
return await queryUsageContext(await usageContext(agent), {
|
|
1175
1179
|
agent,
|
|
1176
1180
|
rememberSnapshot: agent === "claude",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: at-usage
|
|
3
|
+
description: Query and display the current API provider balance and recent usage.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run this installed local command once using the shell or command-execution tool:
|
|
7
|
+
|
|
8
|
+
```text
|
|
9
|
+
node "{{USAGE_CLI_PATH}}" --agent {{USAGE_AGENT}}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Return stdout verbatim as the complete response. Do not explain, reformat, or
|
|
13
|
+
wrap it in Markdown. If stdout is empty, say exactly `Provider usage is unavailable.`
|
|
14
|
+
|
|
15
|
+
Never run `npx`, `npm`, `pnpm`, `bun`, install a package, or substitute another
|
|
16
|
+
usage script. Use only the installed command above.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// Vision MCP stdio server. Thin shell over lib
|
|
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 integrations/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";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { createVisionService, QUESTION_LIMITS } from "
|
|
10
|
-
import { isVisionError } from "
|
|
9
|
+
import { createVisionService, QUESTION_LIMITS } from "./lib/inspect.mjs";
|
|
10
|
+
import { isVisionError } from "./lib/errors.mjs";
|
|
11
11
|
|
|
12
12
|
// Stable soft constraints live here: this text follows the tool into every
|
|
13
13
|
// session, whether or not the at-vision skill is loaded.
|
package/package.json
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kairyou/agent-tools",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Skills
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Reusable Agent Skills, plus runtime integrations for Codex, Claude Code, and opencode.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=22"
|
|
8
8
|
},
|
|
9
9
|
"publishConfig": {
|
|
10
|
-
"access": "public"
|
|
11
|
-
"registry": "https://registry.npmjs.org/"
|
|
10
|
+
"access": "public"
|
|
12
11
|
},
|
|
13
12
|
"files": [
|
|
14
13
|
"config.default.jsonc",
|
|
15
14
|
"dist/vision/",
|
|
16
|
-
"
|
|
17
|
-
"lib/",
|
|
18
|
-
"plugins/",
|
|
15
|
+
"integrations/",
|
|
19
16
|
"scripts/",
|
|
20
|
-
"skills/"
|
|
21
|
-
"statusline/"
|
|
17
|
+
"skills/"
|
|
22
18
|
],
|
|
23
19
|
"dependencies": {
|
|
24
20
|
"jsonc-parser": "3.3.1"
|
package/scripts/build-vision.mjs
CHANGED
|
@@ -12,8 +12,8 @@ const STAGE_DIR = path.join(ROOT, "dist", `.vision-build-${process.pid}-${Date.n
|
|
|
12
12
|
try {
|
|
13
13
|
await build({
|
|
14
14
|
entryPoints: {
|
|
15
|
-
"mcp-server": path.join(ROOT, "
|
|
16
|
-
cli: path.join(ROOT, "
|
|
15
|
+
"mcp-server": path.join(ROOT, "integrations", "vision", "mcp-server.mjs"),
|
|
16
|
+
cli: path.join(ROOT, "integrations", "vision", "lib", "cli.mjs"),
|
|
17
17
|
},
|
|
18
18
|
outdir: STAGE_DIR,
|
|
19
19
|
bundle: true,
|