capix-mcp 2.1.0 → 2.2.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 +51 -72
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +18 -8
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +130 -6
- package/dist/index.js.map +1 -1
- package/dist/prompts.d.ts +6 -1
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +41 -75
- package/dist/prompts.js.map +1 -1
- package/dist/route-families.d.ts +47 -0
- package/dist/route-families.d.ts.map +1 -0
- package/dist/route-families.js +96 -0
- package/dist/route-families.js.map +1 -0
- package/dist/server.d.ts +36 -6
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +67 -11
- package/dist/server.js.map +1 -1
- package/dist/tools/define-tool.d.ts +33 -0
- package/dist/tools/define-tool.d.ts.map +1 -0
- package/dist/tools/define-tool.js +28 -0
- package/dist/tools/define-tool.js.map +1 -0
- package/dist/tools/factory.d.ts +42 -0
- package/dist/tools/factory.d.ts.map +1 -0
- package/dist/tools/factory.js +363 -0
- package/dist/tools/factory.js.map +1 -0
- package/dist/tools/generate.d.ts +108 -0
- package/dist/tools/generate.d.ts.map +1 -0
- package/dist/tools/generate.js +149 -0
- package/dist/tools/generate.js.map +1 -0
- package/dist/tools/infra-context.d.ts +28 -0
- package/dist/tools/infra-context.d.ts.map +1 -0
- package/dist/tools/infra-context.js +90 -0
- package/dist/tools/infra-context.js.map +1 -0
- package/dist/tools/memes.d.ts +31 -0
- package/dist/tools/memes.d.ts.map +1 -0
- package/dist/tools/memes.js +175 -0
- package/dist/tools/memes.js.map +1 -0
- package/dist/tools.d.ts +48 -7
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +346 -911
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +17 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -2
- package/dist/types.js.map +1 -1
- package/package.json +4 -3
package/dist/tools.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Capix MCP Server — all
|
|
2
|
+
* Capix MCP Server — all 37 tool definitions.
|
|
3
|
+
*
|
|
4
|
+
* 2026-07 repair: every tool below targets a route family that EXISTS in the
|
|
5
|
+
* control plane (app/api/v1/* in the protocol repo), verified route-by-route
|
|
6
|
+
* against the live source. Each tool declares its canonical path (`routePath`)
|
|
7
|
+
* and the registry gate (tools/registry.test.ts) asserts it against the
|
|
8
|
+
* allowlist in route-families.ts — no phantom routes can be re-introduced.
|
|
3
9
|
*
|
|
4
10
|
* Each tool is declared with:
|
|
5
11
|
* - inputShape : a Zod raw shape (validated by the McpServer before dispatch)
|
|
@@ -11,88 +17,63 @@
|
|
|
11
17
|
* structured content. The CapixApiError (problem+json) thrown by the client is
|
|
12
18
|
* caught by the server wrapper and surfaced as an MCP error result.
|
|
13
19
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
20
|
+
* CRUD-shaped tools are declared with `defineGeneratedTool` (tools/generate.ts)
|
|
21
|
+
* — a declarative spec (method, path, input) from which the registration AND
|
|
22
|
+
* the HTTP call are generated — instead of a hand-written handler. Everything
|
|
23
|
+
* else uses `defineTool` (tools/define-tool.ts) with an explicit handler.
|
|
24
|
+
*
|
|
25
|
+
* Tools are grouped by scope:
|
|
26
|
+
* discovery (7) · planning (2) · lifecycle (19) · verification (1) ·
|
|
27
|
+
* website (6) · infra-context (2)
|
|
28
|
+
* (The factory tools — jobs/training/agent-deploys — live in
|
|
29
|
+
* tools/factory.ts and join lifecycle; the meme/image tools live in
|
|
30
|
+
* tools/memes.ts: the meme catalog joins discovery, the two billable
|
|
31
|
+
* generators join lifecycle.)
|
|
32
|
+
*
|
|
33
|
+
* Removed in the repair (no backing route in the control plane — hidden, not
|
|
34
|
+
* deleted from git history):
|
|
35
|
+
* - networking scope (8 tools): /api/v1/networking/* and /api/v1/vpc do not
|
|
36
|
+
* exist. Returns with the networking roadmap (N1–N5).
|
|
37
|
+
* - testing scope (6 tools): /api/v1/testing/* does not exist (disposable
|
|
38
|
+
* test envs are not built).
|
|
39
|
+
* - attestation/zkVM/measurement tools (5): /api/v1/verification/* and
|
|
40
|
+
* /api/v1/attestations do not exist. Secured Cloud (TEE/zkVM) is deferred.
|
|
41
|
+
* - planning stubs (capix_compute_plan, capix_model_plan, capix_stack_*):
|
|
42
|
+
* /api/v1/planning/* does not exist; quoting lives at /api/v1/quotes.
|
|
43
|
+
* - lifecycle stubs (capix_start/stop/restart/extend): start/stop exist
|
|
44
|
+
* upstream ONLY as PATCH /api/v1/deployments/[id] { desiredState } with a
|
|
45
|
+
* mandatory If-Match etag — unreachable through the current client
|
|
46
|
+
* surface (no PATCH, no etag access). Restart/extend have no backend.
|
|
47
|
+
* - discovery stubs: capix_projects (no /api/v1/projects),
|
|
48
|
+
* capix_model_catalog (real catalog is /api/v1/models, covered by
|
|
49
|
+
* capix_model_list), capix_attestations (Secured Cloud deferred).
|
|
50
|
+
* - website stubs (12 tools): singular /api/v1/website/* never existed and
|
|
51
|
+
* detect/plan/quote/deploy/preview/deployments/logs/metrics/domains have
|
|
52
|
+
* no routes under the real /api/v1/websites family (build logs surface as
|
|
53
|
+
* `logTail` inside capix_website_get; previews are implicit per release).
|
|
54
|
+
* - infra-context stubs: capix_node_status, capix_earnings_check (no
|
|
55
|
+
* /api/v1/nodes/status or /api/v1/earnings), capix_deployment_list
|
|
56
|
+
* (duplicate of capix_deployments).
|
|
17
57
|
*/
|
|
18
58
|
import { z } from "zod";
|
|
19
59
|
import { APPROVAL_ONLY, BILLABLE, READ_ONLY, } from "./types.js";
|
|
60
|
+
import { defineTool } from "./tools/define-tool.js";
|
|
61
|
+
import { defineGeneratedTool } from "./tools/generate.js";
|
|
62
|
+
import { factoryTools } from "./tools/factory.js";
|
|
63
|
+
import { infraContextTools } from "./tools/infra-context.js";
|
|
64
|
+
import { memeImageTools } from "./tools/memes.js";
|
|
20
65
|
// ===========================================================================
|
|
21
66
|
// Reusable Zod fragments
|
|
22
67
|
// ===========================================================================
|
|
23
68
|
const iso8601 = z.string().datetime().or(z.string());
|
|
24
|
-
const moneyShape = z.object({
|
|
25
|
-
amount: z.string().describe("Integer minor units (e.g. lamports, micro-USDC, cents)."),
|
|
26
|
-
asset: z.enum(["SOL", "USDC", "USD-credit"]),
|
|
27
|
-
scale: z.number().int(),
|
|
28
|
-
}).describe("Integer minor/native money amount serialized as a JSON string.");
|
|
29
69
|
const deploymentIdShape = z.string().describe("Canonical deployment id (dep_…).");
|
|
30
70
|
const operationIdShape = z.string().describe("Canonical operation id (op_…).");
|
|
31
|
-
const quoteIdShape = z.string().describe("Canonical quote id
|
|
32
|
-
const siteIdShape = z.string().describe("Capix website
|
|
33
|
-
const listResultShape = {
|
|
34
|
-
entries: z.array(z.record(z.unknown())).optional().describe("Paginated item array."),
|
|
35
|
-
nextCursor: z.string().optional().describe("Opaque cursor for the next page; absent when exhausted."),
|
|
36
|
-
fetchedAt: iso8601.optional().describe("ISO8601 fetch timestamp."),
|
|
37
|
-
};
|
|
38
|
-
const quoteResultShape = {
|
|
39
|
-
quoteId: quoteIdShape.optional(),
|
|
40
|
-
price: moneyShape.optional(),
|
|
41
|
-
providerCostBasis: moneyShape.optional(),
|
|
42
|
-
fees: moneyShape.optional(),
|
|
43
|
-
margin: moneyShape.optional(),
|
|
44
|
-
provider: z.string().optional(),
|
|
45
|
-
region: z.string().optional(),
|
|
46
|
-
expiresAt: iso8601.optional(),
|
|
47
|
-
feasible: z.boolean().optional(),
|
|
48
|
-
};
|
|
49
|
-
const deploymentResultShape = {
|
|
50
|
-
deploymentId: deploymentIdShape.optional(),
|
|
51
|
-
operationId: operationIdShape.optional(),
|
|
52
|
-
phase: z.string().optional().describe("DeploymentPhase after mutation."),
|
|
53
|
-
quoteId: quoteIdShape.optional(),
|
|
54
|
-
holdId: z.string().optional().describe("Ledger hold that funds the deployment."),
|
|
55
|
-
estimatedCost: moneyShape.optional(),
|
|
56
|
-
acceptedAt: iso8601.optional(),
|
|
57
|
-
};
|
|
58
|
-
const networkResourceShape = {
|
|
59
|
-
resourceId: z.string().optional(),
|
|
60
|
-
kind: z.string().optional().describe("vpc | endpoint | port_forward | private_connection | dedicated_ip."),
|
|
61
|
-
deploymentId: deploymentIdShape.optional(),
|
|
62
|
-
status: z.enum(["provisioning", "ready", "failed", "destroyed"]).optional(),
|
|
63
|
-
endpoint: z.string().optional(),
|
|
64
|
-
acceptedAt: iso8601.optional(),
|
|
65
|
-
};
|
|
66
|
-
const siteResultShape = {
|
|
67
|
-
siteId: siteIdShape.optional(),
|
|
68
|
-
deploymentId: z.string().optional(),
|
|
69
|
-
url: z.string().optional(),
|
|
70
|
-
status: z.enum(["queued", "building", "ready", "failed"]).optional(),
|
|
71
|
-
estimatedCost: moneyShape.optional(),
|
|
72
|
-
acceptedAt: iso8601.optional(),
|
|
73
|
-
};
|
|
71
|
+
const quoteIdShape = z.string().describe("Canonical quote id from capix_compute_quote / capix_model_quote.");
|
|
72
|
+
const siteIdShape = z.string().describe("Capix website id.");
|
|
74
73
|
// ===========================================================================
|
|
75
|
-
// defineTool —
|
|
74
|
+
// defineTool — imported from tools/define-tool.ts (shared with sibling tool
|
|
75
|
+
// modules such as tools/infra-context.ts; see that file for the doc comment).
|
|
76
76
|
// ===========================================================================
|
|
77
|
-
/**
|
|
78
|
-
* Declare a Capix tool with a Zod raw input shape. The handler receives
|
|
79
|
-
* Zod-validated arguments (typed via inference) plus the Capix API client and
|
|
80
|
-
* call context; it returns the upstream JSON object as structured content.
|
|
81
|
-
*/
|
|
82
|
-
function defineTool(opts) {
|
|
83
|
-
return {
|
|
84
|
-
name: opts.name,
|
|
85
|
-
description: opts.description,
|
|
86
|
-
scope: opts.scope,
|
|
87
|
-
billable: opts.billable,
|
|
88
|
-
requiresApproval: opts.requiresApproval,
|
|
89
|
-
inputShape: opts.inputShape,
|
|
90
|
-
outputShape: opts.outputShape,
|
|
91
|
-
// Sound cast: the McpServer validates args against inputShape before
|
|
92
|
-
// invoking the handler, so the inferred arg shape is guaranteed at runtime.
|
|
93
|
-
handler: opts.handler,
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
77
|
/** Convenience: pull a string argument, throwing a typed error if missing. */
|
|
97
78
|
function asStr(value, field) {
|
|
98
79
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -103,982 +84,435 @@ function asStr(value, field) {
|
|
|
103
84
|
}
|
|
104
85
|
return value;
|
|
105
86
|
}
|
|
106
|
-
/** Call the client, passing the approval token through for billable tools. */
|
|
107
|
-
async function callBillable(client, approvalToken, path, body) {
|
|
108
|
-
if (!approvalToken) {
|
|
109
|
-
const err = new Error("approvalToken is required for this billable tool (§5)");
|
|
110
|
-
err.capixCode = "approval_required";
|
|
111
|
-
err.status = 402;
|
|
112
|
-
throw err;
|
|
113
|
-
}
|
|
114
|
-
return client.post(path, body, { idempotent: true, approvalToken });
|
|
115
|
-
}
|
|
116
87
|
// ===========================================================================
|
|
117
|
-
// Discovery tools (
|
|
88
|
+
// Discovery tools (6) — read-only, auto-run after authentication.
|
|
89
|
+
// (capix_meme_templates from tools/memes.ts is the 7th discovery tool.)
|
|
118
90
|
// ===========================================================================
|
|
119
91
|
const discoveryTools = [
|
|
120
92
|
defineTool({
|
|
121
93
|
name: "capix_account",
|
|
122
|
-
description: "Inspect the authenticated account: wallet address,
|
|
94
|
+
description: "Inspect the authenticated account: id, email, wallet address, billing status, identities, devices. Read-only — safe to auto-run.",
|
|
123
95
|
scope: "discovery",
|
|
124
96
|
...READ_ONLY,
|
|
97
|
+
routePath: "/api/v1/account",
|
|
125
98
|
inputShape: {},
|
|
126
99
|
outputShape: {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
lastBilledAt: iso8601.optional(),
|
|
100
|
+
id: z.string().optional(),
|
|
101
|
+
email: z.string().optional(),
|
|
102
|
+
wallet_address: z.string().optional(),
|
|
103
|
+
billing_status: z.string().optional(),
|
|
104
|
+
identities: z.array(z.record(z.unknown())).optional(),
|
|
105
|
+
devices: z.array(z.record(z.unknown())).optional(),
|
|
134
106
|
},
|
|
135
107
|
handler: async (_args, { client }) => client.get("/api/v1/account"),
|
|
136
108
|
}),
|
|
137
109
|
defineTool({
|
|
138
110
|
name: "capix_balance",
|
|
139
|
-
description: "Get the
|
|
111
|
+
description: "Get the account balances (SOL / USDC ledger), USD valuation, and recent transactions. Read-only.",
|
|
140
112
|
scope: "discovery",
|
|
141
113
|
...READ_ONLY,
|
|
114
|
+
routePath: "/api/v1/billing",
|
|
142
115
|
inputShape: {
|
|
143
116
|
asset: z.enum(["SOL", "USDC", "USD-credit"]).optional().describe("Optional asset filter."),
|
|
144
117
|
},
|
|
145
118
|
outputShape: {
|
|
119
|
+
ok: z.boolean().optional(),
|
|
146
120
|
accountId: z.string().optional(),
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
asOf: iso8601.optional(),
|
|
121
|
+
balances: z.record(z.unknown()).optional(),
|
|
122
|
+
valuation: z.record(z.unknown()).optional(),
|
|
123
|
+
transactions: z.array(z.record(z.unknown())).optional(),
|
|
124
|
+
nextCursor: z.string().optional(),
|
|
152
125
|
},
|
|
153
|
-
handler: async (args, { client }) => client.get("/api/v1/
|
|
126
|
+
handler: async (args, { client }) => client.get("/api/v1/billing", {
|
|
154
127
|
asset: args.asset,
|
|
155
128
|
}),
|
|
156
129
|
}),
|
|
157
|
-
defineTool({
|
|
158
|
-
name: "capix_projects",
|
|
159
|
-
description: "List projects visible to the authenticated account. Read-only.",
|
|
160
|
-
scope: "discovery",
|
|
161
|
-
...READ_ONLY,
|
|
162
|
-
inputShape: {
|
|
163
|
-
limit: z.number().int().min(1).max(200).default(50).describe("Max projects to return."),
|
|
164
|
-
},
|
|
165
|
-
outputShape: listResultShape,
|
|
166
|
-
handler: async (args, { client }) => client.get("/api/v1/projects", { limit: args.limit }),
|
|
167
|
-
}),
|
|
168
130
|
defineTool({
|
|
169
131
|
name: "capix_compute_catalog",
|
|
170
|
-
description: "List the
|
|
171
|
-
|
|
172
|
-
...READ_ONLY,
|
|
173
|
-
inputShape: {
|
|
174
|
-
region: z.string().optional().describe("Optional region filter."),
|
|
175
|
-
gpu: z.boolean().optional().describe("Restrict to GPU-capable entries."),
|
|
176
|
-
},
|
|
177
|
-
outputShape: {
|
|
178
|
-
entries: z.array(z.record(z.unknown())).optional(),
|
|
179
|
-
catalogVersion: z.string().optional(),
|
|
180
|
-
fetchedAt: iso8601.optional(),
|
|
181
|
-
},
|
|
182
|
-
handler: async (args, { client }) => client.get("/api/v1/catalog/compute", {
|
|
183
|
-
region: args.region,
|
|
184
|
-
gpu: args.gpu,
|
|
185
|
-
}),
|
|
186
|
-
}),
|
|
187
|
-
defineTool({
|
|
188
|
-
name: "capix_model_catalog",
|
|
189
|
-
description: "List the live model endpoint catalog (model id, context length, price per 1k tokens). Read-only.",
|
|
132
|
+
description: "List the enabled compute capability catalog: workload types (with features) and " +
|
|
133
|
+
"configured providers/regions. Public; reflects live feature gates. Read-only.",
|
|
190
134
|
scope: "discovery",
|
|
191
135
|
...READ_ONLY,
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
},
|
|
136
|
+
routePath: "/api/v1/catalog/capabilities",
|
|
137
|
+
inputShape: {},
|
|
195
138
|
outputShape: {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
139
|
+
workloadTypes: z.array(z.record(z.unknown())).optional(),
|
|
140
|
+
providers: z.array(z.record(z.unknown())).optional(),
|
|
141
|
+
regions: z.array(z.string()).optional(),
|
|
142
|
+
releaseId: z.string().optional(),
|
|
143
|
+
timestamp: iso8601.optional(),
|
|
199
144
|
},
|
|
200
|
-
handler: async (
|
|
201
|
-
provider: args.provider,
|
|
202
|
-
}),
|
|
145
|
+
handler: async (_args, { client }) => client.get("/api/v1/catalog/capabilities"),
|
|
203
146
|
}),
|
|
204
147
|
defineTool({
|
|
205
148
|
name: "capix_network_status",
|
|
206
|
-
description: "Inspect
|
|
149
|
+
description: "Inspect the Capix service health: status, version, release, and live feature gates " +
|
|
150
|
+
"(real money, provider writes, distributed, smart router, …). Public. Read-only.",
|
|
207
151
|
scope: "discovery",
|
|
208
152
|
...READ_ONLY,
|
|
153
|
+
routePath: "/api/v1/health",
|
|
209
154
|
inputShape: {},
|
|
210
155
|
outputShape: {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
156
|
+
status: z.string().optional(),
|
|
157
|
+
service: z.string().optional(),
|
|
158
|
+
version: z.string().optional(),
|
|
159
|
+
releaseId: z.string().optional(),
|
|
160
|
+
features: z.record(z.unknown()).optional(),
|
|
161
|
+
timestamp: iso8601.optional(),
|
|
217
162
|
},
|
|
218
|
-
handler: async (_args, { client }) => client.get("/api/v1/
|
|
163
|
+
handler: async (_args, { client }) => client.get("/api/v1/health"),
|
|
219
164
|
}),
|
|
220
|
-
|
|
165
|
+
defineGeneratedTool({
|
|
221
166
|
name: "capix_deployments",
|
|
222
167
|
description: "List deployments for the account/project with phase + allocation state. Read-only.",
|
|
223
168
|
scope: "discovery",
|
|
224
169
|
...READ_ONLY,
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
170
|
+
method: "GET",
|
|
171
|
+
path: "/api/v1/deployments",
|
|
172
|
+
input: {
|
|
173
|
+
limit: z.number().int().min(1).max(100).default(25).describe("Max deployments to return (upstream bounds)."),
|
|
174
|
+
status: z.string().optional().describe("Optional phase filter (the upstream query param is `status`)."),
|
|
175
|
+
cursor: z.string().optional().describe("Opaque pagination cursor from a previous page."),
|
|
176
|
+
projectId: z.string().optional(),
|
|
177
|
+
},
|
|
178
|
+
outputShape: {
|
|
179
|
+
data: z.array(z.record(z.unknown())).optional(),
|
|
180
|
+
cursor: z.string().optional(),
|
|
181
|
+
hasMore: z.boolean().optional(),
|
|
228
182
|
},
|
|
229
|
-
outputShape: listResultShape,
|
|
230
|
-
handler: async (args, { client }) => client.get("/api/v1/deployments", {
|
|
231
|
-
limit: args.limit,
|
|
232
|
-
phase: args.phase,
|
|
233
|
-
}),
|
|
234
183
|
}),
|
|
235
|
-
|
|
184
|
+
defineGeneratedTool({
|
|
236
185
|
name: "capix_receipts",
|
|
237
|
-
description: "List
|
|
186
|
+
description: "List work receipts (task/commit approval records) for the account. Read-only.",
|
|
238
187
|
scope: "discovery",
|
|
239
188
|
...READ_ONLY,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
189
|
+
method: "GET",
|
|
190
|
+
path: "/api/v1/receipts",
|
|
191
|
+
input: {
|
|
192
|
+
limit: z.number().int().min(1).max(100).default(25),
|
|
193
|
+
approvalStatus: z.string().optional().describe("Optional approval-status filter."),
|
|
194
|
+
agentId: z.string().optional().describe("Optional agent filter."),
|
|
195
|
+
cursor: z.string().optional(),
|
|
196
|
+
projectId: z.string().optional(),
|
|
243
197
|
},
|
|
244
|
-
outputShape:
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}),
|
|
249
|
-
}),
|
|
250
|
-
defineTool({
|
|
251
|
-
name: "capix_attestations",
|
|
252
|
-
description: "List attestation evidence records for the account (TEE / zkVM). Read-only.",
|
|
253
|
-
scope: "discovery",
|
|
254
|
-
...READ_ONLY,
|
|
255
|
-
inputShape: {
|
|
256
|
-
limit: z.number().int().min(1).max(200).default(50),
|
|
257
|
-
kind: z.enum(["tee", "zkvm"]).optional().describe("Optional attestation kind filter."),
|
|
198
|
+
outputShape: {
|
|
199
|
+
data: z.array(z.record(z.unknown())).optional(),
|
|
200
|
+
cursor: z.string().optional(),
|
|
201
|
+
hasMore: z.boolean().optional(),
|
|
258
202
|
},
|
|
259
|
-
outputShape: listResultShape,
|
|
260
|
-
handler: async (args, { client }) => client.get("/api/v1/attestations", {
|
|
261
|
-
limit: args.limit,
|
|
262
|
-
kind: args.kind,
|
|
263
|
-
}),
|
|
264
203
|
}),
|
|
265
204
|
];
|
|
266
205
|
// ===========================================================================
|
|
267
|
-
// Planning tools (
|
|
206
|
+
// Planning tools (2) — read-only quoting against POST /api/v1/quotes.
|
|
207
|
+
// The old /api/v1/planning/* family does not exist; the canonical quote route
|
|
208
|
+
// is /api/v1/quotes (15-minute TTL, locks price/cost/fees/margin/FX/expiry).
|
|
209
|
+
// The route REQUIRES an Idempotency-Key header even though quoting moves no
|
|
210
|
+
// money, so both tools post with the client's idempotency key.
|
|
268
211
|
// ===========================================================================
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
gpuCount: z.number().int().min(1).optional(),
|
|
287
|
-
region: z.string().optional(),
|
|
288
|
-
maxPriceUsdHourly: z.number().optional(),
|
|
289
|
-
maxConcurrency: z.number().int().min(1).optional(),
|
|
290
|
-
};
|
|
291
|
-
const stackManifestShape = {
|
|
292
|
-
name: z.string(),
|
|
293
|
-
services: z.array(z.record(z.unknown())),
|
|
294
|
-
network: z.record(z.unknown()).optional(),
|
|
295
|
-
region: z.string().optional(),
|
|
212
|
+
/** Workload types accepted by POST /api/v1/quotes (workloadSpec.type). */
|
|
213
|
+
const WORKLOAD_TYPES = [
|
|
214
|
+
"dedicated_machine.v1",
|
|
215
|
+
"private_inference.v1",
|
|
216
|
+
"remote_workspace.v1",
|
|
217
|
+
"replicated_service.v1",
|
|
218
|
+
"sharded_batch.v1",
|
|
219
|
+
"agent_run.v1",
|
|
220
|
+
];
|
|
221
|
+
const quoteResultShape = {
|
|
222
|
+
id: quoteIdShape.optional(),
|
|
223
|
+
price: z.record(z.unknown()).optional(),
|
|
224
|
+
providerCostBasis: z.record(z.unknown()).optional(),
|
|
225
|
+
fees: z.record(z.unknown()).optional(),
|
|
226
|
+
margin: z.record(z.unknown()).optional(),
|
|
227
|
+
expiresAt: iso8601.optional(),
|
|
228
|
+
state: z.string().optional(),
|
|
296
229
|
};
|
|
297
230
|
const planningTools = [
|
|
298
|
-
|
|
299
|
-
name: "capix_compute_plan",
|
|
300
|
-
description: "Plan a compute deployment: pick provider/region/spec for the requested workload shape. Read-only.",
|
|
301
|
-
scope: "planning",
|
|
302
|
-
...READ_ONLY,
|
|
303
|
-
inputShape: computeSpecShape,
|
|
304
|
-
outputShape: {
|
|
305
|
-
feasible: z.boolean(),
|
|
306
|
-
provider: z.string().optional(),
|
|
307
|
-
region: z.string().optional(),
|
|
308
|
-
cpu: z.number().int().optional(),
|
|
309
|
-
ramMb: z.number().int().optional(),
|
|
310
|
-
storageGb: z.number().int().optional(),
|
|
311
|
-
gpu: z.number().int().optional(),
|
|
312
|
-
estimatedCostHourly: moneyShape.optional(),
|
|
313
|
-
estimatedCostTotal: moneyShape.optional(),
|
|
314
|
-
notes: z.string().optional(),
|
|
315
|
-
},
|
|
316
|
-
handler: async (args, { client }) => client.post("/api/v1/planning/compute/plan", args),
|
|
317
|
-
}),
|
|
318
|
-
defineTool({
|
|
231
|
+
defineGeneratedTool({
|
|
319
232
|
name: "capix_compute_quote",
|
|
320
|
-
description: "Get a canonical quote for a compute
|
|
233
|
+
description: "Get a canonical quote for a compute workload (locks price/fees/FX/expiry for 15 min). " +
|
|
234
|
+
"Read-only intent; the quote route still requires an Idempotency-Key, which the client supplies.",
|
|
321
235
|
scope: "planning",
|
|
322
236
|
...READ_ONLY,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
237
|
+
method: "POST",
|
|
238
|
+
path: "/api/v1/quotes",
|
|
239
|
+
// Read-only, but the route rejects requests without an Idempotency-Key.
|
|
240
|
+
idempotent: true,
|
|
241
|
+
input: {
|
|
242
|
+
workloadSpec: z
|
|
243
|
+
.object({
|
|
244
|
+
type: z.enum(WORKLOAD_TYPES),
|
|
245
|
+
cpu: z.number().positive(),
|
|
246
|
+
ramMb: z.number().positive(),
|
|
247
|
+
storageGb: z.number().min(0),
|
|
248
|
+
gpu: z.number().min(0).optional(),
|
|
249
|
+
vramMb: z.number().min(0).optional(),
|
|
250
|
+
region: z.string().optional().describe("eu | us | asia | global."),
|
|
251
|
+
maxDurationHours: z.number().optional(),
|
|
252
|
+
maxSpendUsd: z.number().optional(),
|
|
253
|
+
})
|
|
254
|
+
.describe("Workload shape quoted upstream."),
|
|
255
|
+
placementPolicy: z.record(z.unknown()).optional(),
|
|
256
|
+
paymentAsset: z.enum(["AUTO", "SOL", "USDC"]).optional(),
|
|
257
|
+
projectId: z.string().optional(),
|
|
341
258
|
},
|
|
342
|
-
handler: async (args, { client }) => client.post("/api/v1/planning/model/plan", args),
|
|
343
|
-
}),
|
|
344
|
-
defineTool({
|
|
345
|
-
name: "capix_model_quote",
|
|
346
|
-
description: "Get a canonical quote for a model endpoint plan. Read-only.",
|
|
347
|
-
scope: "planning",
|
|
348
|
-
...READ_ONLY,
|
|
349
|
-
inputShape: modelSpecShape,
|
|
350
259
|
outputShape: quoteResultShape,
|
|
351
|
-
handler: async (args, { client }) => client.post("/api/v1/planning/model/quote", args),
|
|
352
|
-
}),
|
|
353
|
-
defineTool({
|
|
354
|
-
name: "capix_stack_validate",
|
|
355
|
-
description: "Validate a stack manifest (services, dependencies, network) without provisioning. Read-only.",
|
|
356
|
-
scope: "planning",
|
|
357
|
-
...READ_ONLY,
|
|
358
|
-
inputShape: stackManifestShape,
|
|
359
|
-
outputShape: {
|
|
360
|
-
valid: z.boolean(),
|
|
361
|
-
errors: z.array(z.string()).optional(),
|
|
362
|
-
warnings: z.array(z.string()).optional(),
|
|
363
|
-
},
|
|
364
|
-
handler: async (args, { client }) => client.post("/api/v1/planning/stack/validate", args),
|
|
365
260
|
}),
|
|
366
261
|
defineTool({
|
|
367
|
-
name: "
|
|
368
|
-
description: "
|
|
262
|
+
name: "capix_model_quote",
|
|
263
|
+
description: "Get a canonical quote for a private model endpoint (private_inference.v1) hosting " +
|
|
264
|
+
"the given model. Read-only intent; the quote route still requires an Idempotency-Key, " +
|
|
265
|
+
"which the client supplies.",
|
|
369
266
|
scope: "planning",
|
|
370
267
|
...READ_ONLY,
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
268
|
+
routePath: "/api/v1/quotes",
|
|
269
|
+
inputShape: {
|
|
270
|
+
modelId: z.string().describe("Model id from capix_model_list."),
|
|
271
|
+
cpu: z.number().positive().describe("vCPUs for the endpoint (required upstream)."),
|
|
272
|
+
ramMb: z.number().positive().describe("RAM for the endpoint (required upstream)."),
|
|
273
|
+
storageGb: z.number().min(0).describe("Storage for weights/cache (required upstream)."),
|
|
274
|
+
gpu: z.number().int().min(1).optional(),
|
|
275
|
+
vramMb: z.number().int().min(0).optional(),
|
|
276
|
+
region: z.string().optional().describe("eu | us | asia | global."),
|
|
277
|
+
maxDurationHours: z.number().optional(),
|
|
278
|
+
paymentAsset: z.enum(["AUTO", "SOL", "USDC"]).optional(),
|
|
279
|
+
projectId: z.string().optional(),
|
|
377
280
|
},
|
|
378
|
-
|
|
281
|
+
outputShape: quoteResultShape,
|
|
282
|
+
handler: async (args, { client }) => client.post("/api/v1/quotes", {
|
|
283
|
+
workloadSpec: {
|
|
284
|
+
type: "private_inference.v1",
|
|
285
|
+
cpu: args.cpu,
|
|
286
|
+
ramMb: args.ramMb,
|
|
287
|
+
storageGb: args.storageGb,
|
|
288
|
+
gpu: args.gpu,
|
|
289
|
+
vramMb: args.vramMb,
|
|
290
|
+
region: args.region,
|
|
291
|
+
maxDurationHours: args.maxDurationHours,
|
|
292
|
+
payload: { modelId: asStr(args.modelId, "modelId"), source: "capix-mcp" },
|
|
293
|
+
},
|
|
294
|
+
paymentAsset: args.paymentAsset,
|
|
295
|
+
projectId: args.projectId,
|
|
296
|
+
}, { idempotent: true }),
|
|
379
297
|
}),
|
|
380
298
|
];
|
|
381
299
|
// ===========================================================================
|
|
382
|
-
// Lifecycle tools (
|
|
300
|
+
// Lifecycle tools (3 here) — billable mutations, require approval.
|
|
301
|
+
// The factory tools (jobs/training/agent-deploys, tools/factory.ts) and the
|
|
302
|
+
// two meme/image generators (tools/memes.ts) join this scope: 19 total.
|
|
303
|
+
//
|
|
304
|
+
// Removed: capix_start / capix_stop / capix_restart / capix_extend.
|
|
305
|
+
// Start/stop exist upstream ONLY as PATCH /api/v1/deployments/[id]
|
|
306
|
+
// { desiredState: "RUNNING" | "STOPPED" } with a mandatory If-Match etag —
|
|
307
|
+
// unreachable through the current CapixClientLike surface (no PATCH method,
|
|
308
|
+
// no etag access). Restart/extend have no backend at all. They return when
|
|
309
|
+
// the client grows PATCH+etag support (see route-families.ts).
|
|
383
310
|
// ===========================================================================
|
|
311
|
+
const deploymentResultShape = {
|
|
312
|
+
operation: z.record(z.unknown()).optional().describe("Long-running operation (poll via its id)."),
|
|
313
|
+
deployment: z.record(z.unknown()).optional(),
|
|
314
|
+
settlement: z.record(z.unknown()).optional().describe("Early-termination settlement, when applicable."),
|
|
315
|
+
};
|
|
384
316
|
const lifecycleTools = [
|
|
385
|
-
|
|
317
|
+
defineGeneratedTool({
|
|
386
318
|
name: "capix_deploy",
|
|
387
|
-
description: "Deploy a workload against a canonical quote
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
inputShape: {
|
|
391
|
-
quoteId: quoteIdShape.describe("Canonical quote from capix_compute_quote / capix_model_quote."),
|
|
392
|
-
workloadType: z.string(),
|
|
393
|
-
region: z.string().optional(),
|
|
394
|
-
imageDigest: z.string().optional(),
|
|
395
|
-
durationHours: z.number().min(1).optional(),
|
|
396
|
-
env: z.record(z.string()).optional(),
|
|
397
|
-
ingress: z.array(z.number().int()).optional(),
|
|
398
|
-
},
|
|
399
|
-
outputShape: deploymentResultShape,
|
|
400
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/lifecycle/deployments", args),
|
|
401
|
-
}),
|
|
402
|
-
defineTool({
|
|
403
|
-
name: "capix_start",
|
|
404
|
-
description: "Start a stopped deployment. Billable (resumes metering); requires approval.",
|
|
319
|
+
description: "Deploy a workload against a canonical quote (from capix_compute_quote / " +
|
|
320
|
+
"capix_model_quote). Takes a ledger hold and returns a long-running operation. " +
|
|
321
|
+
"Billable; requires approval.",
|
|
405
322
|
scope: "lifecycle",
|
|
406
323
|
...BILLABLE,
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}),
|
|
413
|
-
defineTool({
|
|
414
|
-
name: "capix_stop",
|
|
415
|
-
description: "Stop a running deployment (halts metering, keeps allocation). Billable (minimal); requires approval.",
|
|
416
|
-
scope: "lifecycle",
|
|
417
|
-
...BILLABLE,
|
|
418
|
-
inputShape: {
|
|
419
|
-
deploymentId: deploymentIdShape,
|
|
420
|
-
},
|
|
421
|
-
outputShape: deploymentResultShape,
|
|
422
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/lifecycle/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/stop`),
|
|
423
|
-
}),
|
|
424
|
-
defineTool({
|
|
425
|
-
name: "capix_restart",
|
|
426
|
-
description: "Restart a deployment (stop + start cycle). Billable; requires approval.",
|
|
427
|
-
scope: "lifecycle",
|
|
428
|
-
...BILLABLE,
|
|
429
|
-
inputShape: {
|
|
430
|
-
deploymentId: deploymentIdShape,
|
|
324
|
+
method: "POST",
|
|
325
|
+
path: "/api/v1/deployments",
|
|
326
|
+
input: {
|
|
327
|
+
quoteId: quoteIdShape,
|
|
328
|
+
projectId: z.string().optional(),
|
|
431
329
|
},
|
|
432
330
|
outputShape: deploymentResultShape,
|
|
433
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/lifecycle/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/restart`),
|
|
434
331
|
}),
|
|
435
|
-
|
|
332
|
+
defineGeneratedTool({
|
|
436
333
|
name: "capix_delete",
|
|
437
|
-
description: "
|
|
334
|
+
description: "Terminate a deployment and release its allocation (settles early termination). " +
|
|
335
|
+
"Destructive; billable; requires approval.",
|
|
438
336
|
scope: "lifecycle",
|
|
439
337
|
...BILLABLE,
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
338
|
+
method: "DELETE",
|
|
339
|
+
path: "/api/v1/deployments/:id",
|
|
340
|
+
input: {
|
|
341
|
+
id: deploymentIdShape,
|
|
443
342
|
},
|
|
444
343
|
outputShape: deploymentResultShape,
|
|
445
|
-
handler: async (args, { client, ctx }) => {
|
|
446
|
-
const id = asStr(args.deploymentId, "deploymentId");
|
|
447
|
-
const res = await callBillable(client, ctx.approvalToken, `/api/v1/lifecycle/deployments/${encodeURIComponent(id)}`, args.reason ? { reason: args.reason } : undefined);
|
|
448
|
-
// DELETE semantics: the canonical route is DELETE; some gateways express
|
|
449
|
-
// the mutation via POST with idempotency. Use the client delete path with
|
|
450
|
-
// an approval header via a light POST-to-delete fallback.
|
|
451
|
-
return res;
|
|
452
|
-
},
|
|
453
344
|
}),
|
|
454
|
-
|
|
455
|
-
name: "capix_extend",
|
|
456
|
-
description: "Extend a running deployment by additional hours against a fresh hold. Billable; requires approval.",
|
|
457
|
-
scope: "lifecycle",
|
|
458
|
-
...BILLABLE,
|
|
459
|
-
inputShape: {
|
|
460
|
-
deploymentId: deploymentIdShape,
|
|
461
|
-
durationHours: z.number().min(1),
|
|
462
|
-
quoteId: quoteIdShape.optional().describe("Canonical quote for the extension cost."),
|
|
463
|
-
},
|
|
464
|
-
outputShape: deploymentResultShape,
|
|
465
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/lifecycle/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/extend`, { durationHours: args.durationHours, quoteId: args.quoteId }),
|
|
466
|
-
}),
|
|
467
|
-
defineTool({
|
|
345
|
+
defineGeneratedTool({
|
|
468
346
|
name: "capix_cancel",
|
|
469
|
-
description: "Cancel an in-flight operation (
|
|
347
|
+
description: "Cancel an in-flight operation (sets CANCELLING; 409 on terminal states). " +
|
|
348
|
+
"Requires approval to mutate.",
|
|
470
349
|
scope: "lifecycle",
|
|
471
350
|
...APPROVAL_ONLY,
|
|
472
|
-
|
|
351
|
+
method: "POST",
|
|
352
|
+
path: "/api/v1/operations/:operationId",
|
|
353
|
+
input: {
|
|
473
354
|
operationId: operationIdShape,
|
|
474
|
-
reason: z.string().optional(),
|
|
475
|
-
},
|
|
476
|
-
outputShape: {
|
|
477
|
-
operationId: operationIdShape.optional(),
|
|
478
|
-
status: z.string().optional(),
|
|
479
|
-
acceptedAt: iso8601.optional(),
|
|
480
|
-
},
|
|
481
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/operations/${encodeURIComponent(asStr(args.operationId, "operationId"))}/cancel`, args.reason ? { reason: args.reason } : undefined),
|
|
482
|
-
}),
|
|
483
|
-
];
|
|
484
|
-
// ===========================================================================
|
|
485
|
-
// Networking tools (8) — billable mutations + read-only inspection.
|
|
486
|
-
// ===========================================================================
|
|
487
|
-
const networkingTools = [
|
|
488
|
-
defineTool({
|
|
489
|
-
name: "capix_create_vpc",
|
|
490
|
-
description: "Create a VPC for a project. Billable; requires approval.",
|
|
491
|
-
scope: "networking",
|
|
492
|
-
...BILLABLE,
|
|
493
|
-
inputShape: {
|
|
494
|
-
cidr: z.string().describe("VPC CIDR block, e.g. 10.0.0.0/16."),
|
|
495
|
-
region: z.string(),
|
|
496
|
-
name: z.string().optional(),
|
|
497
|
-
},
|
|
498
|
-
outputShape: networkResourceShape,
|
|
499
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/vpcs", args),
|
|
500
|
-
}),
|
|
501
|
-
defineTool({
|
|
502
|
-
name: "capix_create_endpoint",
|
|
503
|
-
description: "Create a public endpoint for a deployment. Billable; requires approval.",
|
|
504
|
-
scope: "networking",
|
|
505
|
-
...BILLABLE,
|
|
506
|
-
inputShape: {
|
|
507
|
-
deploymentId: deploymentIdShape,
|
|
508
|
-
port: z.number().int().min(1).max(65535),
|
|
509
|
-
protocol: z.enum(["http", "https", "tcp"]).default("http"),
|
|
510
|
-
hostname: z.string().optional().describe("Optional requested hostname."),
|
|
511
|
-
},
|
|
512
|
-
outputShape: networkResourceShape,
|
|
513
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/endpoints", args),
|
|
514
|
-
}),
|
|
515
|
-
defineTool({
|
|
516
|
-
name: "capix_expose_port",
|
|
517
|
-
description: "Expose a port (ingress) to the public internet. Billable; requires approval.",
|
|
518
|
-
scope: "networking",
|
|
519
|
-
...BILLABLE,
|
|
520
|
-
inputShape: {
|
|
521
|
-
deploymentId: deploymentIdShape,
|
|
522
|
-
port: z.number().int().min(1).max(65535),
|
|
523
|
-
protocol: z.enum(["tcp", "udp"]).default("tcp"),
|
|
524
|
-
allowedCidrs: z.array(z.string()).optional().describe("Optional ingress allow-list."),
|
|
525
|
-
},
|
|
526
|
-
outputShape: networkResourceShape,
|
|
527
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/ports/expose", args),
|
|
528
|
-
}),
|
|
529
|
-
defineTool({
|
|
530
|
-
name: "capix_close_port",
|
|
531
|
-
description: "Close a previously exposed port. Non-billable soft mutation; requires approval.",
|
|
532
|
-
scope: "networking",
|
|
533
|
-
...APPROVAL_ONLY,
|
|
534
|
-
inputShape: {
|
|
535
|
-
deploymentId: deploymentIdShape,
|
|
536
|
-
port: z.number().int().min(1).max(65535),
|
|
537
|
-
protocol: z.enum(["tcp", "udp"]).default("tcp"),
|
|
538
|
-
},
|
|
539
|
-
outputShape: networkResourceShape,
|
|
540
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/ports/close", args),
|
|
541
|
-
}),
|
|
542
|
-
defineTool({
|
|
543
|
-
name: "capix_inspect_routes",
|
|
544
|
-
description: "Inspect the routing table for a deployment. Read-only.",
|
|
545
|
-
scope: "networking",
|
|
546
|
-
...READ_ONLY,
|
|
547
|
-
inputShape: {
|
|
548
|
-
deploymentId: deploymentIdShape,
|
|
549
|
-
},
|
|
550
|
-
outputShape: {
|
|
551
|
-
deploymentId: deploymentIdShape.optional(),
|
|
552
|
-
routes: z.array(z.record(z.unknown())).optional(),
|
|
553
|
-
fetchedAt: iso8601.optional(),
|
|
554
|
-
},
|
|
555
|
-
handler: async (args, { client }) => client.get(`/api/v1/networking/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/routes`),
|
|
556
|
-
}),
|
|
557
|
-
defineTool({
|
|
558
|
-
name: "capix_create_private_connection",
|
|
559
|
-
description: "Create a private endpoint connection (raw private endpoint). Billable; requires approval.",
|
|
560
|
-
scope: "networking",
|
|
561
|
-
...BILLABLE,
|
|
562
|
-
inputShape: {
|
|
563
|
-
deploymentId: deploymentIdShape,
|
|
564
|
-
service: z.string().describe("Target service identifier."),
|
|
565
|
-
port: z.number().int().min(1).max(65535).optional(),
|
|
566
|
-
},
|
|
567
|
-
outputShape: networkResourceShape,
|
|
568
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/private-connections", args),
|
|
569
|
-
}),
|
|
570
|
-
defineTool({
|
|
571
|
-
name: "capix_request_dedicated_ip",
|
|
572
|
-
description: "Request a dedicated (non-shared) IP for a deployment. Paid; requires approval.",
|
|
573
|
-
scope: "networking",
|
|
574
|
-
...BILLABLE,
|
|
575
|
-
inputShape: {
|
|
576
|
-
deploymentId: deploymentIdShape,
|
|
577
|
-
region: z.string().optional(),
|
|
578
|
-
quoteId: quoteIdShape.describe("Canonical quote for the dedicated IP."),
|
|
579
|
-
},
|
|
580
|
-
outputShape: networkResourceShape,
|
|
581
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/dedicated-ips", args),
|
|
582
|
-
}),
|
|
583
|
-
defineTool({
|
|
584
|
-
name: "capix_port_forward",
|
|
585
|
-
description: "Set up port forwarding between a deployment port and a host port. Billable; requires approval.",
|
|
586
|
-
scope: "networking",
|
|
587
|
-
...BILLABLE,
|
|
588
|
-
inputShape: {
|
|
589
|
-
deploymentId: deploymentIdShape,
|
|
590
|
-
sourcePort: z.number().int().min(1).max(65535),
|
|
591
|
-
targetPort: z.number().int().min(1).max(65535),
|
|
592
|
-
protocol: z.enum(["tcp", "udp"]).default("tcp"),
|
|
593
|
-
},
|
|
594
|
-
outputShape: networkResourceShape,
|
|
595
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/networking/port-forwards", args),
|
|
596
|
-
}),
|
|
597
|
-
];
|
|
598
|
-
// ===========================================================================
|
|
599
|
-
// Testing tools (6) — disposable envs, inspection, bounded commands, cleanup.
|
|
600
|
-
// ===========================================================================
|
|
601
|
-
const testingTools = [
|
|
602
|
-
defineTool({
|
|
603
|
-
name: "capix_create_test_env",
|
|
604
|
-
description: "Create a disposable test environment from a spec. Billable; requires approval.",
|
|
605
|
-
scope: "testing",
|
|
606
|
-
...BILLABLE,
|
|
607
|
-
inputShape: {
|
|
608
|
-
name: z.string(),
|
|
609
|
-
workloadType: z.string(),
|
|
610
|
-
cpu: z.number().int().min(1),
|
|
611
|
-
ramMb: z.number().int().min(128),
|
|
612
|
-
region: z.string().optional(),
|
|
613
|
-
imageDigest: z.string().optional(),
|
|
614
|
-
ttlMinutes: z.number().int().min(1).max(1440).default(60).describe("Auto-destroy TTL."),
|
|
615
|
-
quoteId: quoteIdShape.optional().describe("Canonical quote for the env."),
|
|
616
|
-
},
|
|
617
|
-
outputShape: {
|
|
618
|
-
envId: z.string().optional(),
|
|
619
|
-
status: z.enum(["provisioning", "ready", "failed"]).optional(),
|
|
620
|
-
provider: z.string().optional(),
|
|
621
|
-
region: z.string().optional(),
|
|
622
|
-
endpoint: z.string().optional(),
|
|
623
|
-
provisionedAt: iso8601.optional(),
|
|
624
|
-
},
|
|
625
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, "/api/v1/testing/environments", args),
|
|
626
|
-
}),
|
|
627
|
-
defineTool({
|
|
628
|
-
name: "capix_run_health_checks",
|
|
629
|
-
description: "Run health checks (liveness/readiness probes) on a deployment. Read-only.",
|
|
630
|
-
scope: "testing",
|
|
631
|
-
...READ_ONLY,
|
|
632
|
-
inputShape: {
|
|
633
|
-
deploymentId: deploymentIdShape,
|
|
634
|
-
},
|
|
635
|
-
outputShape: {
|
|
636
|
-
deploymentId: deploymentIdShape.optional(),
|
|
637
|
-
healthy: z.boolean().optional(),
|
|
638
|
-
checks: z.array(z.record(z.unknown())).optional(),
|
|
639
|
-
ranAt: iso8601.optional(),
|
|
640
|
-
},
|
|
641
|
-
handler: async (args, { client }) => client.get(`/api/v1/testing/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/health`),
|
|
642
|
-
}),
|
|
643
|
-
defineTool({
|
|
644
|
-
name: "capix_run_bounded_command",
|
|
645
|
-
description: "Run an allow-listed, time-bounded command on a deployment node. Requires approval (may execute code).",
|
|
646
|
-
scope: "testing",
|
|
647
|
-
...APPROVAL_ONLY,
|
|
648
|
-
inputShape: {
|
|
649
|
-
deploymentId: deploymentIdShape,
|
|
650
|
-
command: z.string().describe("Command string from the allow-list."),
|
|
651
|
-
timeoutSeconds: z.number().int().min(1).max(600).default(60),
|
|
652
|
-
expectedExitCode: z.number().int().default(0),
|
|
653
|
-
},
|
|
654
|
-
outputShape: {
|
|
655
|
-
deploymentId: deploymentIdShape.optional(),
|
|
656
|
-
results: z.array(z.record(z.unknown())).optional(),
|
|
657
|
-
completedAt: iso8601.optional(),
|
|
658
|
-
},
|
|
659
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/testing/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/commands`, args),
|
|
660
|
-
}),
|
|
661
|
-
defineTool({
|
|
662
|
-
name: "capix_inspect_logs",
|
|
663
|
-
description: "Inspect deployment logs. Read-only.",
|
|
664
|
-
scope: "testing",
|
|
665
|
-
...READ_ONLY,
|
|
666
|
-
inputShape: {
|
|
667
|
-
deploymentId: deploymentIdShape,
|
|
668
|
-
limit: z.number().int().min(1).max(1000).default(200),
|
|
669
|
-
since: iso8601.optional(),
|
|
670
|
-
level: z.enum(["debug", "info", "warn", "error"]).optional(),
|
|
671
|
-
},
|
|
672
|
-
outputShape: {
|
|
673
|
-
resourceId: z.string().optional(),
|
|
674
|
-
lines: z.array(z.record(z.unknown())).optional(),
|
|
675
|
-
truncated: z.boolean().optional(),
|
|
676
|
-
},
|
|
677
|
-
handler: async (args, { client }) => client.get(`/api/v1/testing/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/logs`, { limit: args.limit, since: args.since, level: args.level }),
|
|
678
|
-
}),
|
|
679
|
-
defineTool({
|
|
680
|
-
name: "capix_inspect_metrics",
|
|
681
|
-
description: "Inspect deployment metrics. Read-only.",
|
|
682
|
-
scope: "testing",
|
|
683
|
-
...READ_ONLY,
|
|
684
|
-
inputShape: {
|
|
685
|
-
deploymentId: deploymentIdShape,
|
|
686
|
-
windowMinutes: z.number().int().min(1).max(10080).default(60),
|
|
687
|
-
names: z.array(z.string()).optional().describe("Optional metric name filter."),
|
|
688
|
-
},
|
|
689
|
-
outputShape: {
|
|
690
|
-
resourceId: z.string().optional(),
|
|
691
|
-
metrics: z.array(z.record(z.unknown())).optional(),
|
|
692
|
-
},
|
|
693
|
-
handler: async (args, { client }) => client.get(`/api/v1/testing/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/metrics`, { windowMinutes: args.windowMinutes, names: args.names }),
|
|
694
|
-
}),
|
|
695
|
-
defineTool({
|
|
696
|
-
name: "capix_destroy_task_resources",
|
|
697
|
-
description: "Destroy all resources scoped to a task (cleanup safety gate §18). Destructive; requires approval.",
|
|
698
|
-
scope: "testing",
|
|
699
|
-
...APPROVAL_ONLY,
|
|
700
|
-
inputShape: {
|
|
701
|
-
resourceId: z.string().describe("Task-scoped resource id to destroy."),
|
|
702
|
-
reason: z.string().optional(),
|
|
703
|
-
},
|
|
704
|
-
outputShape: {
|
|
705
|
-
resourceId: z.string().optional(),
|
|
706
|
-
status: z.enum(["destroyed", "failed", "not_found"]).optional(),
|
|
707
|
-
destroyedAt: iso8601.optional(),
|
|
708
|
-
},
|
|
709
|
-
handler: async (args, { client, ctx }) => {
|
|
710
|
-
const id = asStr(args.resourceId, "resourceId");
|
|
711
|
-
return callBillable(client, ctx.approvalToken, `/api/v1/testing/environments/${encodeURIComponent(id)}`, args.reason ? { reason: args.reason } : undefined);
|
|
712
355
|
},
|
|
356
|
+
outputShape: deploymentResultShape,
|
|
713
357
|
}),
|
|
714
358
|
];
|
|
715
359
|
// ===========================================================================
|
|
716
|
-
// Verification tools (
|
|
360
|
+
// Verification tools (1) — read-only receipt inspection.
|
|
361
|
+
// The attestation/zkVM/measurement tools were removed: /api/v1/verification/*
|
|
362
|
+
// and /api/v1/attestations do not exist (Secured Cloud deferred — see
|
|
363
|
+
// route-families.ts). capix_inspect_receipt survives, retargeted from the
|
|
364
|
+
// nonexistent /api/v1/verification/receipts/[id] to the real signed
|
|
365
|
+
// route-receipt route (the scheduler's placement receipt tied to a quote:
|
|
366
|
+
// customer price, provider cost basis, fees, margin).
|
|
717
367
|
// ===========================================================================
|
|
718
368
|
const verificationTools = [
|
|
719
|
-
|
|
720
|
-
name: "capix_fetch_attestation",
|
|
721
|
-
description: "Fetch attestation evidence for a deployment (TEE / zkVM). Read-only.",
|
|
722
|
-
scope: "verification",
|
|
723
|
-
...READ_ONLY,
|
|
724
|
-
inputShape: {
|
|
725
|
-
deploymentId: deploymentIdShape,
|
|
726
|
-
},
|
|
727
|
-
outputShape: {
|
|
728
|
-
attestationId: z.string().optional(),
|
|
729
|
-
kind: z.enum(["tee", "zkvm"]).optional(),
|
|
730
|
-
resourceId: z.string().optional(),
|
|
731
|
-
evidence: z.string().optional(),
|
|
732
|
-
measurement: z.string().optional(),
|
|
733
|
-
fetchedAt: iso8601.optional(),
|
|
734
|
-
},
|
|
735
|
-
handler: async (args, { client }) => client.get(`/api/v1/verification/deployments/${encodeURIComponent(asStr(args.deploymentId, "deploymentId"))}/attestation`),
|
|
736
|
-
}),
|
|
737
|
-
defineTool({
|
|
738
|
-
name: "capix_verify_attestation",
|
|
739
|
-
description: "Verify an attestation against the expected reference measurement. Read-only.",
|
|
740
|
-
scope: "verification",
|
|
741
|
-
...READ_ONLY,
|
|
742
|
-
inputShape: {
|
|
743
|
-
attestationId: z.string(),
|
|
744
|
-
expectedMeasurement: z.string().optional().describe("Optional pinned reference measurement."),
|
|
745
|
-
},
|
|
746
|
-
outputShape: {
|
|
747
|
-
subjectId: z.string().optional(),
|
|
748
|
-
kind: z.enum(["tee", "zkvm", "measurement", "receipt"]).optional(),
|
|
749
|
-
verified: z.boolean().optional(),
|
|
750
|
-
reason: z.string().optional(),
|
|
751
|
-
verifier: z.string().optional(),
|
|
752
|
-
verifiedAt: iso8601.optional(),
|
|
753
|
-
},
|
|
754
|
-
handler: async (args, { client }) => client.post(`/api/v1/verification/attestations/${encodeURIComponent(asStr(args.attestationId, "attestationId"))}/verify`, { expectedMeasurement: args.expectedMeasurement }),
|
|
755
|
-
}),
|
|
756
|
-
defineTool({
|
|
757
|
-
name: "capix_fetch_proof",
|
|
758
|
-
description: "Fetch a zkVM proof artifact for a workload. Read-only.",
|
|
759
|
-
scope: "verification",
|
|
760
|
-
...READ_ONLY,
|
|
761
|
-
inputShape: {
|
|
762
|
-
workloadId: z.string(),
|
|
763
|
-
},
|
|
764
|
-
outputShape: {
|
|
765
|
-
proofId: z.string().optional(),
|
|
766
|
-
workloadId: z.string().optional(),
|
|
767
|
-
proofSystem: z.string().optional(),
|
|
768
|
-
artifactRef: z.string().optional(),
|
|
769
|
-
publicInputs: z.string().optional(),
|
|
770
|
-
fetchedAt: iso8601.optional(),
|
|
771
|
-
},
|
|
772
|
-
handler: async (args, { client }) => client.get(`/api/v1/verification/workloads/${encodeURIComponent(asStr(args.workloadId, "workloadId"))}/proof`),
|
|
773
|
-
}),
|
|
774
|
-
defineTool({
|
|
775
|
-
name: "capix_verify_proof",
|
|
776
|
-
description: "Verify a zkVM proof artifact against its public inputs. Read-only.",
|
|
777
|
-
scope: "verification",
|
|
778
|
-
...READ_ONLY,
|
|
779
|
-
inputShape: {
|
|
780
|
-
proofId: z.string(),
|
|
781
|
-
},
|
|
782
|
-
outputShape: {
|
|
783
|
-
subjectId: z.string().optional(),
|
|
784
|
-
kind: z.enum(["tee", "zkvm", "measurement", "receipt"]).optional(),
|
|
785
|
-
verified: z.boolean().optional(),
|
|
786
|
-
reason: z.string().optional(),
|
|
787
|
-
verifier: z.string().optional(),
|
|
788
|
-
verifiedAt: iso8601.optional(),
|
|
789
|
-
},
|
|
790
|
-
handler: async (args, { client }) => client.post(`/api/v1/verification/proofs/${encodeURIComponent(asStr(args.proofId, "proofId"))}/verify`),
|
|
791
|
-
}),
|
|
792
|
-
defineTool({
|
|
793
|
-
name: "capix_inspect_measurement",
|
|
794
|
-
description: "Inspect the recorded measurement of a workload (used to pin expected TEE state). Read-only.",
|
|
795
|
-
scope: "verification",
|
|
796
|
-
...READ_ONLY,
|
|
797
|
-
inputShape: {
|
|
798
|
-
workloadId: z.string(),
|
|
799
|
-
},
|
|
800
|
-
outputShape: {
|
|
801
|
-
workloadId: z.string().optional(),
|
|
802
|
-
measurement: z.string().optional(),
|
|
803
|
-
measurementAlgorithm: z.string().optional(),
|
|
804
|
-
imageDigest: z.string().optional(),
|
|
805
|
-
recordedAt: iso8601.optional(),
|
|
806
|
-
},
|
|
807
|
-
handler: async (args, { client }) => client.get(`/api/v1/verification/workloads/${encodeURIComponent(asStr(args.workloadId, "workloadId"))}/measurement`),
|
|
808
|
-
}),
|
|
809
|
-
defineTool({
|
|
369
|
+
defineGeneratedTool({
|
|
810
370
|
name: "capix_inspect_receipt",
|
|
811
|
-
description: "Inspect a
|
|
371
|
+
description: "Inspect a signed route receipt: the scheduler's placement decision for a quote — " +
|
|
372
|
+
"customer price, provider cost basis, fees, margin, constraints, allocations. Read-only.",
|
|
812
373
|
scope: "verification",
|
|
813
374
|
...READ_ONLY,
|
|
814
|
-
|
|
815
|
-
|
|
375
|
+
method: "GET",
|
|
376
|
+
path: "/api/v1/route-receipts/:receiptId",
|
|
377
|
+
input: {
|
|
378
|
+
receiptId: z.string().describe("Route receipt id (returned as x-capix-route-receipt-id with a quote)."),
|
|
816
379
|
},
|
|
817
380
|
outputShape: {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
postedAt: iso8601.optional(),
|
|
381
|
+
id: z.string().optional(),
|
|
382
|
+
data: z.record(z.unknown()).optional().describe("RouteReceiptData: workloadType, quoteId, customerPrice, providerCostBasis, fees, margin, allocations, …"),
|
|
383
|
+
signature: z.string().optional(),
|
|
384
|
+
kmsKeyId: z.string().optional(),
|
|
823
385
|
},
|
|
824
|
-
handler: async (args, { client }) => client.get(`/api/v1/verification/receipts/${encodeURIComponent(asStr(args.receiptId, "receiptId"))}`),
|
|
825
386
|
}),
|
|
826
387
|
];
|
|
827
388
|
// ===========================================================================
|
|
828
|
-
// Website tools (
|
|
389
|
+
// Website tools (6) — static-site hosting on the REAL /api/v1/websites family
|
|
390
|
+
// (plural; the singular /api/v1/website/* these tools used to target never
|
|
391
|
+
// existed). Real surface (app/api/v1/websites/*):
|
|
392
|
+
// POST /api/v1/websites create + build (name, sourceRef, buildCommand?)
|
|
393
|
+
// GET /api/v1/websites list (with up to 5 releases each)
|
|
394
|
+
// GET /api/v1/websites/[id] detail (releases + 50-line build logTail)
|
|
395
|
+
// POST /api/v1/websites/[id]/promote promote a built release to production
|
|
396
|
+
// POST /api/v1/websites/[id]/rollback roll back to a previous built release
|
|
397
|
+
// DELETE /api/v1/websites/[id] destroy (soft)
|
|
398
|
+
//
|
|
399
|
+
// Known backend gap: promote/rollback are dispatched inside [id]/route.ts on
|
|
400
|
+
// the URL suffix, but the App Router has no [id]/promote/route.ts shim or
|
|
401
|
+
// rewrite, so those paths 404 until the control plane adds the segment
|
|
402
|
+
// shims. The tools are registered against the documented contract (the route
|
|
403
|
+
// file's own header advertises the paths) — track the backend fix before
|
|
404
|
+
// relying on them.
|
|
405
|
+
//
|
|
406
|
+
// Removed (no route): check-project-string, detect (worker-internal only),
|
|
407
|
+
// plan, quote (no website workload type in /api/v1/quotes), deploy (no
|
|
408
|
+
// redeploy route — create builds+deploys), preview (implicit per release),
|
|
409
|
+
// deployments (releases are embedded in list/get), logs (logTail in get),
|
|
410
|
+
// metrics, domain add/verify/remove (wildcard *.capix.dev not live yet).
|
|
829
411
|
// ===========================================================================
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
framework: z.string().optional().describe("Optional pinned framework."),
|
|
835
|
-
};
|
|
412
|
+
const websiteObjectShape = z
|
|
413
|
+
.record(z.unknown())
|
|
414
|
+
.describe("Website: id, name, slug, status (building|preview|live|failed|destroyed), sourceRef, " +
|
|
415
|
+
"previewUrl, productionUrl, futureUrls, releases[{id, contentHash, status, step, error, createdAt, url}], createdAt.");
|
|
836
416
|
const websiteTools = [
|
|
837
|
-
|
|
838
|
-
name: "capix_website_project_string_check",
|
|
839
|
-
description: "Check a repository string for framework/dep compatibility with Capix hosting. Read-only.",
|
|
840
|
-
scope: "website",
|
|
841
|
-
...READ_ONLY,
|
|
842
|
-
inputShape: {
|
|
843
|
-
repoUrl: z.string(),
|
|
844
|
-
},
|
|
845
|
-
outputShape: {
|
|
846
|
-
ok: z.boolean().optional(),
|
|
847
|
-
framework: z.string().optional(),
|
|
848
|
-
notes: z.string().optional(),
|
|
849
|
-
},
|
|
850
|
-
handler: async (args, { client }) => client.post("/api/v1/website/check-project-string", { repoUrl: asStr(args.repoUrl, "repoUrl") }),
|
|
851
|
-
}),
|
|
852
|
-
defineTool({
|
|
417
|
+
defineGeneratedTool({
|
|
853
418
|
name: "capix_website_create",
|
|
854
|
-
description: "Create a
|
|
419
|
+
description: "Create a website from a source ref (repo/archive URL): clones, detects the framework " +
|
|
420
|
+
"server-side, builds, and serves a preview release. Billable; requires approval.",
|
|
855
421
|
scope: "website",
|
|
856
422
|
...BILLABLE,
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
scope: "website",
|
|
865
|
-
...READ_ONLY,
|
|
866
|
-
inputShape: {
|
|
867
|
-
repoUrl: z.string(),
|
|
868
|
-
branch: z.string().optional(),
|
|
423
|
+
method: "POST",
|
|
424
|
+
path: "/api/v1/websites",
|
|
425
|
+
input: {
|
|
426
|
+
name: z.string().min(1).describe("Site name (required upstream; slugified, unique per account)."),
|
|
427
|
+
sourceRef: z.string().min(1).describe("Source reference (repository/archive URL). Required upstream."),
|
|
428
|
+
buildCommand: z.string().optional().describe("Optional build command override (auto-detected when omitted)."),
|
|
429
|
+
projectId: z.string().optional(),
|
|
869
430
|
},
|
|
870
431
|
outputShape: {
|
|
871
|
-
|
|
872
|
-
buildCommand: z.string().optional(),
|
|
873
|
-
outputDir: z.string().optional(),
|
|
874
|
-
nodeVersion: z.string().optional(),
|
|
875
|
-
detectedAt: iso8601.optional(),
|
|
432
|
+
website: websiteObjectShape.optional(),
|
|
876
433
|
},
|
|
877
|
-
handler: async (args, { client }) => client.post("/api/v1/website/detect", {
|
|
878
|
-
repoUrl: asStr(args.repoUrl, "repoUrl"),
|
|
879
|
-
branch: args.branch,
|
|
880
|
-
}),
|
|
881
434
|
}),
|
|
882
|
-
|
|
883
|
-
name: "
|
|
884
|
-
description: "
|
|
435
|
+
defineGeneratedTool({
|
|
436
|
+
name: "capix_website_list",
|
|
437
|
+
description: "List the account's websites with their latest releases. Read-only.",
|
|
885
438
|
scope: "website",
|
|
886
439
|
...READ_ONLY,
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
branch: z.string().optional(),
|
|
891
|
-
subPath: z.string().optional(),
|
|
892
|
-
framework: z.string().optional(),
|
|
893
|
-
},
|
|
440
|
+
method: "GET",
|
|
441
|
+
path: "/api/v1/websites",
|
|
442
|
+
input: {},
|
|
894
443
|
outputShape: {
|
|
895
|
-
|
|
896
|
-
plan: z.record(z.unknown()).optional(),
|
|
897
|
-
notes: z.string().optional(),
|
|
444
|
+
websites: z.array(z.record(z.unknown())).optional(),
|
|
898
445
|
},
|
|
899
|
-
handler: async (args, { client }) => client.post("/api/v1/website/plan", args),
|
|
900
446
|
}),
|
|
901
|
-
|
|
902
|
-
name: "
|
|
903
|
-
description: "Get a
|
|
447
|
+
defineGeneratedTool({
|
|
448
|
+
name: "capix_website_get",
|
|
449
|
+
description: "Get a website by id: status, URLs, and the last 20 releases including per-release " +
|
|
450
|
+
"build step, error, and a 50-line build log tail. Read-only.",
|
|
904
451
|
scope: "website",
|
|
905
452
|
...READ_ONLY,
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
453
|
+
method: "GET",
|
|
454
|
+
path: "/api/v1/websites/:id",
|
|
455
|
+
input: {
|
|
456
|
+
id: siteIdShape,
|
|
910
457
|
},
|
|
911
458
|
outputShape: {
|
|
912
|
-
|
|
913
|
-
price: moneyShape.optional(),
|
|
914
|
-
feasible: z.boolean().optional(),
|
|
915
|
-
expiresAt: iso8601.optional(),
|
|
459
|
+
website: websiteObjectShape.optional(),
|
|
916
460
|
},
|
|
917
|
-
handler: async (args, { client }) => client.post("/api/v1/website/quote", args),
|
|
918
461
|
}),
|
|
919
|
-
|
|
920
|
-
name: "capix_website_deploy",
|
|
921
|
-
description: "Deploy a website build to production. Billable; requires approval.",
|
|
922
|
-
scope: "website",
|
|
923
|
-
...BILLABLE,
|
|
924
|
-
inputShape: {
|
|
925
|
-
siteId: siteIdShape,
|
|
926
|
-
branch: z.string().optional(),
|
|
927
|
-
commit: z.string().optional(),
|
|
928
|
-
quoteId: quoteIdShape.optional(),
|
|
929
|
-
},
|
|
930
|
-
outputShape: siteResultShape,
|
|
931
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/deploy`, { branch: args.branch, commit: args.commit, quoteId: args.quoteId }),
|
|
932
|
-
}),
|
|
933
|
-
defineTool({
|
|
934
|
-
name: "capix_website_preview",
|
|
935
|
-
description: "Create a preview deployment for a branch. Billable; requires approval.",
|
|
936
|
-
scope: "website",
|
|
937
|
-
...BILLABLE,
|
|
938
|
-
inputShape: {
|
|
939
|
-
siteId: siteIdShape,
|
|
940
|
-
branch: z.string(),
|
|
941
|
-
},
|
|
942
|
-
outputShape: siteResultShape,
|
|
943
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/preview`, { branch: args.branch }),
|
|
944
|
-
}),
|
|
945
|
-
defineTool({
|
|
462
|
+
defineGeneratedTool({
|
|
946
463
|
name: "capix_website_promote",
|
|
947
|
-
description: "Promote a
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
inputShape: {
|
|
951
|
-
siteId: siteIdShape,
|
|
952
|
-
},
|
|
953
|
-
outputShape: siteResultShape,
|
|
954
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/promote`),
|
|
955
|
-
}),
|
|
956
|
-
defineTool({
|
|
957
|
-
name: "capix_website_rollback",
|
|
958
|
-
description: "Roll a website back to its previous production deployment. Billable; requires approval.",
|
|
464
|
+
description: "Promote a built release to production (defaults to the latest release). " +
|
|
465
|
+
"NOTE: depends on a pending control-plane route shim for /promote — see tools.ts. " +
|
|
466
|
+
"Requires approval.",
|
|
959
467
|
scope: "website",
|
|
960
468
|
...BILLABLE,
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/rollback`, { targetDeploymentId: args.targetDeploymentId }),
|
|
967
|
-
}),
|
|
968
|
-
defineTool({
|
|
969
|
-
name: "capix_website_get",
|
|
970
|
-
description: "Get a website project descriptor. Read-only.",
|
|
971
|
-
scope: "website",
|
|
972
|
-
...READ_ONLY,
|
|
973
|
-
inputShape: {
|
|
974
|
-
siteId: siteIdShape,
|
|
975
|
-
},
|
|
976
|
-
outputShape: {
|
|
977
|
-
siteId: siteIdShape.optional(),
|
|
978
|
-
name: z.string().optional(),
|
|
979
|
-
url: z.string().optional(),
|
|
980
|
-
framework: z.string().optional(),
|
|
981
|
-
status: z.string().optional(),
|
|
982
|
-
createdAt: iso8601.optional(),
|
|
983
|
-
},
|
|
984
|
-
handler: async (args, { client }) => client.get(`/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}`),
|
|
985
|
-
}),
|
|
986
|
-
defineTool({
|
|
987
|
-
name: "capix_website_deployments",
|
|
988
|
-
description: "List deployments for a website. Read-only.",
|
|
989
|
-
scope: "website",
|
|
990
|
-
...READ_ONLY,
|
|
991
|
-
inputShape: {
|
|
992
|
-
siteId: siteIdShape,
|
|
993
|
-
limit: z.number().int().min(1).max(200).default(50),
|
|
994
|
-
},
|
|
995
|
-
outputShape: listResultShape,
|
|
996
|
-
handler: async (args, { client }) => client.get(`/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/deployments`, { limit: args.limit }),
|
|
997
|
-
}),
|
|
998
|
-
defineTool({
|
|
999
|
-
name: "capix_website_logs",
|
|
1000
|
-
description: "Inspect build/runtime logs for a website. Read-only.",
|
|
1001
|
-
scope: "website",
|
|
1002
|
-
...READ_ONLY,
|
|
1003
|
-
inputShape: {
|
|
1004
|
-
siteId: siteIdShape,
|
|
1005
|
-
deploymentId: z.string().optional(),
|
|
1006
|
-
limit: z.number().int().min(1).max(1000).default(200),
|
|
469
|
+
method: "POST",
|
|
470
|
+
path: "/api/v1/websites/:id/promote",
|
|
471
|
+
input: {
|
|
472
|
+
id: siteIdShape,
|
|
473
|
+
releaseId: z.string().optional().describe("Release to promote; defaults to the latest built release."),
|
|
1007
474
|
},
|
|
1008
475
|
outputShape: {
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
handler: async (args, { client }) => client.get(`/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/logs`, { deploymentId: args.deploymentId, limit: args.limit }),
|
|
1013
|
-
}),
|
|
1014
|
-
defineTool({
|
|
1015
|
-
name: "capix_website_metrics",
|
|
1016
|
-
description: "Inspect request/bandwidth metrics for a website. Read-only.",
|
|
1017
|
-
scope: "website",
|
|
1018
|
-
...READ_ONLY,
|
|
1019
|
-
inputShape: {
|
|
1020
|
-
siteId: siteIdShape,
|
|
1021
|
-
windowMinutes: z.number().int().min(1).max(10080).default(60),
|
|
1022
|
-
},
|
|
1023
|
-
outputShape: {
|
|
1024
|
-
metrics: z.array(z.record(z.unknown())).optional(),
|
|
476
|
+
ok: z.boolean().optional(),
|
|
477
|
+
productionUrl: z.string().optional(),
|
|
478
|
+
releaseId: z.string().optional(),
|
|
1025
479
|
},
|
|
1026
|
-
handler: async (args, { client }) => client.get(`/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/metrics`, { windowMinutes: args.windowMinutes }),
|
|
1027
480
|
}),
|
|
1028
|
-
|
|
1029
|
-
name: "
|
|
1030
|
-
description: "
|
|
481
|
+
defineGeneratedTool({
|
|
482
|
+
name: "capix_website_rollback",
|
|
483
|
+
description: "Roll a website back to a previous built release (defaults to the last built release " +
|
|
484
|
+
"before the current production one). NOTE: depends on a pending control-plane route " +
|
|
485
|
+
"shim for /rollback — see tools.ts. Requires approval.",
|
|
1031
486
|
scope: "website",
|
|
1032
487
|
...BILLABLE,
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/domains`, { domain: asStr(args.domain, "domain") }),
|
|
1039
|
-
}),
|
|
1040
|
-
defineTool({
|
|
1041
|
-
name: "capix_website_domain_verify",
|
|
1042
|
-
description: "Verify DNS ownership for a pending custom domain. Read-only.",
|
|
1043
|
-
scope: "website",
|
|
1044
|
-
...READ_ONLY,
|
|
1045
|
-
inputShape: {
|
|
1046
|
-
siteId: siteIdShape,
|
|
1047
|
-
domain: z.string(),
|
|
488
|
+
method: "POST",
|
|
489
|
+
path: "/api/v1/websites/:id/rollback",
|
|
490
|
+
input: {
|
|
491
|
+
id: siteIdShape,
|
|
492
|
+
releaseId: z.string().optional().describe("Release to restore; defaults to the previous built release."),
|
|
1048
493
|
},
|
|
1049
494
|
outputShape: {
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
handler: async (args, { client }) => client.post(`/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/domains/verify`, { domain: asStr(args.domain, "domain") }),
|
|
1055
|
-
}),
|
|
1056
|
-
defineTool({
|
|
1057
|
-
name: "capix_website_domain_remove",
|
|
1058
|
-
description: "Detach a custom domain from a website. Billable; requires approval.",
|
|
1059
|
-
scope: "website",
|
|
1060
|
-
...BILLABLE,
|
|
1061
|
-
inputShape: {
|
|
1062
|
-
siteId: siteIdShape,
|
|
1063
|
-
domain: z.string(),
|
|
1064
|
-
},
|
|
1065
|
-
outputShape: siteResultShape,
|
|
1066
|
-
handler: async (args, { client, ctx }) => {
|
|
1067
|
-
const res = await callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/domains/${encodeURIComponent(asStr(args.domain, "domain"))}`);
|
|
1068
|
-
return res;
|
|
495
|
+
ok: z.boolean().optional(),
|
|
496
|
+
productionUrl: z.string().optional(),
|
|
497
|
+
releaseId: z.string().optional(),
|
|
498
|
+
rolledBack: z.boolean().optional(),
|
|
1069
499
|
},
|
|
1070
500
|
}),
|
|
1071
|
-
|
|
501
|
+
defineGeneratedTool({
|
|
1072
502
|
name: "capix_website_destroy",
|
|
1073
|
-
description: "Destroy a website
|
|
503
|
+
description: "Destroy a website (soft delete; releases stop serving). Destructive; requires approval.",
|
|
1074
504
|
scope: "website",
|
|
1075
505
|
...BILLABLE,
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
506
|
+
method: "DELETE",
|
|
507
|
+
path: "/api/v1/websites/:id",
|
|
508
|
+
input: {
|
|
509
|
+
id: siteIdShape,
|
|
510
|
+
},
|
|
511
|
+
outputShape: {
|
|
512
|
+
ok: z.boolean().optional(),
|
|
513
|
+
id: z.string().optional(),
|
|
514
|
+
status: z.string().optional(),
|
|
1079
515
|
},
|
|
1080
|
-
outputShape: siteResultShape,
|
|
1081
|
-
handler: async (args, { client, ctx }) => callBillable(client, ctx.approvalToken, `/api/v1/website/sites/${encodeURIComponent(asStr(args.siteId, "siteId"))}/destroy`, args.reason ? { reason: args.reason } : undefined),
|
|
1082
516
|
}),
|
|
1083
517
|
];
|
|
1084
518
|
// ===========================================================================
|
|
@@ -1088,14 +522,15 @@ export const TOOLS = [
|
|
|
1088
522
|
...discoveryTools,
|
|
1089
523
|
...planningTools,
|
|
1090
524
|
...lifecycleTools,
|
|
1091
|
-
...networkingTools,
|
|
1092
|
-
...testingTools,
|
|
1093
525
|
...verificationTools,
|
|
1094
526
|
...websiteTools,
|
|
527
|
+
...factoryTools,
|
|
528
|
+
...infraContextTools,
|
|
529
|
+
...memeImageTools,
|
|
1095
530
|
];
|
|
1096
531
|
export const TOOL_NAMES = TOOLS.map((t) => t.name);
|
|
1097
532
|
export const TOOL_COUNT = TOOLS.length;
|
|
1098
533
|
/** Map of tool name → definition, used by the server for O(1) lookup. */
|
|
1099
534
|
export const TOOL_MAP = new Map(TOOLS.map((t) => [t.name, t]));
|
|
1100
|
-
export { discoveryTools, planningTools, lifecycleTools,
|
|
535
|
+
export { discoveryTools, planningTools, lifecycleTools, verificationTools, websiteTools, factoryTools, infraContextTools, memeImageTools };
|
|
1101
536
|
//# sourceMappingURL=tools.js.map
|