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