@runapi.ai/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/CHANGELOG.md +11 -0
- package/LICENSE +201 -0
- package/README.md +367 -0
- package/data/contract.json +3493 -0
- package/data/pricing.json +1263 -0
- package/dist/bin/runapi-mcp.d.ts +2 -0
- package/dist/bin/runapi-mcp.js +10 -0
- package/dist/bin/runapi-mcp.js.map +1 -0
- package/dist/scripts/sync-data.d.ts +2 -0
- package/dist/scripts/sync-data.js +22 -0
- package/dist/scripts/sync-data.js.map +1 -0
- package/dist/src/config.d.ts +7 -0
- package/dist/src/config.js +32 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/constants.d.ts +5 -0
- package/dist/src/constants.js +6 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +6 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/init.d.ts +1 -0
- package/dist/src/init.js +52 -0
- package/dist/src/init.js.map +1 -0
- package/dist/src/lib/contract.d.ts +21 -0
- package/dist/src/lib/contract.js +81 -0
- package/dist/src/lib/contract.js.map +1 -0
- package/dist/src/lib/data.d.ts +3 -0
- package/dist/src/lib/data.js +22 -0
- package/dist/src/lib/data.js.map +1 -0
- package/dist/src/lib/errors.d.ts +10 -0
- package/dist/src/lib/errors.js +88 -0
- package/dist/src/lib/errors.js.map +1 -0
- package/dist/src/lib/input-rules.d.ts +9 -0
- package/dist/src/lib/input-rules.js +61 -0
- package/dist/src/lib/input-rules.js.map +1 -0
- package/dist/src/lib/pricing.d.ts +7 -0
- package/dist/src/lib/pricing.js +42 -0
- package/dist/src/lib/pricing.js.map +1 -0
- package/dist/src/lib/runapi-client.d.ts +22 -0
- package/dist/src/lib/runapi-client.js +119 -0
- package/dist/src/lib/runapi-client.js.map +1 -0
- package/dist/src/lib/schema.d.ts +3 -0
- package/dist/src/lib/schema.js +44 -0
- package/dist/src/lib/schema.js.map +1 -0
- package/dist/src/lib/text.d.ts +5 -0
- package/dist/src/lib/text.js +27 -0
- package/dist/src/lib/text.js.map +1 -0
- package/dist/src/lib/tool-response.d.ts +6 -0
- package/dist/src/lib/tool-response.js +11 -0
- package/dist/src/lib/tool-response.js.map +1 -0
- package/dist/src/server-instructions.d.ts +1 -0
- package/dist/src/server-instructions.js +66 -0
- package/dist/src/server-instructions.js.map +1 -0
- package/dist/src/server.d.ts +2 -0
- package/dist/src/server.js +20 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/tools/authenticated-handlers.d.ts +77 -0
- package/dist/src/tools/authenticated-handlers.js +144 -0
- package/dist/src/tools/authenticated-handlers.js.map +1 -0
- package/dist/src/tools/authenticated.d.ts +3 -0
- package/dist/src/tools/authenticated.js +53 -0
- package/dist/src/tools/authenticated.js.map +1 -0
- package/dist/src/tools/catalog-handlers.d.ts +88 -0
- package/dist/src/tools/catalog-handlers.js +104 -0
- package/dist/src/tools/catalog-handlers.js.map +1 -0
- package/dist/src/tools/catalog.d.ts +3 -0
- package/dist/src/tools/catalog.js +29 -0
- package/dist/src/tools/catalog.js.map +1 -0
- package/dist/src/types.d.ts +75 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runapi-mcp.js","sourceRoot":"","sources":["../../bin/runapi-mcp.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,CAAC,EAAE,AAAD,EAAG,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;AAE5C,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;IACvB,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;KAAM,CAAC;IACN,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
const railsRoot = path.resolve(process.argv[2] || "..");
|
|
6
|
+
const destination = path.resolve("data");
|
|
7
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
8
|
+
fs.copyFileSync(path.join(railsRoot, "sdk", "contract.json"), path.join(destination, "contract.json"));
|
|
9
|
+
const ruby = spawnSync("ruby", [
|
|
10
|
+
"-r", "yaml",
|
|
11
|
+
"-r", "json",
|
|
12
|
+
"-e",
|
|
13
|
+
"data=YAML.load_file(ARGV[0]); puts JSON.pretty_generate(data)",
|
|
14
|
+
path.join(railsRoot, "db", "pricing.yml")
|
|
15
|
+
], { encoding: "utf8" });
|
|
16
|
+
if (ruby.status !== 0) {
|
|
17
|
+
process.stderr.write(ruby.stderr);
|
|
18
|
+
process.exit(ruby.status || 1);
|
|
19
|
+
}
|
|
20
|
+
fs.writeFileSync(path.join(destination, "pricing.json"), ruby.stdout);
|
|
21
|
+
console.log(`Synced contract.json and pricing.json from ${railsRoot}`);
|
|
22
|
+
//# sourceMappingURL=sync-data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-data.js","sourceRoot":"","sources":["../../scripts/sync-data.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACxD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAEzC,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,eAAe,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;AAEvG,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE;IAC7B,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,IAAI;IACJ,+DAA+D;IAC/D,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,aAAa,CAAC;CAC1C,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;AAEzB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;AACtE,OAAO,CAAC,GAAG,CAAC,8CAA8C,SAAS,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type RunApiConfig = {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function configPath(): string;
|
|
6
|
+
export declare function loadConfig(env?: NodeJS.ProcessEnv): RunApiConfig;
|
|
7
|
+
export declare function requireApiKey(config?: RunApiConfig): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { DEFAULT_BASE_URL, RUNAPI_API_KEY_ENV } from "./constants.js";
|
|
5
|
+
export function configPath() {
|
|
6
|
+
return path.join(os.homedir(), ".config", "runapi", "config.json");
|
|
7
|
+
}
|
|
8
|
+
export function loadConfig(env = process.env) {
|
|
9
|
+
const file = readConfigFile();
|
|
10
|
+
const apiKey = env[RUNAPI_API_KEY_ENV]?.trim() || file.apiKey || file.api_key || undefined;
|
|
11
|
+
const baseUrl = env.RUNAPI_BASE_URL?.trim() || file.baseUrl || file.base_url || DEFAULT_BASE_URL;
|
|
12
|
+
return { apiKey, baseUrl };
|
|
13
|
+
}
|
|
14
|
+
export function requireApiKey(config = loadConfig()) {
|
|
15
|
+
if (!config.apiKey) {
|
|
16
|
+
throw new Error("RunAPI API key is required. Set RUNAPI_API_KEY or add apiKey to ~/.config/runapi/config.json.");
|
|
17
|
+
}
|
|
18
|
+
return config.apiKey;
|
|
19
|
+
}
|
|
20
|
+
function readConfigFile() {
|
|
21
|
+
const file = configPath();
|
|
22
|
+
if (!fs.existsSync(file)) {
|
|
23
|
+
return {};
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AActE,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAyB,OAAO,CAAC,GAAG;IAC7D,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,kBAAkB,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,SAAS,CAAC;IAC3F,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IAEjG,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAM,GAAG,UAAU,EAAE;IACjD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,+FAA+F,CAAC,CAAC;IACnH,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;IAC1B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAe,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const PACKAGE_NAME = "@runapi.ai/mcp";
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.1.0";
|
|
3
|
+
export declare const DEFAULT_BASE_URL = "https://runapi.ai";
|
|
4
|
+
export declare const RUNAPI_API_KEY_ENV = "RUNAPI_API_KEY";
|
|
5
|
+
export declare const USER_AGENT = "@runapi.ai/mcp/0.1.0";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const PACKAGE_NAME = "@runapi.ai/mcp";
|
|
2
|
+
export const PACKAGE_VERSION = "0.1.0";
|
|
3
|
+
export const DEFAULT_BASE_URL = "https://runapi.ai";
|
|
4
|
+
export const RUNAPI_API_KEY_ENV = "RUNAPI_API_KEY";
|
|
5
|
+
export const USER_AGENT = `${PACKAGE_NAME}/${PACKAGE_VERSION}`;
|
|
6
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AACvC,MAAM,CAAC,MAAM,gBAAgB,GAAG,mBAAmB,CAAC;AACpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,gBAAgB,CAAC;AACnD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,YAAY,IAAI,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
const server = createServer();
|
|
5
|
+
await server.connect(new StdioServerTransport());
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAC9B,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runInit(args: string[]): Promise<void>;
|
package/dist/src/init.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const PLATFORM_CONFIGS = {
|
|
4
|
+
claude: ".mcp.json",
|
|
5
|
+
cursor: ".cursor/mcp.json",
|
|
6
|
+
windsurf: ".windsurf/mcp.json",
|
|
7
|
+
vscode: ".vscode/mcp.json",
|
|
8
|
+
roo: ".roo/mcp.json"
|
|
9
|
+
};
|
|
10
|
+
export async function runInit(args) {
|
|
11
|
+
const platform = args[0];
|
|
12
|
+
if (!platform || !(platform in PLATFORM_CONFIGS)) {
|
|
13
|
+
console.error("Usage: runapi-mcp init <claude|cursor|windsurf|vscode|roo>");
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const file = path.resolve(process.cwd(), PLATFORM_CONFIGS[platform]);
|
|
18
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
19
|
+
const existing = readJson(file);
|
|
20
|
+
const serverConfig = {
|
|
21
|
+
command: "npx",
|
|
22
|
+
args: ["-y", "@runapi.ai/mcp"],
|
|
23
|
+
env: {
|
|
24
|
+
RUNAPI_API_KEY: "${RUNAPI_API_KEY}"
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const next = platform === "vscode" ? {
|
|
28
|
+
...existing,
|
|
29
|
+
servers: {
|
|
30
|
+
...(existing.servers || {}),
|
|
31
|
+
runapi: {
|
|
32
|
+
type: "stdio",
|
|
33
|
+
...serverConfig
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} : {
|
|
37
|
+
...existing,
|
|
38
|
+
mcpServers: {
|
|
39
|
+
...(existing.mcpServers || {}),
|
|
40
|
+
runapi: serverConfig
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
fs.writeFileSync(file, `${JSON.stringify(next, null, 2)}\n`);
|
|
44
|
+
console.log(`Wrote ${file}`);
|
|
45
|
+
}
|
|
46
|
+
function readJson(file) {
|
|
47
|
+
if (!fs.existsSync(file)) {
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
return JSON.parse(fs.readFileSync(file, "utf8"));
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,gBAAgB,GAAG;IACvB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,kBAAkB;IAC1B,QAAQ,EAAE,oBAAoB;IAC9B,MAAM,EAAE,kBAAkB;IAC1B,GAAG,EAAE,eAAe;CACZ,CAAC;AAIX,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAc;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAyB,CAAC;IACjD,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,IAAI,gBAAgB,CAAC,EAAE,CAAC;QACjD,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,YAAY,GAAG;QACnB,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,IAAI,EAAE,gBAAgB,CAAC;QAC9B,GAAG,EAAE;YACH,cAAc,EAAE,mBAAmB;SACpC;KACF,CAAC;IAEF,MAAM,IAAI,GAAG,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC;QACnC,GAAG,QAAQ;QACX,OAAO,EAAE;YACP,GAAG,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC;YAC3B,MAAM,EAAE;gBACN,IAAI,EAAE,OAAO;gBACb,GAAG,YAAY;aAChB;SACF;KACF,CAAC,CAAC,CAAC;QACF,GAAG,QAAQ;QACX,UAAU,EAAE;YACV,GAAG,CAAC,QAAQ,CAAC,UAAU,IAAI,EAAE,CAAC;YAC9B,MAAM,EAAE,YAAY;SACrB;KACF,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAwB,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Contract, ContractAction, ContractField, ModelInfo } from "../types.js";
|
|
2
|
+
export declare const contract: Contract;
|
|
3
|
+
export declare function listContractModels(source?: Contract): ModelInfo[];
|
|
4
|
+
export declare function listActionGroups(source?: Contract): {
|
|
5
|
+
modality: string;
|
|
6
|
+
actions: string[];
|
|
7
|
+
}[];
|
|
8
|
+
export declare function findAction(service: string, action: string, source?: Contract): ContractAction | undefined;
|
|
9
|
+
export declare function findModel(model: string, source?: Contract): ModelInfo | undefined;
|
|
10
|
+
export declare function findModels(model: string, source?: Contract): ModelInfo[];
|
|
11
|
+
export declare function findModelForAction(service: string, action: string, model?: string, source?: Contract): ModelInfo | undefined;
|
|
12
|
+
export declare function fieldsForModel(action: ContractAction, model: string): Record<string, ContractField>;
|
|
13
|
+
export declare function fieldSummary(fields: Record<string, ContractField>): {
|
|
14
|
+
name: string;
|
|
15
|
+
required: boolean;
|
|
16
|
+
enum: unknown[] | undefined;
|
|
17
|
+
default: unknown;
|
|
18
|
+
min: number | undefined;
|
|
19
|
+
max: number | undefined;
|
|
20
|
+
type: string | undefined;
|
|
21
|
+
}[];
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { contractKey, modalityForAction, routeAction } from "./text.js";
|
|
2
|
+
import { readContract } from "./data.js";
|
|
3
|
+
export const contract = readContract();
|
|
4
|
+
export function listContractModels(source = contract) {
|
|
5
|
+
return Object.entries(source.actions).flatMap(([key, action]) => {
|
|
6
|
+
const [service, actionSlug] = key.split("/");
|
|
7
|
+
return action.models.map((model) => ({
|
|
8
|
+
service,
|
|
9
|
+
action: action.endpoint,
|
|
10
|
+
route_action: routeAction(actionSlug),
|
|
11
|
+
provider: action.provider,
|
|
12
|
+
model_line: action.model,
|
|
13
|
+
model,
|
|
14
|
+
fields: fieldsForModel(action, model)
|
|
15
|
+
}));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function listActionGroups(source = contract) {
|
|
19
|
+
const groups = new Map();
|
|
20
|
+
for (const action of Object.values(source.actions)) {
|
|
21
|
+
const modality = modalityForAction(action.endpoint);
|
|
22
|
+
if (!groups.has(modality)) {
|
|
23
|
+
groups.set(modality, new Set());
|
|
24
|
+
}
|
|
25
|
+
groups.get(modality)?.add(action.endpoint);
|
|
26
|
+
}
|
|
27
|
+
return [...groups.entries()].map(([modality, actions]) => ({
|
|
28
|
+
modality,
|
|
29
|
+
actions: [...actions].sort()
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
export function findAction(service, action, source = contract) {
|
|
33
|
+
const direct = source.actions[contractKey(service, action)];
|
|
34
|
+
if (direct) {
|
|
35
|
+
return direct;
|
|
36
|
+
}
|
|
37
|
+
return Object.entries(source.actions).find(([key, value]) => {
|
|
38
|
+
const [candidateService] = key.split("/");
|
|
39
|
+
return candidateService === service && value.endpoint === action;
|
|
40
|
+
})?.[1];
|
|
41
|
+
}
|
|
42
|
+
export function findModel(model, source = contract) {
|
|
43
|
+
return listContractModels(source).find((entry) => entry.model === model);
|
|
44
|
+
}
|
|
45
|
+
export function findModels(model, source = contract) {
|
|
46
|
+
return listContractModels(source).filter((entry) => entry.model === model);
|
|
47
|
+
}
|
|
48
|
+
export function findModelForAction(service, action, model, source = contract) {
|
|
49
|
+
const entry = findAction(service, action, source);
|
|
50
|
+
if (!entry) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
const selectedModel = model || entry.models[0];
|
|
54
|
+
if (!entry.models.includes(selectedModel)) {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
service,
|
|
59
|
+
action: entry.endpoint,
|
|
60
|
+
route_action: entry.endpoint,
|
|
61
|
+
provider: entry.provider,
|
|
62
|
+
model_line: entry.model,
|
|
63
|
+
model: selectedModel,
|
|
64
|
+
fields: fieldsForModel(entry, selectedModel)
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function fieldsForModel(action, model) {
|
|
68
|
+
return action.fields_by_model[model] || action.fields_by_model.__nil_model__ || {};
|
|
69
|
+
}
|
|
70
|
+
export function fieldSummary(fields) {
|
|
71
|
+
return Object.entries(fields).map(([name, field]) => ({
|
|
72
|
+
name,
|
|
73
|
+
required: Boolean(field.required),
|
|
74
|
+
enum: field.enum,
|
|
75
|
+
default: field.default,
|
|
76
|
+
min: field.min ?? field.minimum,
|
|
77
|
+
max: field.max ?? field.maximum,
|
|
78
|
+
type: field.type
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../../../src/lib/contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
function repoRoot() {
|
|
5
|
+
const current = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const candidates = [
|
|
7
|
+
path.resolve(current, "..", "..", ".."),
|
|
8
|
+
path.resolve(current, "..", "..")
|
|
9
|
+
];
|
|
10
|
+
const root = candidates.find((candidate) => existsSync(path.join(candidate, "data", "contract.json")));
|
|
11
|
+
if (!root) {
|
|
12
|
+
throw new Error("Unable to locate RunAPI MCP data directory.");
|
|
13
|
+
}
|
|
14
|
+
return root;
|
|
15
|
+
}
|
|
16
|
+
export function readContract() {
|
|
17
|
+
return JSON.parse(readFileSync(path.join(repoRoot(), "data", "contract.json"), "utf8"));
|
|
18
|
+
}
|
|
19
|
+
export function readPricing() {
|
|
20
|
+
return JSON.parse(readFileSync(path.join(repoRoot(), "data", "pricing.json"), "utf8"));
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../src/lib/data.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,SAAS,QAAQ;IACf,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;KAClC,CAAC;IAEF,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IACvG,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,CAAa,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAkB,CAAC;AAC1G,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class RunApiClientError extends Error {
|
|
2
|
+
readonly status?: number | undefined;
|
|
3
|
+
readonly details?: unknown | undefined;
|
|
4
|
+
constructor(message: string, status?: number | undefined, details?: unknown | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class PollTimeoutError extends Error {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
export declare function friendlyError(error: unknown): string;
|
|
10
|
+
export declare function errorFromResponse(response: Response): Promise<RunApiClientError>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export class RunApiClientError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
details;
|
|
4
|
+
constructor(message, status, details) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.details = details;
|
|
8
|
+
this.name = "RunApiClientError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class PollTimeoutError extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "PollTimeoutError";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function friendlyError(error) {
|
|
18
|
+
if (error instanceof RunApiClientError) {
|
|
19
|
+
switch (error.status) {
|
|
20
|
+
case 401:
|
|
21
|
+
return "RunAPI rejected the API key. Check RUNAPI_API_KEY or ~/.config/runapi/config.json.";
|
|
22
|
+
case 402:
|
|
23
|
+
return "The RunAPI account has insufficient credits. Add credits in the RunAPI dashboard, then retry.";
|
|
24
|
+
case 429:
|
|
25
|
+
return "RunAPI rate limited this request. Wait briefly, then retry.";
|
|
26
|
+
case 503:
|
|
27
|
+
return "This RunAPI service is temporarily unavailable. Retry later or choose another model.";
|
|
28
|
+
default:
|
|
29
|
+
return error.message;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (error instanceof Error) {
|
|
33
|
+
return error.message;
|
|
34
|
+
}
|
|
35
|
+
return "RunAPI request failed.";
|
|
36
|
+
}
|
|
37
|
+
export async function errorFromResponse(response) {
|
|
38
|
+
const text = await response.text();
|
|
39
|
+
let body = text;
|
|
40
|
+
try {
|
|
41
|
+
body = text ? JSON.parse(text) : undefined;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
body = text;
|
|
45
|
+
}
|
|
46
|
+
return new RunApiClientError(extractMessage(body) || defaultMessage(response.status), response.status, body);
|
|
47
|
+
}
|
|
48
|
+
function extractMessage(body) {
|
|
49
|
+
if (typeof body === "string") {
|
|
50
|
+
return body.trim() || undefined;
|
|
51
|
+
}
|
|
52
|
+
if (!body || typeof body !== "object") {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
const record = body;
|
|
56
|
+
for (const key of ["message", "detail", "error", "msg"]) {
|
|
57
|
+
const value = record[key];
|
|
58
|
+
if (typeof value === "string" && value.trim()) {
|
|
59
|
+
return value.trim();
|
|
60
|
+
}
|
|
61
|
+
const nested = extractMessage(value);
|
|
62
|
+
if (nested) {
|
|
63
|
+
return nested;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
function defaultMessage(status) {
|
|
69
|
+
switch (status) {
|
|
70
|
+
case 400:
|
|
71
|
+
return "RunAPI rejected the request parameters.";
|
|
72
|
+
case 401:
|
|
73
|
+
return "RunAPI API key is invalid or missing.";
|
|
74
|
+
case 402:
|
|
75
|
+
return "Insufficient RunAPI credits.";
|
|
76
|
+
case 404:
|
|
77
|
+
return "RunAPI resource was not found.";
|
|
78
|
+
case 422:
|
|
79
|
+
return "RunAPI could not validate the request.";
|
|
80
|
+
case 429:
|
|
81
|
+
return "RunAPI rate limit exceeded.";
|
|
82
|
+
case 503:
|
|
83
|
+
return "RunAPI service unavailable.";
|
|
84
|
+
default:
|
|
85
|
+
return `RunAPI request failed with HTTP ${status}.`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/lib/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ModelInfo } from "../types.js";
|
|
2
|
+
export type InputRule = {
|
|
3
|
+
when: Record<string, unknown>;
|
|
4
|
+
required: string[];
|
|
5
|
+
forbidden: string[];
|
|
6
|
+
description: string;
|
|
7
|
+
};
|
|
8
|
+
export declare function inputRulesForModel(info: Pick<ModelInfo, "service" | "action">): InputRule[];
|
|
9
|
+
export declare function validateInputRules(info: ModelInfo, params: Record<string, unknown>): string | undefined;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export function inputRulesForModel(info) {
|
|
2
|
+
if (info.service === "suno" && info.action === "text_to_music") {
|
|
3
|
+
return [
|
|
4
|
+
{
|
|
5
|
+
when: { vocal_mode: "auto_lyrics" },
|
|
6
|
+
required: ["prompt"],
|
|
7
|
+
forbidden: ["lyrics", "style", "title"],
|
|
8
|
+
description: "auto_lyrics requires prompt and must not include lyrics, style, or title."
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
when: { vocal_mode: "exact_lyrics" },
|
|
12
|
+
required: ["lyrics", "style", "title"],
|
|
13
|
+
forbidden: ["prompt"],
|
|
14
|
+
description: "exact_lyrics requires lyrics, style, and title, and must not include prompt."
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
when: { vocal_mode: "instrumental" },
|
|
18
|
+
required: ["style", "title"],
|
|
19
|
+
forbidden: ["prompt", "lyrics"],
|
|
20
|
+
description: "instrumental requires style and title, and must not include prompt or lyrics."
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
export function validateInputRules(info, params) {
|
|
27
|
+
const rules = inputRulesForModel(info);
|
|
28
|
+
if (rules.length === 0) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const controllingFields = new Set(rules.flatMap((rule) => Object.keys(rule.when)));
|
|
32
|
+
for (const field of controllingFields) {
|
|
33
|
+
if (!hasValue(params[field])) {
|
|
34
|
+
return `${field} is required to choose a valid parameter shape.`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const rule = rules.find((candidate) => Object.entries(candidate.when).every(([field, value]) => params[field] === value));
|
|
38
|
+
if (!rule) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
const missing = rule.required.filter((field) => !hasValue(params[field]));
|
|
42
|
+
const presentForbidden = rule.forbidden.filter((field) => hasValue(params[field]));
|
|
43
|
+
if (missing.length === 0 && presentForbidden.length === 0) {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const parts = [];
|
|
47
|
+
if (missing.length > 0) {
|
|
48
|
+
parts.push(`requires ${missing.join(", ")}`);
|
|
49
|
+
}
|
|
50
|
+
if (presentForbidden.length > 0) {
|
|
51
|
+
parts.push(`must not include ${presentForbidden.join(", ")}`);
|
|
52
|
+
}
|
|
53
|
+
return `${formatWhen(rule.when)} ${parts.join(" and ")}.`;
|
|
54
|
+
}
|
|
55
|
+
function hasValue(value) {
|
|
56
|
+
return value !== undefined && value !== null && !(typeof value === "string" && value.trim() === "");
|
|
57
|
+
}
|
|
58
|
+
function formatWhen(when) {
|
|
59
|
+
return Object.entries(when).map(([field, value]) => `${field}=${String(value)}`).join(", ");
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=input-rules.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-rules.js","sourceRoot":"","sources":["../../../src/lib/input-rules.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ModelInfo, PricingConfig } from "../types.js";
|
|
2
|
+
export declare const pricing: PricingConfig;
|
|
3
|
+
export declare function priceForModel(info: ModelInfo, source?: PricingConfig): {
|
|
4
|
+
pricing: Record<string, unknown> | undefined;
|
|
5
|
+
pricing_source: string;
|
|
6
|
+
pricing_url: string;
|
|
7
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { readPricing } from "./data.js";
|
|
2
|
+
export const pricing = readPricing();
|
|
3
|
+
export function priceForModel(info, source = pricing) {
|
|
4
|
+
const key = pricingKey(info);
|
|
5
|
+
const endpoint = source.endpoints?.[key];
|
|
6
|
+
const markup = effectiveMarkup(key, info.provider, source);
|
|
7
|
+
return {
|
|
8
|
+
pricing: endpoint ? presentPrice(endpoint, markup) : undefined,
|
|
9
|
+
pricing_source: endpoint ? "build-time pricing snapshot" : "pricing page",
|
|
10
|
+
pricing_url: "https://runapi.ai/pricing"
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function pricingKey(info) {
|
|
14
|
+
return `${info.provider}/${info.model_line}/${info.model}/${info.action}`;
|
|
15
|
+
}
|
|
16
|
+
function effectiveMarkup(key, provider, source) {
|
|
17
|
+
return source.endpoint_markup?.[key] ?? source.provider_markup?.[provider] ?? source.markup_rate ?? 1;
|
|
18
|
+
}
|
|
19
|
+
function presentPrice(endpoint, markup) {
|
|
20
|
+
const result = {};
|
|
21
|
+
for (const [name, value] of Object.entries(endpoint)) {
|
|
22
|
+
if (name === "cost_billing_config") {
|
|
23
|
+
result.billing_config = presentBillingConfig(endpoint.cost_billing_config, markup);
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (typeof value === "number") {
|
|
27
|
+
const publicName = name.replace(/^cost_/, "");
|
|
28
|
+
result[publicName] = Number.isInteger(value * markup) ? value * markup : Math.ceil(value * markup);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
function presentBillingConfig(config, markup) {
|
|
34
|
+
if (!config) {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
key: config.key,
|
|
39
|
+
overrides: Object.fromEntries(Object.entries(config.overrides || {}).map(([key, value]) => [key, value * markup]))
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=pricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../../src/lib/pricing.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,CAAC,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;AAErC,MAAM,UAAU,aAAa,CAAC,IAAe,EAAE,SAAwB,OAAO;IAC5E,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,eAAe,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAE3D,OAAO;QACL,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;QAC9D,cAAc,EAAE,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,cAAc;QACzE,WAAW,EAAE,2BAA2B;KACzC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAe;IACjC,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;AAC5E,CAAC;AAED,SAAS,eAAe,CAAC,GAAW,EAAE,QAAgB,EAAE,MAAqB;IAC3E,OAAO,MAAM,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,YAAY,CAAC,QAAyB,EAAE,MAAc;IAC7D,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,IAAI,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACnC,MAAM,CAAC,cAAc,GAAG,oBAAoB,CAAC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;YACnF,SAAS;QACX,CAAC;QAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,oBAAoB,CAAC,MAA8C,EAAE,MAAc;IAC1F,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO;QACL,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC;KACnH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type RunApiConfig } from "../config.js";
|
|
2
|
+
import type { ChatMessage, PollingOptions, RunApiTaskResponse } from "../types.js";
|
|
3
|
+
export declare class RunApiClient {
|
|
4
|
+
private readonly config;
|
|
5
|
+
private readonly fetchImpl;
|
|
6
|
+
constructor(config?: RunApiConfig, fetchImpl?: typeof fetch);
|
|
7
|
+
listModels(): Promise<unknown>;
|
|
8
|
+
balance(): Promise<unknown>;
|
|
9
|
+
createTask(service: string, action: string, params: Record<string, unknown>): Promise<RunApiTaskResponse>;
|
|
10
|
+
getTask(service: string, taskId: string, action?: string): Promise<RunApiTaskResponse>;
|
|
11
|
+
pollTask(service: string, taskId: string, action?: string, options?: PollingOptions): Promise<RunApiTaskResponse>;
|
|
12
|
+
chat(params: {
|
|
13
|
+
model: string;
|
|
14
|
+
messages: ChatMessage[];
|
|
15
|
+
max_tokens?: number;
|
|
16
|
+
temperature?: number;
|
|
17
|
+
api?: "messages" | "chat_completions";
|
|
18
|
+
}): Promise<unknown>;
|
|
19
|
+
private request;
|
|
20
|
+
}
|
|
21
|
+
export declare function taskStatus(task?: RunApiTaskResponse): string;
|
|
22
|
+
export declare function taskIdFromResponse(task: RunApiTaskResponse): string | undefined;
|