@caplets/core 0.18.9 → 0.20.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/dist/attach/options.d.ts +10 -0
- package/dist/attach/server.d.ts +5 -0
- package/dist/caplet-files-bundle.d.ts +430 -0
- package/dist/caplet-files.d.ts +3 -266
- package/dist/caplet-source/bundle.d.ts +7 -0
- package/dist/caplet-source/filesystem.d.ts +7 -0
- package/dist/caplet-source/filesystem.js +2 -0
- package/dist/caplet-source/index.d.ts +4 -0
- package/dist/caplet-source/parse.d.ts +35 -0
- package/dist/caplet-source/types.d.ts +9 -0
- package/dist/caplet-source.js +7011 -0
- package/dist/cli/auth.d.ts +40 -2
- package/dist/cli/cloud-add.d.ts +8 -0
- package/dist/cli/code-mode.d.ts +16 -0
- package/dist/cli/commands.d.ts +8 -1
- package/dist/cli/doctor.d.ts +21 -0
- package/dist/cli/setup-caplet.d.ts +12 -0
- package/dist/cli/setup.d.ts +11 -0
- package/dist/cli-tools.d.ts +1 -1
- package/dist/cli.d.ts +8 -1
- package/dist/cloud/apply.d.ts +36 -0
- package/dist/cloud/client.d.ts +30 -0
- package/dist/cloud/presence.d.ts +29 -0
- package/dist/cloud/project-root.d.ts +2 -0
- package/dist/cloud/runtime-adapter.d.ts +23 -0
- package/dist/cloud/runtime-http.d.ts +6 -0
- package/dist/cloud/sync.d.ts +10 -0
- package/dist/cloud-auth/client.d.ts +57 -0
- package/dist/cloud-auth/errors.d.ts +11 -0
- package/dist/cloud-auth/open-url.d.ts +7 -0
- package/dist/cloud-auth/store.d.ts +35 -0
- package/dist/cloud-auth/types.d.ts +67 -0
- package/dist/code-mode/api.d.ts +32 -0
- package/dist/code-mode/declarations.d.ts +5 -0
- package/dist/code-mode/diagnostics.d.ts +8 -0
- package/dist/code-mode/index.d.ts +4 -0
- package/dist/code-mode/logs.d.ts +21 -0
- package/dist/code-mode/runner.d.ts +15 -0
- package/dist/code-mode/runtime-api.generated.d.ts +1 -0
- package/dist/code-mode/sandbox.d.ts +28 -0
- package/dist/code-mode/static-analysis.d.ts +2 -0
- package/dist/code-mode/tool.d.ts +11 -0
- package/dist/code-mode/types.d.ts +120 -0
- package/dist/code-mode.js +147855 -0
- package/dist/{completion-RqzHpHRY.js → completion-CbazRAiL.js} +20 -1
- package/dist/config/paths.d.ts +2 -0
- package/dist/config-runtime.d.ts +183 -0
- package/dist/config-runtime.js +421 -0
- package/dist/config.d.ts +76 -9
- package/dist/downstream.d.ts +20 -2
- package/dist/engine.d.ts +20 -0
- package/dist/exposure/direct-names.d.ts +9 -0
- package/dist/exposure/discovery.d.ts +75 -0
- package/dist/exposure/policy.d.ts +8 -0
- package/dist/filesystem-Kkg32TOJ.js +66 -0
- package/dist/generated-tool-input-schema.d.ts +89 -59
- package/dist/generated-tool-input-schema.js +172 -1
- package/dist/graphql.d.ts +1 -1
- package/dist/http-actions.d.ts +1 -1
- package/dist/index.d.ts +48 -0
- package/dist/index.js +4176 -501
- package/dist/native/options.d.ts +22 -3
- package/dist/native/remote.d.ts +2 -1
- package/dist/native/service.d.ts +13 -3
- package/dist/native/tools.d.ts +2 -0
- package/dist/native.d.ts +1 -1
- package/dist/native.js +3 -431
- package/dist/observed-output-shapes/extract.d.ts +5 -0
- package/dist/observed-output-shapes/file-store.d.ts +17 -0
- package/dist/observed-output-shapes/index.d.ts +7 -0
- package/dist/observed-output-shapes/key.d.ts +14 -0
- package/dist/observed-output-shapes/merge.d.ts +2 -0
- package/dist/observed-output-shapes/pure.d.ts +5 -0
- package/dist/observed-output-shapes/pure.js +241 -0
- package/dist/observed-output-shapes/schema.d.ts +1 -0
- package/dist/observed-output-shapes/types.d.ts +84 -0
- package/dist/observed-output-shapes/typescript.d.ts +7 -0
- package/dist/observed-output-shapes-uzAMQPhg.js +485 -0
- package/dist/observed-output-shapes.js +2 -0
- package/dist/openapi.d.ts +1 -1
- package/dist/project-binding/attach.d.ts +46 -0
- package/dist/project-binding/errors.d.ts +17 -0
- package/dist/project-binding/gitignore.d.ts +5 -0
- package/dist/project-binding/index.d.ts +2 -0
- package/dist/project-binding/mutagen.d.ts +65 -0
- package/dist/project-binding/routes.d.ts +9 -0
- package/dist/project-binding/session.d.ts +82 -0
- package/dist/project-binding/sync-filter.d.ts +19 -0
- package/dist/project-binding/sync-size.d.ts +27 -0
- package/dist/project-binding/transport.d.ts +21 -0
- package/dist/project-binding/types.d.ts +31 -0
- package/dist/project-binding/workspaces.d.ts +60 -0
- package/dist/project-binding.js +22 -0
- package/dist/redaction.d.ts +14 -0
- package/dist/redaction.js +30 -0
- package/dist/registry.d.ts +4 -0
- package/dist/remote/options.d.ts +44 -0
- package/dist/remote/selection.d.ts +26 -0
- package/dist/remote-control/types.d.ts +1 -1
- package/dist/runtime-plan/features.d.ts +7 -0
- package/dist/runtime-plan/index.d.ts +4 -0
- package/dist/runtime-plan/planner.d.ts +5 -0
- package/dist/runtime-plan/resources.d.ts +13 -0
- package/dist/runtime-plan/types.d.ts +82 -0
- package/dist/runtime-plan.js +281 -0
- package/dist/schemas-1HZ0kFpx.js +4270 -0
- package/dist/{generated-tool-input-schema--kVuUNc5.js → schemas-BZ6BBrh7.js} +1 -161
- package/dist/serve/daemon/config.d.ts +8 -0
- package/dist/serve/daemon/index.d.ts +16 -0
- package/dist/serve/daemon/paths.d.ts +3 -0
- package/dist/serve/daemon/platform-darwin.d.ts +2 -0
- package/dist/serve/daemon/platform-linux.d.ts +2 -0
- package/dist/serve/daemon/platform-windows.d.ts +2 -0
- package/dist/serve/daemon/platform.d.ts +9 -0
- package/dist/serve/daemon/process.d.ts +5 -0
- package/dist/serve/daemon/types.d.ts +86 -0
- package/dist/serve/http.d.ts +8 -0
- package/dist/serve/index.d.ts +5 -1
- package/dist/serve/native-session.d.ts +19 -0
- package/dist/serve/options.d.ts +1 -0
- package/dist/serve/session.d.ts +15 -3
- package/dist/server/options.d.ts +1 -1
- package/dist/{options-DnOUjft1.js → service-D0MwLNyb.js} +38003 -27618
- package/dist/setup/hash.d.ts +3 -0
- package/dist/setup/local-store.d.ts +34 -0
- package/dist/setup/runner.d.ts +40 -0
- package/dist/setup/types.d.ts +52 -0
- package/dist/stable-json.d.ts +3 -0
- package/dist/stable-json.js +26 -0
- package/dist/tools.d.ts +38 -12
- package/dist/validation-CdqbI2zN.js +174 -0
- package/package.json +48 -6
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { St as resolveProjectConfigPath, Y as loadConfigWithSources, bt as resolveConfigPath, mt as DEFAULT_COMPLETION_CACHE_DIR, pt as DEFAULT_AUTH_DIR, vn as __exportAll, yt as resolveCapletsRoot } from "./service-D0MwLNyb.js";
|
|
2
|
+
import { u as CapletsError } from "./validation-CdqbI2zN.js";
|
|
2
3
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
4
5
|
import { createHash } from "node:crypto";
|
|
@@ -13,9 +14,13 @@ const completionShells = [
|
|
|
13
14
|
const cliCommands = {
|
|
14
15
|
completion: "completion",
|
|
15
16
|
completeHidden: "__complete",
|
|
17
|
+
codeMode: "code-mode",
|
|
16
18
|
serve: "serve",
|
|
19
|
+
attach: "attach",
|
|
20
|
+
cloud: "cloud",
|
|
17
21
|
init: "init",
|
|
18
22
|
setup: "setup",
|
|
23
|
+
doctor: "doctor",
|
|
19
24
|
list: "list",
|
|
20
25
|
install: "install",
|
|
21
26
|
add: "add",
|
|
@@ -38,8 +43,12 @@ const cliCommands = {
|
|
|
38
43
|
};
|
|
39
44
|
const topLevelCommandNames = [
|
|
40
45
|
cliCommands.serve,
|
|
46
|
+
cliCommands.codeMode,
|
|
47
|
+
cliCommands.attach,
|
|
48
|
+
cliCommands.cloud,
|
|
41
49
|
cliCommands.init,
|
|
42
50
|
cliCommands.setup,
|
|
51
|
+
cliCommands.doctor,
|
|
43
52
|
cliCommands.list,
|
|
44
53
|
cliCommands.install,
|
|
45
54
|
cliCommands.add,
|
|
@@ -74,8 +83,18 @@ const cliSubcommands = {
|
|
|
74
83
|
"logout",
|
|
75
84
|
"list"
|
|
76
85
|
],
|
|
86
|
+
[cliCommands.cloud]: ["auth"],
|
|
87
|
+
[cliCommands.codeMode]: ["types"],
|
|
77
88
|
[cliCommands.completion]: [...completionShells],
|
|
78
89
|
[cliCommands.config]: ["path", "paths"],
|
|
90
|
+
[cliCommands.serve]: [
|
|
91
|
+
"start",
|
|
92
|
+
"stop",
|
|
93
|
+
"status",
|
|
94
|
+
"restart",
|
|
95
|
+
"enable",
|
|
96
|
+
"disable"
|
|
97
|
+
],
|
|
79
98
|
[cliCommands.setup]: [
|
|
80
99
|
"codex",
|
|
81
100
|
"claude-code",
|
package/dist/config/paths.d.ts
CHANGED
|
@@ -6,9 +6,11 @@ export declare function defaultCacheBaseDir(env?: PathEnv, home?: string, platfo
|
|
|
6
6
|
export declare function defaultConfigPath(env?: PathEnv, home?: string, platform?: Platform): string;
|
|
7
7
|
export declare function defaultAuthDir(env?: PathEnv, home?: string, platform?: Platform): string;
|
|
8
8
|
export declare function defaultCompletionCacheDir(env?: PathEnv, home?: string, platform?: Platform): string;
|
|
9
|
+
export declare function defaultObservedOutputShapeCacheDir(env?: PathEnv, home?: string, platform?: Platform): string;
|
|
9
10
|
export declare const DEFAULT_CONFIG_PATH: string;
|
|
10
11
|
export declare const DEFAULT_AUTH_DIR: string;
|
|
11
12
|
export declare const DEFAULT_COMPLETION_CACHE_DIR: string;
|
|
13
|
+
export declare const DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR: string;
|
|
12
14
|
export declare const PROJECT_CONFIG_FILE: string;
|
|
13
15
|
export declare function resolveConfigPath(path?: string): string;
|
|
14
16
|
export declare function resolveProjectConfigPath(cwd?: string): string;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
export type RemoteAuthConfig = {
|
|
2
|
+
type: "none";
|
|
3
|
+
} | {
|
|
4
|
+
type: "bearer";
|
|
5
|
+
token: string;
|
|
6
|
+
} | {
|
|
7
|
+
type: "headers";
|
|
8
|
+
headers: Record<string, string>;
|
|
9
|
+
} | {
|
|
10
|
+
type: "oauth2" | "oidc";
|
|
11
|
+
authorizationUrl?: string | undefined;
|
|
12
|
+
tokenUrl?: string | undefined;
|
|
13
|
+
issuer?: string | undefined;
|
|
14
|
+
resourceMetadataUrl?: string | undefined;
|
|
15
|
+
authorizationServerMetadataUrl?: string | undefined;
|
|
16
|
+
openidConfigurationUrl?: string | undefined;
|
|
17
|
+
clientMetadataUrl?: string | undefined;
|
|
18
|
+
clientId?: string | undefined;
|
|
19
|
+
clientSecret?: string | undefined;
|
|
20
|
+
scopes?: string[] | undefined;
|
|
21
|
+
redirectUri?: string | undefined;
|
|
22
|
+
};
|
|
23
|
+
export type CapletSetupCommandConfig = {
|
|
24
|
+
label: string;
|
|
25
|
+
command: string;
|
|
26
|
+
args?: string[] | undefined;
|
|
27
|
+
env?: Record<string, string> | undefined;
|
|
28
|
+
cwd?: string | undefined;
|
|
29
|
+
timeoutMs?: number | undefined;
|
|
30
|
+
maxOutputBytes?: number | undefined;
|
|
31
|
+
};
|
|
32
|
+
export type CapletSetupConfig = {
|
|
33
|
+
commands?: CapletSetupCommandConfig[] | undefined;
|
|
34
|
+
verify?: CapletSetupCommandConfig[] | undefined;
|
|
35
|
+
};
|
|
36
|
+
export type ProjectBindingConfig = {
|
|
37
|
+
required: true;
|
|
38
|
+
};
|
|
39
|
+
export type RuntimeFeature = "docker" | "browser";
|
|
40
|
+
export type RuntimeResourceClass = "standard" | "large" | "heavy";
|
|
41
|
+
export type RuntimeRequirementsConfig = {
|
|
42
|
+
features?: RuntimeFeature[] | undefined;
|
|
43
|
+
resources?: {
|
|
44
|
+
class?: RuntimeResourceClass | undefined;
|
|
45
|
+
} | undefined;
|
|
46
|
+
};
|
|
47
|
+
export type AgentSelectionHintsConfig = {
|
|
48
|
+
useWhen?: string | undefined;
|
|
49
|
+
avoidWhen?: string | undefined;
|
|
50
|
+
};
|
|
51
|
+
export type CapletExposure = "direct" | "progressive" | "code_mode" | "direct_and_code_mode" | "progressive_and_code_mode";
|
|
52
|
+
export type CapletServerConfig = CommonCapletConfig & {
|
|
53
|
+
backend: "mcp";
|
|
54
|
+
transport: "stdio" | "http" | "sse";
|
|
55
|
+
command?: string | undefined;
|
|
56
|
+
args?: string[] | undefined;
|
|
57
|
+
env?: Record<string, string> | undefined;
|
|
58
|
+
cwd?: string | undefined;
|
|
59
|
+
url?: string | undefined;
|
|
60
|
+
auth?: RemoteAuthConfig | undefined;
|
|
61
|
+
startupTimeoutMs: number;
|
|
62
|
+
callTimeoutMs: number;
|
|
63
|
+
toolCacheTtlMs: number;
|
|
64
|
+
};
|
|
65
|
+
export type OpenApiAuthConfig = RemoteAuthConfig;
|
|
66
|
+
export type OpenApiEndpointConfig = CommonCapletConfig & {
|
|
67
|
+
backend: "openapi";
|
|
68
|
+
specPath?: string | undefined;
|
|
69
|
+
specUrl?: string | undefined;
|
|
70
|
+
baseUrl?: string | undefined;
|
|
71
|
+
auth: OpenApiAuthConfig;
|
|
72
|
+
requestTimeoutMs: number;
|
|
73
|
+
operationCacheTtlMs: number;
|
|
74
|
+
};
|
|
75
|
+
export type GraphQlOperationConfig = AgentSelectionHintsConfig & {
|
|
76
|
+
document?: string | undefined;
|
|
77
|
+
documentPath?: string | undefined;
|
|
78
|
+
operationName?: string | undefined;
|
|
79
|
+
description?: string | undefined;
|
|
80
|
+
};
|
|
81
|
+
export type GraphQlEndpointConfig = CommonCapletConfig & {
|
|
82
|
+
backend: "graphql";
|
|
83
|
+
endpointUrl: string;
|
|
84
|
+
schemaPath?: string | undefined;
|
|
85
|
+
schemaUrl?: string | undefined;
|
|
86
|
+
introspection?: true | undefined;
|
|
87
|
+
operations?: Record<string, GraphQlOperationConfig> | undefined;
|
|
88
|
+
auth: OpenApiAuthConfig;
|
|
89
|
+
requestTimeoutMs: number;
|
|
90
|
+
operationCacheTtlMs: number;
|
|
91
|
+
selectionDepth: number;
|
|
92
|
+
};
|
|
93
|
+
export type HttpActionConfig = AgentSelectionHintsConfig & {
|
|
94
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
95
|
+
path: string;
|
|
96
|
+
description?: string | undefined;
|
|
97
|
+
inputSchema?: Record<string, unknown> | undefined;
|
|
98
|
+
outputSchema?: Record<string, unknown> | undefined;
|
|
99
|
+
query?: Record<string, string | number | boolean> | undefined;
|
|
100
|
+
headers?: Record<string, string | number | boolean> | undefined;
|
|
101
|
+
jsonBody?: unknown;
|
|
102
|
+
};
|
|
103
|
+
export type HttpApiConfig = CommonCapletConfig & {
|
|
104
|
+
backend: "http";
|
|
105
|
+
baseUrl: string;
|
|
106
|
+
auth: OpenApiAuthConfig;
|
|
107
|
+
actions: Record<string, HttpActionConfig>;
|
|
108
|
+
requestTimeoutMs: number;
|
|
109
|
+
maxResponseBytes: number;
|
|
110
|
+
};
|
|
111
|
+
export type CliToolActionConfig = AgentSelectionHintsConfig & {
|
|
112
|
+
description?: string | undefined;
|
|
113
|
+
inputSchema?: Record<string, unknown> | undefined;
|
|
114
|
+
outputSchema?: Record<string, unknown> | undefined;
|
|
115
|
+
command: string;
|
|
116
|
+
args?: string[] | undefined;
|
|
117
|
+
env?: Record<string, string> | undefined;
|
|
118
|
+
cwd?: string | undefined;
|
|
119
|
+
timeoutMs?: number | undefined;
|
|
120
|
+
maxOutputBytes?: number | undefined;
|
|
121
|
+
output?: {
|
|
122
|
+
type: "text" | "json";
|
|
123
|
+
} | undefined;
|
|
124
|
+
annotations?: {
|
|
125
|
+
readOnlyHint?: boolean | undefined;
|
|
126
|
+
destructiveHint?: boolean | undefined;
|
|
127
|
+
idempotentHint?: boolean | undefined;
|
|
128
|
+
openWorldHint?: boolean | undefined;
|
|
129
|
+
} | undefined;
|
|
130
|
+
};
|
|
131
|
+
export type CliToolsConfig = CommonCapletConfig & {
|
|
132
|
+
backend: "cli";
|
|
133
|
+
actions: Record<string, CliToolActionConfig>;
|
|
134
|
+
cwd?: string | undefined;
|
|
135
|
+
env?: Record<string, string> | undefined;
|
|
136
|
+
timeoutMs: number;
|
|
137
|
+
maxOutputBytes: number;
|
|
138
|
+
};
|
|
139
|
+
export type CapletSetConfig = CommonCapletConfig & {
|
|
140
|
+
backend: "caplets";
|
|
141
|
+
configPath?: string | undefined;
|
|
142
|
+
capletsRoot?: string | undefined;
|
|
143
|
+
defaultSearchLimit: number;
|
|
144
|
+
maxSearchLimit: number;
|
|
145
|
+
toolCacheTtlMs: number;
|
|
146
|
+
};
|
|
147
|
+
export type CapletConfig = CapletServerConfig | OpenApiEndpointConfig | GraphQlEndpointConfig | HttpApiConfig | CliToolsConfig | CapletSetConfig;
|
|
148
|
+
export type CapletsConfig = {
|
|
149
|
+
version: 1;
|
|
150
|
+
options: {
|
|
151
|
+
defaultSearchLimit: number;
|
|
152
|
+
maxSearchLimit: number;
|
|
153
|
+
exposure: CapletExposure;
|
|
154
|
+
exposureDiscoveryTimeoutMs: number;
|
|
155
|
+
exposureDiscoveryConcurrency: number;
|
|
156
|
+
completion: {
|
|
157
|
+
discoveryTimeoutMs: number;
|
|
158
|
+
overallTimeoutMs: number;
|
|
159
|
+
cacheTtlMs: number;
|
|
160
|
+
negativeCacheTtlMs: number;
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
mcpServers: Record<string, CapletServerConfig>;
|
|
164
|
+
openapiEndpoints: Record<string, OpenApiEndpointConfig>;
|
|
165
|
+
graphqlEndpoints: Record<string, GraphQlEndpointConfig>;
|
|
166
|
+
httpApis: Record<string, HttpApiConfig>;
|
|
167
|
+
cliTools: Record<string, CliToolsConfig>;
|
|
168
|
+
capletSets: Record<string, CapletSetConfig>;
|
|
169
|
+
};
|
|
170
|
+
type CommonCapletConfig = AgentSelectionHintsConfig & {
|
|
171
|
+
server: string;
|
|
172
|
+
name: string;
|
|
173
|
+
description: string;
|
|
174
|
+
exposure?: CapletExposure | undefined;
|
|
175
|
+
tags?: string[] | undefined;
|
|
176
|
+
body?: string | undefined;
|
|
177
|
+
setup?: CapletSetupConfig | undefined;
|
|
178
|
+
projectBinding?: ProjectBindingConfig | undefined;
|
|
179
|
+
runtime?: RuntimeRequirementsConfig | undefined;
|
|
180
|
+
disabled: boolean;
|
|
181
|
+
};
|
|
182
|
+
export declare function parseConfig(input: unknown): CapletsConfig;
|
|
183
|
+
export {};
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { _ as record, b as unknown, d as literal, l as discriminatedUnion, m as object, o as array, p as number, r as _enum, s as boolean, v as string, y as union } from "./schemas-BZ6BBrh7.js";
|
|
2
|
+
import { a as isAllowedHttpBaseUrl, c as validateHttpActionHeaders, i as SERVER_ID_PATTERN, n as HEADER_NAME_PATTERN, o as isAllowedRemoteUrl, r as HTTP_BASE_URL_PATTERN, s as isUrl, t as FORBIDDEN_HEADERS, u as CapletsError } from "./validation-CdqbI2zN.js";
|
|
3
|
+
//#region src/config-runtime.ts
|
|
4
|
+
const stringMapSchema = record(string(), string());
|
|
5
|
+
const authSchema = discriminatedUnion("type", [
|
|
6
|
+
object({ type: literal("none") }).strict(),
|
|
7
|
+
object({
|
|
8
|
+
type: literal("bearer"),
|
|
9
|
+
token: string().min(1)
|
|
10
|
+
}).strict(),
|
|
11
|
+
object({
|
|
12
|
+
type: literal("headers"),
|
|
13
|
+
headers: stringMapSchema
|
|
14
|
+
}).strict(),
|
|
15
|
+
oauthLikeSchema("oauth2"),
|
|
16
|
+
oauthLikeSchema("oidc")
|
|
17
|
+
]);
|
|
18
|
+
const setupCommandSchema = object({
|
|
19
|
+
label: string().min(1),
|
|
20
|
+
command: string().min(1),
|
|
21
|
+
args: array(string()).optional(),
|
|
22
|
+
env: stringMapSchema.optional(),
|
|
23
|
+
cwd: string().min(1).optional(),
|
|
24
|
+
timeoutMs: number().int().positive().optional(),
|
|
25
|
+
maxOutputBytes: number().int().positive().optional()
|
|
26
|
+
}).strict();
|
|
27
|
+
const setupSchema = object({
|
|
28
|
+
commands: array(setupCommandSchema).optional(),
|
|
29
|
+
verify: array(setupCommandSchema).optional()
|
|
30
|
+
}).strict().refine((setup) => (setup.commands?.length ?? 0) > 0 || (setup.verify?.length ?? 0) > 0, "setup must define at least one command or verify step");
|
|
31
|
+
const projectBindingSchema = object({ required: literal(true) }).strict();
|
|
32
|
+
const runtimeRequirementsSchema = object({
|
|
33
|
+
features: array(_enum(["docker", "browser"])).refine((features) => new Set(features).size === features.length, { message: "runtime.features must not contain duplicate feature names" }).optional(),
|
|
34
|
+
resources: object({ class: _enum([
|
|
35
|
+
"standard",
|
|
36
|
+
"large",
|
|
37
|
+
"heavy"
|
|
38
|
+
]).optional() }).strict().optional()
|
|
39
|
+
}).strict();
|
|
40
|
+
const agentSelectionHintSchema = string().trim().min(1).max(500);
|
|
41
|
+
const agentSelectionHintsSchema = {
|
|
42
|
+
useWhen: agentSelectionHintSchema.optional(),
|
|
43
|
+
avoidWhen: agentSelectionHintSchema.optional()
|
|
44
|
+
};
|
|
45
|
+
const exposureSchema = _enum([
|
|
46
|
+
"direct",
|
|
47
|
+
"progressive",
|
|
48
|
+
"code_mode",
|
|
49
|
+
"direct_and_code_mode",
|
|
50
|
+
"progressive_and_code_mode"
|
|
51
|
+
]);
|
|
52
|
+
const commonSchema = {
|
|
53
|
+
name: string().trim().min(1).max(80),
|
|
54
|
+
description: string().refine((value) => value.trim().length >= 10, "description must contain at least 10 non-whitespace characters").refine((value) => value.length <= 1500, "description must be at most 1500 characters"),
|
|
55
|
+
tags: array(string().trim().min(1).max(80)).optional(),
|
|
56
|
+
exposure: exposureSchema.optional(),
|
|
57
|
+
...agentSelectionHintsSchema,
|
|
58
|
+
body: string().optional(),
|
|
59
|
+
setup: setupSchema.optional(),
|
|
60
|
+
projectBinding: projectBindingSchema.optional(),
|
|
61
|
+
runtime: runtimeRequirementsSchema.optional(),
|
|
62
|
+
disabled: boolean().default(false)
|
|
63
|
+
};
|
|
64
|
+
const mcpServerSchema = object({
|
|
65
|
+
...commonSchema,
|
|
66
|
+
transport: _enum([
|
|
67
|
+
"stdio",
|
|
68
|
+
"http",
|
|
69
|
+
"sse"
|
|
70
|
+
]).optional(),
|
|
71
|
+
command: string().min(1).optional(),
|
|
72
|
+
args: array(string()).optional(),
|
|
73
|
+
env: stringMapSchema.optional(),
|
|
74
|
+
cwd: string().min(1).optional(),
|
|
75
|
+
url: string().min(1).optional(),
|
|
76
|
+
auth: authSchema.optional(),
|
|
77
|
+
startupTimeoutMs: number().int().positive().default(1e4),
|
|
78
|
+
callTimeoutMs: number().int().positive().default(6e4),
|
|
79
|
+
toolCacheTtlMs: number().int().nonnegative().default(3e4)
|
|
80
|
+
}).strict();
|
|
81
|
+
const openApiEndpointSchema = object({
|
|
82
|
+
...commonSchema,
|
|
83
|
+
specPath: string().min(1).optional(),
|
|
84
|
+
specUrl: string().min(1).optional(),
|
|
85
|
+
baseUrl: string().min(1).optional(),
|
|
86
|
+
auth: authSchema,
|
|
87
|
+
requestTimeoutMs: number().int().positive().default(6e4),
|
|
88
|
+
operationCacheTtlMs: number().int().nonnegative().default(3e4)
|
|
89
|
+
}).strict();
|
|
90
|
+
const graphQlOperationSchema = object({
|
|
91
|
+
document: string().min(1).optional(),
|
|
92
|
+
documentPath: string().min(1).optional(),
|
|
93
|
+
operationName: string().min(1).optional(),
|
|
94
|
+
description: string().min(1).optional(),
|
|
95
|
+
...agentSelectionHintsSchema
|
|
96
|
+
}).strict().refine((operation) => Boolean(operation.document) !== Boolean(operation.documentPath), { message: "GraphQL operation must define exactly one document source" });
|
|
97
|
+
const graphQlEndpointSchema = object({
|
|
98
|
+
...commonSchema,
|
|
99
|
+
endpointUrl: string().min(1),
|
|
100
|
+
schemaPath: string().min(1).optional(),
|
|
101
|
+
schemaUrl: string().min(1).optional(),
|
|
102
|
+
introspection: literal(true).optional(),
|
|
103
|
+
operations: record(string().regex(SERVER_ID_PATTERN), graphQlOperationSchema).optional(),
|
|
104
|
+
auth: authSchema,
|
|
105
|
+
requestTimeoutMs: number().int().positive().default(6e4),
|
|
106
|
+
operationCacheTtlMs: number().int().nonnegative().default(3e4),
|
|
107
|
+
selectionDepth: number().int().positive().max(5).default(2)
|
|
108
|
+
}).strict();
|
|
109
|
+
const scalarMapSchema = record(string(), union([
|
|
110
|
+
string(),
|
|
111
|
+
number(),
|
|
112
|
+
boolean()
|
|
113
|
+
]));
|
|
114
|
+
const httpActionSchema = object({
|
|
115
|
+
method: _enum([
|
|
116
|
+
"GET",
|
|
117
|
+
"POST",
|
|
118
|
+
"PUT",
|
|
119
|
+
"PATCH",
|
|
120
|
+
"DELETE"
|
|
121
|
+
]),
|
|
122
|
+
path: string().min(1).regex(/^\//, "HTTP action path must start with /").refine((value) => !value.startsWith("//"), "HTTP action path must not start with //").refine((value) => !isUrl(value), "HTTP action path must be a URL path, not a URL"),
|
|
123
|
+
description: string().min(1).optional(),
|
|
124
|
+
...agentSelectionHintsSchema,
|
|
125
|
+
inputSchema: record(string(), unknown()).optional(),
|
|
126
|
+
outputSchema: record(string(), unknown()).optional(),
|
|
127
|
+
query: scalarMapSchema.optional(),
|
|
128
|
+
headers: scalarMapSchema.optional(),
|
|
129
|
+
jsonBody: unknown().optional()
|
|
130
|
+
}).strict().refine((action) => action.method !== "GET" || action.jsonBody === void 0, {
|
|
131
|
+
path: ["jsonBody"],
|
|
132
|
+
message: "HTTP GET actions must not define jsonBody"
|
|
133
|
+
});
|
|
134
|
+
const httpApiSchema = object({
|
|
135
|
+
...commonSchema,
|
|
136
|
+
baseUrl: string().min(1).regex(HTTP_BASE_URL_PATTERN, "HTTP API baseUrl must not include credentials, query, or fragment"),
|
|
137
|
+
auth: authSchema,
|
|
138
|
+
actions: record(string().regex(SERVER_ID_PATTERN), httpActionSchema).refine((actions) => Object.keys(actions).length > 0, "HTTP API must define at least one action"),
|
|
139
|
+
requestTimeoutMs: number().int().positive().default(6e4),
|
|
140
|
+
maxResponseBytes: number().int().positive().default(2e5)
|
|
141
|
+
}).strict();
|
|
142
|
+
const cliActionSchema = object({
|
|
143
|
+
description: string().min(1).optional(),
|
|
144
|
+
...agentSelectionHintsSchema,
|
|
145
|
+
inputSchema: record(string(), unknown()).optional(),
|
|
146
|
+
outputSchema: record(string(), unknown()).optional(),
|
|
147
|
+
command: string().min(1),
|
|
148
|
+
args: array(string()).optional(),
|
|
149
|
+
env: stringMapSchema.optional(),
|
|
150
|
+
cwd: string().min(1).optional(),
|
|
151
|
+
timeoutMs: number().int().positive().optional(),
|
|
152
|
+
maxOutputBytes: number().int().positive().optional(),
|
|
153
|
+
output: object({ type: _enum(["text", "json"]).default("text") }).strict().optional(),
|
|
154
|
+
annotations: object({
|
|
155
|
+
readOnlyHint: boolean().optional(),
|
|
156
|
+
destructiveHint: boolean().optional(),
|
|
157
|
+
idempotentHint: boolean().optional(),
|
|
158
|
+
openWorldHint: boolean().optional()
|
|
159
|
+
}).strict().optional()
|
|
160
|
+
}).strict();
|
|
161
|
+
const cliToolsSchema = object({
|
|
162
|
+
...commonSchema,
|
|
163
|
+
actions: record(string().regex(SERVER_ID_PATTERN), cliActionSchema).refine((actions) => Object.keys(actions).length > 0, "CLI tools backend must define at least one action"),
|
|
164
|
+
cwd: string().min(1).optional(),
|
|
165
|
+
env: stringMapSchema.optional(),
|
|
166
|
+
timeoutMs: number().int().positive().default(6e4),
|
|
167
|
+
maxOutputBytes: number().int().positive().default(2e5)
|
|
168
|
+
}).strict();
|
|
169
|
+
const capletSetSchema = object({
|
|
170
|
+
...commonSchema,
|
|
171
|
+
configPath: string().min(1).optional(),
|
|
172
|
+
capletsRoot: string().min(1).optional(),
|
|
173
|
+
defaultSearchLimit: number().int().positive().default(20),
|
|
174
|
+
maxSearchLimit: number().int().positive().max(50).default(50),
|
|
175
|
+
toolCacheTtlMs: number().int().nonnegative().default(3e4)
|
|
176
|
+
}).strict();
|
|
177
|
+
const configSchema = object({
|
|
178
|
+
version: literal(1).default(1),
|
|
179
|
+
defaultSearchLimit: number().int().positive().default(20),
|
|
180
|
+
maxSearchLimit: number().int().positive().max(50).default(50),
|
|
181
|
+
completion: object({
|
|
182
|
+
discoveryTimeoutMs: number().int().positive().default(750),
|
|
183
|
+
overallTimeoutMs: number().int().positive().default(1500),
|
|
184
|
+
cacheTtlMs: number().int().nonnegative().default(3e5),
|
|
185
|
+
negativeCacheTtlMs: number().int().nonnegative().default(3e4)
|
|
186
|
+
}).strict().default({
|
|
187
|
+
discoveryTimeoutMs: 750,
|
|
188
|
+
overallTimeoutMs: 1500,
|
|
189
|
+
cacheTtlMs: 3e5,
|
|
190
|
+
negativeCacheTtlMs: 3e4
|
|
191
|
+
}),
|
|
192
|
+
options: object({
|
|
193
|
+
exposure: exposureSchema.default("code_mode"),
|
|
194
|
+
exposureDiscoveryTimeoutMs: number().int().positive().default(15e3),
|
|
195
|
+
exposureDiscoveryConcurrency: number().int().positive().max(32).default(4)
|
|
196
|
+
}).strict().default({
|
|
197
|
+
exposure: "code_mode",
|
|
198
|
+
exposureDiscoveryTimeoutMs: 15e3,
|
|
199
|
+
exposureDiscoveryConcurrency: 4
|
|
200
|
+
}),
|
|
201
|
+
mcpServers: record(string().regex(SERVER_ID_PATTERN), mcpServerSchema).default({}),
|
|
202
|
+
openapiEndpoints: record(string().regex(SERVER_ID_PATTERN), openApiEndpointSchema).default({}),
|
|
203
|
+
graphqlEndpoints: record(string().regex(SERVER_ID_PATTERN), graphQlEndpointSchema).default({}),
|
|
204
|
+
httpApis: record(string().regex(SERVER_ID_PATTERN), httpApiSchema).default({}),
|
|
205
|
+
cliTools: record(string().regex(SERVER_ID_PATTERN), cliToolsSchema).default({}),
|
|
206
|
+
capletSets: record(string().regex(SERVER_ID_PATTERN), capletSetSchema).default({})
|
|
207
|
+
}).strict().superRefine((config, ctx) => {
|
|
208
|
+
if (config.defaultSearchLimit > config.maxSearchLimit) ctx.addIssue({
|
|
209
|
+
code: "custom",
|
|
210
|
+
path: ["defaultSearchLimit"],
|
|
211
|
+
message: "defaultSearchLimit must be <= maxSearchLimit"
|
|
212
|
+
});
|
|
213
|
+
validateBackends(config, ctx);
|
|
214
|
+
});
|
|
215
|
+
function parseConfig(input) {
|
|
216
|
+
const parsed = configSchema.safeParse(input);
|
|
217
|
+
if (!parsed.success) throw new CapletsError("CONFIG_INVALID", "Caplets config is invalid", parsed.error.issues);
|
|
218
|
+
const config = parsed.data;
|
|
219
|
+
return {
|
|
220
|
+
version: 1,
|
|
221
|
+
options: {
|
|
222
|
+
defaultSearchLimit: config.defaultSearchLimit,
|
|
223
|
+
maxSearchLimit: config.maxSearchLimit,
|
|
224
|
+
exposure: config.options.exposure,
|
|
225
|
+
exposureDiscoveryTimeoutMs: config.options.exposureDiscoveryTimeoutMs,
|
|
226
|
+
exposureDiscoveryConcurrency: config.options.exposureDiscoveryConcurrency,
|
|
227
|
+
completion: config.completion
|
|
228
|
+
},
|
|
229
|
+
mcpServers: mapBackend(config.mcpServers, "mcp", (id, raw) => {
|
|
230
|
+
const server = raw;
|
|
231
|
+
return {
|
|
232
|
+
...server,
|
|
233
|
+
server: id,
|
|
234
|
+
transport: server.transport ?? (server.command ? "stdio" : "http")
|
|
235
|
+
};
|
|
236
|
+
}),
|
|
237
|
+
openapiEndpoints: mapBackend(config.openapiEndpoints, "openapi"),
|
|
238
|
+
graphqlEndpoints: mapBackend(config.graphqlEndpoints, "graphql"),
|
|
239
|
+
httpApis: mapBackend(config.httpApis, "http"),
|
|
240
|
+
cliTools: mapBackend(config.cliTools, "cli"),
|
|
241
|
+
capletSets: mapBackend(config.capletSets, "caplets")
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function oauthLikeSchema(type) {
|
|
245
|
+
return object({
|
|
246
|
+
type: literal(type),
|
|
247
|
+
authorizationUrl: string().min(1).optional(),
|
|
248
|
+
tokenUrl: string().min(1).optional(),
|
|
249
|
+
issuer: string().min(1).optional(),
|
|
250
|
+
resourceMetadataUrl: string().min(1).optional(),
|
|
251
|
+
authorizationServerMetadataUrl: string().min(1).optional(),
|
|
252
|
+
openidConfigurationUrl: string().min(1).optional(),
|
|
253
|
+
clientMetadataUrl: string().min(1).optional(),
|
|
254
|
+
clientId: string().min(1).optional(),
|
|
255
|
+
clientSecret: string().min(1).optional(),
|
|
256
|
+
scopes: array(string().min(1)).optional(),
|
|
257
|
+
redirectUri: string().min(1).optional()
|
|
258
|
+
}).strict();
|
|
259
|
+
}
|
|
260
|
+
function validateBackends(config, ctx) {
|
|
261
|
+
for (const [server, raw] of Object.entries(config.mcpServers)) {
|
|
262
|
+
const effectiveTransport = raw.transport ?? (raw.command ? "stdio" : void 0);
|
|
263
|
+
if (Boolean(raw.command) === Boolean(raw.url)) ctx.addIssue({
|
|
264
|
+
code: "custom",
|
|
265
|
+
path: ["mcpServers", server],
|
|
266
|
+
message: "MCP server must define exactly one connection shape: command or url"
|
|
267
|
+
});
|
|
268
|
+
if (effectiveTransport === "stdio" && !raw.command) ctx.addIssue({
|
|
269
|
+
code: "custom",
|
|
270
|
+
path: [
|
|
271
|
+
"mcpServers",
|
|
272
|
+
server,
|
|
273
|
+
"command"
|
|
274
|
+
],
|
|
275
|
+
message: "stdio servers require command"
|
|
276
|
+
});
|
|
277
|
+
if ((effectiveTransport === "http" || effectiveTransport === "sse") && !raw.url) ctx.addIssue({
|
|
278
|
+
code: "custom",
|
|
279
|
+
path: [
|
|
280
|
+
"mcpServers",
|
|
281
|
+
server,
|
|
282
|
+
"url"
|
|
283
|
+
],
|
|
284
|
+
message: "remote servers require url"
|
|
285
|
+
});
|
|
286
|
+
if (raw.url && !hasEnvReference(raw.url) && !isAllowedRemoteUrl(raw.url)) ctx.addIssue({
|
|
287
|
+
code: "custom",
|
|
288
|
+
path: [
|
|
289
|
+
"mcpServers",
|
|
290
|
+
server,
|
|
291
|
+
"url"
|
|
292
|
+
],
|
|
293
|
+
message: "remote url must use https except loopback development urls"
|
|
294
|
+
});
|
|
295
|
+
validateAuthHeaders(raw.auth, ctx, [
|
|
296
|
+
"mcpServers",
|
|
297
|
+
server,
|
|
298
|
+
"auth"
|
|
299
|
+
]);
|
|
300
|
+
}
|
|
301
|
+
for (const [server, raw] of Object.entries(config.openapiEndpoints)) {
|
|
302
|
+
if (Boolean(raw.specPath) === Boolean(raw.specUrl)) ctx.addIssue({
|
|
303
|
+
code: "custom",
|
|
304
|
+
path: ["openapiEndpoints", server],
|
|
305
|
+
message: "OpenAPI endpoint must define exactly one spec source: specPath or specUrl"
|
|
306
|
+
});
|
|
307
|
+
if (raw.specUrl && !hasEnvReference(raw.specUrl) && !isAllowedRemoteUrl(raw.specUrl)) ctx.addIssue({
|
|
308
|
+
code: "custom",
|
|
309
|
+
path: [
|
|
310
|
+
"openapiEndpoints",
|
|
311
|
+
server,
|
|
312
|
+
"specUrl"
|
|
313
|
+
],
|
|
314
|
+
message: "OpenAPI specUrl must use https except loopback development urls"
|
|
315
|
+
});
|
|
316
|
+
if (raw.baseUrl && !hasEnvReference(raw.baseUrl) && !isAllowedRemoteUrl(raw.baseUrl)) ctx.addIssue({
|
|
317
|
+
code: "custom",
|
|
318
|
+
path: [
|
|
319
|
+
"openapiEndpoints",
|
|
320
|
+
server,
|
|
321
|
+
"baseUrl"
|
|
322
|
+
],
|
|
323
|
+
message: "OpenAPI baseUrl must use https except loopback development urls"
|
|
324
|
+
});
|
|
325
|
+
validateAuthHeaders(raw.auth, ctx, [
|
|
326
|
+
"openapiEndpoints",
|
|
327
|
+
server,
|
|
328
|
+
"auth"
|
|
329
|
+
]);
|
|
330
|
+
}
|
|
331
|
+
for (const [server, raw] of Object.entries(config.graphqlEndpoints)) {
|
|
332
|
+
if (Number(Boolean(raw.schemaPath)) + Number(Boolean(raw.schemaUrl)) + Number(raw.introspection === true) !== 1) ctx.addIssue({
|
|
333
|
+
code: "custom",
|
|
334
|
+
path: ["graphqlEndpoints", server],
|
|
335
|
+
message: "GraphQL endpoint must define exactly one schema source"
|
|
336
|
+
});
|
|
337
|
+
if (raw.endpointUrl && !hasEnvReference(raw.endpointUrl) && !isAllowedRemoteUrl(raw.endpointUrl)) ctx.addIssue({
|
|
338
|
+
code: "custom",
|
|
339
|
+
path: [
|
|
340
|
+
"graphqlEndpoints",
|
|
341
|
+
server,
|
|
342
|
+
"endpointUrl"
|
|
343
|
+
],
|
|
344
|
+
message: "GraphQL endpointUrl must use https except loopback development urls"
|
|
345
|
+
});
|
|
346
|
+
validateAuthHeaders(raw.auth, ctx, [
|
|
347
|
+
"graphqlEndpoints",
|
|
348
|
+
server,
|
|
349
|
+
"auth"
|
|
350
|
+
]);
|
|
351
|
+
}
|
|
352
|
+
for (const [server, raw] of Object.entries(config.httpApis)) {
|
|
353
|
+
if (raw.baseUrl && !hasEnvReference(raw.baseUrl) && !isAllowedHttpBaseUrl(raw.baseUrl)) ctx.addIssue({
|
|
354
|
+
code: "custom",
|
|
355
|
+
path: [
|
|
356
|
+
"httpApis",
|
|
357
|
+
server,
|
|
358
|
+
"baseUrl"
|
|
359
|
+
],
|
|
360
|
+
message: "HTTP API baseUrl must use https except loopback development urls and must not include credentials, query, or fragment"
|
|
361
|
+
});
|
|
362
|
+
validateAuthHeaders(raw.auth, ctx, [
|
|
363
|
+
"httpApis",
|
|
364
|
+
server,
|
|
365
|
+
"auth"
|
|
366
|
+
]);
|
|
367
|
+
for (const [actionName, action] of Object.entries(raw.actions)) if (action.headers) validateHttpActionHeaders(action.headers, ctx, [
|
|
368
|
+
"httpApis",
|
|
369
|
+
server,
|
|
370
|
+
"actions",
|
|
371
|
+
actionName,
|
|
372
|
+
"headers"
|
|
373
|
+
]);
|
|
374
|
+
}
|
|
375
|
+
for (const [server, raw] of Object.entries(config.capletSets)) {
|
|
376
|
+
if (!raw.configPath && !raw.capletsRoot) ctx.addIssue({
|
|
377
|
+
code: "custom",
|
|
378
|
+
path: ["capletSets", server],
|
|
379
|
+
message: "Caplet set must define at least one source: configPath or capletsRoot"
|
|
380
|
+
});
|
|
381
|
+
if (raw.defaultSearchLimit > raw.maxSearchLimit) ctx.addIssue({
|
|
382
|
+
code: "custom",
|
|
383
|
+
path: [
|
|
384
|
+
"capletSets",
|
|
385
|
+
server,
|
|
386
|
+
"defaultSearchLimit"
|
|
387
|
+
],
|
|
388
|
+
message: "defaultSearchLimit must be <= maxSearchLimit"
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
function validateAuthHeaders(auth, ctx, path) {
|
|
393
|
+
if (auth?.type !== "headers") return;
|
|
394
|
+
for (const headerName of Object.keys(auth.headers)) {
|
|
395
|
+
const normalized = headerName.toLowerCase();
|
|
396
|
+
if (!HEADER_NAME_PATTERN.test(headerName) || FORBIDDEN_HEADERS.has(normalized)) ctx.addIssue({
|
|
397
|
+
code: "custom",
|
|
398
|
+
path: [
|
|
399
|
+
...path,
|
|
400
|
+
"headers",
|
|
401
|
+
headerName
|
|
402
|
+
],
|
|
403
|
+
message: `header ${headerName} is not allowed`
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function mapBackend(records, backend, prepare) {
|
|
408
|
+
return Object.fromEntries(Object.entries(records).map(([id, raw]) => [id, stripUndefined({
|
|
409
|
+
...prepare ? prepare(id, raw) : raw,
|
|
410
|
+
server: id,
|
|
411
|
+
backend
|
|
412
|
+
})]));
|
|
413
|
+
}
|
|
414
|
+
function stripUndefined(value) {
|
|
415
|
+
return Object.fromEntries(Object.entries(value).filter(([, nested]) => nested !== void 0));
|
|
416
|
+
}
|
|
417
|
+
function hasEnvReference(value) {
|
|
418
|
+
return /\$\{?[A-Z_][A-Z0-9_]*\}?|\$env:[A-Z_][A-Z0-9_]*/u.test(value);
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
export { parseConfig };
|