@deeprelay/mcp 0.0.1 → 0.1.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 +194 -1
- package/dist/auth.d.ts +52 -0
- package/dist/auth.js +122 -0
- package/dist/auth.js.map +1 -0
- package/dist/errors.d.ts +83 -0
- package/dist/errors.js +307 -0
- package/dist/errors.js.map +1 -0
- package/dist/guardrail/budget.d.ts +95 -0
- package/dist/guardrail/budget.js +225 -0
- package/dist/guardrail/budget.js.map +1 -0
- package/dist/guardrail/elicitation.d.ts +12 -0
- package/dist/guardrail/elicitation.js +79 -0
- package/dist/guardrail/elicitation.js.map +1 -0
- package/dist/guardrail/estimate.d.ts +67 -0
- package/dist/guardrail/estimate.js +171 -0
- package/dist/guardrail/estimate.js.map +1 -0
- package/dist/guardrail/handshake.d.ts +32 -0
- package/dist/guardrail/handshake.js +164 -0
- package/dist/guardrail/handshake.js.map +1 -0
- package/dist/guardrail/types.d.ts +61 -0
- package/dist/guardrail/types.js +10 -0
- package/dist/guardrail/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/roster.d.ts +36 -0
- package/dist/roster.js +130 -0
- package/dist/roster.js.map +1 -0
- package/dist/tools/crypto-deposit-gate.d.ts +21 -0
- package/dist/tools/crypto-deposit-gate.js +91 -0
- package/dist/tools/crypto-deposit-gate.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.js +108 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/readonly/define.d.ts +32 -0
- package/dist/tools/readonly/define.js +64 -0
- package/dist/tools/readonly/define.js.map +1 -0
- package/dist/tools/readonly/index.d.ts +7 -0
- package/dist/tools/readonly/index.js +286 -0
- package/dist/tools/readonly/index.js.map +1 -0
- package/dist/tools/readonly/usage.d.ts +29 -0
- package/dist/tools/readonly/usage.js +126 -0
- package/dist/tools/readonly/usage.js.map +1 -0
- package/dist/tools/readonly/video-reads.d.ts +11 -0
- package/dist/tools/readonly/video-reads.js +170 -0
- package/dist/tools/readonly/video-reads.js.map +1 -0
- package/dist/tools/result.d.ts +22 -0
- package/dist/tools/result.js +63 -0
- package/dist/tools/result.js.map +1 -0
- package/dist/tools/spend/define.d.ts +93 -0
- package/dist/tools/spend/define.js +286 -0
- package/dist/tools/spend/define.js.map +1 -0
- package/dist/tools/spend/index.d.ts +11 -0
- package/dist/tools/spend/index.js +163 -0
- package/dist/tools/spend/index.js.map +1 -0
- package/dist/tools/spend/media.d.ts +9 -0
- package/dist/tools/spend/media.js +164 -0
- package/dist/tools/spend/media.js.map +1 -0
- package/dist/tools/spend/pricing.d.ts +17 -0
- package/dist/tools/spend/pricing.js +58 -0
- package/dist/tools/spend/pricing.js.map +1 -0
- package/dist/tools/types.d.ts +45 -0
- package/dist/tools/types.js +3 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/write/define.d.ts +60 -0
- package/dist/tools/write/define.js +110 -0
- package/dist/tools/write/define.js.map +1 -0
- package/dist/tools/write/index.d.ts +12 -0
- package/dist/tools/write/index.js +159 -0
- package/dist/tools/write/index.js.map +1 -0
- package/dist/tools/write/payment-links.d.ts +3 -0
- package/dist/tools/write/payment-links.js +161 -0
- package/dist/tools/write/payment-links.js.map +1 -0
- package/dist/tools/write/spending-limit.d.ts +2 -0
- package/dist/tools/write/spending-limit.js +229 -0
- package/dist/tools/write/spending-limit.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.js +36 -0
- package/dist/version.js.map +1 -0
- package/package.json +39 -3
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readonlyTools = exports.videoReadTools = exports.VIDEO_TMP_DIR = exports.observeVideoJob = exports.READ_ANNOTATIONS = exports.defineTool = void 0;
|
|
4
|
+
exports.renderSessionBudget = renderSessionBudget;
|
|
5
|
+
// The free read tier (Phase 104, D-03/D-04/D-05/D-10). Authored fresh (D-12).
|
|
6
|
+
//
|
|
7
|
+
// Every tool here is a GET mapped to one @deeprelay/sdk method (D-05; the usage
|
|
8
|
+
// tool calls it once per modality when unfiltered, see usage.ts),
|
|
9
|
+
// built with defineTool (define.ts): no confirmation, no quote, no budget
|
|
10
|
+
// accounting, and every result goes through ok(), so credential fields are
|
|
11
|
+
// sanitized and key-shaped text is redacted before the agent sees it.
|
|
12
|
+
//
|
|
13
|
+
// There is no operations tool (D-04). The video reads, which are the only
|
|
14
|
+
// place a pending video reservation settles (D-07), live in video-reads.ts.
|
|
15
|
+
const sdk_1 = require("@deeprelay/sdk");
|
|
16
|
+
const zod_1 = require("zod");
|
|
17
|
+
const auth_js_1 = require("../../auth.js");
|
|
18
|
+
const errors_js_1 = require("../../errors.js");
|
|
19
|
+
const budget_js_1 = require("../../guardrail/budget.js");
|
|
20
|
+
const define_js_1 = require("./define.js");
|
|
21
|
+
const usage_js_1 = require("./usage.js");
|
|
22
|
+
const video_reads_js_1 = require("./video-reads.js");
|
|
23
|
+
var define_js_2 = require("./define.js");
|
|
24
|
+
Object.defineProperty(exports, "defineTool", { enumerable: true, get: function () { return define_js_2.defineTool; } });
|
|
25
|
+
Object.defineProperty(exports, "READ_ANNOTATIONS", { enumerable: true, get: function () { return define_js_2.READ_ANNOTATIONS; } });
|
|
26
|
+
var video_reads_js_2 = require("./video-reads.js");
|
|
27
|
+
Object.defineProperty(exports, "observeVideoJob", { enumerable: true, get: function () { return video_reads_js_2.observeVideoJob; } });
|
|
28
|
+
Object.defineProperty(exports, "VIDEO_TMP_DIR", { enumerable: true, get: function () { return video_reads_js_2.VIDEO_TMP_DIR; } });
|
|
29
|
+
Object.defineProperty(exports, "videoReadTools", { enumerable: true, get: function () { return video_reads_js_2.videoReadTools; } });
|
|
30
|
+
/** Render 1e-6-cent units as dollars, for the agent's summary to the user. */
|
|
31
|
+
function dollars(microCents) {
|
|
32
|
+
return `$${(microCents / (budget_js_1.MICRO_CENTS_PER_CENT * 100)).toFixed(2)}`;
|
|
33
|
+
}
|
|
34
|
+
/** Run a read whose 404 is a normal answer ("nothing configured"), not an error. */
|
|
35
|
+
async function orNotFound(call, onNotFound) {
|
|
36
|
+
try {
|
|
37
|
+
return await call();
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if ((0, errors_js_1.httpStatusOf)(err) === 404) {
|
|
41
|
+
return onNotFound();
|
|
42
|
+
}
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** The in-process session budget (D-06/D-08), in dollars, with pending video holds. */
|
|
47
|
+
function renderSessionBudget() {
|
|
48
|
+
const s = (0, budget_js_1.budgetStatus)();
|
|
49
|
+
return {
|
|
50
|
+
approved: s.approved,
|
|
51
|
+
limit: dollars(s.limitCents * budget_js_1.MICRO_CENTS_PER_CENT),
|
|
52
|
+
per_call_ceiling: dollars(s.ceilingMicroCents),
|
|
53
|
+
settled: dollars(s.settledMicroCents),
|
|
54
|
+
reserved: dollars(s.pendingMicroCents),
|
|
55
|
+
remaining: dollars(s.remainingMicroCents),
|
|
56
|
+
pending_video_reservations: (0, budget_js_1.pendingVideoReservations)().map((r) => ({
|
|
57
|
+
video_id: r.videoId,
|
|
58
|
+
reserved: dollars(r.microCents),
|
|
59
|
+
})),
|
|
60
|
+
note: s.approved
|
|
61
|
+
? "Spend tools draw from this budget. Pending video reservations settle when deeprelay_videos_get or deeprelay_videos_list observes the job finished."
|
|
62
|
+
: `No session budget approved yet. The first spend call asks the user to approve one (default ${dollars(s.limitCents * budget_js_1.MICRO_CENTS_PER_CENT)}).`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function balanceView(b) {
|
|
66
|
+
return {
|
|
67
|
+
balance_cents: b.balanceCents,
|
|
68
|
+
balance_dollars: b.balanceDollars,
|
|
69
|
+
auto_pay_enabled: b.autoPayEnabled,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function spendingLimitView(l) {
|
|
73
|
+
return {
|
|
74
|
+
monthly_limit_cents: l.monthlyLimitCents,
|
|
75
|
+
current_month_spend_cents: l.currentMonthSpendCents,
|
|
76
|
+
percent_used: l.percentUsed,
|
|
77
|
+
daily_limit_cents: l.dailyLimitCents ?? null,
|
|
78
|
+
current_day_spend_cents: l.currentDaySpendCents,
|
|
79
|
+
enforcement: l.enforcement,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const FREE = "Free: a read-only call with no charge and no confirmation.";
|
|
83
|
+
/** Diagnostics, catalog and usage reads. */
|
|
84
|
+
const coreReadTools = [
|
|
85
|
+
(0, define_js_1.defineTool)({
|
|
86
|
+
name: "deeprelay_auth_status",
|
|
87
|
+
title: "Check deeprelay credentials and session budget",
|
|
88
|
+
description: "Call this FIRST in a session. It confirms the configured deeprelay API key works and reports, in one call: " +
|
|
89
|
+
"the API base in use, the account's monthly/daily spending limit (null when none is configured), the prepaid " +
|
|
90
|
+
"balance, and this session's spend budget (approved or not, settled and reserved spend, remaining headroom, " +
|
|
91
|
+
`and any video jobs whose cost is still pending). ${FREE} It never returns the key itself.`,
|
|
92
|
+
inputSchema: {},
|
|
93
|
+
context: "checking the deeprelay credentials",
|
|
94
|
+
async call(_args, config, env) {
|
|
95
|
+
const billing = new sdk_1.BillingApi(config);
|
|
96
|
+
const limit = await orNotFound(() => billing.getSpendingLimit(), () => null);
|
|
97
|
+
const balance = await billing.getBalance();
|
|
98
|
+
return {
|
|
99
|
+
authenticated: true,
|
|
100
|
+
api_base: (0, auth_js_1.resolveBaseUrl)(env),
|
|
101
|
+
spending_limit: limit === null ? null : spendingLimitView(limit),
|
|
102
|
+
balance: balanceView(balance),
|
|
103
|
+
session_budget: renderSessionBudget(),
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
}),
|
|
107
|
+
(0, define_js_1.defineTool)({
|
|
108
|
+
name: "deeprelay_health",
|
|
109
|
+
title: "Check deeprelay API liveness",
|
|
110
|
+
description: "Is the deeprelay API up? Call this when other calls fail with network errors, to tell an outage apart from " +
|
|
111
|
+
`a key problem. It uses the unauthenticated liveness endpoint, so a wrong or revoked key does not affect it. ${FREE}`,
|
|
112
|
+
inputSchema: {},
|
|
113
|
+
context: "checking deeprelay API health",
|
|
114
|
+
keyless: true,
|
|
115
|
+
async call(_args, config, env) {
|
|
116
|
+
const health = await new sdk_1.MetaApi(config).getHealth();
|
|
117
|
+
return { status: health.status ?? "unknown", api_base: (0, auth_js_1.resolveBaseUrl)(env) };
|
|
118
|
+
},
|
|
119
|
+
}),
|
|
120
|
+
(0, define_js_1.defineTool)({
|
|
121
|
+
name: "deeprelay_models_list",
|
|
122
|
+
title: "List deeprelay models",
|
|
123
|
+
description: "List the models deeprelay serves, with their modality (chat, embedding, image, video) and pricing. Call this " +
|
|
124
|
+
"before any inference call to pick a model id and see what it costs; filter with `modality`. " +
|
|
125
|
+
FREE,
|
|
126
|
+
inputSchema: {
|
|
127
|
+
modality: zod_1.z.enum(sdk_1.ListModelsModalityEnum).optional().describe("Only models of this modality."),
|
|
128
|
+
},
|
|
129
|
+
context: "listing models",
|
|
130
|
+
async call(args, config) {
|
|
131
|
+
return new sdk_1.InferenceApi(config).listModels({ modality: args.modality });
|
|
132
|
+
},
|
|
133
|
+
}),
|
|
134
|
+
(0, define_js_1.defineTool)({
|
|
135
|
+
name: "deeprelay_models_get",
|
|
136
|
+
title: "Get one deeprelay model",
|
|
137
|
+
description: "Get one model by id: modality, parameters and pricing. Call this to confirm a model id exists and to read " +
|
|
138
|
+
`its exact rates before quoting a spend call. ${FREE}`,
|
|
139
|
+
inputSchema: {
|
|
140
|
+
id: zod_1.z.string().min(1).describe("Model id, as returned by deeprelay_models_list."),
|
|
141
|
+
},
|
|
142
|
+
context: "getting a model",
|
|
143
|
+
async call(args, config) {
|
|
144
|
+
return new sdk_1.InferenceApi(config).getModel({ id: args.id });
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
(0, define_js_1.defineTool)({
|
|
148
|
+
name: "deeprelay_inference_preflight",
|
|
149
|
+
title: "Preflight an inference call",
|
|
150
|
+
description: "Will a call to this model succeed for this account right now? Returns a verdict (ok, warn or block) with the " +
|
|
151
|
+
"reason and whether the account is funded, subscribed and plan-covered for the model. Call this before a spend " +
|
|
152
|
+
`call when unsure, instead of trying the call and failing. ${FREE}`,
|
|
153
|
+
inputSchema: {
|
|
154
|
+
model: zod_1.z.string().min(1).describe("Model id to check."),
|
|
155
|
+
},
|
|
156
|
+
context: "preflighting an inference call",
|
|
157
|
+
async call(args, config) {
|
|
158
|
+
return new sdk_1.InferenceApi(config).inferencePreflight({ model: args.model });
|
|
159
|
+
},
|
|
160
|
+
}),
|
|
161
|
+
(0, define_js_1.defineTool)({
|
|
162
|
+
name: "deeprelay_usage_get",
|
|
163
|
+
title: "Get deeprelay inference usage",
|
|
164
|
+
description: "How much serverless inference has this account used and spent, over time? Returns time-bucketed inference " +
|
|
165
|
+
"usage (hour, day, week or month buckets; default day over the last 30 days), one row per bucket, modality " +
|
|
166
|
+
"and model, with cost in cents and token/image counts, plus `total_cost_cents` and per-modality subtotals " +
|
|
167
|
+
"(`by_modality`). Filter with `modality` (chat, image, video, embedding) and/or `model`; with neither it " +
|
|
168
|
+
"covers all four modalities. Pages are followed automatically; `truncated: true` means the window was too " +
|
|
169
|
+
"large, so narrow `start`/`end`. Use this to answer spend questions about past days; for this session's " +
|
|
170
|
+
`spend use deeprelay_auth_status. ${FREE}`,
|
|
171
|
+
inputSchema: usage_js_1.usageInputSchema,
|
|
172
|
+
context: "getting usage",
|
|
173
|
+
async call(args, config) {
|
|
174
|
+
return (0, usage_js_1.getInferenceUsage)(args, config);
|
|
175
|
+
},
|
|
176
|
+
}),
|
|
177
|
+
];
|
|
178
|
+
const DEPOSITS_NOTE = "Crypto deposits are visible only on accounts with crypto deposits enabled. If the feature is not enabled the " +
|
|
179
|
+
"result is `{ crypto_deposits_enabled: false }`: that is a final answer, not an error, so do not retry.";
|
|
180
|
+
const NO_SECRET_NOTE = "The endpoint's signing secret is never returned by any read; it is shown once, when the endpoint is created.";
|
|
181
|
+
/** Webhook endpoints without their signing secret, even if the API sent one. */
|
|
182
|
+
function withoutSecret(endpoint) {
|
|
183
|
+
const { secret: _secret, ...rest } = endpoint;
|
|
184
|
+
return rest;
|
|
185
|
+
}
|
|
186
|
+
/** Billing and webhook reads. */
|
|
187
|
+
const billingReadTools = [
|
|
188
|
+
(0, define_js_1.defineTool)({
|
|
189
|
+
name: "deeprelay_balance_get",
|
|
190
|
+
title: "Get deeprelay balance",
|
|
191
|
+
description: "How much prepaid credit does the account have? Returns the balance in cents and dollars and the auto-pay " +
|
|
192
|
+
`settings. Call this before a large spend, or after a 402 insufficient-balance error. ${FREE}`,
|
|
193
|
+
inputSchema: {},
|
|
194
|
+
context: "getting the balance",
|
|
195
|
+
async call(_args, config) {
|
|
196
|
+
return new sdk_1.BillingApi(config).getBalance();
|
|
197
|
+
},
|
|
198
|
+
}),
|
|
199
|
+
(0, define_js_1.defineTool)({
|
|
200
|
+
name: "deeprelay_spending_limit_get",
|
|
201
|
+
title: "Get the deeprelay spending limit",
|
|
202
|
+
description: "What is the account's monthly (and optional daily) spending limit, and how much of it is used? When no limit " +
|
|
203
|
+
"is configured the result is `{ configured: false }`, which is a normal answer. To lower the limit use " +
|
|
204
|
+
`deeprelay_spending_limit_update. ${FREE}`,
|
|
205
|
+
inputSchema: {},
|
|
206
|
+
context: "getting the spending limit",
|
|
207
|
+
async call(_args, config) {
|
|
208
|
+
return orNotFound(async () => ({ configured: true, ...(await new sdk_1.BillingApi(config).getSpendingLimit()) }), () => ({ configured: false }));
|
|
209
|
+
},
|
|
210
|
+
}),
|
|
211
|
+
(0, define_js_1.defineTool)({
|
|
212
|
+
name: "deeprelay_subscription_get",
|
|
213
|
+
title: "Get the deeprelay subscription",
|
|
214
|
+
description: "Is the account subscribed, to which plan, and how much of the plan's quota is used this period? Call this to " +
|
|
215
|
+
`explain a plan-coverage verdict from deeprelay_inference_preflight. ${FREE}`,
|
|
216
|
+
inputSchema: {},
|
|
217
|
+
context: "getting the subscription",
|
|
218
|
+
async call(_args, config) {
|
|
219
|
+
return new sdk_1.BillingApi(config).getSubscription();
|
|
220
|
+
},
|
|
221
|
+
}),
|
|
222
|
+
(0, define_js_1.defineTool)({
|
|
223
|
+
name: "deeprelay_deposits_list",
|
|
224
|
+
title: "List crypto deposits",
|
|
225
|
+
description: `List the account's crypto deposits and the minimum deposit. ${DEPOSITS_NOTE} ${FREE}`,
|
|
226
|
+
inputSchema: {},
|
|
227
|
+
context: "listing crypto deposits",
|
|
228
|
+
async call(_args, config) {
|
|
229
|
+
return orNotFound(async () => ({ crypto_deposits_enabled: true, ...(await new sdk_1.BillingApi(config).listDeposits()) }), () => ({ crypto_deposits_enabled: false }));
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
232
|
+
(0, define_js_1.defineTool)({
|
|
233
|
+
name: "deeprelay_deposits_get",
|
|
234
|
+
title: "Get a crypto deposit",
|
|
235
|
+
description: `Get one crypto deposit by id: status, chain, asset, amount and credited cents. ${DEPOSITS_NOTE} ` +
|
|
236
|
+
FREE,
|
|
237
|
+
inputSchema: {
|
|
238
|
+
id: zod_1.z.string().min(1).describe("Deposit id, as returned by deeprelay_deposits_list."),
|
|
239
|
+
},
|
|
240
|
+
context: "getting a crypto deposit",
|
|
241
|
+
async call(args, config) {
|
|
242
|
+
return orNotFound(async () => ({ crypto_deposits_enabled: true, ...(await new sdk_1.BillingApi(config).getDeposit({ id: args.id })) }), () => ({ crypto_deposits_enabled: false }));
|
|
243
|
+
},
|
|
244
|
+
}),
|
|
245
|
+
(0, define_js_1.defineTool)({
|
|
246
|
+
name: "deeprelay_referrals_get",
|
|
247
|
+
title: "Get the deeprelay referral link",
|
|
248
|
+
description: "Get the account's referral code and invite link, the program terms (reward amounts, qualifying spend, hold " +
|
|
249
|
+
`days) and the referral stats. Call this when the user asks how to invite someone or earn credit. ${FREE}`,
|
|
250
|
+
inputSchema: {},
|
|
251
|
+
context: "getting the referral program",
|
|
252
|
+
async call(_args, config) {
|
|
253
|
+
return new sdk_1.BillingApi(config).getReferral();
|
|
254
|
+
},
|
|
255
|
+
}),
|
|
256
|
+
(0, define_js_1.defineTool)({
|
|
257
|
+
name: "deeprelay_webhooks_list",
|
|
258
|
+
title: "List webhook endpoints",
|
|
259
|
+
description: "List the account's webhook endpoints: id, URL, subscribed event types and whether each is enabled. Pass " +
|
|
260
|
+
`\`cursor\` from \`nextCursor\` to page. ${NO_SECRET_NOTE} ${FREE}`,
|
|
261
|
+
inputSchema: {
|
|
262
|
+
cursor: zod_1.z.string().min(1).optional().describe("Page cursor from a previous result's nextCursor."),
|
|
263
|
+
limit: zod_1.z.number().int().min(1).max(100).optional().describe("Endpoints per page (1-100)."),
|
|
264
|
+
},
|
|
265
|
+
context: "listing webhook endpoints",
|
|
266
|
+
async call(args, config) {
|
|
267
|
+
const page = await new sdk_1.WebhooksApi(config).listWebhookEndpoints({ cursor: args.cursor, limit: args.limit });
|
|
268
|
+
return { ...page, data: page.data.map(withoutSecret) };
|
|
269
|
+
},
|
|
270
|
+
}),
|
|
271
|
+
(0, define_js_1.defineTool)({
|
|
272
|
+
name: "deeprelay_webhooks_get",
|
|
273
|
+
title: "Get a webhook endpoint",
|
|
274
|
+
description: `Get one webhook endpoint by id: URL, event types and enabled flag. ${NO_SECRET_NOTE} ${FREE}`,
|
|
275
|
+
inputSchema: {
|
|
276
|
+
id: zod_1.z.string().min(1).describe("Webhook endpoint id, as returned by deeprelay_webhooks_list."),
|
|
277
|
+
},
|
|
278
|
+
context: "getting a webhook endpoint",
|
|
279
|
+
async call(args, config) {
|
|
280
|
+
return withoutSecret(await new sdk_1.WebhooksApi(config).getWebhookEndpoint({ id: args.id }));
|
|
281
|
+
},
|
|
282
|
+
}),
|
|
283
|
+
];
|
|
284
|
+
/** The full read tier. Every name in roster READ_TOOLS appears here exactly once. */
|
|
285
|
+
exports.readonlyTools = [...coreReadTools, ...billingReadTools, ...video_reads_js_1.videoReadTools];
|
|
286
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/readonly/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Configuration } from "@deeprelay/sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
/** Rows per page requested from the API (its maximum). */
|
|
4
|
+
export declare const USAGE_PAGE_SIZE = 100;
|
|
5
|
+
/** Pages followed per query before the result is reported as truncated. */
|
|
6
|
+
export declare const USAGE_MAX_PAGES = 10;
|
|
7
|
+
/** Every modality, in the order the fan-out queries them. */
|
|
8
|
+
export declare const USAGE_MODALITIES: ("chat" | "image" | "video" | "embedding")[];
|
|
9
|
+
export declare const usageInputSchema: {
|
|
10
|
+
modality: z.ZodOptional<z.ZodEnum<{
|
|
11
|
+
readonly Chat: "chat";
|
|
12
|
+
readonly Image: "image";
|
|
13
|
+
readonly Video: "video";
|
|
14
|
+
readonly Embedding: "embedding";
|
|
15
|
+
}>>;
|
|
16
|
+
model: z.ZodOptional<z.ZodString>;
|
|
17
|
+
bucket: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
readonly Hour: "hour";
|
|
19
|
+
readonly Day: "day";
|
|
20
|
+
readonly Week: "week";
|
|
21
|
+
readonly Month: "month";
|
|
22
|
+
}>>;
|
|
23
|
+
start: z.ZodOptional<z.ZodISODateTime>;
|
|
24
|
+
end: z.ZodOptional<z.ZodISODateTime>;
|
|
25
|
+
};
|
|
26
|
+
type UsageArgs = z.infer<z.ZodObject<typeof usageInputSchema>>;
|
|
27
|
+
/** Read inference usage: one query when filtered, one per modality otherwise. */
|
|
28
|
+
export declare function getInferenceUsage(args: UsageArgs, config: Configuration): Promise<Record<string, unknown>>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usageInputSchema = exports.USAGE_MODALITIES = exports.USAGE_MAX_PAGES = exports.USAGE_PAGE_SIZE = void 0;
|
|
4
|
+
exports.getInferenceUsage = getInferenceUsage;
|
|
5
|
+
// deeprelay_usage_get: serverless inference usage (Phase 104 follow-up).
|
|
6
|
+
//
|
|
7
|
+
// GET /v1/usage has two row shapes. With `modality` or `model` set it returns
|
|
8
|
+
// inference-usage rows (one per bucket × modality × model); with neither it
|
|
9
|
+
// returns GPU-instance usage, which deeprelay does not surface (no GPU supply
|
|
10
|
+
// on the platform), so an unfiltered call reads as "no usage" even for an
|
|
11
|
+
// account that spent money on inference. There is no single call for every
|
|
12
|
+
// modality, so with no filter this tool asks once per modality and merges.
|
|
13
|
+
//
|
|
14
|
+
// It never sends `group_by` (instance/GPU split) and drops `gpu_seconds`,
|
|
15
|
+
// which is always 0 on inference rows.
|
|
16
|
+
const sdk_1 = require("@deeprelay/sdk");
|
|
17
|
+
const zod_1 = require("zod");
|
|
18
|
+
/** Rows per page requested from the API (its maximum). */
|
|
19
|
+
exports.USAGE_PAGE_SIZE = 100;
|
|
20
|
+
/** Pages followed per query before the result is reported as truncated. */
|
|
21
|
+
exports.USAGE_MAX_PAGES = 10;
|
|
22
|
+
/** Every modality, in the order the fan-out queries them. */
|
|
23
|
+
exports.USAGE_MODALITIES = Object.values(sdk_1.ListUsageModalityEnum);
|
|
24
|
+
exports.usageInputSchema = {
|
|
25
|
+
modality: zod_1.z
|
|
26
|
+
.enum(sdk_1.ListUsageModalityEnum)
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Only this modality (chat, image, video or embedding). Omit for all four."),
|
|
29
|
+
model: zod_1.z.string().min(1).optional().describe("Only this model id, as returned by deeprelay_models_list."),
|
|
30
|
+
bucket: zod_1.z.enum(sdk_1.ListUsageBucketEnum).default("day").describe("Bucket width (hour, day, week or month)."),
|
|
31
|
+
start: zod_1.z.iso
|
|
32
|
+
.datetime({ offset: true })
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("ISO-8601 start of the window (inclusive). Default: 30 days before end."),
|
|
35
|
+
end: zod_1.z.iso.datetime({ offset: true }).optional().describe("ISO-8601 end of the window (exclusive). Default: now."),
|
|
36
|
+
};
|
|
37
|
+
/** Sum cents without binary-float noise (costs can be fractional cents). */
|
|
38
|
+
function addCents(a, b) {
|
|
39
|
+
return Math.round((a + b) * 1e6) / 1e6;
|
|
40
|
+
}
|
|
41
|
+
function toRow(b, fallbackModality) {
|
|
42
|
+
const start = b.bucketStart instanceof Date ? b.bucketStart.toISOString() : String(b.bucketStart);
|
|
43
|
+
return {
|
|
44
|
+
bucket_start: start,
|
|
45
|
+
modality: b.modality ?? fallbackModality ?? null,
|
|
46
|
+
model: b.model ?? null,
|
|
47
|
+
cost_cents: b.costCents,
|
|
48
|
+
prompt_tokens: b.promptTokens ?? null,
|
|
49
|
+
completion_tokens: b.completionTokens ?? null,
|
|
50
|
+
image_count: b.imageCount ?? null,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** One filtered query, following cursors up to USAGE_MAX_PAGES. */
|
|
54
|
+
async function fetchAll(api, args, filter) {
|
|
55
|
+
const rows = [];
|
|
56
|
+
let cursor;
|
|
57
|
+
for (let pageNo = 0; pageNo < exports.USAGE_MAX_PAGES; pageNo += 1) {
|
|
58
|
+
const page = await api.listUsage({
|
|
59
|
+
bucket: args.bucket,
|
|
60
|
+
start: args.start === undefined ? undefined : new Date(args.start),
|
|
61
|
+
end: args.end === undefined ? undefined : new Date(args.end),
|
|
62
|
+
cursor,
|
|
63
|
+
limit: exports.USAGE_PAGE_SIZE,
|
|
64
|
+
modality: filter.modality,
|
|
65
|
+
model: filter.model,
|
|
66
|
+
});
|
|
67
|
+
rows.push(...page.data.map((b) => toRow(b, filter.modality)));
|
|
68
|
+
if (page.nextCursor === null || page.nextCursor === undefined || page.nextCursor === "") {
|
|
69
|
+
return { rows, truncated: false };
|
|
70
|
+
}
|
|
71
|
+
cursor = page.nextCursor;
|
|
72
|
+
}
|
|
73
|
+
return { rows, truncated: true };
|
|
74
|
+
}
|
|
75
|
+
/** Read inference usage: one query when filtered, one per modality otherwise. */
|
|
76
|
+
async function getInferenceUsage(args, config) {
|
|
77
|
+
const api = new sdk_1.UsageApi(config);
|
|
78
|
+
const filtered = args.modality !== undefined || args.model !== undefined;
|
|
79
|
+
const queries = filtered
|
|
80
|
+
? [{ modality: args.modality, model: args.model }]
|
|
81
|
+
: exports.USAGE_MODALITIES.map((modality) => ({ modality }));
|
|
82
|
+
const results = await Promise.all(queries.map((q) => fetchAll(api, args, q)));
|
|
83
|
+
const rows = results.flatMap((r) => r.rows);
|
|
84
|
+
// Newest bucket first (the API's order), then by modality and model.
|
|
85
|
+
rows.sort((a, b) => b.bucket_start.localeCompare(a.bucket_start) ||
|
|
86
|
+
(a.modality ?? "").localeCompare(b.modality ?? "") ||
|
|
87
|
+
(a.model ?? "").localeCompare(b.model ?? ""));
|
|
88
|
+
const byModality = {};
|
|
89
|
+
// With no filter every modality was asked, so report the zeros too.
|
|
90
|
+
if (!filtered) {
|
|
91
|
+
for (const m of exports.USAGE_MODALITIES)
|
|
92
|
+
byModality[m] = { cost_cents: 0, rows: 0 };
|
|
93
|
+
}
|
|
94
|
+
let total = 0;
|
|
95
|
+
for (const row of rows) {
|
|
96
|
+
const key = row.modality ?? "unknown";
|
|
97
|
+
const sub = (byModality[key] ??= { cost_cents: 0, rows: 0 });
|
|
98
|
+
sub.cost_cents = addCents(sub.cost_cents, row.cost_cents);
|
|
99
|
+
sub.rows += 1;
|
|
100
|
+
total = addCents(total, row.cost_cents);
|
|
101
|
+
}
|
|
102
|
+
const truncatedQueries = queries.filter((_, i) => results[i].truncated);
|
|
103
|
+
const truncated = truncatedQueries.length > 0;
|
|
104
|
+
return {
|
|
105
|
+
usage_kind: "inference",
|
|
106
|
+
note: "Serverless inference usage (what this account is billed for), from GET /v1/usage filtered by modality/model. " +
|
|
107
|
+
(filtered
|
|
108
|
+
? "One filtered query."
|
|
109
|
+
: `No modality or model was given, so this merges one query per modality (${exports.USAGE_MODALITIES.join(", ")}).`) +
|
|
110
|
+
(truncated
|
|
111
|
+
? ` TRUNCATED: stopped after ${exports.USAGE_MAX_PAGES} pages of ${exports.USAGE_PAGE_SIZE} rows for ` +
|
|
112
|
+
truncatedQueries.map((q) => q.modality ?? q.model ?? "the query").join(", ") +
|
|
113
|
+
"; totals cover only the rows returned. Narrow start/end or use a wider bucket."
|
|
114
|
+
: ""),
|
|
115
|
+
filter: { modality: args.modality ?? null, model: args.model ?? null },
|
|
116
|
+
bucket: args.bucket,
|
|
117
|
+
start: args.start ?? null,
|
|
118
|
+
end: args.end ?? null,
|
|
119
|
+
total_cost_cents: total,
|
|
120
|
+
total_cost_dollars: `$${(total / 100).toFixed(2)}`,
|
|
121
|
+
by_modality: byModality,
|
|
122
|
+
truncated,
|
|
123
|
+
rows,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/tools/readonly/usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type VideoJob } from "@deeprelay/sdk";
|
|
2
|
+
import type { ToolDefinition } from "../types.js";
|
|
3
|
+
/** Where deeprelay_videos_content saves when no output_path is given. */
|
|
4
|
+
export declare const VIDEO_TMP_DIR: string;
|
|
5
|
+
export type SessionSettlement = "settled" | "released" | "pending" | "not_tracked";
|
|
6
|
+
/**
|
|
7
|
+
* Settle (or release) this session's reservation for the job, then return the
|
|
8
|
+
* job's public fields plus what happened to the reservation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function observeVideoJob(job: VideoJob): Record<string, unknown>;
|
|
11
|
+
export declare const videoReadTools: ToolDefinition[];
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.videoReadTools = exports.VIDEO_TMP_DIR = void 0;
|
|
4
|
+
exports.observeVideoJob = observeVideoJob;
|
|
5
|
+
// Video reads: list, get and content (Phase 104 D-02/D-07). Authored fresh (D-12).
|
|
6
|
+
//
|
|
7
|
+
// Video generation is asynchronous. deeprelay_videos_create reserves a floor
|
|
8
|
+
// estimate against the session budget keyed by the video id, and the actual
|
|
9
|
+
// charge (cost_cents) is only known once the job reaches `completed`. These
|
|
10
|
+
// reads are the only place that reservation resolves: every job they observe
|
|
11
|
+
// goes through observeVideoJob → settleVideo, which
|
|
12
|
+
//
|
|
13
|
+
// completed → settles at cost_cents (the floor if absent)
|
|
14
|
+
// failed | cancelled | expired → releases the hold (never billed)
|
|
15
|
+
// queued | in_progress → leaves it pending
|
|
16
|
+
//
|
|
17
|
+
// settleVideo drops the reservation on first settlement, so observing the same
|
|
18
|
+
// finished job again reports "not_tracked" and never double-counts (T-104-21).
|
|
19
|
+
//
|
|
20
|
+
// Content is delivered as a file on the MCP host, never encoded inline: an MP4
|
|
21
|
+
// can be tens of MB and would flood the agent's context (T-104-20). The stdio
|
|
22
|
+
// server runs as the user, so an agent-chosen path is the user's own
|
|
23
|
+
// filesystem; it must be absolute (T-104-19). The write uses flag "wx", so an
|
|
24
|
+
// existing file is never overwritten: this tool advertises readOnlyHint, and
|
|
25
|
+
// clobbering a file the agent happened to name would contradict that.
|
|
26
|
+
const promises_1 = require("node:fs/promises");
|
|
27
|
+
const node_os_1 = require("node:os");
|
|
28
|
+
const node_path_1 = require("node:path");
|
|
29
|
+
const sdk_1 = require("@deeprelay/sdk");
|
|
30
|
+
const zod_1 = require("zod");
|
|
31
|
+
const budget_js_1 = require("../../guardrail/budget.js");
|
|
32
|
+
const define_js_1 = require("./define.js");
|
|
33
|
+
/** Where deeprelay_videos_content saves when no output_path is given. */
|
|
34
|
+
exports.VIDEO_TMP_DIR = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "deeprelay-mcp");
|
|
35
|
+
const FREE = "Free: a read-only call with no charge and no confirmation.";
|
|
36
|
+
function isTracked(videoId) {
|
|
37
|
+
return (0, budget_js_1.pendingVideoReservations)().some((r) => r.videoId === videoId);
|
|
38
|
+
}
|
|
39
|
+
function iso(unixSeconds) {
|
|
40
|
+
return typeof unixSeconds === "number" && Number.isFinite(unixSeconds)
|
|
41
|
+
? new Date(unixSeconds * 1000).toISOString()
|
|
42
|
+
: null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Settle (or release) this session's reservation for the job, then return the
|
|
46
|
+
* job's public fields plus what happened to the reservation.
|
|
47
|
+
*/
|
|
48
|
+
function observeVideoJob(job) {
|
|
49
|
+
const tracked = isTracked(job.id);
|
|
50
|
+
const outcome = (0, budget_js_1.settleVideo)(job.id, { status: job.status, costCents: job.costCents });
|
|
51
|
+
let settlement;
|
|
52
|
+
if (!tracked) {
|
|
53
|
+
settlement = "not_tracked";
|
|
54
|
+
}
|
|
55
|
+
else if (!outcome.settled) {
|
|
56
|
+
settlement = "pending";
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
settlement = job.status === "completed" ? "settled" : "released";
|
|
60
|
+
}
|
|
61
|
+
return {
|
|
62
|
+
id: job.id,
|
|
63
|
+
model: job.model,
|
|
64
|
+
status: job.status,
|
|
65
|
+
progress: job.progress,
|
|
66
|
+
size: job.size ?? null,
|
|
67
|
+
seconds: job.seconds ?? null,
|
|
68
|
+
created_at: iso(job.createdAt),
|
|
69
|
+
completed_at: iso(job.completedAt),
|
|
70
|
+
expires_at: iso(job.expiresAt),
|
|
71
|
+
error: job.error ?? null,
|
|
72
|
+
cost_cents: job.costCents ?? null,
|
|
73
|
+
session_settlement: settlement,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/** A filesystem-safe default file name for a video id. */
|
|
77
|
+
function defaultPath(videoId) {
|
|
78
|
+
const safe = videoId.replace(/[^A-Za-z0-9._-]/g, "_").replace(/^\.+/, "_");
|
|
79
|
+
return (0, node_path_1.join)(exports.VIDEO_TMP_DIR, `${safe || "video"}.mp4`);
|
|
80
|
+
}
|
|
81
|
+
exports.videoReadTools = [
|
|
82
|
+
(0, define_js_1.defineTool)({
|
|
83
|
+
name: "deeprelay_videos_list",
|
|
84
|
+
title: "List video generation jobs",
|
|
85
|
+
description: "List this account's video generation jobs, newest first, with status, progress and cost_cents once finished. " +
|
|
86
|
+
"Page with `after` (the last id seen). Observing a finished job here also settles this session's video " +
|
|
87
|
+
`reservation for it, like deeprelay_videos_get. ${FREE}`,
|
|
88
|
+
inputSchema: {
|
|
89
|
+
after: zod_1.z.string().min(1).optional().describe("Return jobs after this video id (pagination)."),
|
|
90
|
+
limit: zod_1.z.number().int().min(1).max(100).default(20).describe("Jobs per page (1-100)."),
|
|
91
|
+
},
|
|
92
|
+
context: "listing video jobs",
|
|
93
|
+
async call(args, config) {
|
|
94
|
+
const page = await new sdk_1.InferenceApi(config).listVideos({ after: args.after, limit: args.limit });
|
|
95
|
+
return { data: page.data.map((job) => observeVideoJob(job)), has_more: page.hasMore };
|
|
96
|
+
},
|
|
97
|
+
}),
|
|
98
|
+
(0, define_js_1.defineTool)({
|
|
99
|
+
name: "deeprelay_videos_get",
|
|
100
|
+
title: "Get a video generation job",
|
|
101
|
+
description: "Poll one video job: status (queued, in_progress, completed, failed, cancelled, expired), progress, and " +
|
|
102
|
+
"cost_cents once completed. Calling this after the job completes is what settles this session's video " +
|
|
103
|
+
"reservation and reports the actual charge; a failed, cancelled or expired job releases it unbilled. When " +
|
|
104
|
+
`status is completed, download the file with deeprelay_videos_content. ${FREE}`,
|
|
105
|
+
inputSchema: {
|
|
106
|
+
id: zod_1.z.string().min(1).describe("Video job id, as returned by deeprelay_videos_create."),
|
|
107
|
+
},
|
|
108
|
+
context: "getting a video job",
|
|
109
|
+
async call(args, config) {
|
|
110
|
+
return observeVideoJob(await new sdk_1.InferenceApi(config).getVideo({ id: args.id }));
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
(0, define_js_1.defineTool)({
|
|
114
|
+
name: "deeprelay_videos_content",
|
|
115
|
+
title: "Download a generated video",
|
|
116
|
+
description: "Download a completed video's MP4 to a file on this machine and return its path and size (the video is never " +
|
|
117
|
+
"returned inline). Pass `output_path` as an absolute file path, or omit it to save under the system temp " +
|
|
118
|
+
"directory. It never overwrites an existing file: if the path exists the call is refused and you must choose a " +
|
|
119
|
+
"new path. Also settles this session's reservation for the job. Artifacts are kept for 24 hours after " +
|
|
120
|
+
`completion. ${FREE}`,
|
|
121
|
+
inputSchema: {
|
|
122
|
+
id: zod_1.z.string().min(1).describe("Video job id."),
|
|
123
|
+
output_path: zod_1.z
|
|
124
|
+
.string()
|
|
125
|
+
.min(1)
|
|
126
|
+
.refine((p) => (0, node_path_1.isAbsolute)(p), { message: "output_path must be an absolute file path" })
|
|
127
|
+
.optional()
|
|
128
|
+
.describe("Absolute path to write the MP4 to. Default: <system temp>/deeprelay-mcp/<id>.mp4"),
|
|
129
|
+
},
|
|
130
|
+
context: "downloading a video",
|
|
131
|
+
async call(args, config) {
|
|
132
|
+
const api = new sdk_1.InferenceApi(config);
|
|
133
|
+
const job = observeVideoJob(await api.getVideo({ id: args.id }));
|
|
134
|
+
if (job.status !== "completed") {
|
|
135
|
+
return {
|
|
136
|
+
video_id: args.id,
|
|
137
|
+
downloaded: false,
|
|
138
|
+
status: job.status,
|
|
139
|
+
session_settlement: job.session_settlement,
|
|
140
|
+
next: job.status === "queued" || job.status === "in_progress"
|
|
141
|
+
? "The video is not ready. Poll deeprelay_videos_get until status is completed, then call this again."
|
|
142
|
+
: `The video is ${String(job.status)} and has no downloadable content.`,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const blob = await api.getVideoContent({ id: args.id });
|
|
146
|
+
const bytes = Buffer.from(await blob.arrayBuffer());
|
|
147
|
+
const target = args.output_path ?? defaultPath(args.id);
|
|
148
|
+
await (0, promises_1.mkdir)((0, node_path_1.dirname)(target), { recursive: true });
|
|
149
|
+
try {
|
|
150
|
+
await (0, promises_1.writeFile)(target, bytes, { mode: 0o600, flag: "wx" });
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
if (err?.code === "EEXIST") {
|
|
154
|
+
throw new define_js_1.ReadRefusal(`Refused to download video ${args.id}: a file already exists at ${target} and this tool never ` +
|
|
155
|
+
"overwrites files. Call deeprelay_videos_content again with a new absolute output_path.");
|
|
156
|
+
}
|
|
157
|
+
throw err;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
video_id: args.id,
|
|
161
|
+
saved_to: target,
|
|
162
|
+
bytes: bytes.length,
|
|
163
|
+
mime_type: "video/mp4",
|
|
164
|
+
cost_cents: job.cost_cents,
|
|
165
|
+
session_settlement: job.session_settlement,
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
}),
|
|
169
|
+
];
|
|
170
|
+
//# sourceMappingURL=video-reads.js.map
|