run402-mcp 0.1.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 +122 -0
- package/dist/client.d.ts +15 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +42 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +10 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/keystore.d.ts +14 -0
- package/dist/keystore.d.ts.map +1 -0
- package/dist/keystore.js +38 -0
- package/dist/keystore.js.map +1 -0
- package/dist/tools/deploy-function.d.ts +34 -0
- package/dist/tools/deploy-function.d.ts.map +1 -0
- package/dist/tools/deploy-function.js +87 -0
- package/dist/tools/deploy-function.js.map +1 -0
- package/dist/tools/deploy-site.d.ts +36 -0
- package/dist/tools/deploy-site.d.ts.map +1 -0
- package/dist/tools/deploy-site.js +88 -0
- package/dist/tools/deploy-site.js.map +1 -0
- package/dist/tools/get-function-logs.d.ts +18 -0
- package/dist/tools/get-function-logs.d.ts.map +1 -0
- package/dist/tools/get-function-logs.js +64 -0
- package/dist/tools/get-function-logs.js.map +1 -0
- package/dist/tools/invoke-function.d.ts +22 -0
- package/dist/tools/invoke-function.d.ts.map +1 -0
- package/dist/tools/invoke-function.js +82 -0
- package/dist/tools/invoke-function.js.map +1 -0
- package/dist/tools/provision.d.ts +16 -0
- package/dist/tools/provision.d.ts.map +1 -0
- package/dist/tools/provision.js +77 -0
- package/dist/tools/provision.js.map +1 -0
- package/dist/tools/renew.d.ts +16 -0
- package/dist/tools/renew.d.ts.map +1 -0
- package/dist/tools/renew.js +78 -0
- package/dist/tools/renew.js.map +1 -0
- package/dist/tools/rest-query.d.ts +24 -0
- package/dist/tools/rest-query.d.ts.map +1 -0
- package/dist/tools/rest-query.js +82 -0
- package/dist/tools/rest-query.js.map +1 -0
- package/dist/tools/run-sql.d.ts +16 -0
- package/dist/tools/run-sql.d.ts.map +1 -0
- package/dist/tools/run-sql.js +56 -0
- package/dist/tools/run-sql.js.map +1 -0
- package/dist/tools/set-secret.d.ts +18 -0
- package/dist/tools/set-secret.d.ts.map +1 -0
- package/dist/tools/set-secret.js +53 -0
- package/dist/tools/set-secret.js.map +1 -0
- package/dist/tools/subdomain.d.ts +32 -0
- package/dist/tools/subdomain.d.ts.map +1 -0
- package/dist/tools/subdomain.js +93 -0
- package/dist/tools/subdomain.js.map +1 -0
- package/dist/tools/upload-file.d.ts +22 -0
- package/dist/tools/upload-file.d.ts.map +1 -0
- package/dist/tools/upload-file.js +56 -0
- package/dist/tools/upload-file.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# @run402/mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [Run402](https://run402.com) — provision and manage AI-native Postgres databases from any MCP-compatible client.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx @run402/mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Tools
|
|
12
|
+
|
|
13
|
+
| Tool | Description |
|
|
14
|
+
|------|-------------|
|
|
15
|
+
| `provision_postgres_project` | Provision a new Postgres database (prototype/hobby/team tier) |
|
|
16
|
+
| `run_sql` | Execute SQL (DDL or queries) against a project |
|
|
17
|
+
| `rest_query` | Query/mutate data via PostgREST REST API |
|
|
18
|
+
| `upload_file` | Upload text content to project storage |
|
|
19
|
+
| `renew_project` | Renew a project's database lease |
|
|
20
|
+
|
|
21
|
+
## Client Configuration
|
|
22
|
+
|
|
23
|
+
### Claude Desktop
|
|
24
|
+
|
|
25
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"mcpServers": {
|
|
30
|
+
"run402": {
|
|
31
|
+
"command": "npx",
|
|
32
|
+
"args": ["-y", "@run402/mcp"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Cursor
|
|
39
|
+
|
|
40
|
+
Add to `.cursor/mcp.json` in your project:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"run402": {
|
|
46
|
+
"command": "npx",
|
|
47
|
+
"args": ["-y", "@run402/mcp"]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Cline
|
|
54
|
+
|
|
55
|
+
Add to Cline MCP settings:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"run402": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": ["-y", "@run402/mcp"]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Claude Code
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
claude mcp add run402 -- npx -y @run402/mcp
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## How It Works
|
|
75
|
+
|
|
76
|
+
1. **Provision** — Call `provision_postgres_project` to create a database. The server handles x402 payment negotiation and stores credentials locally.
|
|
77
|
+
2. **Build** — Use `run_sql` to create tables, `rest_query` to insert/query data, and `upload_file` for storage.
|
|
78
|
+
3. **Renew** — Call `renew_project` before your lease expires.
|
|
79
|
+
|
|
80
|
+
### Payment Flow
|
|
81
|
+
|
|
82
|
+
Provisioning and renewing require x402 micropayments. When payment is needed, tools return payment details (not errors) so the LLM can reason about them and guide the user through payment.
|
|
83
|
+
|
|
84
|
+
### Key Storage
|
|
85
|
+
|
|
86
|
+
Project credentials are saved to `~/.config/run402/projects.json` with `0600` permissions. Each project stores:
|
|
87
|
+
- `anon_key` — for public-facing queries (respects RLS)
|
|
88
|
+
- `service_key` — for admin operations (bypasses RLS)
|
|
89
|
+
- `tier` — prototype, hobby, or team
|
|
90
|
+
- `expires_at` — lease expiration timestamp
|
|
91
|
+
|
|
92
|
+
## Environment Variables
|
|
93
|
+
|
|
94
|
+
| Variable | Default | Description |
|
|
95
|
+
|----------|---------|-------------|
|
|
96
|
+
| `RUN402_API_BASE` | `https://api.run402.com` | API base URL |
|
|
97
|
+
| `RUN402_CONFIG_DIR` | `~/.config/run402` | Config directory for key storage |
|
|
98
|
+
|
|
99
|
+
## Tiers
|
|
100
|
+
|
|
101
|
+
| Tier | Price | Lease | Storage | API Calls |
|
|
102
|
+
|------|-------|-------|---------|-----------|
|
|
103
|
+
| prototype | $0.10 | 7 days | 250 MB | 500K |
|
|
104
|
+
| hobby | $5.00 | 30 days | 1 GB | 5M |
|
|
105
|
+
| team | $20.00 | 30 days | 10 GB | 50M |
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Build
|
|
111
|
+
npm run build -w packages/mcp
|
|
112
|
+
|
|
113
|
+
# Unit tests
|
|
114
|
+
npm run test:mcp
|
|
115
|
+
|
|
116
|
+
# Integration tests (needs running API)
|
|
117
|
+
npm run test:mcp:e2e
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface ApiResponse {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
is402?: boolean;
|
|
4
|
+
status: number;
|
|
5
|
+
body: unknown;
|
|
6
|
+
}
|
|
7
|
+
export interface ApiRequestOptions {
|
|
8
|
+
method?: string;
|
|
9
|
+
headers?: Record<string, string>;
|
|
10
|
+
body?: unknown;
|
|
11
|
+
/** Send body as raw string (e.g. for text/plain SQL) */
|
|
12
|
+
rawBody?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function apiRequest(path: string, opts?: ApiRequestOptions): Promise<ApiResponse>;
|
|
15
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,WAAW,CAAC,CA0CtB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getApiBase } from "./config.js";
|
|
2
|
+
export async function apiRequest(path, opts = {}) {
|
|
3
|
+
const { method = "GET", headers = {}, body, rawBody } = opts;
|
|
4
|
+
const url = `${getApiBase()}${path}`;
|
|
5
|
+
const fetchHeaders = { ...headers };
|
|
6
|
+
let fetchBody;
|
|
7
|
+
if (rawBody !== undefined) {
|
|
8
|
+
fetchBody = rawBody;
|
|
9
|
+
}
|
|
10
|
+
else if (body !== undefined) {
|
|
11
|
+
fetchHeaders["Content-Type"] = fetchHeaders["Content-Type"] || "application/json";
|
|
12
|
+
fetchBody = JSON.stringify(body);
|
|
13
|
+
}
|
|
14
|
+
let res;
|
|
15
|
+
try {
|
|
16
|
+
res = await fetch(url, {
|
|
17
|
+
method,
|
|
18
|
+
headers: fetchHeaders,
|
|
19
|
+
body: fetchBody,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
return {
|
|
24
|
+
ok: false,
|
|
25
|
+
status: 0,
|
|
26
|
+
body: { error: `Network error: ${err.message}` },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
let resBody;
|
|
30
|
+
const contentType = res.headers.get("content-type") || "";
|
|
31
|
+
if (contentType.includes("application/json")) {
|
|
32
|
+
resBody = await res.json();
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
resBody = await res.text();
|
|
36
|
+
}
|
|
37
|
+
if (res.status === 402) {
|
|
38
|
+
return { ok: false, is402: true, status: 402, body: resBody };
|
|
39
|
+
}
|
|
40
|
+
return { ok: res.ok, status: res.status, body: resBody };
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiBzC,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,OAA0B,EAAE;IAE5B,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC7D,MAAM,GAAG,GAAG,GAAG,UAAU,EAAE,GAAG,IAAI,EAAE,CAAC;IAErC,MAAM,YAAY,GAA2B,EAAE,GAAG,OAAO,EAAE,CAAC;IAC5D,IAAI,SAA6B,CAAC;IAElC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,SAAS,GAAG,OAAO,CAAC;IACtB,CAAC;SAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,YAAY,CAAC,cAAc,CAAC,GAAG,YAAY,CAAC,cAAc,CAAC,IAAI,kBAAkB,CAAC;QAClF,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YACrB,MAAM;YACN,OAAO,EAAE,YAAY;YACrB,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,CAAC;YACT,IAAI,EAAE,EAAE,KAAK,EAAE,kBAAmB,GAAa,CAAC,OAAO,EAAE,EAAE;SAC5D,CAAC;IACJ,CAAC;IAED,IAAI,OAAgB,CAAC;IACrB,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;IAC1D,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAChE,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;AAC3D,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,eAAe,IAAI,MAAM,CAIxC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export function getApiBase() {
|
|
4
|
+
return process.env.RUN402_API_BASE || "https://api.run402.com";
|
|
5
|
+
}
|
|
6
|
+
export function getKeystorePath() {
|
|
7
|
+
const configDir = process.env.RUN402_CONFIG_DIR || join(homedir(), ".config", "run402");
|
|
8
|
+
return join(configDir, "projects.json");
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACxE,OAAO,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;AAC1C,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { provisionSchema, handleProvision } from "./tools/provision.js";
|
|
5
|
+
import { runSqlSchema, handleRunSql } from "./tools/run-sql.js";
|
|
6
|
+
import { restQuerySchema, handleRestQuery } from "./tools/rest-query.js";
|
|
7
|
+
import { uploadFileSchema, handleUploadFile } from "./tools/upload-file.js";
|
|
8
|
+
import { renewSchema, handleRenew } from "./tools/renew.js";
|
|
9
|
+
import { deploySiteSchema, handleDeploySite } from "./tools/deploy-site.js";
|
|
10
|
+
import { claimSubdomainSchema, handleClaimSubdomain } from "./tools/subdomain.js";
|
|
11
|
+
import { deleteSubdomainSchema, handleDeleteSubdomain } from "./tools/subdomain.js";
|
|
12
|
+
import { deployFunctionSchema, handleDeployFunction } from "./tools/deploy-function.js";
|
|
13
|
+
import { invokeFunctionSchema, handleInvokeFunction } from "./tools/invoke-function.js";
|
|
14
|
+
import { getFunctionLogsSchema, handleGetFunctionLogs } from "./tools/get-function-logs.js";
|
|
15
|
+
import { setSecretSchema, handleSetSecret } from "./tools/set-secret.js";
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: "run402",
|
|
18
|
+
version: "0.1.0",
|
|
19
|
+
});
|
|
20
|
+
server.tool("provision_postgres_project", "Provision a new Postgres database. Returns project credentials on success, or payment details if x402 payment is needed.", provisionSchema, async (args) => handleProvision(args));
|
|
21
|
+
server.tool("run_sql", "Execute SQL (DDL or queries) against a provisioned project. Returns results as a markdown table.", runSqlSchema, async (args) => handleRunSql(args));
|
|
22
|
+
server.tool("rest_query", "Query or mutate data via the PostgREST REST API. Supports GET/POST/PATCH/DELETE with query params.", restQuerySchema, async (args) => handleRestQuery(args));
|
|
23
|
+
server.tool("upload_file", "Upload text content to project storage. Returns the storage key and size.", uploadFileSchema, async (args) => handleUploadFile(args));
|
|
24
|
+
server.tool("renew_project", "Renew a project's lease. Returns success or payment details if x402 payment is needed.", renewSchema, async (args) => handleRenew(args));
|
|
25
|
+
server.tool("deploy_site", "Deploy a static site (HTML/CSS/JS). Files are uploaded to S3 and served via CloudFront at a unique URL. Costs $0.05 USDC via x402.", deploySiteSchema, async (args) => handleDeploySite(args));
|
|
26
|
+
server.tool("claim_subdomain", "Claim a custom subdomain (e.g. myapp.run402.com) and point it at an existing deployment. Free, requires service_key auth.", claimSubdomainSchema, async (args) => handleClaimSubdomain(args));
|
|
27
|
+
server.tool("delete_subdomain", "Release a custom subdomain. The URL will stop serving content.", deleteSubdomainSchema, async (args) => handleDeleteSubdomain(args));
|
|
28
|
+
server.tool("deploy_function", "Deploy a serverless function (Node 22) to a project. Handler signature: export default async (req: Request) => Response. Pre-bundled packages: stripe, openai, @anthropic-ai/sdk, resend, zod, uuid, jsonwebtoken, bcryptjs, cheerio, csv-parse.", deployFunctionSchema, async (args) => handleDeployFunction(args));
|
|
29
|
+
server.tool("invoke_function", "Invoke a deployed function via HTTP. Returns the function's response body and status code. Useful for testing functions without building a frontend.", invokeFunctionSchema, async (args) => handleInvokeFunction(args));
|
|
30
|
+
server.tool("get_function_logs", "Get recent logs from a deployed function. Shows console.log/error output and error stack traces from CloudWatch.", getFunctionLogsSchema, async (args) => handleGetFunctionLogs(args));
|
|
31
|
+
server.tool("set_secret", "Set a project secret (e.g. STRIPE_SECRET_KEY). Secrets are injected as process.env variables in functions. Setting an existing key overwrites it.", setSecretSchema, async (args) => handleSetSecret(args));
|
|
32
|
+
const transport = new StdioServerTransport();
|
|
33
|
+
await server.connect(transport);
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface StoredProject {
|
|
2
|
+
anon_key: string;
|
|
3
|
+
service_key: string;
|
|
4
|
+
tier: string;
|
|
5
|
+
expires_at: string;
|
|
6
|
+
}
|
|
7
|
+
export interface KeyStore {
|
|
8
|
+
projects: Record<string, StoredProject>;
|
|
9
|
+
}
|
|
10
|
+
export declare function loadKeyStore(path?: string): KeyStore;
|
|
11
|
+
export declare function saveKeyStore(store: KeyStore, path?: string): void;
|
|
12
|
+
export declare function getProject(projectId: string, path?: string): StoredProject | undefined;
|
|
13
|
+
export declare function saveProject(projectId: string, project: StoredProject, path?: string): void;
|
|
14
|
+
//# sourceMappingURL=keystore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keystore.d.ts","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACzC;AAED,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAYpD;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,UAAU,CACxB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,aAAa,GAAG,SAAS,CAG3B;AAED,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,aAAa,EACtB,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAKN"}
|
package/dist/keystore.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, renameSync, chmodSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { getKeystorePath } from "./config.js";
|
|
5
|
+
export function loadKeyStore(path) {
|
|
6
|
+
const p = path ?? getKeystorePath();
|
|
7
|
+
try {
|
|
8
|
+
const data = readFileSync(p, "utf-8");
|
|
9
|
+
const parsed = JSON.parse(data);
|
|
10
|
+
if (parsed && typeof parsed === "object" && parsed.projects) {
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
return { projects: {} };
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return { projects: {} };
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function saveKeyStore(store, path) {
|
|
20
|
+
const p = path ?? getKeystorePath();
|
|
21
|
+
const dir = dirname(p);
|
|
22
|
+
mkdirSync(dir, { recursive: true });
|
|
23
|
+
const tmp = join(dir, `.projects.${randomBytes(4).toString("hex")}.tmp`);
|
|
24
|
+
writeFileSync(tmp, JSON.stringify(store, null, 2), { mode: 0o600 });
|
|
25
|
+
renameSync(tmp, p);
|
|
26
|
+
chmodSync(p, 0o600);
|
|
27
|
+
}
|
|
28
|
+
export function getProject(projectId, path) {
|
|
29
|
+
const store = loadKeyStore(path);
|
|
30
|
+
return store.projects[projectId];
|
|
31
|
+
}
|
|
32
|
+
export function saveProject(projectId, project, path) {
|
|
33
|
+
const p = path ?? getKeystorePath();
|
|
34
|
+
const store = loadKeyStore(p);
|
|
35
|
+
store.projects[projectId] = project;
|
|
36
|
+
saveKeyStore(store, p);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=keystore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keystore.js","sourceRoot":"","sources":["../src/keystore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACxF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAa9C,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,MAAM,CAAC,GAAG,IAAI,IAAI,eAAe,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC5D,OAAO,MAAkB,CAAC;QAC5B,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAe,EAAE,IAAa;IACzD,MAAM,CAAC,GAAG,IAAI,IAAI,eAAe,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzE,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACnB,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,SAAiB,EACjB,IAAa;IAEb,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,SAAiB,EACjB,OAAsB,EACtB,IAAa;IAEb,MAAM,CAAC,GAAG,IAAI,IAAI,eAAe,EAAE,CAAC;IACpC,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC;IACpC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const deployFunctionSchema: {
|
|
3
|
+
project_id: z.ZodString;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
code: z.ZodString;
|
|
6
|
+
config: z.ZodOptional<z.ZodObject<{
|
|
7
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
8
|
+
memory: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
timeout?: number | undefined;
|
|
11
|
+
memory?: number | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
timeout?: number | undefined;
|
|
14
|
+
memory?: number | undefined;
|
|
15
|
+
}>>;
|
|
16
|
+
deps: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
17
|
+
};
|
|
18
|
+
export declare function handleDeployFunction(args: {
|
|
19
|
+
project_id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
code: string;
|
|
22
|
+
config?: {
|
|
23
|
+
timeout?: number;
|
|
24
|
+
memory?: number;
|
|
25
|
+
};
|
|
26
|
+
deps?: string[];
|
|
27
|
+
}): Promise<{
|
|
28
|
+
content: Array<{
|
|
29
|
+
type: "text";
|
|
30
|
+
text: string;
|
|
31
|
+
}>;
|
|
32
|
+
isError?: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
//# sourceMappingURL=deploy-function.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-function.d.ts","sourceRoot":"","sources":["../../src/tools/deploy-function.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;CAmBhC,CAAC;AAEF,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA4EjF"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { getProject } from "../keystore.js";
|
|
4
|
+
export const deployFunctionSchema = {
|
|
5
|
+
project_id: z.string().describe("The project ID to deploy the function to"),
|
|
6
|
+
name: z
|
|
7
|
+
.string()
|
|
8
|
+
.describe("Function name (URL-safe slug: lowercase, hyphens, alphanumeric, e.g. 'stripe-webhook')"),
|
|
9
|
+
code: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("TypeScript or JavaScript source code. Must export a default async function: export default async (req: Request) => Response"),
|
|
12
|
+
config: z
|
|
13
|
+
.object({
|
|
14
|
+
timeout: z.number().optional().describe("Timeout in seconds (default: tier max)"),
|
|
15
|
+
memory: z.number().optional().describe("Memory in MB (default: tier max)"),
|
|
16
|
+
})
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Optional function configuration"),
|
|
19
|
+
deps: z
|
|
20
|
+
.array(z.string())
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Optional npm packages to install alongside pre-bundled packages"),
|
|
23
|
+
};
|
|
24
|
+
export async function handleDeployFunction(args) {
|
|
25
|
+
const project = getProject(args.project_id);
|
|
26
|
+
if (!project) {
|
|
27
|
+
return {
|
|
28
|
+
content: [
|
|
29
|
+
{
|
|
30
|
+
type: "text",
|
|
31
|
+
text: `Error: Project \`${args.project_id}\` not found in key store. Provision a project first with \`provision_postgres_project\`.`,
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
isError: true,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const res = await apiRequest(`/admin/v1/projects/${args.project_id}/functions`, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: {
|
|
40
|
+
Authorization: `Bearer ${project.service_key}`,
|
|
41
|
+
},
|
|
42
|
+
body: {
|
|
43
|
+
name: args.name,
|
|
44
|
+
code: args.code,
|
|
45
|
+
config: args.config,
|
|
46
|
+
deps: args.deps,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
if (res.is402) {
|
|
50
|
+
const body = res.body;
|
|
51
|
+
return {
|
|
52
|
+
content: [
|
|
53
|
+
{
|
|
54
|
+
type: "text",
|
|
55
|
+
text: `## Payment Required\n\nProject lease expired. Renew to continue deploying functions.\n\n\`\`\`json\n${JSON.stringify(body, null, 2)}\n\`\`\``,
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
const body = res.body;
|
|
62
|
+
const msg = body.error || `HTTP ${res.status}`;
|
|
63
|
+
return {
|
|
64
|
+
content: [{ type: "text", text: `Error: ${msg}` }],
|
|
65
|
+
isError: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const body = res.body;
|
|
69
|
+
const lines = [
|
|
70
|
+
`## Function Deployed`,
|
|
71
|
+
``,
|
|
72
|
+
`| Field | Value |`,
|
|
73
|
+
`|-------|-------|`,
|
|
74
|
+
`| name | \`${body.name}\` |`,
|
|
75
|
+
`| url | ${body.url} |`,
|
|
76
|
+
`| status | ${body.status} |`,
|
|
77
|
+
`| runtime | ${body.runtime} |`,
|
|
78
|
+
`| timeout | ${body.timeout}s |`,
|
|
79
|
+
`| memory | ${body.memory}MB |`,
|
|
80
|
+
``,
|
|
81
|
+
`The function is live at **${body.url}**`,
|
|
82
|
+
``,
|
|
83
|
+
`Invoke with: \`invoke_function(project_id: "${args.project_id}", name: "${body.name}")\``,
|
|
84
|
+
];
|
|
85
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=deploy-function.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-function.js","sourceRoot":"","sources":["../../src/tools/deploy-function.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const deploySiteSchema: {
|
|
3
|
+
name: z.ZodString;
|
|
4
|
+
project: z.ZodOptional<z.ZodString>;
|
|
5
|
+
target: z.ZodOptional<z.ZodString>;
|
|
6
|
+
files: z.ZodArray<z.ZodObject<{
|
|
7
|
+
file: z.ZodString;
|
|
8
|
+
data: z.ZodString;
|
|
9
|
+
encoding: z.ZodOptional<z.ZodEnum<["utf-8", "base64"]>>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
file: string;
|
|
12
|
+
data: string;
|
|
13
|
+
encoding?: "utf-8" | "base64" | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
file: string;
|
|
16
|
+
data: string;
|
|
17
|
+
encoding?: "utf-8" | "base64" | undefined;
|
|
18
|
+
}>, "many">;
|
|
19
|
+
};
|
|
20
|
+
export declare function handleDeploySite(args: {
|
|
21
|
+
name: string;
|
|
22
|
+
project?: string;
|
|
23
|
+
target?: string;
|
|
24
|
+
files: Array<{
|
|
25
|
+
file: string;
|
|
26
|
+
data: string;
|
|
27
|
+
encoding?: string;
|
|
28
|
+
}>;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
content: Array<{
|
|
31
|
+
type: "text";
|
|
32
|
+
text: string;
|
|
33
|
+
}>;
|
|
34
|
+
isError?: boolean;
|
|
35
|
+
}>;
|
|
36
|
+
//# sourceMappingURL=deploy-site.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-site.d.ts","sourceRoot":"","sources":["../../src/tools/deploy-site.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;CAwB5B,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjE,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA6EjF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
export const deploySiteSchema = {
|
|
4
|
+
name: z
|
|
5
|
+
.string()
|
|
6
|
+
.describe("Site name (e.g. 'family-todo', 'portfolio')"),
|
|
7
|
+
project: z
|
|
8
|
+
.string()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Optional project ID to link this deployment to an existing Run402 project"),
|
|
11
|
+
target: z
|
|
12
|
+
.string()
|
|
13
|
+
.optional()
|
|
14
|
+
.describe("Deployment target (e.g. 'production'). Tracked in DB for future alias support."),
|
|
15
|
+
files: z
|
|
16
|
+
.array(z.object({
|
|
17
|
+
file: z.string().describe("File path (e.g. 'index.html', 'assets/logo.png')"),
|
|
18
|
+
data: z.string().describe("File content (text or base64-encoded)"),
|
|
19
|
+
encoding: z
|
|
20
|
+
.enum(["utf-8", "base64"])
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Encoding: 'utf-8' (default) for text, 'base64' for binary files"),
|
|
23
|
+
}))
|
|
24
|
+
.describe("Array of files to deploy. Must include at least index.html."),
|
|
25
|
+
};
|
|
26
|
+
export async function handleDeploySite(args) {
|
|
27
|
+
const res = await apiRequest("/v1/deployments", {
|
|
28
|
+
method: "POST",
|
|
29
|
+
body: {
|
|
30
|
+
name: args.name,
|
|
31
|
+
project: args.project,
|
|
32
|
+
target: args.target,
|
|
33
|
+
files: args.files,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
if (res.is402) {
|
|
37
|
+
const body = res.body;
|
|
38
|
+
const lines = [
|
|
39
|
+
`## Payment Required`,
|
|
40
|
+
``,
|
|
41
|
+
`To deploy a static site, an x402 payment of **$0.05 USDC** is needed.`,
|
|
42
|
+
``,
|
|
43
|
+
];
|
|
44
|
+
if (body.x402) {
|
|
45
|
+
lines.push(`**Payment details:**`);
|
|
46
|
+
lines.push("```json");
|
|
47
|
+
lines.push(JSON.stringify(body.x402, null, 2));
|
|
48
|
+
lines.push("```");
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
lines.push(`**Server response:**`);
|
|
52
|
+
lines.push("```json");
|
|
53
|
+
lines.push(JSON.stringify(body, null, 2));
|
|
54
|
+
lines.push("```");
|
|
55
|
+
}
|
|
56
|
+
lines.push(``);
|
|
57
|
+
lines.push(`The user's wallet or payment agent must send the required amount. ` +
|
|
58
|
+
`Once payment is confirmed, retry this tool call.`);
|
|
59
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
60
|
+
}
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
const body = res.body;
|
|
63
|
+
const msg = body.error || `HTTP ${res.status}`;
|
|
64
|
+
return {
|
|
65
|
+
content: [{ type: "text", text: `Error: ${msg}` }],
|
|
66
|
+
isError: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const body = res.body;
|
|
70
|
+
const lines = [
|
|
71
|
+
`## Site Deployed`,
|
|
72
|
+
``,
|
|
73
|
+
`| Field | Value |`,
|
|
74
|
+
`|-------|-------|`,
|
|
75
|
+
`| id | \`${body.id}\` |`,
|
|
76
|
+
`| url | ${body.url} |`,
|
|
77
|
+
`| status | ${body.status} |`,
|
|
78
|
+
`| files | ${body.files_count} |`,
|
|
79
|
+
`| size | ${(body.total_size / 1024).toFixed(1)} KB |`,
|
|
80
|
+
``,
|
|
81
|
+
`The site is live at **${body.url}**`,
|
|
82
|
+
];
|
|
83
|
+
if (body.project_id) {
|
|
84
|
+
lines.push(`Linked to project \`${body.project_id}\``);
|
|
85
|
+
}
|
|
86
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=deploy-site.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-site.js","sourceRoot":"","sources":["../../src/tools/deploy-site.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const getFunctionLogsSchema: {
|
|
3
|
+
project_id: z.ZodString;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
tail: z.ZodOptional<z.ZodNumber>;
|
|
6
|
+
};
|
|
7
|
+
export declare function handleGetFunctionLogs(args: {
|
|
8
|
+
project_id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
tail?: number;
|
|
11
|
+
}): Promise<{
|
|
12
|
+
content: Array<{
|
|
13
|
+
type: "text";
|
|
14
|
+
text: string;
|
|
15
|
+
}>;
|
|
16
|
+
isError?: boolean;
|
|
17
|
+
}>;
|
|
18
|
+
//# sourceMappingURL=get-function-logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-function-logs.d.ts","sourceRoot":"","sources":["../../src/tools/get-function-logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,qBAAqB;;;;CAOjC,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA+DjF"}
|