@weirgate/cli 0.1.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 +13 -0
- package/dist/cli/browser-session-grant.js +2 -2
- package/dist/cli/index.js +20 -8
- package/dist/cli/listing.js +66 -0
- package/dist/mcp/server.js +5 -4
- package/dist/shared/api-client.js +5 -4
- package/dist/shared/tools.js +10 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,4 +30,17 @@ Provider-key values are entered only through `weirgate provider-keys put|rotate`
|
|
|
30
30
|
local browser page by default, or hidden terminal input with `--stdin`) and never appear
|
|
31
31
|
in output. Exit codes are listed in the guide.
|
|
32
32
|
|
|
33
|
+
`weirgate models list` shows model prices and provider policy (`--upstream`,
|
|
34
|
+
`--modality`), and `weirgate audit list --all` reads the whole audit log (up to 10,000
|
|
35
|
+
events; `--limit` and `--cursor` page by hand).
|
|
36
|
+
|
|
37
|
+
## Changes
|
|
38
|
+
|
|
39
|
+
- **0.3.0**: `weirgate models list` and the MCP tool `weirgate_list_models` (model prices
|
|
40
|
+
and provider policy, with the reason a model isn't allowed); `weirgate audit list`
|
|
41
|
+
pages with `--limit`, `--cursor`, and `--all`.
|
|
42
|
+
- **0.2.0**: CLI and MCP failures use the API's error envelope; `grants create
|
|
43
|
+
--source`; `doctor payments`.
|
|
44
|
+
- **0.1.0**: first release.
|
|
45
|
+
|
|
33
46
|
MIT licensed. Copyright 2026 Astraen Labs LLC.
|
|
@@ -74,10 +74,10 @@ async function exchangeSessionGrantCode(apiUrl, code, fetchImpl) {
|
|
|
74
74
|
const apiVersion = response.headers.get("Weirgate-Api-Version") ?? "unknown";
|
|
75
75
|
const payload = await response.json().catch(() => ({}));
|
|
76
76
|
if (apiVersion !== API_VERSION) {
|
|
77
|
-
throw new WeirgateApiError({ message: `API version mismatch: expected ${API_VERSION}, received ${apiVersion}`, errorType: "api_version_mismatch", status: 502, requestId, apiVersion,
|
|
77
|
+
throw new WeirgateApiError({ message: `API version mismatch: expected ${API_VERSION}, received ${apiVersion}`, errorType: "api_version_mismatch", status: 502, requestId, apiVersion, detail: { expected: API_VERSION, received: apiVersion } });
|
|
78
78
|
}
|
|
79
79
|
if (!response.ok || typeof payload.value !== "string") {
|
|
80
|
-
throw new WeirgateApiError({ message: payload.error?.message ?? `Weirgate API returned HTTP ${response.status}`, errorType: response.headers.get("X-Weirgate-Error-Type") ?? payload.error?.type ?? "remote_error", status: response.status, requestId, apiVersion,
|
|
80
|
+
throw new WeirgateApiError({ message: payload.error?.message ?? `Weirgate API returned HTTP ${response.status}`, errorType: response.headers.get("X-Weirgate-Error-Type") ?? payload.error?.type ?? "remote_error", status: response.status, requestId, apiVersion, ...(payload.error?.detail ? { detail: payload.error.detail } : {}) });
|
|
81
81
|
}
|
|
82
82
|
return payload.value;
|
|
83
83
|
}
|
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,10 @@ import { AgentApiClient, API_VERSION, DEFAULT_API_URL, pathPart, WeirgateApiErro
|
|
|
10
10
|
import { invokeTool } from "../shared/tools.js";
|
|
11
11
|
import { browserSessionGrant } from "./browser-session-grant.js";
|
|
12
12
|
import { exitCodeFor } from "./exit-codes.js";
|
|
13
|
+
import { AUDIT_ALL_CAP, listAllAuditEvents, modelsTable } from "./listing.js";
|
|
13
14
|
let deferringRequiredFlags = false;
|
|
15
|
+
/** A command-specific `--output table` view; other commands print YAML. */
|
|
16
|
+
let tableView;
|
|
14
17
|
const parsed = parse(process.argv.slice(2));
|
|
15
18
|
try {
|
|
16
19
|
const result = await run(parsed);
|
|
@@ -140,21 +143,24 @@ async function commandToTool(client, noun, verb, flags) {
|
|
|
140
143
|
"proposals:get": ["weirgate_get_proposal", { proposal_id: requiredFlag(flags, "proposal") }],
|
|
141
144
|
"proposals:cancel": ["weirgate_cancel_proposal", { proposal_id: requiredFlag(flags, "proposal") }],
|
|
142
145
|
"proposals:apply": ["weirgate_apply_proposal", { proposal_id: requiredFlag(flags, "proposal"), expected_base_revision: numberFlag(flags, "expected-base-revision"), idempotency_key: requiredFlag(flags, "idempotency-key") }],
|
|
143
|
-
"usage:query": ["weirgate_query_usage", { ...common, since: requiredFlag(flags, "since"), until: requiredFlag(flags, "until"), group_by: stringFlag(flags, "group-by"), limit: numberFlag(flags, "limit") }],
|
|
146
|
+
"usage:query": ["weirgate_query_usage", { ...common, since: requiredFlag(flags, "since"), until: requiredFlag(flags, "until"), group_by: stringFlag(flags, "group-by"), bucket: stringFlag(flags, "bucket"), limit: numberFlag(flags, "limit") }],
|
|
147
|
+
"usage:failures": ["weirgate_list_failures", { ...common, since: stringFlag(flags, "since"), until: stringFlag(flags, "until"), cursor: stringFlag(flags, "cursor"), limit: numberFlag(flags, "limit") }],
|
|
144
148
|
"pricing-insights:get": ["weirgate_get_pricing_insights", { ...common, since: requiredFlag(flags, "since"), until: requiredFlag(flags, "until") }],
|
|
145
149
|
"users:timeline": ["weirgate_get_user_timeline", { ...common, external_id: requiredFlag(flags, "user") }],
|
|
146
150
|
"events:list": ["weirgate_list_events", common],
|
|
147
|
-
"audit:list": ["weirgate_list_audit_events", { ...common, since: stringFlag(flags, "since"), until: stringFlag(flags, "until"), action: stringFlag(flags, "action") }],
|
|
151
|
+
"audit:list": ["weirgate_list_audit_events", { ...common, since: stringFlag(flags, "since"), until: stringFlag(flags, "until"), action: stringFlag(flags, "action"), limit: numberFlag(flags, "limit"), cursor: stringFlag(flags, "cursor") }],
|
|
152
|
+
"models:list": ["weirgate_list_models", { upstream: stringFlag(flags, "upstream"), modality: stringFlag(flags, "modality") }],
|
|
148
153
|
"provider-keys:list": ["weirgate_list_provider_key_slots", common],
|
|
149
154
|
"provider-keys:test": ["weirgate_test_provider_key", { ...common, provider: requiredFlag(flags, "provider") }],
|
|
150
|
-
"grants:create": ["weirgate_grant_allowance", { ...common, external_id: requiredFlag(flags, "user"), units: numberRequired(flags, "units"),
|
|
155
|
+
"grants:create": ["weirgate_grant_allowance", { ...common, external_id: requiredFlag(flags, "user"), units: numberRequired(flags, "units"), source: stringFlag(flags, "source") }],
|
|
151
156
|
"grants:reverse": ["weirgate_reverse_grant", { ...common, grant_id: requiredFlag(flags, "grant") }],
|
|
152
157
|
"user-tiers:assign": ["weirgate_assign_user_tier", { ...common, external_id: requiredFlag(flags, "user"), tier: requiredFlag(flags, "tier"), top_up_now: booleanFlag(flags, "top-up-now") }],
|
|
153
158
|
"user-tiers:revert": ["weirgate_revert_user_tier", { ...common, external_id: requiredFlag(flags, "user"), top_up_now: booleanFlag(flags, "top-up-now") }],
|
|
154
|
-
"doctor:all": ["weirgate_run_config_doctor", { ...common, checks: ["auth", "provider", "webhook"] }],
|
|
159
|
+
"doctor:all": ["weirgate_run_config_doctor", { ...common, checks: ["auth", "provider", "webhook", "payments"] }],
|
|
155
160
|
"doctor:auth": ["weirgate_run_config_doctor", { ...common, checks: ["auth"] }],
|
|
156
161
|
"doctor:provider": ["weirgate_run_config_doctor", { ...common, checks: ["provider"] }],
|
|
157
162
|
"doctor:webhook": ["weirgate_run_config_doctor", { ...common, checks: ["webhook"] }],
|
|
163
|
+
"doctor:payments": ["weirgate_run_config_doctor", { ...common, checks: ["payments"] }],
|
|
158
164
|
"sandbox:call": ["weirgate_run_mock_call", { ...common, fixture: stringFlag(flags, "fixture") ?? "success", session_name: stringFlag(flags, "session-name") }],
|
|
159
165
|
"docs:search": ["weirgate_search_docs", { query: requiredFlag(flags, "query"), section: stringFlag(flags, "section"), limit: numberFlag(flags, "limit") }],
|
|
160
166
|
"docs:get": ["weirgate_get_doc", { page_id: requiredFlag(flags, "page") }],
|
|
@@ -169,6 +175,12 @@ async function commandToTool(client, noun, verb, flags) {
|
|
|
169
175
|
return invokeTool(client, "weirgate_get_proposal", { proposal_id: entry[1].proposal_id });
|
|
170
176
|
return localResult({ dry_run: true, operation: `${noun}:${verb}`, input: redact(entry[1]) });
|
|
171
177
|
}
|
|
178
|
+
if (noun === "models")
|
|
179
|
+
tableView = modelsTable;
|
|
180
|
+
if (noun === "audit" && flags.all) {
|
|
181
|
+
const input = entry[1];
|
|
182
|
+
return listAllAuditEvents(client, { app_id: input.app_id, action: input.action, since: input.since, until: input.until }, { cursor: input.cursor, pageSize: input.limit });
|
|
183
|
+
}
|
|
172
184
|
if (entry[0] === "__auth_presets")
|
|
173
185
|
return client.request("/v1/admin/auth-presets");
|
|
174
186
|
if (entry[0] === "__config_propose")
|
|
@@ -297,13 +309,13 @@ function printSuccess(result, flags) {
|
|
|
297
309
|
if (output === "yaml")
|
|
298
310
|
stdout.write(`${YAML.stringify(envelope)}`);
|
|
299
311
|
else if (output === "table")
|
|
300
|
-
stdout.write(`${human(result.data)}${flags["request-id"] ? `\nrequest_id: ${result.request_id}` : ""}\n`);
|
|
312
|
+
stdout.write(`${(tableView ?? human)(result.data)}${flags["request-id"] ? `\nrequest_id: ${result.request_id}` : ""}\n`);
|
|
301
313
|
else
|
|
302
314
|
stdout.write(`${JSON.stringify(envelope)}\n`);
|
|
303
315
|
}
|
|
304
316
|
function printError(error, flags) {
|
|
305
317
|
const typed = error instanceof WeirgateApiError ? error : new WeirgateApiError({ message: error instanceof Error ? error.message : String(error), errorType: "internal", status: 500, requestId: "local", apiVersion: API_VERSION });
|
|
306
|
-
const envelope = { ok: false, error: { type: typed.errorType, message: typed.message,
|
|
318
|
+
const envelope = { ok: false, error: { type: typed.errorType, message: typed.message, request_id: typed.requestId, ...(typed.detail ? { detail: typed.detail } : {}) }, api_version: typed.apiVersion };
|
|
307
319
|
if (flags.json || !process.stderr.isTTY)
|
|
308
320
|
process.stderr.write(`${JSON.stringify(envelope)}\n`);
|
|
309
321
|
else
|
|
@@ -342,10 +354,10 @@ function redact(value) { if (Array.isArray(value))
|
|
|
342
354
|
return value.map(redact); if (!value || typeof value !== "object")
|
|
343
355
|
return value; return Object.fromEntries(Object.entries(value).map(([key, item]) => [/^(key|secret|token|password|credential|authorization)$/i.test(key) ? key : key, /^(key|secret|token|password|credential|authorization)$/i.test(key) ? "[redacted]" : redact(item)])); }
|
|
344
356
|
function help() {
|
|
345
|
-
return `weirgate <noun> <verb> [flags]\n\nAuth: auth login|status|logout, mcp install, init\nApps: apps list|get|propose, config export|validate|propose|apply, auth-presets list\nConfig: features/tiers/rules/overrides/proposals, doctor, sandbox\nOps: usage, pricing-insights, users, user-tiers, events, audit, provider-keys, grants, docs\nOutput: --output json|table|yaml; --json; mutations use --idempotency-key\nAuth login: browser consent by default; --stdin accepts a pre-minted key\nSecrets: provider-keys put|rotate defaults to --browser; --stdin rejects pipes without --allow-pipe\n`;
|
|
357
|
+
return `weirgate <noun> <verb> [flags]\n\nAuth: auth login|status|logout, mcp install, init\nApps: apps list|get|propose, config export|validate|propose|apply, auth-presets list\nConfig: features/tiers/rules/overrides/proposals, doctor, sandbox\nOps: usage, pricing-insights, users, user-tiers, events, audit, provider-keys, grants, docs\nModels: models list [--upstream openrouter|openai|anthropic|google|xai] [--modality chat|embedding|image|audio]\nAudit: audit list [--limit n] [--cursor c] [--all] (--all follows next_cursor, up to ${AUDIT_ALL_CAP} events)\nOutput: --output json|table|yaml; --json; mutations use --idempotency-key\nAuth login: browser consent by default; --stdin accepts a pre-minted key\nSecrets: provider-keys put|rotate defaults to --browser; --stdin rejects pipes without --allow-pipe\n`;
|
|
346
358
|
}
|
|
347
359
|
function completion(shell) {
|
|
348
|
-
const commands = "auth mcp init apps config auth-presets features tiers rules overrides proposals usage pricing-insights users user-tiers events audit provider-keys grants doctor sandbox docs completion";
|
|
360
|
+
const commands = "auth mcp init apps config auth-presets models features tiers rules overrides proposals usage pricing-insights users user-tiers events audit provider-keys grants doctor sandbox docs completion";
|
|
349
361
|
if (shell === "zsh")
|
|
350
362
|
return `#compdef weirgate\n_arguments '1:command:(${commands})'\n`;
|
|
351
363
|
if (shell === "fish")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { record } from "../shared/api-client.js";
|
|
2
|
+
/** `weirgate audit list --all` stops after this many events; resume with `--cursor <next_cursor>`. */
|
|
3
|
+
export const AUDIT_ALL_CAP = 10_000;
|
|
4
|
+
const AUDIT_MAX_PAGE = 500;
|
|
5
|
+
/**
|
|
6
|
+
* Follows `pagination.next_cursor` from `cursor` (or the newest event) until the log ends or
|
|
7
|
+
* `cap` events are read. The first page asks for `include=total`, so the result says how many
|
|
8
|
+
* events match the filters. A capped result keeps `truncated: true` and the `next_cursor` to resume from.
|
|
9
|
+
*/
|
|
10
|
+
export async function listAllAuditEvents(client, filters, options = {}) {
|
|
11
|
+
const cap = options.cap ?? AUDIT_ALL_CAP;
|
|
12
|
+
const pageSize = Math.min(options.pageSize ?? AUDIT_MAX_PAGE, AUDIT_MAX_PAGE);
|
|
13
|
+
const events = [];
|
|
14
|
+
let cursor = options.cursor;
|
|
15
|
+
let total;
|
|
16
|
+
let pages = 0;
|
|
17
|
+
let last;
|
|
18
|
+
do {
|
|
19
|
+
const limit = Math.min(pageSize, cap - events.length);
|
|
20
|
+
last = await client.request("/v1/admin/audit", {
|
|
21
|
+
query: { ...filters, limit, cursor, ...(pages === 0 ? { include: "total" } : {}) },
|
|
22
|
+
});
|
|
23
|
+
pages += 1;
|
|
24
|
+
const page = record(last.data);
|
|
25
|
+
if (pages === 1)
|
|
26
|
+
total = page.pagination?.total;
|
|
27
|
+
events.push(...(page.data ?? []));
|
|
28
|
+
cursor = page.pagination?.truncated ? page.pagination.next_cursor ?? undefined : undefined;
|
|
29
|
+
} while (cursor && events.length < cap);
|
|
30
|
+
return {
|
|
31
|
+
...last,
|
|
32
|
+
data: {
|
|
33
|
+
data: events,
|
|
34
|
+
pagination: {
|
|
35
|
+
limit: pageSize,
|
|
36
|
+
returned: events.length,
|
|
37
|
+
pages,
|
|
38
|
+
cap,
|
|
39
|
+
truncated: cursor !== undefined,
|
|
40
|
+
next_cursor: cursor ?? null,
|
|
41
|
+
...(total === undefined ? {} : { total }),
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
const price = (value) => value === null ? "-" : `$${value}`;
|
|
47
|
+
const policyCell = (entry) => entry.allowed ? (entry.state === "allowed" ? "yes" : `yes (${entry.state})`) : "no";
|
|
48
|
+
/** The `--output table` view of `weirgate models list`: one line per row, prices in USD per 1M tokens. */
|
|
49
|
+
export function modelsTable(data) {
|
|
50
|
+
const catalog = record(data);
|
|
51
|
+
const rows = catalog.data ?? [];
|
|
52
|
+
const header = ["UPSTREAM", "MODEL", "IN/1M", "OUT/1M", "CONTEXT", "DEV KEY", "USER KEY"];
|
|
53
|
+
const lines = rows.map((row) => [
|
|
54
|
+
row.upstream,
|
|
55
|
+
row.model,
|
|
56
|
+
price(row.input_usd_per_million),
|
|
57
|
+
price(row.output_usd_per_million),
|
|
58
|
+
row.context_length === null ? "-" : String(row.context_length),
|
|
59
|
+
policyCell(row.policy.developer),
|
|
60
|
+
policyCell(row.policy.user),
|
|
61
|
+
]);
|
|
62
|
+
const widths = header.map((title, column) => Math.max(title.length, ...lines.map((line) => line[column].length)));
|
|
63
|
+
const format = (line) => line.map((cell, column) => column === line.length - 1 ? cell : cell.padEnd(widths[column])).join(" ");
|
|
64
|
+
const footer = `${rows.length} models · prices as of ${catalog.as_of ?? "unknown"}${catalog.stale ? " (stale)" : ""} · policy revision ${catalog.policy_revision}`;
|
|
65
|
+
return [format(header), ...lines.map(format), "", footer].join("\n");
|
|
66
|
+
}
|
package/dist/mcp/server.js
CHANGED
|
@@ -20,7 +20,7 @@ const rank = { read: 0, propose: 1, apply: 2 };
|
|
|
20
20
|
export function createMcpServer(auth) {
|
|
21
21
|
const server = new Server({ name: "weirgate", version: API_VERSION }, {
|
|
22
22
|
capabilities: { tools: { listChanged: false } },
|
|
23
|
-
instructions: "Operate Weirgate only through the
|
|
23
|
+
instructions: "Operate Weirgate only through the 2026-07-18 public API. Propose before apply. Provider keys are entered outside the model-facing MCP surface.",
|
|
24
24
|
});
|
|
25
25
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
26
26
|
tools: allowedTools({ scope: auth.identity.scope, tool_groups: auth.identity.tool_groups }).map((tool) => ({
|
|
@@ -60,7 +60,7 @@ export function createMcpServer(auth) {
|
|
|
60
60
|
}
|
|
61
61
|
catch (error) {
|
|
62
62
|
if (error instanceof WeirgateApiError)
|
|
63
|
-
return errorResult(error.errorType, error.message, error.requestId, error.
|
|
63
|
+
return errorResult(error.errorType, error.message, error.requestId, error.detail, error.apiVersion);
|
|
64
64
|
return errorResult("invalid_request", error instanceof Error ? error.message : String(error), "local");
|
|
65
65
|
}
|
|
66
66
|
});
|
|
@@ -75,8 +75,9 @@ function removeSecretValues(value) {
|
|
|
75
75
|
? []
|
|
76
76
|
: [[key, removeSecretValues(item)]]));
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
/** Mirrors the HTTP error envelope (`error.type`, `message`, `request_id`, `detail`), plus `api_version`. */
|
|
79
|
+
function errorResult(type, message, requestId, detail, apiVersion = API_VERSION) {
|
|
80
|
+
const body = { error: { type, message, request_id: requestId, ...(detail === undefined ? {} : { detail }) }, api_version: apiVersion };
|
|
80
81
|
return {
|
|
81
82
|
isError: true,
|
|
82
83
|
content: [{ type: "text", text: JSON.stringify(body) }],
|
|
@@ -5,7 +5,8 @@ export class WeirgateApiError extends Error {
|
|
|
5
5
|
status;
|
|
6
6
|
requestId;
|
|
7
7
|
apiVersion;
|
|
8
|
-
|
|
8
|
+
/** The API error's `detail` (for example `detail.reason`), as the HTTP envelope carries it. */
|
|
9
|
+
detail;
|
|
9
10
|
constructor(input) {
|
|
10
11
|
super(input.message);
|
|
11
12
|
this.name = "WeirgateApiError";
|
|
@@ -13,7 +14,7 @@ export class WeirgateApiError extends Error {
|
|
|
13
14
|
this.status = input.status;
|
|
14
15
|
this.requestId = input.requestId;
|
|
15
16
|
this.apiVersion = input.apiVersion;
|
|
16
|
-
this.
|
|
17
|
+
this.detail = input.detail;
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
export class AgentApiClient {
|
|
@@ -73,7 +74,7 @@ export class AgentApiClient {
|
|
|
73
74
|
status: 502,
|
|
74
75
|
requestId,
|
|
75
76
|
apiVersion,
|
|
76
|
-
|
|
77
|
+
detail: { expected: API_VERSION, received: apiVersion },
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
80
|
if (!response.ok) {
|
|
@@ -84,7 +85,7 @@ export class AgentApiClient {
|
|
|
84
85
|
status: response.status,
|
|
85
86
|
requestId,
|
|
86
87
|
apiVersion,
|
|
87
|
-
|
|
88
|
+
...(body?.error?.detail ? { detail: body.error.detail } : {}),
|
|
88
89
|
});
|
|
89
90
|
}
|
|
90
91
|
return { data: payload, request_id: requestId, api_version: API_VERSION };
|
package/dist/shared/tools.js
CHANGED
|
@@ -16,15 +16,17 @@ export const TOOL_DEFINITIONS = [
|
|
|
16
16
|
{ name: "weirgate_get_app", title: "Get app", description: "Get one visible app configuration.", scope: "read", group: "setup", inputSchema: objectSchema(app, appRequired) },
|
|
17
17
|
{ name: "weirgate_list_features", title: "List features", description: "List configured features for an app.", scope: "read", group: "setup", inputSchema: objectSchema(app, appRequired) },
|
|
18
18
|
{ name: "weirgate_get_feature", title: "Get feature", description: "Get a configured feature.", scope: "read", group: "setup", inputSchema: objectSchema({ ...app, feature_id: str() }, ["app_id", "feature_id"]) },
|
|
19
|
+
{ name: "weirgate_list_models", title: "List models", description: "List models a feature can use, with list prices per million tokens (USD), context length, and whether the provider policy allows each for the developer's key and the user's own key (with a reason when not). Use `upstream` and `model` from a row as the feature's values.", scope: "read", group: "setup", inputSchema: objectSchema({ upstream: { enum: ["openrouter", "openai", "anthropic", "google", "xai"], description: "Provider slot the feature uses" }, modality: { enum: ["chat", "embedding", "image", "audio"] } }) },
|
|
19
20
|
{ name: "weirgate_search_docs", title: "Search docs", description: "Search the authenticated canonical Markdown corpus.", scope: "read", group: "docs", inputSchema: objectSchema({ query: str(), section: str(), limit: integer() }, ["query"]) },
|
|
20
21
|
{ name: "weirgate_get_doc", title: "Get doc", description: "Read one canonical Markdown document.", scope: "read", group: "docs", inputSchema: objectSchema({ page_id: str() }, ["page_id"]) },
|
|
21
22
|
{ name: "weirgate_get_onboarding_state", title: "Get onboarding state", description: "Read durable onboarding readiness evidence.", scope: "read", group: "setup", inputSchema: objectSchema(app, appRequired) },
|
|
22
|
-
{ name: "weirgate_run_config_doctor", title: "Run config doctor", description: "Run non-billable configuration checks.", scope: "read", group: "setup", inputSchema: objectSchema({ ...app, checks: { type: "array", items: { enum: ["auth", "provider", "webhook"] } } }, appRequired) },
|
|
23
|
+
{ name: "weirgate_run_config_doctor", title: "Run config doctor", description: "Run non-billable configuration checks.", scope: "read", group: "setup", inputSchema: objectSchema({ ...app, checks: { type: "array", items: { enum: ["auth", "provider", "webhook", "payments"] } } }, appRequired) },
|
|
23
24
|
{ name: "weirgate_list_provider_key_slots", title: "List provider key slots", description: "List write-only provider slot metadata. No key values are returned.", scope: "read", group: "provider_keys", inputSchema: objectSchema(app) },
|
|
24
25
|
{ name: "weirgate_test_provider_key", title: "Test provider key", description: "Run a non-billable metadata probe for an existing provider slot.", scope: "read", group: "provider_keys", inputSchema: objectSchema({ ...app, provider: str() }, ["app_id", "provider"]) },
|
|
25
26
|
{ name: "weirgate_get_integration_snippet", title: "Get integration snippet", description: "Generate an HTTP/curl integration snippet.", scope: "read", group: "setup", inputSchema: objectSchema({ ...app, mode: { enum: ["http", "curl"] }, feature_id: str() }, appRequired) },
|
|
26
27
|
{ name: "weirgate_run_mock_call", title: "Run mock call", description: "Run a deterministic sandbox fixture; never invokes live inference.", scope: "apply", group: "sandbox", inputSchema: objectSchema({ ...app, fixture: str(), session_name: str(), idempotency_key: str() }, ["app_id", "fixture"]) },
|
|
27
|
-
{ name: "weirgate_query_usage", title: "Query usage", description: "Query windowed usage
|
|
28
|
+
{ name: "weirgate_query_usage", title: "Query usage", description: "Query windowed usage totals, groups, latency, refusals, and an optional day/hour series.", scope: "read", group: "usage", inputSchema: objectSchema({ ...app, since: str(), until: str(), group_by: { enum: ["feature", "user", "model", "funding_rail", "refusal_code"] }, bucket: { enum: ["day", "hour"] }, limit: integer() }, ["app_id", "since", "until"]) },
|
|
29
|
+
{ name: "weirgate_list_failures", title: "List failures", description: "List recent refused and failed metered requests, newest first, with request ids for request traces.", scope: "read", group: "usage", inputSchema: objectSchema({ ...app, since: str(), until: str(), cursor: str(), limit: integer() }, appRequired) },
|
|
28
30
|
{ name: "weirgate_get_pricing_insights", title: "Get pricing insights", description: "Read closed-window pricing evidence.", scope: "read", group: "usage", inputSchema: objectSchema({ ...app, since: str(), until: str() }, ["app_id", "since", "until"]) },
|
|
29
31
|
{ name: "weirgate_get_user_timeline", title: "Get user timeline", description: "Read one user's tenant-scoped operational timeline.", scope: "read", group: "usage", inputSchema: objectSchema({ ...app, external_id: str() }, ["app_id", "external_id"]) },
|
|
30
32
|
{ name: "weirgate_list_events", title: "List events", description: "List webhook delivery events for an app.", scope: "read", group: "webhooks", inputSchema: objectSchema({ ...app, status: str(), cursor: str(), limit: integer() }, appRequired) },
|
|
@@ -44,7 +46,7 @@ export const TOOL_DEFINITIONS = [
|
|
|
44
46
|
{ name: "weirgate_preview_rules", title: "Preview rules", description: "Preview rules against recent traffic and bind a content hash.", scope: "propose", group: "rules", inputSchema: objectSchema({ ...app, ruleset: document(), since: str(), until: str() }, ["app_id", "ruleset", "since", "until"]) },
|
|
45
47
|
{ name: "weirgate_propose_rules", title: "Propose rules", description: "Create a preview-hash-bound rules proposal.", scope: "propose", group: "rules", inputSchema: objectSchema({ ...app, ruleset: document(), preview_id: str() }, ["app_id", "ruleset", "preview_id"]) },
|
|
46
48
|
{ name: "weirgate_propose_user_override", title: "Propose user override", description: "Preview and propose a per-user velocity override.", scope: "propose", group: "rules", inputSchema: objectSchema({ ...app, external_id: str(), override: document(), since: str(), until: str() }, ["app_id", "external_id", "override"]) },
|
|
47
|
-
{ name: "weirgate_grant_allowance", title: "Grant allowance", description: "Grant units idempotently to a user.", scope: "apply", group: "credits", inputSchema: objectSchema({ ...app, external_id: str(), units:
|
|
49
|
+
{ name: "weirgate_grant_allowance", title: "Grant allowance", description: "Grant units idempotently to a user.", scope: "apply", group: "credits", inputSchema: objectSchema({ ...app, external_id: str(), units: { type: "number", exclusiveMinimum: 0 }, source: str(), idempotency_key: str() }, ["app_id", "external_id", "units", "idempotency_key"]) },
|
|
48
50
|
{ name: "weirgate_reverse_grant", title: "Reverse grant", description: "Reverse an allowance grant idempotently.", scope: "apply", group: "credits", inputSchema: objectSchema({ ...app, grant_id: str(), idempotency_key: str() }, ["app_id", "grant_id", "idempotency_key"]) },
|
|
49
51
|
{ name: "weirgate_assign_user_tier", title: "Assign user tier", description: "Schedule a configured user tier for the next monthly grant, with an optional current-period delta top-up.", scope: "apply", group: "plans", inputSchema: objectSchema({ ...app, external_id: str(), tier: str(), top_up_now: { type: "boolean" }, idempotency_key: str() }, ["app_id", "external_id", "tier", "idempotency_key"]) },
|
|
50
52
|
{ name: "weirgate_revert_user_tier", title: "Revert user tier", description: "Schedule a user to return to the app default tier, with an optional current-period delta top-up.", scope: "apply", group: "plans", inputSchema: objectSchema({ ...app, external_id: str(), top_up_now: { type: "boolean" }, idempotency_key: str() }, ["app_id", "external_id", "idempotency_key"]) },
|
|
@@ -106,10 +108,11 @@ export async function invokeTool(client, name, rawInput) {
|
|
|
106
108
|
const r = await client.request("/v1/admin/config");
|
|
107
109
|
return { ...r, data: record(findApp(r.data, String(input.app_id)).features)[String(input.feature_id)] };
|
|
108
110
|
}
|
|
111
|
+
case "weirgate_list_models": return client.request("/v1/admin/provider-policy/models", { query: q(input, ["upstream", "modality"]) });
|
|
109
112
|
case "weirgate_search_docs": return client.request("/v1/admin/docs/search", { query: q(input, ["query", "section", "limit"]) });
|
|
110
113
|
case "weirgate_get_doc": return client.request(`/v1/admin/docs/${pathPart(input.page_id)}`);
|
|
111
114
|
case "weirgate_get_onboarding_state": return client.request(`/v1/admin/apps/${a()}/readiness`);
|
|
112
|
-
case "weirgate_run_config_doctor": return client.request(`/v1/admin/apps/${a()}/doctor`, { method: "POST", body: { checks: input.checks ?? ["auth", "provider", "webhook"] } });
|
|
115
|
+
case "weirgate_run_config_doctor": return client.request(`/v1/admin/apps/${a()}/doctor`, { method: "POST", body: { checks: input.checks ?? ["auth", "provider", "webhook", "payments"] } });
|
|
113
116
|
case "weirgate_list_provider_key_slots": return client.request("/v1/admin/provider-keys", { query: q(input, ["app_id"]) });
|
|
114
117
|
case "weirgate_test_provider_key": return client.request(`/v1/admin/provider-keys/${pathPart(input.provider)}/health`, { method: "POST", query: { app_id: String(input.app_id) } });
|
|
115
118
|
case "weirgate_get_integration_snippet": return client.request(`/v1/admin/apps/${a()}/integration-snippet`, { query: q(input, ["mode", "feature_id"]) });
|
|
@@ -117,7 +120,8 @@ export async function invokeTool(client, name, rawInput) {
|
|
|
117
120
|
const session = await client.request(`/v1/admin/apps/${a()}/sandbox/sessions`, { method: "POST", body: { name: input.session_name ?? "agent mock call" }, idempotencyKey: input.idempotency_key });
|
|
118
121
|
return client.request(`/v1/admin/apps/${a()}/sandbox/sessions/${pathPart(session.data.id)}/runs`, { method: "POST", body: { fixture: input.fixture } });
|
|
119
122
|
}
|
|
120
|
-
case "weirgate_query_usage": return client.request(`/v1/admin/apps/${a()}/usage`, { query: q(input, ["since", "until", "group_by", "limit"]) });
|
|
123
|
+
case "weirgate_query_usage": return client.request(`/v1/admin/apps/${a()}/usage`, { query: q(input, ["since", "until", "group_by", "bucket", "limit"]) });
|
|
124
|
+
case "weirgate_list_failures": return client.request(`/v1/admin/apps/${a()}/failures`, { query: q(input, ["since", "until", "cursor", "limit"]) });
|
|
121
125
|
case "weirgate_get_pricing_insights": return client.request(`/v1/admin/apps/${a()}/pricing-insights`, { query: q(input, ["since", "until"]) });
|
|
122
126
|
case "weirgate_get_user_timeline": return client.request(`/v1/admin/apps/${a()}/users/${pathPart(input.external_id)}`);
|
|
123
127
|
case "weirgate_list_events": return client.request(`/v1/admin/apps/${a()}/webhooks/deliveries`, { query: q(input, ["status", "cursor", "limit"]) });
|
|
@@ -154,7 +158,7 @@ export async function invokeTool(client, name, rawInput) {
|
|
|
154
158
|
const preview = await client.request(`/v1/admin/apps/${a()}/rules:preview`, { method: "POST", body: { ruleset, since: input.since, until: input.until } });
|
|
155
159
|
return client.request(`/v1/admin/apps/${a()}/rules/proposals`, { method: "POST", body: { ruleset, preview_id: preview.data.preview_id } });
|
|
156
160
|
}
|
|
157
|
-
case "weirgate_grant_allowance": return client.request(`/v1/admin/apps/${a()}/users/${pathPart(input.external_id)}/grants`, { method: "POST", idempotencyKey: String(input.idempotency_key), body: { units: input.units,
|
|
161
|
+
case "weirgate_grant_allowance": return client.request(`/v1/admin/apps/${a()}/users/${pathPart(input.external_id)}/grants`, { method: "POST", idempotencyKey: String(input.idempotency_key), body: { units: input.units, ...(input.source === undefined ? {} : { source: input.source }) } });
|
|
158
162
|
case "weirgate_reverse_grant": return client.request(`/v1/admin/apps/${a()}/grants/${pathPart(input.grant_id)}/reverse`, { method: "POST", idempotencyKey: String(input.idempotency_key) });
|
|
159
163
|
case "weirgate_assign_user_tier": return client.request(`/v1/admin/apps/${a()}/users/${pathPart(input.external_id)}/tier`, { method: "PUT", idempotencyKey: String(input.idempotency_key), body: { tier: input.tier, top_up_now: input.top_up_now ?? false } });
|
|
160
164
|
case "weirgate_revert_user_tier": return client.request(`/v1/admin/apps/${a()}/users/${pathPart(input.external_id)}/tier`, { method: "DELETE", idempotencyKey: String(input.idempotency_key), body: { top_up_now: input.top_up_now ?? false } });
|