@caplets/core 0.15.0 → 0.17.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/auth.d.ts +14 -0
- package/dist/cli/auth.d.ts +24 -0
- package/dist/cli.d.ts +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4136 -180
- package/dist/native/options.d.ts +33 -0
- package/dist/native/remote.d.ts +46 -0
- package/dist/native/service.d.ts +7 -1
- package/dist/native.d.ts +2 -0
- package/dist/native.js +233 -2
- package/dist/{engine-Bh55p8Lm.js → options-CJEOqS87.js} +26545 -26325
- package/dist/remote-control/auth-flow.d.ts +22 -0
- package/dist/remote-control/client.d.ts +11 -0
- package/dist/remote-control/dispatch.d.ts +9 -0
- package/dist/remote-control/types.d.ts +17 -0
- package/dist/runtime.d.ts +3 -8
- package/dist/serve/http.d.ts +23 -0
- package/dist/serve/index.d.ts +14 -0
- package/dist/serve/options.d.ts +36 -0
- package/dist/serve/session.d.ts +21 -0
- package/dist/serve/stdio.d.ts +5 -0
- package/dist/server/options.d.ts +41 -0
- package/package.json +4 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type CapletsMode, type CapletsServerEnv, type CapletsServerInput } from "../server/options";
|
|
2
|
+
export type NativeCapletsMode = CapletsMode;
|
|
3
|
+
export type NativeRemoteCapletsOptions = {
|
|
4
|
+
pollIntervalMs?: number;
|
|
5
|
+
fetch?: typeof fetch;
|
|
6
|
+
};
|
|
7
|
+
export type NativeCapletsServiceResolutionInput = {
|
|
8
|
+
mode?: NativeCapletsMode;
|
|
9
|
+
server?: CapletsServerInput;
|
|
10
|
+
remote?: NativeRemoteCapletsOptions;
|
|
11
|
+
};
|
|
12
|
+
export type NativeCapletsEnv = CapletsServerEnv;
|
|
13
|
+
export type NativeRemoteAuthOptions = {
|
|
14
|
+
enabled: false;
|
|
15
|
+
user: string;
|
|
16
|
+
} | {
|
|
17
|
+
enabled: true;
|
|
18
|
+
user: string;
|
|
19
|
+
password: string;
|
|
20
|
+
};
|
|
21
|
+
export type ResolvedNativeCapletsServiceOptions = {
|
|
22
|
+
mode: "local";
|
|
23
|
+
} | {
|
|
24
|
+
mode: "remote";
|
|
25
|
+
remote: {
|
|
26
|
+
url: URL;
|
|
27
|
+
auth: NativeRemoteAuthOptions;
|
|
28
|
+
pollIntervalMs: number;
|
|
29
|
+
requestInit: RequestInit;
|
|
30
|
+
fetch?: typeof fetch;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
export declare function resolveNativeCapletsServiceOptions(input?: NativeCapletsServiceResolutionInput, env?: NativeCapletsEnv): ResolvedNativeCapletsServiceOptions;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ResolvedNativeCapletsServiceOptions } from "./options";
|
|
2
|
+
import type { NativeCapletsService, NativeCapletsToolsChangedListener, NativeCapletTool } from "./service";
|
|
3
|
+
export type RemoteCapletsTool = {
|
|
4
|
+
name: string;
|
|
5
|
+
title?: string | undefined;
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
export type RemoteCapletsClient = {
|
|
9
|
+
listTools(): Promise<RemoteCapletsTool[]>;
|
|
10
|
+
callTool(name: string, args: unknown): Promise<unknown>;
|
|
11
|
+
onToolsChanged(listener: () => void): () => void;
|
|
12
|
+
close(): Promise<void>;
|
|
13
|
+
};
|
|
14
|
+
export type RemoteCapletsClientOptions = ResolvedNativeCapletsServiceOptions & {
|
|
15
|
+
mode: "remote";
|
|
16
|
+
};
|
|
17
|
+
export type RemoteNativeCapletsServiceOptions = {
|
|
18
|
+
client: RemoteCapletsClient;
|
|
19
|
+
clientFactory?: () => RemoteCapletsClient;
|
|
20
|
+
pollIntervalMs: number;
|
|
21
|
+
writeErr?: (value: string) => void;
|
|
22
|
+
};
|
|
23
|
+
export declare function createSdkRemoteCapletsClient(options: RemoteCapletsClientOptions["remote"]): RemoteCapletsClient;
|
|
24
|
+
export declare class RemoteNativeCapletsService implements NativeCapletsService {
|
|
25
|
+
private readonly options;
|
|
26
|
+
private tools;
|
|
27
|
+
private readonly listeners;
|
|
28
|
+
private readonly clientFactory;
|
|
29
|
+
private client;
|
|
30
|
+
private unsubscribeRemote;
|
|
31
|
+
private readonly pollTimer;
|
|
32
|
+
private closed;
|
|
33
|
+
private resetInFlight;
|
|
34
|
+
constructor(options: RemoteNativeCapletsServiceOptions);
|
|
35
|
+
listTools(): NativeCapletTool[];
|
|
36
|
+
execute(capletId: string, request: unknown): Promise<unknown>;
|
|
37
|
+
reload(): Promise<boolean>;
|
|
38
|
+
onToolsChanged(listener: NativeCapletsToolsChangedListener): () => void;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
private reloadFromClient;
|
|
41
|
+
private subscribeRemote;
|
|
42
|
+
private resetClient;
|
|
43
|
+
private doResetClient;
|
|
44
|
+
private emitToolsChanged;
|
|
45
|
+
private warn;
|
|
46
|
+
}
|
package/dist/native/service.d.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import type { NativeCapletsServiceResolutionInput } from "./options";
|
|
2
|
+
import { resolveNativeCapletsServiceOptions } from "./options";
|
|
3
|
+
import { type RemoteCapletsClient } from "./remote";
|
|
4
|
+
export type NativeCapletsServiceOptions = NativeCapletsServiceResolutionInput & {
|
|
2
5
|
configPath?: string;
|
|
3
6
|
projectConfigPath?: string;
|
|
4
7
|
authDir?: string;
|
|
5
8
|
watchDebounceMs?: number;
|
|
6
9
|
watch?: boolean;
|
|
7
10
|
writeErr?: (value: string) => void;
|
|
11
|
+
remoteClientFactory?: (options: Extract<ReturnType<typeof resolveNativeCapletsServiceOptions>, {
|
|
12
|
+
mode: "remote";
|
|
13
|
+
}>["remote"]) => RemoteCapletsClient;
|
|
8
14
|
};
|
|
9
15
|
export type NativeCapletTool = {
|
|
10
16
|
caplet: string;
|
package/dist/native.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export { registerNativeCapletsProcessCleanup } from "./native/process-cleanup";
|
|
|
3
3
|
export { nativeCapletPromptGuidance, nativeCapletToolDescription, nativeCapletToolName, nativeCapletsSystemGuidance, } from "./native/tools";
|
|
4
4
|
export { generatedToolInputSchema } from "./tools";
|
|
5
5
|
export { generatedToolInputJsonSchema } from "./generated-tool-input-schema";
|
|
6
|
+
export { resolveNativeCapletsServiceOptions, type NativeCapletsEnv, type NativeCapletsMode, type NativeCapletsServiceResolutionInput, type NativeRemoteAuthOptions, type NativeRemoteCapletsOptions, type ResolvedNativeCapletsServiceOptions, } from "./native/options";
|
|
7
|
+
export { createSdkRemoteCapletsClient, RemoteNativeCapletsService, type RemoteCapletsClient, type RemoteCapletsClientOptions, type RemoteCapletsTool, type RemoteNativeCapletsServiceOptions, } from "./native/remote";
|
package/dist/native.js
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { $ as ToolListChangedNotificationSchema, Nt as CapletsError, a as resolveCapletsServer, i as resolveCapletsMode, n as mcpUrlForBase, o as CapletsEngine, s as generatedToolInputSchema, u as capabilityDescription, v as StreamableHTTPClientTransport, x as Client } from "./options-CJEOqS87.js";
|
|
2
2
|
import { generatedToolInputJsonSchema } from "./generated-tool-input-schema.js";
|
|
3
|
+
//#region src/native/options.ts
|
|
4
|
+
const DEFAULT_POLL_INTERVAL_MS = 3e4;
|
|
5
|
+
function resolveNativeCapletsServiceOptions(input = {}, env = process.env) {
|
|
6
|
+
if (resolveCapletsMode({
|
|
7
|
+
...input.mode ? { mode: input.mode } : {},
|
|
8
|
+
...input.server?.url ? { serverUrl: input.server.url } : {}
|
|
9
|
+
}, env).mode === "local") return { mode: "local" };
|
|
10
|
+
const serverFetch = input.remote?.fetch ?? input.server?.fetch;
|
|
11
|
+
const server = resolveCapletsServer({
|
|
12
|
+
...input.server,
|
|
13
|
+
...serverFetch ? { fetch: serverFetch } : {}
|
|
14
|
+
}, env);
|
|
15
|
+
return {
|
|
16
|
+
mode: "remote",
|
|
17
|
+
remote: {
|
|
18
|
+
url: mcpUrlForBase(server.baseUrl),
|
|
19
|
+
auth: server.auth,
|
|
20
|
+
pollIntervalMs: parsePollInterval(input.remote?.pollIntervalMs),
|
|
21
|
+
requestInit: server.requestInit,
|
|
22
|
+
...server.fetch ? { fetch: server.fetch } : {}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function parsePollInterval(value) {
|
|
27
|
+
if (value === void 0) return DEFAULT_POLL_INTERVAL_MS;
|
|
28
|
+
if (!Number.isInteger(value) || value < 1e3) throw new CapletsError("REQUEST_INVALID", "remote.pollIntervalMs must be an integer >= 1000.");
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
3
32
|
//#region src/native/tools.ts
|
|
4
33
|
function nativeCapletToolName(capletId) {
|
|
5
34
|
return `caplets_${capletId.replace(/_/g, "__").replace(/-/g, "_")}`;
|
|
@@ -29,8 +58,210 @@ function nativeCapletToolDescription(toolName, caplet) {
|
|
|
29
58
|
].join("\n");
|
|
30
59
|
}
|
|
31
60
|
//#endregion
|
|
61
|
+
//#region src/native/remote.ts
|
|
62
|
+
function createSdkRemoteCapletsClient(options) {
|
|
63
|
+
const client = new Client({
|
|
64
|
+
name: "caplets-native",
|
|
65
|
+
version: "1.0.0"
|
|
66
|
+
}, { capabilities: {} });
|
|
67
|
+
const transport = new StreamableHTTPClientTransport(options.url, {
|
|
68
|
+
requestInit: options.requestInit,
|
|
69
|
+
...options.fetch ? { fetch: options.fetch } : {}
|
|
70
|
+
});
|
|
71
|
+
const ready = client.connect(transport);
|
|
72
|
+
const readyObserved = ready.catch(() => void 0);
|
|
73
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
74
|
+
client.setNotificationHandler(ToolListChangedNotificationSchema, () => {
|
|
75
|
+
for (const listener of listeners) listener();
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
async listTools() {
|
|
79
|
+
await ready;
|
|
80
|
+
return ((await client.listTools()).tools ?? []).map((tool) => ({
|
|
81
|
+
name: tool.name,
|
|
82
|
+
...tool.title ? { title: tool.title } : {},
|
|
83
|
+
...tool.description ? { description: tool.description } : {}
|
|
84
|
+
}));
|
|
85
|
+
},
|
|
86
|
+
async callTool(name, args) {
|
|
87
|
+
await ready;
|
|
88
|
+
const toolArguments = args && typeof args === "object" && !Array.isArray(args) ? args : void 0;
|
|
89
|
+
return await client.callTool({
|
|
90
|
+
name,
|
|
91
|
+
arguments: toolArguments
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
onToolsChanged(listener) {
|
|
95
|
+
listeners.add(listener);
|
|
96
|
+
return () => listeners.delete(listener);
|
|
97
|
+
},
|
|
98
|
+
async close() {
|
|
99
|
+
listeners.clear();
|
|
100
|
+
await readyObserved;
|
|
101
|
+
await transport.terminateSession().catch(() => void 0);
|
|
102
|
+
await client.close();
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
var RemoteNativeCapletsService = class {
|
|
107
|
+
options;
|
|
108
|
+
tools = [];
|
|
109
|
+
listeners = /* @__PURE__ */ new Set();
|
|
110
|
+
clientFactory;
|
|
111
|
+
client;
|
|
112
|
+
unsubscribeRemote;
|
|
113
|
+
pollTimer;
|
|
114
|
+
closed = false;
|
|
115
|
+
resetInFlight;
|
|
116
|
+
constructor(options) {
|
|
117
|
+
this.options = options;
|
|
118
|
+
this.client = options.client;
|
|
119
|
+
this.clientFactory = options.clientFactory ?? (() => options.client);
|
|
120
|
+
this.unsubscribeRemote = this.subscribeRemote(this.client);
|
|
121
|
+
this.pollTimer = setInterval(() => {
|
|
122
|
+
this.reload();
|
|
123
|
+
}, options.pollIntervalMs);
|
|
124
|
+
this.pollTimer.unref?.();
|
|
125
|
+
}
|
|
126
|
+
listTools() {
|
|
127
|
+
return [...this.tools];
|
|
128
|
+
}
|
|
129
|
+
async execute(capletId, request) {
|
|
130
|
+
try {
|
|
131
|
+
return await this.client.callTool(capletId, request);
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (isAuthFailure(error)) throw remoteAuthError();
|
|
134
|
+
if (isSessionFailure(error)) {
|
|
135
|
+
if (!await this.resetClient() || this.closed) throw error;
|
|
136
|
+
try {
|
|
137
|
+
return await this.client.callTool(capletId, request);
|
|
138
|
+
} catch (retryError) {
|
|
139
|
+
if (isAuthFailure(retryError)) throw remoteAuthError();
|
|
140
|
+
throw retryError;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async reload() {
|
|
147
|
+
if (this.closed) return false;
|
|
148
|
+
try {
|
|
149
|
+
await this.reloadFromClient();
|
|
150
|
+
return true;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (isSessionFailure(error)) try {
|
|
153
|
+
if (!await this.resetClient() || this.closed) return false;
|
|
154
|
+
await this.reloadFromClient();
|
|
155
|
+
return !this.closed;
|
|
156
|
+
} catch (retryError) {
|
|
157
|
+
this.warn(`Could not reload remote Caplets tools: ${errorMessage(retryError)}\n`);
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
this.warn(`Could not reload remote Caplets tools: ${errorMessage(error)}\n`);
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
onToolsChanged(listener) {
|
|
165
|
+
this.listeners.add(listener);
|
|
166
|
+
return () => this.listeners.delete(listener);
|
|
167
|
+
}
|
|
168
|
+
async close() {
|
|
169
|
+
if (this.closed) return;
|
|
170
|
+
this.closed = true;
|
|
171
|
+
clearInterval(this.pollTimer);
|
|
172
|
+
this.unsubscribeRemote();
|
|
173
|
+
this.listeners.clear();
|
|
174
|
+
await this.client.close();
|
|
175
|
+
}
|
|
176
|
+
async reloadFromClient() {
|
|
177
|
+
const tools = (await this.client.listTools()).map(remoteToolToNativeTool);
|
|
178
|
+
const changed = JSON.stringify(tools) !== JSON.stringify(this.tools);
|
|
179
|
+
this.tools = tools;
|
|
180
|
+
if (changed) this.emitToolsChanged();
|
|
181
|
+
}
|
|
182
|
+
subscribeRemote(client) {
|
|
183
|
+
return client.onToolsChanged(() => {
|
|
184
|
+
this.reload();
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
async resetClient() {
|
|
188
|
+
if (this.resetInFlight) return await this.resetInFlight;
|
|
189
|
+
this.resetInFlight = this.doResetClient();
|
|
190
|
+
try {
|
|
191
|
+
return await this.resetInFlight;
|
|
192
|
+
} finally {
|
|
193
|
+
this.resetInFlight = void 0;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
async doResetClient() {
|
|
197
|
+
if (this.closed) return false;
|
|
198
|
+
this.unsubscribeRemote();
|
|
199
|
+
await this.client.close().catch(() => void 0);
|
|
200
|
+
if (this.closed) return false;
|
|
201
|
+
const nextClient = this.clientFactory();
|
|
202
|
+
if (this.closed) {
|
|
203
|
+
await nextClient.close().catch(() => void 0);
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
this.client = nextClient;
|
|
207
|
+
this.unsubscribeRemote = this.subscribeRemote(this.client);
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
emitToolsChanged() {
|
|
211
|
+
const tools = this.listTools();
|
|
212
|
+
for (const listener of this.listeners) listener(tools);
|
|
213
|
+
}
|
|
214
|
+
warn(message) {
|
|
215
|
+
if (this.options.writeErr) {
|
|
216
|
+
this.options.writeErr(message);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
process.stderr.write(message);
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
function remoteToolToNativeTool(tool) {
|
|
223
|
+
const toolName = nativeCapletToolName(tool.name);
|
|
224
|
+
return {
|
|
225
|
+
caplet: tool.name,
|
|
226
|
+
toolName,
|
|
227
|
+
title: tool.title ?? tool.name,
|
|
228
|
+
description: [
|
|
229
|
+
tool.description ?? "Remote Caplets tool.",
|
|
230
|
+
"",
|
|
231
|
+
`Native tool name: ${toolName}`,
|
|
232
|
+
`Remote Caplet ID: ${tool.name}`
|
|
233
|
+
].join("\n"),
|
|
234
|
+
promptGuidance: [`Use ${toolName} through the remote Caplets service.`]
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function errorMessage(error) {
|
|
238
|
+
return error instanceof Error ? error.message : String(error);
|
|
239
|
+
}
|
|
240
|
+
function remoteAuthError() {
|
|
241
|
+
return new CapletsError("AUTH_FAILED", "Remote Caplets authentication failed; check CAPLETS_SERVER_USER and CAPLETS_SERVER_PASSWORD.");
|
|
242
|
+
}
|
|
243
|
+
function isSessionFailure(error) {
|
|
244
|
+
const message = errorMessage(error).toLowerCase();
|
|
245
|
+
return /session|transport|connection|connect|closed|invalid/u.test(message);
|
|
246
|
+
}
|
|
247
|
+
function isAuthFailure(error) {
|
|
248
|
+
const candidate = error;
|
|
249
|
+
const status = typeof candidate?.status === "number" ? candidate.status : void 0;
|
|
250
|
+
const statusCode = typeof candidate?.statusCode === "number" ? candidate.statusCode : void 0;
|
|
251
|
+
const code = typeof candidate?.code === "number" ? candidate.code : void 0;
|
|
252
|
+
if (status === 401 || status === 403 || statusCode === 401 || statusCode === 403 || code === 401 || code === 403) return true;
|
|
253
|
+
return /\b(401|403|unauthorized|forbidden)\b/iu.test(errorMessage(error));
|
|
254
|
+
}
|
|
255
|
+
//#endregion
|
|
32
256
|
//#region src/native/service.ts
|
|
33
257
|
function createNativeCapletsService(options = {}) {
|
|
258
|
+
const resolved = resolveNativeCapletsServiceOptions(options);
|
|
259
|
+
if (resolved.mode === "remote") return new RemoteNativeCapletsService({
|
|
260
|
+
client: (options.remoteClientFactory ?? createSdkRemoteCapletsClient)(resolved.remote),
|
|
261
|
+
clientFactory: () => (options.remoteClientFactory ?? createSdkRemoteCapletsClient)(resolved.remote),
|
|
262
|
+
pollIntervalMs: resolved.remote.pollIntervalMs,
|
|
263
|
+
...options.writeErr ? { writeErr: options.writeErr } : {}
|
|
264
|
+
});
|
|
34
265
|
return new DefaultNativeCapletsService(options);
|
|
35
266
|
}
|
|
36
267
|
var DefaultNativeCapletsService = class {
|
|
@@ -90,4 +321,4 @@ function registerNativeCapletsProcessCleanup(service) {
|
|
|
90
321
|
process.once("SIGTERM", closeAndExit);
|
|
91
322
|
}
|
|
92
323
|
//#endregion
|
|
93
|
-
export { createNativeCapletsService, generatedToolInputJsonSchema, generatedToolInputSchema, nativeCapletPromptGuidance, nativeCapletToolDescription, nativeCapletToolName, nativeCapletsSystemGuidance, registerNativeCapletsProcessCleanup };
|
|
324
|
+
export { RemoteNativeCapletsService, createNativeCapletsService, createSdkRemoteCapletsClient, generatedToolInputJsonSchema, generatedToolInputSchema, nativeCapletPromptGuidance, nativeCapletToolDescription, nativeCapletToolName, nativeCapletsSystemGuidance, registerNativeCapletsProcessCleanup, resolveNativeCapletsServiceOptions };
|