@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
package/dist/index.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SERVER_NAME = void 0;
|
|
5
|
+
exports.createServer = createServer;
|
|
6
|
+
exports.buildServer = buildServer;
|
|
7
|
+
exports.main = main;
|
|
8
|
+
// Entry point for the deeprelay MCP server (Phase 104, D-15). Authored fresh
|
|
9
|
+
// (D-12).
|
|
10
|
+
//
|
|
11
|
+
// The server speaks MCP over stdio: the client spawns this file and exchanges
|
|
12
|
+
// JSON-RPC on stdin/stdout. stdout is therefore a protocol channel. Every
|
|
13
|
+
// human-facing line goes to stderr, or it corrupts the framing (T-104-36).
|
|
14
|
+
//
|
|
15
|
+
// Boot order:
|
|
16
|
+
// 1. validate configuration (offline: key presence and base URL only)
|
|
17
|
+
// 2. build the server and register every tool through the one door
|
|
18
|
+
// 3. connect the stdio transport
|
|
19
|
+
// 4. start the crypto-deposit availability probe in the background (D-03)
|
|
20
|
+
//
|
|
21
|
+
// Steps 1-3 make no network call, so a misconfigured server fails with a
|
|
22
|
+
// readable message and a transient network blip can never stop it booting.
|
|
23
|
+
// Step 4 is fire-and-forget and never throws.
|
|
24
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
25
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
26
|
+
const auth_js_1 = require("./auth.js");
|
|
27
|
+
const crypto_deposit_gate_js_1 = require("./tools/crypto-deposit-gate.js");
|
|
28
|
+
const index_js_1 = require("./tools/index.js");
|
|
29
|
+
const version_js_1 = require("./version.js");
|
|
30
|
+
/** Server name as MCP clients see it. */
|
|
31
|
+
exports.SERVER_NAME = "deeprelay";
|
|
32
|
+
/** A bare server with no tools. Tests use it to register a partial surface. */
|
|
33
|
+
function createServer() {
|
|
34
|
+
return new mcp_js_1.McpServer({ name: exports.SERVER_NAME, version: (0, version_js_1.readVersion)() });
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The server a client talks to: every roster tool registered. Offline and
|
|
38
|
+
* instant; throws only if the registry has drifted from the roster.
|
|
39
|
+
*/
|
|
40
|
+
function buildServer() {
|
|
41
|
+
const server = createServer();
|
|
42
|
+
const roster = (0, index_js_1.registerAllTools)(server);
|
|
43
|
+
return { server, roster };
|
|
44
|
+
}
|
|
45
|
+
/** Validate → build → connect → schedule the D-03 probe. */
|
|
46
|
+
async function main() {
|
|
47
|
+
// Throws StartupConfigError when DEEPRELAY_API_KEY is missing or the base
|
|
48
|
+
// URL is malformed. No request is made.
|
|
49
|
+
(0, auth_js_1.buildConfiguration)();
|
|
50
|
+
const { server, roster } = buildServer();
|
|
51
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
52
|
+
await server.connect(transport);
|
|
53
|
+
void (0, crypto_deposit_gate_js_1.probeCryptoDeposits)({ roster });
|
|
54
|
+
}
|
|
55
|
+
if (require.main === module) {
|
|
56
|
+
main().catch((err) => {
|
|
57
|
+
process.stderr.write(`${(0, auth_js_1.describeStartupError)(err)}\n`);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;AA6BA,oCAEC;AAWD,kCAIC;AAGD,oBAUC;AA1DD,6EAA6E;AAC7E,UAAU;AACV,EAAE;AACF,8EAA8E;AAC9E,0EAA0E;AAC1E,2EAA2E;AAC3E,EAAE;AACF,cAAc;AACd,wEAAwE;AACxE,qEAAqE;AACrE,mCAAmC;AACnC,4EAA4E;AAC5E,EAAE;AACF,yEAAyE;AACzE,2EAA2E;AAC3E,8CAA8C;AAC9C,oEAAoE;AACpE,wEAAiF;AAEjF,uCAAqE;AACrE,2EAAqE;AACrE,+CAA2E;AAC3E,6CAA2C;AAE3C,yCAAyC;AAC5B,QAAA,WAAW,GAAG,WAAW,CAAC;AAEvC,+EAA+E;AAC/E,SAAgB,YAAY;IAC1B,OAAO,IAAI,kBAAS,CAAC,EAAE,IAAI,EAAE,mBAAW,EAAE,OAAO,EAAE,IAAA,wBAAW,GAAE,EAAE,CAAC,CAAC;AACtE,CAAC;AAOD;;;GAGG;AACH,SAAgB,WAAW;IACzB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,IAAA,2BAAgB,EAAC,MAAM,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,4DAA4D;AACrD,KAAK,UAAU,IAAI;IACxB,0EAA0E;IAC1E,wCAAwC;IACxC,IAAA,4BAAkB,GAAE,CAAC;IAErB,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,KAAK,IAAA,4CAAmB,EAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACvC,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAA,8BAAoB,EAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACvD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/roster.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare const TOOL_PREFIX = "deeprelay_";
|
|
2
|
+
/** Free, non-mutating reads. No confirmation. Every route is a GET. */
|
|
3
|
+
export declare const READ_TOOLS: readonly ["deeprelay_auth_status", "deeprelay_health", "deeprelay_models_list", "deeprelay_models_get", "deeprelay_inference_preflight", "deeprelay_usage_get", "deeprelay_balance_get", "deeprelay_spending_limit_get", "deeprelay_subscription_get", "deeprelay_deposits_list", "deeprelay_deposits_get", "deeprelay_referrals_get", "deeprelay_webhooks_list", "deeprelay_webhooks_get", "deeprelay_videos_list", "deeprelay_videos_get", "deeprelay_videos_content"];
|
|
4
|
+
/**
|
|
5
|
+
* Mutations that do not charge the account directly. Each one asks for
|
|
6
|
+
* confirmation once. Payment-link tools are here with no quote (D-09), because
|
|
7
|
+
* nothing is charged until the user acts on the link.
|
|
8
|
+
*/
|
|
9
|
+
export declare const WRITE_TOOLS: readonly ["deeprelay_webhooks_create", "deeprelay_webhooks_delete", "deeprelay_spending_limit_update", "deeprelay_spending_limit_clear", "deeprelay_subscription_checkout", "deeprelay_billing_portal", "deeprelay_deposits_create_crypto", "deeprelay_videos_cancel"];
|
|
10
|
+
/** Billable inference. Each call goes quote → session budget → confirm (D-06..D-08, D-10). */
|
|
11
|
+
export declare const SPEND_TOOLS: readonly ["deeprelay_chat_completion", "deeprelay_embeddings_create", "deeprelay_images_generate", "deeprelay_videos_create"];
|
|
12
|
+
export declare const ALL_TOOLS: readonly ["deeprelay_auth_status", "deeprelay_health", "deeprelay_models_list", "deeprelay_models_get", "deeprelay_inference_preflight", "deeprelay_usage_get", "deeprelay_balance_get", "deeprelay_spending_limit_get", "deeprelay_subscription_get", "deeprelay_deposits_list", "deeprelay_deposits_get", "deeprelay_referrals_get", "deeprelay_webhooks_list", "deeprelay_webhooks_get", "deeprelay_videos_list", "deeprelay_videos_get", "deeprelay_videos_content", "deeprelay_webhooks_create", "deeprelay_webhooks_delete", "deeprelay_spending_limit_update", "deeprelay_spending_limit_clear", "deeprelay_subscription_checkout", "deeprelay_billing_portal", "deeprelay_deposits_create_crypto", "deeprelay_videos_cancel", "deeprelay_chat_completion", "deeprelay_embeddings_create", "deeprelay_images_generate", "deeprelay_videos_create"];
|
|
13
|
+
export type ReadToolName = (typeof READ_TOOLS)[number];
|
|
14
|
+
export type WriteToolName = (typeof WRITE_TOOLS)[number];
|
|
15
|
+
export type SpendToolName = (typeof SPEND_TOOLS)[number];
|
|
16
|
+
export type ToolName = (typeof ALL_TOOLS)[number];
|
|
17
|
+
export type HttpMethod = "GET" | "POST" | "PUT" | "DELETE";
|
|
18
|
+
export interface ToolRoute {
|
|
19
|
+
method: HttpMethod;
|
|
20
|
+
/** Path relative to the /v1 base, exactly as keyed in openapi/v1.yaml. */
|
|
21
|
+
path: string;
|
|
22
|
+
/**
|
|
23
|
+
* Additional unpaused paths the tool reads besides its primary route. Only
|
|
24
|
+
* deeprelay_auth_status uses this: it confirms the key via the spending
|
|
25
|
+
* limit, then reports the balance.
|
|
26
|
+
*/
|
|
27
|
+
secondaryPaths?: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
/** Each tool mapped to its one unpaused route (D-05). */
|
|
30
|
+
export declare const TOOL_ROUTES: Record<ToolName, ToolRoute>;
|
|
31
|
+
/**
|
|
32
|
+
* Unpaused spec paths that are deliberately NOT tools, each with its reason (D-05).
|
|
33
|
+
* Once Phase 103 pauses /operations/{id}, it drops out of the unpaused set and
|
|
34
|
+
* its entry here can go.
|
|
35
|
+
*/
|
|
36
|
+
export declare const EXCLUDED_PATHS: Readonly<Record<string, string>>;
|
package/dist/roster.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The canonical deeprelay MCP tool roster (Phase 104, D-01/D-05).
|
|
3
|
+
//
|
|
4
|
+
// This is the one place the roster is written down. Each later module (the
|
|
5
|
+
// tier files, the registration door, the docs-count checks) reads its names from
|
|
6
|
+
// here instead of re-listing them. The file holds constants and types only: no
|
|
7
|
+
// handlers and no I/O.
|
|
8
|
+
//
|
|
9
|
+
// Rules this file encodes:
|
|
10
|
+
// * D-01: every tool name starts with `deeprelay_`. No GPU-era name survives.
|
|
11
|
+
// * D-02: all four live inference modalities ship: chat, embeddings, image
|
|
12
|
+
// and async video.
|
|
13
|
+
// * D-04: there is no operations tool. `GET /operations/{id}` has no
|
|
14
|
+
// serverless producer of operation ids and is paused by Phase 103 D-08.
|
|
15
|
+
// * D-05: the roster is the SDK and nothing more. Every tool maps to exactly
|
|
16
|
+
// one unpaused path in openapi/v1.yaml, and every unpaused path is either
|
|
17
|
+
// some tool's route or is listed in EXCLUDED_PATHS with a reason.
|
|
18
|
+
// test/roster-audit.test.ts checks this against the live spec.
|
|
19
|
+
// * D-10: three tiers, enforced by the server. READ tools are free. WRITE tools
|
|
20
|
+
// ask for confirmation once. SPEND tools go quote → budget → confirm.
|
|
21
|
+
//
|
|
22
|
+
// Tier/method invariant (the harness sentinel depends on it): every READ route
|
|
23
|
+
// is a GET, and every WRITE or SPEND route is not a GET. So a stub API can flag
|
|
24
|
+
// any non-GET that arrives without a confirmation as a guardrail breach.
|
|
25
|
+
//
|
|
26
|
+
// `deeprelay_videos_cancel` is in the WRITE tier. `POST /videos/{id}/cancel` is
|
|
27
|
+
// a mutation, and D-10 says every mutation asks for confirmation.
|
|
28
|
+
// `deeprelay_spending_limit_clear` is tool 29 (Plan 104-12): the shipping pin,
|
|
29
|
+
// @deeprelay/sdk@0.2.0, exposes BillingApi.deleteSpendingLimit
|
|
30
|
+
// (DELETE /billing/spending-limit). It is a WRITE because it removes a safety
|
|
31
|
+
// cap: it confirms once, and requires the org-admin role server-side.
|
|
32
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
33
|
+
exports.EXCLUDED_PATHS = exports.TOOL_ROUTES = exports.ALL_TOOLS = exports.SPEND_TOOLS = exports.WRITE_TOOLS = exports.READ_TOOLS = exports.TOOL_PREFIX = void 0;
|
|
34
|
+
exports.TOOL_PREFIX = "deeprelay_";
|
|
35
|
+
/** Free, non-mutating reads. No confirmation. Every route is a GET. */
|
|
36
|
+
exports.READ_TOOLS = [
|
|
37
|
+
"deeprelay_auth_status",
|
|
38
|
+
"deeprelay_health",
|
|
39
|
+
"deeprelay_models_list",
|
|
40
|
+
"deeprelay_models_get",
|
|
41
|
+
"deeprelay_inference_preflight",
|
|
42
|
+
"deeprelay_usage_get",
|
|
43
|
+
"deeprelay_balance_get",
|
|
44
|
+
"deeprelay_spending_limit_get",
|
|
45
|
+
"deeprelay_subscription_get",
|
|
46
|
+
"deeprelay_deposits_list",
|
|
47
|
+
"deeprelay_deposits_get",
|
|
48
|
+
"deeprelay_referrals_get",
|
|
49
|
+
"deeprelay_webhooks_list",
|
|
50
|
+
"deeprelay_webhooks_get",
|
|
51
|
+
"deeprelay_videos_list",
|
|
52
|
+
"deeprelay_videos_get",
|
|
53
|
+
"deeprelay_videos_content",
|
|
54
|
+
];
|
|
55
|
+
/**
|
|
56
|
+
* Mutations that do not charge the account directly. Each one asks for
|
|
57
|
+
* confirmation once. Payment-link tools are here with no quote (D-09), because
|
|
58
|
+
* nothing is charged until the user acts on the link.
|
|
59
|
+
*/
|
|
60
|
+
exports.WRITE_TOOLS = [
|
|
61
|
+
"deeprelay_webhooks_create",
|
|
62
|
+
"deeprelay_webhooks_delete",
|
|
63
|
+
"deeprelay_spending_limit_update",
|
|
64
|
+
"deeprelay_spending_limit_clear",
|
|
65
|
+
"deeprelay_subscription_checkout",
|
|
66
|
+
"deeprelay_billing_portal",
|
|
67
|
+
"deeprelay_deposits_create_crypto",
|
|
68
|
+
"deeprelay_videos_cancel",
|
|
69
|
+
];
|
|
70
|
+
/** Billable inference. Each call goes quote → session budget → confirm (D-06..D-08, D-10). */
|
|
71
|
+
exports.SPEND_TOOLS = [
|
|
72
|
+
"deeprelay_chat_completion",
|
|
73
|
+
"deeprelay_embeddings_create",
|
|
74
|
+
"deeprelay_images_generate",
|
|
75
|
+
"deeprelay_videos_create",
|
|
76
|
+
];
|
|
77
|
+
exports.ALL_TOOLS = [...exports.READ_TOOLS, ...exports.WRITE_TOOLS, ...exports.SPEND_TOOLS];
|
|
78
|
+
/** Each tool mapped to its one unpaused route (D-05). */
|
|
79
|
+
exports.TOOL_ROUTES = {
|
|
80
|
+
// READ
|
|
81
|
+
deeprelay_auth_status: {
|
|
82
|
+
method: "GET",
|
|
83
|
+
path: "/billing/spending-limit",
|
|
84
|
+
secondaryPaths: ["/billing/balance"],
|
|
85
|
+
},
|
|
86
|
+
deeprelay_health: { method: "GET", path: "/health" },
|
|
87
|
+
deeprelay_models_list: { method: "GET", path: "/models" },
|
|
88
|
+
deeprelay_models_get: { method: "GET", path: "/models/{id}" },
|
|
89
|
+
deeprelay_inference_preflight: { method: "GET", path: "/inference/preflight" },
|
|
90
|
+
deeprelay_usage_get: { method: "GET", path: "/usage" },
|
|
91
|
+
deeprelay_balance_get: { method: "GET", path: "/billing/balance" },
|
|
92
|
+
deeprelay_spending_limit_get: { method: "GET", path: "/billing/spending-limit" },
|
|
93
|
+
deeprelay_subscription_get: { method: "GET", path: "/billing/subscription" },
|
|
94
|
+
deeprelay_deposits_list: { method: "GET", path: "/billing/deposits" },
|
|
95
|
+
deeprelay_deposits_get: { method: "GET", path: "/billing/deposits/{id}" },
|
|
96
|
+
deeprelay_referrals_get: { method: "GET", path: "/referrals" },
|
|
97
|
+
deeprelay_webhooks_list: { method: "GET", path: "/webhook-endpoints" },
|
|
98
|
+
deeprelay_webhooks_get: { method: "GET", path: "/webhook-endpoints/{id}" },
|
|
99
|
+
deeprelay_videos_list: { method: "GET", path: "/videos" },
|
|
100
|
+
deeprelay_videos_get: { method: "GET", path: "/videos/{id}" },
|
|
101
|
+
deeprelay_videos_content: { method: "GET", path: "/videos/{id}/content" },
|
|
102
|
+
// WRITE
|
|
103
|
+
deeprelay_webhooks_create: { method: "POST", path: "/webhook-endpoints" },
|
|
104
|
+
deeprelay_webhooks_delete: { method: "DELETE", path: "/webhook-endpoints/{id}" },
|
|
105
|
+
deeprelay_spending_limit_update: { method: "PUT", path: "/billing/spending-limit" },
|
|
106
|
+
deeprelay_spending_limit_clear: { method: "DELETE", path: "/billing/spending-limit" },
|
|
107
|
+
deeprelay_subscription_checkout: { method: "POST", path: "/billing/subscription/checkout" },
|
|
108
|
+
deeprelay_billing_portal: { method: "POST", path: "/billing/subscription/portal" },
|
|
109
|
+
deeprelay_deposits_create_crypto: { method: "POST", path: "/billing/deposits/crypto" },
|
|
110
|
+
deeprelay_videos_cancel: { method: "POST", path: "/videos/{id}/cancel" },
|
|
111
|
+
// SPEND
|
|
112
|
+
deeprelay_chat_completion: { method: "POST", path: "/chat/completions" },
|
|
113
|
+
deeprelay_embeddings_create: { method: "POST", path: "/embeddings" },
|
|
114
|
+
deeprelay_images_generate: { method: "POST", path: "/images/generations" },
|
|
115
|
+
deeprelay_videos_create: { method: "POST", path: "/videos" },
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Unpaused spec paths that are deliberately NOT tools, each with its reason (D-05).
|
|
119
|
+
* Once Phase 103 pauses /operations/{id}, it drops out of the unpaused set and
|
|
120
|
+
* its entry here can go.
|
|
121
|
+
*/
|
|
122
|
+
exports.EXCLUDED_PATHS = {
|
|
123
|
+
"/openapi.json": "spec download, not an agent capability (D-05)",
|
|
124
|
+
// /operations/{id} was listed here while it was still an UNPAUSED path with
|
|
125
|
+
// no tool. Phase 103 D-08 landed the x-gpu-supply-paused marker, so it is no
|
|
126
|
+
// longer unpaused and an exclusion entry for it would now fail the audit's
|
|
127
|
+
// "excluded path must be a real unpaused path" assertion. There is still no
|
|
128
|
+
// operations tool (D-04) — the path simply left the audit's domain.
|
|
129
|
+
};
|
|
130
|
+
//# sourceMappingURL=roster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roster.js","sourceRoot":"","sources":["../src/roster.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RegisteredRoster } from "./index.js";
|
|
2
|
+
import type { Env } from "./types.js";
|
|
3
|
+
export declare const CRYPTO_DEPOSIT_TOOL: "deeprelay_deposits_create_crypto";
|
|
4
|
+
/** The one line written when the probe fails for a reason other than 404. */
|
|
5
|
+
export declare const PROBE_FAILURE_LINE: string;
|
|
6
|
+
/** Where the probe may write its single diagnostic line. Never stdout (JSON-RPC). */
|
|
7
|
+
export interface ProbeStderr {
|
|
8
|
+
write(chunk: string): unknown;
|
|
9
|
+
}
|
|
10
|
+
export interface ProbeOptions {
|
|
11
|
+
roster: RegisteredRoster;
|
|
12
|
+
env?: Env;
|
|
13
|
+
stderr?: ProbeStderr;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Enable deeprelay_deposits_create_crypto if and only if GET /billing/deposits
|
|
17
|
+
* succeeds for this key. Resolves in every case; never rejects.
|
|
18
|
+
*/
|
|
19
|
+
export declare function probeCryptoDeposits(options: ProbeOptions): Promise<void>;
|
|
20
|
+
/** Enable the crypto-deposit tool if it is still hidden. Idempotent. */
|
|
21
|
+
export declare function enableOnDepositsRead(roster: RegisteredRoster): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PROBE_FAILURE_LINE = exports.CRYPTO_DEPOSIT_TOOL = void 0;
|
|
4
|
+
exports.probeCryptoDeposits = probeCryptoDeposits;
|
|
5
|
+
exports.enableOnDepositsRead = enableOnDepositsRead;
|
|
6
|
+
// The crypto-deposit advertisement probe (Phase 104, D-03). Authored fresh
|
|
7
|
+
// (D-12).
|
|
8
|
+
//
|
|
9
|
+
// deeprelay_deposits_create_crypto is the one tool whose availability depends
|
|
10
|
+
// on the account: crypto deposits are enabled per account, and on an account
|
|
11
|
+
// without them the API answers 404. Advertising a tool the API will refuse
|
|
12
|
+
// wastes the agent's turn, so the registry registers it disabled at boot and
|
|
13
|
+
// this module turns it on once the account is shown to have the feature.
|
|
14
|
+
//
|
|
15
|
+
// Mechanism (recorded for verify-phase in 104-08-PLAN.md):
|
|
16
|
+
//
|
|
17
|
+
// * Boot is offline (D-15). The tool is registered and disabled before the
|
|
18
|
+
// transport connects, and disabling it then sends nothing, because the
|
|
19
|
+
// pinned SDK only emits tools/list_changed once connected.
|
|
20
|
+
// * After connect, main() starts one probe in the background: a single
|
|
21
|
+
// GET /billing/deposits through the SDK.
|
|
22
|
+
// 2xx → enable the tool (the SDK emits tools/list_changed)
|
|
23
|
+
// 404 → leave it hidden, say nothing (the normal "not enabled")
|
|
24
|
+
// anything else → leave it hidden, write one fixed stderr line
|
|
25
|
+
// The probe never throws and never blocks boot.
|
|
26
|
+
// * Defense in depth: when a later deeprelay_deposits_list / _get read shows
|
|
27
|
+
// crypto deposits enabled, the registry calls enableOnDepositsRead, so a
|
|
28
|
+
// probe that failed on a transient error does not hide the tool for the
|
|
29
|
+
// whole session.
|
|
30
|
+
//
|
|
31
|
+
// This is NOT a general gate. The GPU-era provisioning gate was deleted
|
|
32
|
+
// outright (D-13) and has no successor; this module only ever touches the one
|
|
33
|
+
// tool named below.
|
|
34
|
+
const sdk_1 = require("@deeprelay/sdk");
|
|
35
|
+
const auth_js_1 = require("../auth.js");
|
|
36
|
+
const errors_js_1 = require("../errors.js");
|
|
37
|
+
exports.CRYPTO_DEPOSIT_TOOL = "deeprelay_deposits_create_crypto";
|
|
38
|
+
/** The one line written when the probe fails for a reason other than 404. */
|
|
39
|
+
exports.PROBE_FAILURE_LINE = `deeprelay: crypto-deposit availability probe failed; ${exports.CRYPTO_DEPOSIT_TOOL} stays hidden\n`;
|
|
40
|
+
/**
|
|
41
|
+
* Enable deeprelay_deposits_create_crypto if and only if GET /billing/deposits
|
|
42
|
+
* succeeds for this key. Resolves in every case; never rejects.
|
|
43
|
+
*/
|
|
44
|
+
async function probeCryptoDeposits(options) {
|
|
45
|
+
const { roster, env = process.env, stderr = process.stderr } = options;
|
|
46
|
+
try {
|
|
47
|
+
const tool = roster.get(exports.CRYPTO_DEPOSIT_TOOL);
|
|
48
|
+
if (tool === undefined || tool.enabled) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
let config;
|
|
52
|
+
try {
|
|
53
|
+
config = (0, auth_js_1.buildConfiguration)(env);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// No key or a bad base URL: main() already refuses to boot on these, so
|
|
57
|
+
// reaching here means a test or embedder built the server without config.
|
|
58
|
+
// Nothing to probe with; stay hidden and quiet.
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
await new sdk_1.BillingApi(config).listDeposits();
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if ((0, errors_js_1.httpStatusOf)(err) === 404) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
stderr.write((0, errors_js_1.redactSecrets)(exports.PROBE_FAILURE_LINE, env));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
tool.enable();
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Belt and braces: the probe runs fire-and-forget after connect, so an
|
|
75
|
+
// unexpected throw here must not become an unhandled rejection.
|
|
76
|
+
try {
|
|
77
|
+
stderr.write((0, errors_js_1.redactSecrets)(exports.PROBE_FAILURE_LINE, env));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// stderr itself is gone; nothing left to report to.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** Enable the crypto-deposit tool if it is still hidden. Idempotent. */
|
|
85
|
+
function enableOnDepositsRead(roster) {
|
|
86
|
+
const tool = roster.get(exports.CRYPTO_DEPOSIT_TOOL);
|
|
87
|
+
if (tool !== undefined && !tool.enabled) {
|
|
88
|
+
tool.enable();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=crypto-deposit-gate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto-deposit-gate.js","sourceRoot":"","sources":["../../src/tools/crypto-deposit-gate.ts"],"names":[],"mappings":";;;AAwDA,kDAqCC;AAGD,oDAKC;AArGD,2EAA2E;AAC3E,UAAU;AACV,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,6EAA6E;AAC7E,yEAAyE;AACzE,EAAE;AACF,2DAA2D;AAC3D,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,+DAA+D;AAC/D,yEAAyE;AACzE,6CAA6C;AAC7C,0EAA0E;AAC1E,+EAA+E;AAC/E,qEAAqE;AACrE,oDAAoD;AACpD,+EAA+E;AAC/E,6EAA6E;AAC7E,4EAA4E;AAC5E,qBAAqB;AACrB,EAAE;AACF,wEAAwE;AACxE,8EAA8E;AAC9E,oBAAoB;AACpB,wCAAgE;AAEhE,wCAAgD;AAChD,4CAA2D;AAI9C,QAAA,mBAAmB,GAAG,kCAA2C,CAAC;AAE/E,6EAA6E;AAChE,QAAA,kBAAkB,GAC7B,wDAAwD,2BAAmB,iBAAiB,CAAC;AAa/F;;;GAGG;AACI,KAAK,UAAU,mBAAmB,CAAC,OAAqB;IAC7D,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC;IACvE,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,2BAAmB,CAAC,CAAC;QAC7C,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACvC,OAAO;QACT,CAAC;QAED,IAAI,MAAqB,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,GAAG,IAAA,4BAAkB,EAAC,GAAG,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,0EAA0E;YAC1E,gDAAgD;YAChD,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,MAAM,IAAI,gBAAU,CAAC,MAAM,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,IAAA,wBAAY,EAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9B,OAAO;YACT,CAAC;YACD,MAAM,CAAC,KAAK,CAAC,IAAA,yBAAa,EAAC,0BAAkB,EAAE,GAAG,CAAC,CAAC,CAAC;YACrD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,gEAAgE;QAChE,IAAI,CAAC;YACH,MAAM,CAAC,KAAK,CAAC,IAAA,yBAAa,EAAC,0BAAkB,EAAE,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;IACH,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,SAAgB,oBAAoB,CAAC,MAAwB;IAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,2BAAmB,CAAC,CAAC;IAC7C,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { McpServer, RegisteredTool } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ElicitationHost } from "../guardrail/types.js";
|
|
3
|
+
import { type ToolName } from "../roster.js";
|
|
4
|
+
/** Every registered tool, by roster name. */
|
|
5
|
+
export type RegisteredRoster = ReadonlyMap<ToolName, RegisteredTool>;
|
|
6
|
+
/**
|
|
7
|
+
* Adapt the low-level server's elicitation surface to the structural
|
|
8
|
+
* ElicitationHost the guardrail uses. In the pinned SDK, elicitInput lives on
|
|
9
|
+
* `server.server`, not on the per-request `extra` a tool callback receives.
|
|
10
|
+
*/
|
|
11
|
+
export declare function elicitationHost(server: McpServer): ElicitationHost;
|
|
12
|
+
/**
|
|
13
|
+
* Register every roster tool on `server` and return the registered handles by
|
|
14
|
+
* name. The one door (D-13): a plain three-array walk.
|
|
15
|
+
*/
|
|
16
|
+
export declare function registerAllTools(server: McpServer): RegisteredRoster;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.elicitationHost = elicitationHost;
|
|
4
|
+
exports.registerAllTools = registerAllTools;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const roster_js_1 = require("../roster.js");
|
|
7
|
+
const crypto_deposit_gate_js_1 = require("./crypto-deposit-gate.js");
|
|
8
|
+
const index_js_1 = require("./readonly/index.js");
|
|
9
|
+
const index_js_2 = require("./spend/index.js");
|
|
10
|
+
const index_js_3 = require("./write/index.js");
|
|
11
|
+
/** The two reads whose success shows the account has crypto deposits. */
|
|
12
|
+
const DEPOSIT_READS = new Set(["deeprelay_deposits_list", "deeprelay_deposits_get"]);
|
|
13
|
+
/**
|
|
14
|
+
* Adapt the low-level server's elicitation surface to the structural
|
|
15
|
+
* ElicitationHost the guardrail uses. In the pinned SDK, elicitInput lives on
|
|
16
|
+
* `server.server`, not on the per-request `extra` a tool callback receives.
|
|
17
|
+
*/
|
|
18
|
+
function elicitationHost(server) {
|
|
19
|
+
return {
|
|
20
|
+
getClientCapabilities: () => server.server.getClientCapabilities(),
|
|
21
|
+
elicitInput: async (params) => {
|
|
22
|
+
// The guardrail builds a form-mode request with primitive properties; the
|
|
23
|
+
// SDK's own schema check validates it again at send time.
|
|
24
|
+
const result = await server.server.elicitInput(params);
|
|
25
|
+
return { action: result.action, ...(result.content === undefined ? {} : { content: result.content }) };
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Throw unless the definitions are exactly ALL_TOOLS, each once. */
|
|
30
|
+
function assertRosterMatches(definitions) {
|
|
31
|
+
const seen = new Map();
|
|
32
|
+
for (const def of definitions) {
|
|
33
|
+
seen.set(def.name, (seen.get(def.name) ?? 0) + 1);
|
|
34
|
+
}
|
|
35
|
+
const expected = new Set(roster_js_1.ALL_TOOLS);
|
|
36
|
+
const missing = [...expected].filter((name) => !seen.has(name));
|
|
37
|
+
const extra = [...seen.keys()].filter((name) => !expected.has(name));
|
|
38
|
+
const duplicated = [...seen.entries()].filter(([, count]) => count > 1).map(([name]) => name);
|
|
39
|
+
const wronglyHidden = definitions
|
|
40
|
+
.filter((def) => def.enabledAtBoot === false && def.name !== crypto_deposit_gate_js_1.CRYPTO_DEPOSIT_TOOL)
|
|
41
|
+
.map((def) => def.name);
|
|
42
|
+
const problems = [];
|
|
43
|
+
if (missing.length > 0)
|
|
44
|
+
problems.push(`missing: ${missing.join(", ")}`);
|
|
45
|
+
if (extra.length > 0)
|
|
46
|
+
problems.push(`not in the roster: ${extra.join(", ")}`);
|
|
47
|
+
if (duplicated.length > 0)
|
|
48
|
+
problems.push(`registered twice: ${duplicated.join(", ")}`);
|
|
49
|
+
if (wronglyHidden.length > 0)
|
|
50
|
+
problems.push(`hidden at boot without a D-03 reason: ${wronglyHidden.join(", ")}`);
|
|
51
|
+
if (problems.length > 0) {
|
|
52
|
+
throw new Error(`deeprelay-mcp tool registry does not match the roster (${problems.join("; ")})`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/** True when a deposit read's payload reports crypto deposits as enabled. */
|
|
56
|
+
function readShowsCryptoEnabled(result) {
|
|
57
|
+
if (result.isError === true) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const first = result.content[0];
|
|
61
|
+
if (first === undefined || first.type !== "text") {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const payload = JSON.parse(first.text);
|
|
66
|
+
return (typeof payload === "object" &&
|
|
67
|
+
payload !== null &&
|
|
68
|
+
payload.crypto_deposits_enabled === true);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Register every roster tool on `server` and return the registered handles by
|
|
76
|
+
* name. The one door (D-13): a plain three-array walk.
|
|
77
|
+
*/
|
|
78
|
+
function registerAllTools(server) {
|
|
79
|
+
const definitions = [...index_js_1.readonlyTools, ...index_js_3.writeTools, ...index_js_2.spendTools];
|
|
80
|
+
assertRosterMatches(definitions);
|
|
81
|
+
const roster = new Map();
|
|
82
|
+
const host = elicitationHost(server);
|
|
83
|
+
for (const def of definitions) {
|
|
84
|
+
const inputSchema = def.tier === "read" ? def.inputSchema : zod_1.z.strictObject(def.inputSchema);
|
|
85
|
+
const watchesDeposits = DEPOSIT_READS.has(def.name);
|
|
86
|
+
const registered = server.registerTool(def.name, {
|
|
87
|
+
title: def.title,
|
|
88
|
+
description: def.description,
|
|
89
|
+
inputSchema,
|
|
90
|
+
annotations: { ...def.annotations },
|
|
91
|
+
}, async (args) => {
|
|
92
|
+
const result = await def.handler(args, { elicitation: host });
|
|
93
|
+
if (watchesDeposits && readShowsCryptoEnabled(result)) {
|
|
94
|
+
(0, crypto_deposit_gate_js_1.enableOnDepositsRead)(roster);
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
});
|
|
98
|
+
// D-03: registered, then hidden until the post-connect probe (or a deposit
|
|
99
|
+
// read) proves the account has crypto deposits. Offline: the SDK sends no
|
|
100
|
+
// list_changed before the transport is connected.
|
|
101
|
+
if (def.enabledAtBoot === false) {
|
|
102
|
+
registered.disable();
|
|
103
|
+
}
|
|
104
|
+
roster.set(def.name, registered);
|
|
105
|
+
}
|
|
106
|
+
return roster;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Configuration } from "@deeprelay/sdk";
|
|
2
|
+
import { z, type ZodRawShape } from "zod";
|
|
3
|
+
import type { ReadToolName } from "../../roster.js";
|
|
4
|
+
import type { Env, ToolAnnotations, ToolDefinition } from "../types.js";
|
|
5
|
+
/**
|
|
6
|
+
* A read refusing on local grounds (not an API failure), in words already
|
|
7
|
+
* written for the agent. defineTool serializes it through fail() as-is rather
|
|
8
|
+
* than routing it through the SDK error mapper, which would prefix it as an
|
|
9
|
+
* "Unexpected error".
|
|
10
|
+
*/
|
|
11
|
+
export declare class ReadRefusal extends Error {
|
|
12
|
+
constructor(message: string);
|
|
13
|
+
}
|
|
14
|
+
/** Every read tool advertises the same four hints. */
|
|
15
|
+
export declare const READ_ANNOTATIONS: ToolAnnotations;
|
|
16
|
+
export interface ReadToolSpec<Shape extends ZodRawShape> {
|
|
17
|
+
name: ReadToolName;
|
|
18
|
+
title: string;
|
|
19
|
+
/** Agent-shaped: what it answers, when to call it, that it is free. */
|
|
20
|
+
description: string;
|
|
21
|
+
inputSchema: Shape;
|
|
22
|
+
/** What was being attempted, for error messages ("listing models"). */
|
|
23
|
+
context: string;
|
|
24
|
+
/**
|
|
25
|
+
* Build the Configuration even when DEEPRELAY_API_KEY is unset. Only the
|
|
26
|
+
* unauthenticated liveness probe sets this.
|
|
27
|
+
*/
|
|
28
|
+
keyless?: boolean;
|
|
29
|
+
call(args: z.infer<z.ZodObject<Shape>>, config: Configuration, env: Env): Promise<unknown>;
|
|
30
|
+
}
|
|
31
|
+
/** Wrap a typed SDK call into a read-tier ToolDefinition. */
|
|
32
|
+
export declare function defineTool<Shape extends ZodRawShape>(spec: ReadToolSpec<Shape>): ToolDefinition;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.READ_ANNOTATIONS = exports.ReadRefusal = void 0;
|
|
4
|
+
exports.defineTool = defineTool;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const auth_js_1 = require("../../auth.js");
|
|
7
|
+
const errors_js_1 = require("../../errors.js");
|
|
8
|
+
const result_js_1 = require("../result.js");
|
|
9
|
+
/**
|
|
10
|
+
* A read refusing on local grounds (not an API failure), in words already
|
|
11
|
+
* written for the agent. defineTool serializes it through fail() as-is rather
|
|
12
|
+
* than routing it through the SDK error mapper, which would prefix it as an
|
|
13
|
+
* "Unexpected error".
|
|
14
|
+
*/
|
|
15
|
+
class ReadRefusal extends Error {
|
|
16
|
+
constructor(message) {
|
|
17
|
+
super(message);
|
|
18
|
+
this.name = "ReadRefusal";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.ReadRefusal = ReadRefusal;
|
|
22
|
+
/** Every read tool advertises the same four hints. */
|
|
23
|
+
exports.READ_ANNOTATIONS = Object.freeze({
|
|
24
|
+
readOnlyHint: true,
|
|
25
|
+
destructiveHint: false,
|
|
26
|
+
idempotentHint: true,
|
|
27
|
+
openWorldHint: true,
|
|
28
|
+
});
|
|
29
|
+
/** Wrap a typed SDK call into a read-tier ToolDefinition. */
|
|
30
|
+
function defineTool(spec) {
|
|
31
|
+
const schema = zod_1.z.object(spec.inputSchema);
|
|
32
|
+
return {
|
|
33
|
+
name: spec.name,
|
|
34
|
+
tier: "read",
|
|
35
|
+
title: spec.title,
|
|
36
|
+
description: spec.description,
|
|
37
|
+
inputSchema: spec.inputSchema,
|
|
38
|
+
annotations: { ...exports.READ_ANNOTATIONS },
|
|
39
|
+
enabledAtBoot: true,
|
|
40
|
+
async handler(args, ctx) {
|
|
41
|
+
const env = ctx?.env ?? process.env;
|
|
42
|
+
let parsed;
|
|
43
|
+
let config;
|
|
44
|
+
try {
|
|
45
|
+
parsed = schema.parse(args ?? {});
|
|
46
|
+
config = (0, auth_js_1.buildConfiguration)(env, { allowMissingKey: spec.keyless === true });
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
return (0, result_js_1.fail)((0, errors_js_1.mapSdkError)(err, spec.context, { env }), env);
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const payload = await spec.call(parsed, config, env);
|
|
53
|
+
return (0, result_js_1.ok)(payload, { env });
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
if (err instanceof ReadRefusal) {
|
|
57
|
+
return (0, result_js_1.fail)(err, env);
|
|
58
|
+
}
|
|
59
|
+
return (0, result_js_1.fail)(await (0, errors_js_1.mapSdkErrorAsync)(err, spec.context, env), env);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../../src/tools/readonly/define.ts"],"names":[],"mappings":";;;AA6DA,gCA+BC;AA7ED,6BAA0C;AAE1C,2CAAmD;AACnD,+CAAgE;AAEhE,4CAAwC;AAGxC;;;;;GAKG;AACH,MAAa,WAAY,SAAQ,KAAK;IACpC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AALD,kCAKC;AAED,sDAAsD;AACzC,QAAA,gBAAgB,GAAoB,MAAM,CAAC,MAAM,CAAC;IAC7D,YAAY,EAAE,IAAI;IAClB,eAAe,EAAE,KAAK;IACtB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;CACpB,CAAC,CAAC;AAkBH,6DAA6D;AAC7D,SAAgB,UAAU,CAA4B,IAAyB;IAC7E,MAAM,MAAM,GAAG,OAAC,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,WAAW,EAAE,EAAE,GAAG,wBAAgB,EAAE;QACpC,aAAa,EAAE,IAAI;QACnB,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG;YACrB,MAAM,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;YACpC,IAAI,MAA8B,CAAC;YACnC,IAAI,MAAqB,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;gBAClC,MAAM,GAAG,IAAA,4BAAkB,EAAC,GAAG,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,CAAC;YAC/E,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,IAAA,gBAAI,EAAC,IAAA,uBAAW,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;gBACrD,OAAO,IAAA,cAAE,EAAC,OAAO,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YAC9B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;oBAC/B,OAAO,IAAA,gBAAI,EAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBACxB,CAAC;gBACD,OAAO,IAAA,gBAAI,EAAC,MAAM,IAAA,4BAAgB,EAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ToolDefinition } from "../types.js";
|
|
2
|
+
export { defineTool, READ_ANNOTATIONS } from "./define.js";
|
|
3
|
+
export { observeVideoJob, VIDEO_TMP_DIR, videoReadTools } from "./video-reads.js";
|
|
4
|
+
/** The in-process session budget (D-06/D-08), in dollars, with pending video holds. */
|
|
5
|
+
export declare function renderSessionBudget(): Record<string, unknown>;
|
|
6
|
+
/** The full read tier. Every name in roster READ_TOOLS appears here exactly once. */
|
|
7
|
+
export declare const readonlyTools: ToolDefinition[];
|