getagenthook 1.0.0 → 1.0.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 +28 -2
- package/dist/commands/run.js +27 -38
- package/dist/commands/tools.js +7 -4
- package/dist/flags.js +38 -0
- package/dist/http.js +2 -1
- package/dist/main.js +0 -0
- package/dist/schemas.js +21 -5
- package/dist/validate.js +16 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# agenthook
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/getagenthook)
|
|
4
|
+
|
|
3
5
|
CLI for the AgentHook hosted media-generation API. Built for agents:
|
|
4
6
|
progress goes to stderr, output URLs go to stdout, exit codes are meaningful.
|
|
5
7
|
|
|
@@ -18,7 +20,7 @@ agenthook history
|
|
|
18
20
|
|
|
19
21
|
- Credentials live at `~/.agenthook/credentials.json` (chmod 600).
|
|
20
22
|
- API base: `--api-url` flag > `AGENTHOOK_API_URL` env > stored value >
|
|
21
|
-
`https://
|
|
23
|
+
`https://getagenthook.com`; all requests hit `<base>/api/v1/…`.
|
|
22
24
|
- Reference images (`--ref`, repeatable) require `--owns-references`: you attest
|
|
23
25
|
you own, or have the rights to use, the likeness of every person appearing in
|
|
24
26
|
the referenced images.
|
|
@@ -27,4 +29,28 @@ agenthook history
|
|
|
27
29
|
submitted: consent, prompt length caps, enum values, ranges, and
|
|
28
30
|
`nano-banana-2` (edit-only) without references.
|
|
29
31
|
|
|
30
|
-
|
|
32
|
+
## MCP server
|
|
33
|
+
|
|
34
|
+
If your agent speaks MCP, it can call AgentHook directly instead of going through
|
|
35
|
+
the CLI. The server ships as `@getagenthook/mcp` and runs over `npx`. Add this to
|
|
36
|
+
your MCP client config (Claude Code, Cursor, and similar):
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"agenthook": {
|
|
42
|
+
"command": "npx",
|
|
43
|
+
"args": ["-y", "@getagenthook/mcp"],
|
|
44
|
+
"env": { "AGENTHOOK_API_KEY": "ah_your_key" }
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
It exposes `make_video`, `make_image`, `caption_video`, and `create_influencer`,
|
|
51
|
+
plus `get_run`. The generation tools return a `run_id`; pass it to `get_run` to
|
|
52
|
+
fetch the finished URL once the job is done.
|
|
53
|
+
|
|
54
|
+
## Develop
|
|
55
|
+
|
|
56
|
+
`npm run build` (emits `dist/`), `npx vitest run`, `npx tsc --noEmit`.
|
package/dist/commands/run.js
CHANGED
|
@@ -38,40 +38,12 @@ const crypto = __importStar(require("node:crypto"));
|
|
|
38
38
|
const args_1 = require("../args");
|
|
39
39
|
const config_1 = require("../config");
|
|
40
40
|
const exit_1 = require("../exit");
|
|
41
|
+
const flags_1 = require("../flags");
|
|
41
42
|
const http_1 = require("../http");
|
|
42
43
|
const jobs_1 = require("../jobs");
|
|
43
44
|
const schemas_1 = require("../schemas");
|
|
44
45
|
const types_1 = require("../types");
|
|
45
46
|
const validate_1 = require("../validate");
|
|
46
|
-
const RUN_FLAGS = {
|
|
47
|
-
"api-url": "string",
|
|
48
|
-
key: "string",
|
|
49
|
-
json: "boolean",
|
|
50
|
-
"dry-run": "boolean",
|
|
51
|
-
prompt: "string",
|
|
52
|
-
ref: "array",
|
|
53
|
-
"owns-references": "boolean",
|
|
54
|
-
model: "string",
|
|
55
|
-
quality: "string",
|
|
56
|
-
duration: "number",
|
|
57
|
-
"aspect-ratio": "string",
|
|
58
|
-
"no-audio": "boolean",
|
|
59
|
-
captions: "boolean",
|
|
60
|
-
"caption-style": "string",
|
|
61
|
-
"caption-size": "string",
|
|
62
|
-
"caption-placement": "string",
|
|
63
|
-
"enhance-prompt": "boolean",
|
|
64
|
-
"video-url": "string",
|
|
65
|
-
style: "string",
|
|
66
|
-
size: "string",
|
|
67
|
-
placement: "string",
|
|
68
|
-
count: "number",
|
|
69
|
-
resolution: "string",
|
|
70
|
-
language: "string",
|
|
71
|
-
name: "string",
|
|
72
|
-
slug: "string",
|
|
73
|
-
influencer: "string",
|
|
74
|
-
};
|
|
75
47
|
// Poll cadence: 5s (spec); overridable for tests. Every watcher gets a
|
|
76
48
|
// give-up (donor rule): a wall-clock deadline + bounded consecutive misses.
|
|
77
49
|
const pollIntervalMs = () => Number(process.env.AGENTHOOK_POLL_MS || 5000);
|
|
@@ -81,7 +53,14 @@ const MAX_POLL_MISSES = 5;
|
|
|
81
53
|
// submit must never double-charge; the server dedupes on the key).
|
|
82
54
|
const SUBMIT_RETRIES = 1;
|
|
83
55
|
async function run(argv) {
|
|
84
|
-
|
|
56
|
+
// Flags are DERIVED from the live tool schema (so a new API param is a usable
|
|
57
|
+
// flag without a CLI upgrade), and the schema source is per-api-url — so the
|
|
58
|
+
// api-url is pulled from argv BEFORE the full parse, the schema is resolved,
|
|
59
|
+
// then the flag spec is built to parse against.
|
|
60
|
+
const apiUrl = (0, config_1.resolveApiUrl)(preScanApiUrl(argv));
|
|
61
|
+
const schemas = await (0, schemas_1.resolveRunSchemas)(apiUrl);
|
|
62
|
+
const { spec, paramForFlag, flagFor } = (0, flags_1.deriveRunFlags)(schemas);
|
|
63
|
+
const { positionals, flags, errors } = (0, args_1.parseArgs)(argv, spec);
|
|
85
64
|
if (errors.length) {
|
|
86
65
|
errors.forEach((e) => console.error(e));
|
|
87
66
|
return exit_1.EXIT.GENERIC;
|
|
@@ -92,19 +71,16 @@ async function run(argv) {
|
|
|
92
71
|
console.error("Usage: agenthook run <tool> [flags] — see `agenthook tools`");
|
|
93
72
|
return exit_1.EXIT.GENERIC;
|
|
94
73
|
}
|
|
95
|
-
const apiUrl = (0, config_1.resolveApiUrl)(flags["api-url"]);
|
|
96
74
|
const key = (0, config_1.resolveApiKey)(flags["key"]);
|
|
97
75
|
if (!key) {
|
|
98
76
|
emitError(asJson, "Not logged in — run `agenthook auth:login` first.", exit_1.EXIT.AUTH);
|
|
99
77
|
return exit_1.EXIT.AUTH;
|
|
100
78
|
}
|
|
101
|
-
// Deterministic pre-validation BEFORE
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
const input = (0, validate_1.buildToolInput)(flags);
|
|
107
|
-
const problems = (0, validate_1.preValidate)(tool, input, schemas);
|
|
79
|
+
// Deterministic pre-validation BEFORE the run is submitted (spec §3): every
|
|
80
|
+
// locally-checkable rule the server would 400 on. The server re-validates
|
|
81
|
+
// authoritatively on submit.
|
|
82
|
+
const input = (0, validate_1.buildToolInput)(flags, paramForFlag);
|
|
83
|
+
const problems = (0, validate_1.preValidate)(tool, input, schemas, flagFor);
|
|
108
84
|
if (problems.length) {
|
|
109
85
|
if (asJson)
|
|
110
86
|
emitError(true, problems.join("; "), exit_1.EXIT.VALIDATION);
|
|
@@ -235,6 +211,19 @@ async function submitWithRetry(apiUrl, tool, input, key, idempotencyKey) {
|
|
|
235
211
|
}
|
|
236
212
|
}
|
|
237
213
|
}
|
|
214
|
+
/** Pull --api-url out of raw argv before the flag spec exists (spec derivation
|
|
215
|
+
* needs the schema, fetched per api-url). Mirrors parseArgs' two forms; full
|
|
216
|
+
* precedence (flag > env > file > default) is applied by resolveApiUrl. */
|
|
217
|
+
function preScanApiUrl(argv) {
|
|
218
|
+
for (let i = 0; i < argv.length; i++) {
|
|
219
|
+
const a = argv[i];
|
|
220
|
+
if (a === "--api-url")
|
|
221
|
+
return argv[i + 1];
|
|
222
|
+
if (a.startsWith("--api-url="))
|
|
223
|
+
return a.slice("--api-url=".length);
|
|
224
|
+
}
|
|
225
|
+
return undefined;
|
|
226
|
+
}
|
|
238
227
|
const topUpUrl = (apiUrl) => `${apiUrl}/credits`;
|
|
239
228
|
/** Machine JSON to stdout (one object per line, ndjson). */
|
|
240
229
|
function emit(obj) {
|
package/dist/commands/tools.js
CHANGED
|
@@ -4,9 +4,9 @@ exports.tools = tools;
|
|
|
4
4
|
const args_1 = require("../args");
|
|
5
5
|
const config_1 = require("../config");
|
|
6
6
|
const exit_1 = require("../exit");
|
|
7
|
+
const flags_1 = require("../flags");
|
|
7
8
|
const json_error_1 = require("../json-error");
|
|
8
9
|
const schemas_1 = require("../schemas");
|
|
9
|
-
const validate_1 = require("../validate");
|
|
10
10
|
async function tools(argv) {
|
|
11
11
|
const { flags, errors } = (0, args_1.parseArgs)(argv, { "api-url": "string", key: "string", json: "boolean" });
|
|
12
12
|
if (errors.length) {
|
|
@@ -22,10 +22,13 @@ async function tools(argv) {
|
|
|
22
22
|
console.log(JSON.stringify({ tools: schemas }));
|
|
23
23
|
return exit_1.EXIT.OK;
|
|
24
24
|
}
|
|
25
|
+
// Same derivation `run` parses against — the flag spelling shown here is
|
|
26
|
+
// exactly the one that will work.
|
|
27
|
+
const { flagFor } = (0, flags_1.deriveRunFlags)(schemas);
|
|
25
28
|
for (const tool of schemas) {
|
|
26
29
|
console.log(`${tool.name} — ${tool.description}`);
|
|
27
30
|
for (const [name, spec] of Object.entries(tool.params)) {
|
|
28
|
-
console.log(` ${renderParam(name, spec)}`);
|
|
31
|
+
console.log(` ${renderParam(name, spec, flagFor)}`);
|
|
29
32
|
}
|
|
30
33
|
console.log("");
|
|
31
34
|
}
|
|
@@ -33,8 +36,8 @@ async function tools(argv) {
|
|
|
33
36
|
return exit_1.EXIT.OK;
|
|
34
37
|
});
|
|
35
38
|
}
|
|
36
|
-
function renderParam(name, spec) {
|
|
37
|
-
const flagName =
|
|
39
|
+
function renderParam(name, spec, flagFor) {
|
|
40
|
+
const flagName = flagFor[name] ?? `--${name.replace(/_/g, "-")}`;
|
|
38
41
|
const hint = spec.type === "boolean"
|
|
39
42
|
? ""
|
|
40
43
|
: spec.enum
|
package/dist/flags.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FLAG_ALIAS = exports.CLI_FLAGS = void 0;
|
|
4
|
+
exports.deriveRunFlags = deriveRunFlags;
|
|
5
|
+
/** Flags that are NOT tool params and must always parse (any command shape). */
|
|
6
|
+
exports.CLI_FLAGS = {
|
|
7
|
+
"api-url": "string",
|
|
8
|
+
key: "string",
|
|
9
|
+
json: "boolean",
|
|
10
|
+
"dry-run": "boolean",
|
|
11
|
+
};
|
|
12
|
+
/** The two places the CLI flag intentionally differs from a mechanical
|
|
13
|
+
* snake→kebab of the param name (everything else is derived). */
|
|
14
|
+
exports.FLAG_ALIAS = {
|
|
15
|
+
reference_images: { flag: "ref" },
|
|
16
|
+
audio: { flag: "no-audio", invertBoolean: true }, // --no-audio sets audio:false
|
|
17
|
+
};
|
|
18
|
+
const FLAG_TYPES = ["string", "number", "boolean", "array"];
|
|
19
|
+
/** Union every tool's params into the run flag spec + flag⇄param maps. Params
|
|
20
|
+
* repeat across tools (same flag name each time) — the union is idempotent. */
|
|
21
|
+
function deriveRunFlags(schemas) {
|
|
22
|
+
const spec = { ...exports.CLI_FLAGS };
|
|
23
|
+
const paramForFlag = {};
|
|
24
|
+
const flagFor = {};
|
|
25
|
+
for (const schema of schemas) {
|
|
26
|
+
for (const [param, p] of Object.entries(schema.params)) {
|
|
27
|
+
const alias = exports.FLAG_ALIAS[param];
|
|
28
|
+
const flag = alias?.flag ?? param.replace(/_/g, "-");
|
|
29
|
+
let type = FLAG_TYPES.includes(p.type) ? p.type : "string";
|
|
30
|
+
if (alias?.invertBoolean)
|
|
31
|
+
type = "boolean";
|
|
32
|
+
spec[flag] = type;
|
|
33
|
+
paramForFlag[flag] = { param, invert: alias?.invertBoolean };
|
|
34
|
+
flagFor[param] = "--" + flag;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { spec, paramForFlag, flagFor };
|
|
38
|
+
}
|
package/dist/http.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.timeoutSignal = timeoutSignal;
|
|
|
5
5
|
exports.api = api;
|
|
6
6
|
exports.describeApiError = describeApiError;
|
|
7
7
|
const config_1 = require("./config");
|
|
8
|
+
const version_1 = require("./version");
|
|
8
9
|
// Timeout policy mirrors the frozen packages/core/net.ts (DEFAULT_TIMEOUT_MS +
|
|
9
10
|
// AbortSignal.timeout). Duplicated here because the published CLI cannot
|
|
10
11
|
// runtime-import workspace TypeScript; test/parity.test.ts pins the value.
|
|
@@ -36,7 +37,7 @@ async function api(apiUrl, pathname, opts = {}) {
|
|
|
36
37
|
if (v !== undefined && v !== "")
|
|
37
38
|
url.searchParams.set(k, v);
|
|
38
39
|
}
|
|
39
|
-
const headers = { ...opts.headers };
|
|
40
|
+
const headers = { "user-agent": `agenthook-cli/${version_1.VERSION}`, ...opts.headers };
|
|
40
41
|
if (opts.key)
|
|
41
42
|
headers.authorization = `Bearer ${opts.key}`;
|
|
42
43
|
if (opts.body !== undefined)
|
package/dist/main.js
CHANGED
|
File without changes
|
package/dist/schemas.js
CHANGED
|
@@ -36,12 +36,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.TOOLS_CACHE_TTL_MS = void 0;
|
|
37
37
|
exports.toolsCachePath = toolsCachePath;
|
|
38
38
|
exports.getLocalToolSchemas = getLocalToolSchemas;
|
|
39
|
+
exports.resolveRunSchemas = resolveRunSchemas;
|
|
39
40
|
exports.getToolSchemas = getToolSchemas;
|
|
40
|
-
// Tool-schema source
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
41
|
+
// Tool-schema source. GET /v1/tools is the single live schema source, and
|
|
42
|
+
// `run` DERIVES its flags from it (a new API param is a usable flag with no CLI
|
|
43
|
+
// upgrade) via resolveRunSchemas: the cached fetch when fresh, a live keyless
|
|
44
|
+
// fetch on miss (public endpoint), and the bundled snapshot as the offline
|
|
45
|
+
// fallback — so it stays current online and still works offline. (This relaxes
|
|
46
|
+
// the original spec §3 "no network before submit" guarantee to a cached,
|
|
47
|
+
// at-most-hourly, keyless fetch — the cost of never-stale flags.)
|
|
45
48
|
const fs = __importStar(require("node:fs"));
|
|
46
49
|
const path = __importStar(require("node:path"));
|
|
47
50
|
const config_1 = require("./config");
|
|
@@ -72,6 +75,19 @@ function writeCache(cache) {
|
|
|
72
75
|
function getLocalToolSchemas(apiUrl) {
|
|
73
76
|
return readCache()[apiUrl]?.tools ?? schema_snapshot_1.TOOLS_SNAPSHOT;
|
|
74
77
|
}
|
|
78
|
+
/** Schema source for `run`'s flag derivation + pre-validation. Live-and-cached
|
|
79
|
+
* (GET /v1/tools is PUBLIC — no key) so a new tool param becomes a usable flag
|
|
80
|
+
* without a CLI upgrade; falls back to the last cache, then the bundled
|
|
81
|
+
* snapshot, so it never throws (offline / fresh install still work). The server
|
|
82
|
+
* re-validates authoritatively on submit. */
|
|
83
|
+
async function resolveRunSchemas(apiUrl) {
|
|
84
|
+
try {
|
|
85
|
+
return await getToolSchemas(apiUrl);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return getLocalToolSchemas(apiUrl);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
75
91
|
/** Cached-first schema load. `fresh: true` (the `tools` command) always
|
|
76
92
|
* refetches; otherwise a fresh cache entry short-circuits the network, and a
|
|
77
93
|
* stale one is the fallback when the API is unreachable (the server re-checks
|
package/dist/validate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.OWNS_REFERENCES_CONSENT = exports.PROMPT_CAPS = void 0;
|
|
4
4
|
exports.buildToolInput = buildToolInput;
|
|
5
5
|
exports.preValidate = preValidate;
|
|
6
6
|
// Per-model prompt caps, mirroring packages/core/models.ts promptMax (frozen).
|
|
@@ -13,77 +13,25 @@ exports.PROMPT_CAPS = {
|
|
|
13
13
|
};
|
|
14
14
|
exports.OWNS_REFERENCES_CONSENT = "By passing --owns-references you attest that you own, or have the rights to use, " +
|
|
15
15
|
"the likeness of every person appearing in the referenced images.";
|
|
16
|
-
/** CLI
|
|
17
|
-
*
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
model: "--model",
|
|
23
|
-
quality: "--quality",
|
|
24
|
-
duration: "--duration",
|
|
25
|
-
aspect_ratio: "--aspect-ratio",
|
|
26
|
-
audio: "--no-audio",
|
|
27
|
-
captions: "--captions",
|
|
28
|
-
caption_style: "--caption-style",
|
|
29
|
-
caption_size: "--caption-size",
|
|
30
|
-
caption_placement: "--caption-placement",
|
|
31
|
-
enhance_prompt: "--enhance-prompt",
|
|
32
|
-
video_url: "--video-url",
|
|
33
|
-
style: "--style",
|
|
34
|
-
size: "--size",
|
|
35
|
-
placement: "--placement",
|
|
36
|
-
count: "--count",
|
|
37
|
-
resolution: "--resolution",
|
|
38
|
-
language: "--language",
|
|
39
|
-
name: "--name",
|
|
40
|
-
slug: "--slug",
|
|
41
|
-
influencer: "--influencer",
|
|
42
|
-
};
|
|
43
|
-
/** Map parsed CLI flags onto the tool-input body the API expects. Only flags
|
|
44
|
-
* the user actually passed are included, so server defaults stay in charge. */
|
|
45
|
-
function buildToolInput(flags) {
|
|
16
|
+
/** Map parsed CLI flags onto the tool-input body the API expects, using the
|
|
17
|
+
* flag→param map derived from the tool schema (see flags.ts). Only flags the
|
|
18
|
+
* user actually passed are present in `flags`, so server defaults stay in
|
|
19
|
+
* charge; a global CLI flag (api-url/key/json/dry-run) has no param and is
|
|
20
|
+
* skipped. The one non-direct case is `--no-audio` inverting to audio:false. */
|
|
21
|
+
function buildToolInput(flags, paramForFlag) {
|
|
46
22
|
const input = {};
|
|
47
|
-
const
|
|
48
|
-
[
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
[
|
|
52
|
-
["aspect-ratio", "aspect_ratio"],
|
|
53
|
-
["caption-style", "caption_style"],
|
|
54
|
-
["caption-size", "caption_size"],
|
|
55
|
-
["caption-placement", "caption_placement"],
|
|
56
|
-
["video-url", "video_url"],
|
|
57
|
-
["style", "style"],
|
|
58
|
-
["size", "size"],
|
|
59
|
-
["placement", "placement"],
|
|
60
|
-
["count", "count"],
|
|
61
|
-
["resolution", "resolution"],
|
|
62
|
-
["language", "language"],
|
|
63
|
-
["name", "name"],
|
|
64
|
-
["slug", "slug"],
|
|
65
|
-
["influencer", "influencer"],
|
|
66
|
-
];
|
|
67
|
-
for (const [flag, param] of direct) {
|
|
68
|
-
if (flags[flag] !== undefined)
|
|
69
|
-
input[param] = flags[flag];
|
|
23
|
+
for (const [flag, value] of Object.entries(flags)) {
|
|
24
|
+
const mapping = paramForFlag[flag];
|
|
25
|
+
if (!mapping)
|
|
26
|
+
continue; // a global CLI flag, not a tool param
|
|
27
|
+
input[mapping.param] = mapping.invert ? !value : value;
|
|
70
28
|
}
|
|
71
|
-
const refs = flags["ref"];
|
|
72
|
-
if (refs?.length)
|
|
73
|
-
input.reference_images = refs;
|
|
74
|
-
if (flags["owns-references"])
|
|
75
|
-
input.owns_references = true;
|
|
76
|
-
if (flags["no-audio"])
|
|
77
|
-
input.audio = false;
|
|
78
|
-
if (flags["captions"])
|
|
79
|
-
input.captions = true;
|
|
80
|
-
if (flags["enhance-prompt"])
|
|
81
|
-
input.enhance_prompt = true;
|
|
82
29
|
return input;
|
|
83
30
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
function preValidate(tool, input, schemas) {
|
|
31
|
+
/** Returns human-readable problems (empty array = locally valid). `flagFor`
|
|
32
|
+
* (derived from the schema) supplies the CLI flag spelling for messages. */
|
|
33
|
+
function preValidate(tool, input, schemas, flagFor) {
|
|
34
|
+
const flag = (param) => flagFor[param] ?? "--" + param.replace(/_/g, "-");
|
|
87
35
|
const schema = schemas.find((s) => s.name === tool);
|
|
88
36
|
if (!schema) {
|
|
89
37
|
return [`Unknown tool "${tool}". Available tools: ${schemas.map((s) => s.name).join(", ")}`];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "getagenthook",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "CLI for the AgentHook hosted media-generation API — generate video, images, and captions from your terminal or agent.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://getagenthook.com",
|