@caplets/core 0.27.0 → 0.28.1
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/api.d.ts +8 -0
- package/dist/cli/code-mode.d.ts +3 -2
- package/dist/cli/commands.d.ts +3 -1
- package/dist/cli.d.ts +4 -0
- package/dist/code-mode/types.d.ts +1 -0
- package/dist/{completion-1wDjwHkC.js → completion-D9253pYs.js} +13 -2
- package/dist/config/paths.d.ts +9 -0
- package/dist/config.d.ts +3 -1
- package/dist/engine.d.ts +18 -0
- package/dist/esm-Db9dhnIG.js +7488 -0
- package/dist/index.js +833 -482
- package/dist/native/options.d.ts +1 -0
- package/dist/native/remote.d.ts +2 -1
- package/dist/native/service.d.ts +14 -0
- package/dist/native.js +1 -1
- package/dist/node-BgWIvSVP.js +17214 -0
- package/dist/rolldown-runtime-CE-6LUnI.js +44 -0
- package/dist/serve/http.d.ts +16 -1
- package/dist/serve/options.d.ts +2 -0
- package/dist/{service-BGGiZLHa.js → service-B6YvNthO.js} +1688 -121
- package/dist/src-Cd2QIUm1.js +813 -0
- package/dist/telemetry/context.d.ts +13 -0
- package/dist/telemetry/debug.d.ts +10 -0
- package/dist/telemetry/delivery.d.ts +1 -0
- package/dist/telemetry/events.d.ts +70 -0
- package/dist/telemetry/identity.d.ts +1 -0
- package/dist/telemetry/index.d.ts +8 -0
- package/dist/telemetry/intake.generated.d.ts +2 -0
- package/dist/telemetry/notice.d.ts +8 -0
- package/dist/telemetry/privacy.d.ts +3 -0
- package/dist/telemetry/providers.d.ts +21 -0
- package/dist/telemetry/runtime.d.ts +40 -0
- package/dist/telemetry/state.d.ts +53 -0
- package/package.json +3 -1
|
@@ -1,53 +1,20 @@
|
|
|
1
|
+
import { i as __require, o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CE-6LUnI.js";
|
|
1
2
|
import { A as safeParseAsync$1, C as toJSONSchema, D as parse$3, E as $ZodType, F as NEVER, M as defineLazy, N as normalizeParams, O as parseAsync, P as $constructor, S as datetime, T as $ZodObject, _ as record, a as any, b as unknown, c as custom, d as literal, f as looseObject, g as preprocess, h as optional, i as _null, j as clone, k as safeParse$1, l as discriminatedUnion, m as object$1, o as array, p as number$1, r as _enum, s as boolean, t as ZodNumber$1, u as intersection, v as string, w as _coercedNumber, x as url, y as union } from "./schemas-BoqMu4MG.js";
|
|
2
3
|
import { a as SERVER_ID_PATTERN, c as isUrl, d as CapletsError, f as errorResult, i as NAMESPACE_ALIAS_LABEL_PATTERN, l as validateHttpActionHeaders, m as toSafeError, n as HEADER_NAME_PATTERN, o as isAllowedHttpBaseUrl, p as redactSecrets, r as HTTP_BASE_URL_PATTERN, s as isAllowedRemoteUrl, t as FORBIDDEN_HEADERS } from "./validation-CWzd2gtn.js";
|
|
3
4
|
import { generatedToolInputJsonSchema, generatedToolInputJsonSchemaForCaplet, generatedToolInputSchemaForCaplet, mcpOperations, operations } from "./generated-tool-input-schema.js";
|
|
4
|
-
import { f as observedOutputShapeKey, i as observeOutputShape, r as normalizedObservableValue, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-DuP7mJQf.js";
|
|
5
|
-
import {
|
|
6
|
-
import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
|
|
5
|
+
import { f as observedOutputShapeKey, g as stableJsonStringify, h as schemaHash, i as observeOutputShape, r as normalizedObservableValue, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-DuP7mJQf.js";
|
|
6
|
+
import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
|
|
7
7
|
import { basename, delimiter, dirname, extname, isAbsolute, join, parse, posix, relative, resolve, sep, win32 } from "node:path";
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import process$1 from "node:process";
|
|
10
10
|
import { PassThrough } from "node:stream";
|
|
11
11
|
import { createServer } from "node:http";
|
|
12
12
|
import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
|
|
13
|
-
import { homedir } from "node:os";
|
|
13
|
+
import { arch, homedir, platform } from "node:os";
|
|
14
14
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
15
15
|
import { readFile } from "node:fs/promises";
|
|
16
16
|
import ts from "typescript";
|
|
17
17
|
import { getQuickJS, shouldInterruptAfterDeadline } from "quickjs-emscripten";
|
|
18
|
-
//#region \0rolldown/runtime.js
|
|
19
|
-
var __create = Object.create;
|
|
20
|
-
var __defProp = Object.defineProperty;
|
|
21
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
22
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
23
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
24
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
25
|
-
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
26
|
-
var __exportAll = (all, no_symbols) => {
|
|
27
|
-
let target = {};
|
|
28
|
-
for (var name in all) __defProp(target, name, {
|
|
29
|
-
get: all[name],
|
|
30
|
-
enumerable: true
|
|
31
|
-
});
|
|
32
|
-
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
33
|
-
return target;
|
|
34
|
-
};
|
|
35
|
-
var __copyProps = (to, from, except, desc) => {
|
|
36
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
37
|
-
key = keys[i];
|
|
38
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
39
|
-
get: ((k) => from[k]).bind(null, key),
|
|
40
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
return to;
|
|
44
|
-
};
|
|
45
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
46
|
-
value: mod,
|
|
47
|
-
enumerable: true
|
|
48
|
-
}) : target, mod));
|
|
49
|
-
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
|
|
50
|
-
//#endregion
|
|
51
18
|
//#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v3/helpers/util.js
|
|
52
19
|
var util$1;
|
|
53
20
|
(function(util) {
|
|
@@ -17242,6 +17209,18 @@ function defaultConfigPath(env = process.env, home = homedir(), platform = proce
|
|
|
17242
17209
|
function defaultAuthDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
17243
17210
|
return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "auth");
|
|
17244
17211
|
}
|
|
17212
|
+
function defaultTelemetryStateDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
17213
|
+
return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "telemetry");
|
|
17214
|
+
}
|
|
17215
|
+
function defaultTelemetryIdentityPath(env = process.env, home = homedir(), platform = process.platform) {
|
|
17216
|
+
return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "identity.json");
|
|
17217
|
+
}
|
|
17218
|
+
function defaultTelemetryNoticePath(env = process.env, home = homedir(), platform = process.platform) {
|
|
17219
|
+
return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "notice.json");
|
|
17220
|
+
}
|
|
17221
|
+
function defaultTelemetryDeliveryHealthPath(env = process.env, home = homedir(), platform = process.platform) {
|
|
17222
|
+
return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "delivery-health.json");
|
|
17223
|
+
}
|
|
17245
17224
|
function defaultArtifactDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
17246
17225
|
return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "artifacts");
|
|
17247
17226
|
}
|
|
@@ -17256,6 +17235,10 @@ function defaultObservedOutputShapeCacheDir(env = process.env, home = homedir(),
|
|
|
17256
17235
|
const DEFAULT_CONFIG_PATH = defaultConfigPath();
|
|
17257
17236
|
const DEFAULT_AUTH_DIR = defaultAuthDir();
|
|
17258
17237
|
const DEFAULT_ARTIFACT_DIR = defaultArtifactDir();
|
|
17238
|
+
const DEFAULT_TELEMETRY_STATE_DIR = defaultTelemetryStateDir();
|
|
17239
|
+
defaultTelemetryIdentityPath();
|
|
17240
|
+
defaultTelemetryNoticePath();
|
|
17241
|
+
defaultTelemetryDeliveryHealthPath();
|
|
17259
17242
|
const DEFAULT_COMPLETION_CACHE_DIR = defaultCompletionCacheDir();
|
|
17260
17243
|
const DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR = defaultObservedOutputShapeCacheDir();
|
|
17261
17244
|
const PROJECT_CONFIG_FILE = join(".caplets", "config.json");
|
|
@@ -18627,8 +18610,8 @@ function compactToolSafetyHints(tool) {
|
|
|
18627
18610
|
};
|
|
18628
18611
|
}
|
|
18629
18612
|
function compactToolSchemaHints(tool) {
|
|
18630
|
-
const schema = isRecord$
|
|
18631
|
-
const properties = isRecord$
|
|
18613
|
+
const schema = isRecord$9(tool.inputSchema) ? tool.inputSchema : void 0;
|
|
18614
|
+
const properties = isRecord$9(schema?.properties) ? schema.properties : {};
|
|
18632
18615
|
const acceptedArgs = Object.keys(properties).sort();
|
|
18633
18616
|
const requiredArgs = Array.isArray(schema?.required) ? schema.required.filter((value) => typeof value === "string").sort() : [];
|
|
18634
18617
|
const argsTemplate = compactArgsTemplate(properties, requiredArgs, acceptedArgs);
|
|
@@ -18652,7 +18635,7 @@ function compactArgsTemplate(properties, requiredArgs, acceptedArgs) {
|
|
|
18652
18635
|
if (templateArgs.length === 0 || templateArgs.length > 4) return void 0;
|
|
18653
18636
|
if (requiredArgs.length === 0 && acceptedArgs.length > 3) return void 0;
|
|
18654
18637
|
const entries = templateArgs.flatMap((name) => {
|
|
18655
|
-
const value = placeholderForSchema(isRecord$
|
|
18638
|
+
const value = placeholderForSchema(isRecord$9(properties[name]) ? properties[name] : void 0);
|
|
18656
18639
|
return value === void 0 ? [] : [[name, value]];
|
|
18657
18640
|
});
|
|
18658
18641
|
return entries.length === templateArgs.length ? Object.fromEntries(entries) : void 0;
|
|
@@ -18672,13 +18655,13 @@ function placeholderForSchema(schema) {
|
|
|
18672
18655
|
}
|
|
18673
18656
|
}
|
|
18674
18657
|
function compactToolSelectionHints(tool) {
|
|
18675
|
-
if (!isRecord$
|
|
18658
|
+
if (!isRecord$9(tool)) return {};
|
|
18676
18659
|
return {
|
|
18677
18660
|
...typeof tool.useWhen === "string" && tool.useWhen.trim() ? { useWhen: tool.useWhen.trim() } : {},
|
|
18678
18661
|
...typeof tool.avoidWhen === "string" && tool.avoidWhen.trim() ? { avoidWhen: tool.avoidWhen.trim() } : {}
|
|
18679
18662
|
};
|
|
18680
18663
|
}
|
|
18681
|
-
function isRecord$
|
|
18664
|
+
function isRecord$9(value) {
|
|
18682
18665
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
18683
18666
|
}
|
|
18684
18667
|
function sameServerConfig(left, right) {
|
|
@@ -18753,7 +18736,7 @@ function markdownCallToolResultContent(result, context = {}) {
|
|
|
18753
18736
|
return textContent(renderStructuredMarkdown(result, context));
|
|
18754
18737
|
}
|
|
18755
18738
|
function hasRenderableStructuredContent(value) {
|
|
18756
|
-
if (!isRecord$
|
|
18739
|
+
if (!isRecord$8(value)) return false;
|
|
18757
18740
|
return Object.keys(value).some((key) => key !== "caplets" && key !== "elapsedMs");
|
|
18758
18741
|
}
|
|
18759
18742
|
function renderStructuredMarkdown(value, context) {
|
|
@@ -18887,13 +18870,13 @@ function renderErrorMarkdown(value, title) {
|
|
|
18887
18870
|
].join("\n");
|
|
18888
18871
|
}
|
|
18889
18872
|
function isDiscoveryWrapper(value) {
|
|
18890
|
-
return isRecord$
|
|
18873
|
+
return isRecord$8(value) && "result" in value;
|
|
18891
18874
|
}
|
|
18892
18875
|
function isErrorStructuredContent(value) {
|
|
18893
|
-
return isRecord$
|
|
18876
|
+
return isRecord$8(value) && "error" in value;
|
|
18894
18877
|
}
|
|
18895
18878
|
function isHttpLikeResult(value) {
|
|
18896
|
-
return isRecord$
|
|
18879
|
+
return isRecord$8(value) && ("status" in value || "statusText" in value || "body" in value);
|
|
18897
18880
|
}
|
|
18898
18881
|
function isGraphQlHttpResult(value) {
|
|
18899
18882
|
if (!isHttpLikeResult(value)) return false;
|
|
@@ -18901,7 +18884,7 @@ function isGraphQlHttpResult(value) {
|
|
|
18901
18884
|
return Boolean(body && ("data" in body || "errors" in body));
|
|
18902
18885
|
}
|
|
18903
18886
|
function isCliResult(value) {
|
|
18904
|
-
return isRecord$
|
|
18887
|
+
return isRecord$8(value) && ("exitCode" in value || "stdout" in value || "stderr" in value);
|
|
18905
18888
|
}
|
|
18906
18889
|
function renderBodyValue(value) {
|
|
18907
18890
|
if (value === void 0) return "_No response body._";
|
|
@@ -18969,8 +18952,8 @@ function compactListHints(record) {
|
|
|
18969
18952
|
const acceptedArgs = stringArrayValue(record.acceptedArgs);
|
|
18970
18953
|
if (requiredArgs.length > 0) hints.push(`required args: ${requiredArgs.join(", ")}`);
|
|
18971
18954
|
else if (acceptedArgs.length > 0) hints.push(`args: ${acceptedArgs.join(", ")}`);
|
|
18972
|
-
if (isRecord$
|
|
18973
|
-
if (isRecord$
|
|
18955
|
+
if (isRecord$8(record.argsTemplate)) hints.push(`args template: ${compactJsonText(record.argsTemplate, 160)}`);
|
|
18956
|
+
if (isRecord$8(record.callTemplate)) hints.push(`call: ${compactJsonText(record.callTemplate, 220)}`);
|
|
18974
18957
|
if (record.supportsFields === true) hints.push("supports fields");
|
|
18975
18958
|
if (record.readOnlyHint === true) hints.push("read-only");
|
|
18976
18959
|
if (record.destructiveHint === true) hints.push("destructive");
|
|
@@ -19040,9 +19023,9 @@ function humanizeKey(key) {
|
|
|
19040
19023
|
return key.replace(/([A-Z])/gu, " $1").replace(/^./u, (char) => char.toUpperCase());
|
|
19041
19024
|
}
|
|
19042
19025
|
function asRecord$3(value) {
|
|
19043
|
-
return isRecord$
|
|
19026
|
+
return isRecord$8(value) ? value : void 0;
|
|
19044
19027
|
}
|
|
19045
|
-
function isRecord$
|
|
19028
|
+
function isRecord$8(value) {
|
|
19046
19029
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
19047
19030
|
}
|
|
19048
19031
|
//#endregion
|
|
@@ -27555,6 +27538,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, googleDi
|
|
|
27555
27538
|
version: literal(1).default(1).describe("Caplets config schema version."),
|
|
27556
27539
|
defaultSearchLimit: number$1().int().positive().default(20).describe("Default maximum number of same-server search results."),
|
|
27557
27540
|
maxSearchLimit: number$1().int().positive().max(50).default(50).describe("Maximum accepted search_tools limit."),
|
|
27541
|
+
telemetry: boolean().optional().describe("Set false to disable anonymous Caplets telemetry for this user config."),
|
|
27558
27542
|
completion: object$1({
|
|
27559
27543
|
discoveryTimeoutMs: number$1().int().positive().default(750),
|
|
27560
27544
|
overallTimeoutMs: number$1().int().positive().default(1500),
|
|
@@ -28352,6 +28336,7 @@ function mergeConfigInputs(...inputs) {
|
|
|
28352
28336
|
merged = {
|
|
28353
28337
|
...merged,
|
|
28354
28338
|
...input,
|
|
28339
|
+
telemetry: input.telemetry === void 0 ? merged?.telemetry : input.telemetry,
|
|
28355
28340
|
namespaceAliases: mergeNamespaceAliases(merged?.namespaceAliases, input.namespaceAliases),
|
|
28356
28341
|
mcpServers: {
|
|
28357
28342
|
...merged?.mcpServers,
|
|
@@ -28408,13 +28393,14 @@ function mergeConfigInputsWithSources(...inputs) {
|
|
|
28408
28393
|
const shadows = {};
|
|
28409
28394
|
for (const entry of inputs) {
|
|
28410
28395
|
if (entry?.input === void 0) continue;
|
|
28411
|
-
|
|
28396
|
+
const entryInput = entry.source.kind === "global-config" ? entry.input : stripUserOnlyConfig(entry.input);
|
|
28397
|
+
for (const id of capletIds(entryInput)) {
|
|
28412
28398
|
const source = sourceForId(entry.source, id);
|
|
28413
28399
|
if (sources[id]) shadows[id] = [...shadows[id] ?? [], sources[id]];
|
|
28414
28400
|
sources[id] = source;
|
|
28415
28401
|
merged = removeCapletId(merged, id);
|
|
28416
28402
|
}
|
|
28417
|
-
merged = mergeConfigInputs(merged,
|
|
28403
|
+
merged = mergeConfigInputs(merged, entryInput) ?? {};
|
|
28418
28404
|
}
|
|
28419
28405
|
return {
|
|
28420
28406
|
input: merged,
|
|
@@ -28422,6 +28408,10 @@ function mergeConfigInputsWithSources(...inputs) {
|
|
|
28422
28408
|
shadows
|
|
28423
28409
|
};
|
|
28424
28410
|
}
|
|
28411
|
+
function stripUserOnlyConfig(input) {
|
|
28412
|
+
const { telemetry: _telemetry, ...rest } = input;
|
|
28413
|
+
return rest;
|
|
28414
|
+
}
|
|
28425
28415
|
function removeCapletBackendId(input, backend, id) {
|
|
28426
28416
|
const caplets = input[backend];
|
|
28427
28417
|
if (!isPlainObject$5(caplets)) return input;
|
|
@@ -28518,6 +28508,7 @@ function parseConfig(input, options = {}) {
|
|
|
28518
28508
|
});
|
|
28519
28509
|
return {
|
|
28520
28510
|
version: parsed.data.version,
|
|
28511
|
+
telemetry: parsed.data.telemetry,
|
|
28521
28512
|
options: {
|
|
28522
28513
|
defaultSearchLimit: parsed.data.defaultSearchLimit,
|
|
28523
28514
|
maxSearchLimit: parsed.data.maxSearchLimit,
|
|
@@ -28662,17 +28653,17 @@ function googleDiscoveryScopesForOperations(operations) {
|
|
|
28662
28653
|
return [...new Set(operations.flatMap((operation) => operation.scopes))].sort();
|
|
28663
28654
|
}
|
|
28664
28655
|
function validateGoogleDiscoveryDocument(value) {
|
|
28665
|
-
if (!isRecord$
|
|
28656
|
+
if (!isRecord$7(value)) throw new Error("Invalid Google Discovery document: expected an object");
|
|
28666
28657
|
if (value.kind !== void 0 && value.kind !== "discovery#restDescription") throw new Error("Invalid Google Discovery document: expected kind discovery#restDescription");
|
|
28667
|
-
if (value.resources !== void 0 && !isRecord$
|
|
28668
|
-
if (value.methods !== void 0 && !isRecord$
|
|
28669
|
-
if (!isRecord$
|
|
28670
|
-
if (value.schemas !== void 0 && !isRecord$
|
|
28671
|
-
if (value.parameters !== void 0 && !isRecord$
|
|
28658
|
+
if (value.resources !== void 0 && !isRecord$7(value.resources)) throw new Error("Invalid Google Discovery document: expected resources object");
|
|
28659
|
+
if (value.methods !== void 0 && !isRecord$7(value.methods)) throw new Error("Invalid Google Discovery document: expected methods object");
|
|
28660
|
+
if (!isRecord$7(value.resources) && !isRecord$7(value.methods)) throw new Error("Invalid Google Discovery document: expected resources or methods object");
|
|
28661
|
+
if (value.schemas !== void 0 && !isRecord$7(value.schemas)) throw new Error("Invalid Google Discovery document: expected schemas object");
|
|
28662
|
+
if (value.parameters !== void 0 && !isRecord$7(value.parameters)) throw new Error("Invalid Google Discovery document: expected parameters object");
|
|
28672
28663
|
return value;
|
|
28673
28664
|
}
|
|
28674
28665
|
function collectDocumentMethods(document) {
|
|
28675
|
-
return [...Object.entries(document.methods ?? {}).filter((entry) => isRecord$
|
|
28666
|
+
return [...Object.entries(document.methods ?? {}).filter((entry) => isRecord$7(entry[1])).map(([methodKey, method]) => ({
|
|
28676
28667
|
resourcePath: [],
|
|
28677
28668
|
methodKey,
|
|
28678
28669
|
method
|
|
@@ -28681,9 +28672,9 @@ function collectDocumentMethods(document) {
|
|
|
28681
28672
|
function collectMethods(resources, resourcePath = []) {
|
|
28682
28673
|
const entries = [];
|
|
28683
28674
|
for (const [resourceName, resource] of Object.entries(resources)) {
|
|
28684
|
-
if (!isRecord$
|
|
28675
|
+
if (!isRecord$7(resource)) continue;
|
|
28685
28676
|
const nextPath = [...resourcePath, resourceName];
|
|
28686
|
-
for (const [methodKey, method] of Object.entries(resource.methods ?? {})) if (isRecord$
|
|
28677
|
+
for (const [methodKey, method] of Object.entries(resource.methods ?? {})) if (isRecord$7(method)) entries.push({
|
|
28687
28678
|
resourcePath: nextPath,
|
|
28688
28679
|
methodKey,
|
|
28689
28680
|
method
|
|
@@ -28856,7 +28847,7 @@ function globMatches(pattern, name) {
|
|
|
28856
28847
|
function isJsonSchemaObject(value) {
|
|
28857
28848
|
return value.type === "object" || "properties" in value || "additionalProperties" in value;
|
|
28858
28849
|
}
|
|
28859
|
-
function isRecord$
|
|
28850
|
+
function isRecord$7(value) {
|
|
28860
28851
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28861
28852
|
}
|
|
28862
28853
|
function collapseWhitespace(value) {
|
|
@@ -63945,6 +63936,746 @@ async function withTimeout(promise, timeoutMs) {
|
|
|
63945
63936
|
}
|
|
63946
63937
|
}
|
|
63947
63938
|
//#endregion
|
|
63939
|
+
//#region src/telemetry/state.ts
|
|
63940
|
+
function telemetryStateDir(options = {}) {
|
|
63941
|
+
return options.stateDir ?? DEFAULT_TELEMETRY_STATE_DIR;
|
|
63942
|
+
}
|
|
63943
|
+
function telemetryIdentityPath(options = {}) {
|
|
63944
|
+
return join(telemetryStateDir(options), "identity.json");
|
|
63945
|
+
}
|
|
63946
|
+
function telemetryNoticePath(options = {}) {
|
|
63947
|
+
return join(telemetryStateDir(options), "notice.json");
|
|
63948
|
+
}
|
|
63949
|
+
function telemetryDeliveryHealthPath(options = {}) {
|
|
63950
|
+
return join(telemetryStateDir(options), "delivery-health.json");
|
|
63951
|
+
}
|
|
63952
|
+
function readTelemetryIdentity(options = {}) {
|
|
63953
|
+
const path = telemetryIdentityPath(options);
|
|
63954
|
+
const existing = readJson(path);
|
|
63955
|
+
if (typeof existing?.id === "string" && /^anon_[a-f0-9]{32}$/u.test(existing.id)) return {
|
|
63956
|
+
kind: "stable",
|
|
63957
|
+
id: existing.id
|
|
63958
|
+
};
|
|
63959
|
+
if (!options.create) return {
|
|
63960
|
+
kind: "ephemeral",
|
|
63961
|
+
id: ephemeralId(),
|
|
63962
|
+
reason: "state-unavailable"
|
|
63963
|
+
};
|
|
63964
|
+
const identity = {
|
|
63965
|
+
id: stableId(),
|
|
63966
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
63967
|
+
};
|
|
63968
|
+
if (!writePrivateJson(path, identity)) return {
|
|
63969
|
+
kind: "ephemeral",
|
|
63970
|
+
id: ephemeralId(),
|
|
63971
|
+
reason: "state-unavailable"
|
|
63972
|
+
};
|
|
63973
|
+
return {
|
|
63974
|
+
kind: "stable",
|
|
63975
|
+
id: identity.id
|
|
63976
|
+
};
|
|
63977
|
+
}
|
|
63978
|
+
function rotateTelemetryIdentity(options = {}) {
|
|
63979
|
+
const identity = {
|
|
63980
|
+
id: stableId(),
|
|
63981
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
63982
|
+
};
|
|
63983
|
+
if (!writePrivateJson(telemetryIdentityPath(options), identity)) return {
|
|
63984
|
+
kind: "ephemeral",
|
|
63985
|
+
id: ephemeralId(),
|
|
63986
|
+
reason: "state-unavailable"
|
|
63987
|
+
};
|
|
63988
|
+
return {
|
|
63989
|
+
kind: "stable",
|
|
63990
|
+
id: identity.id
|
|
63991
|
+
};
|
|
63992
|
+
}
|
|
63993
|
+
function deleteTelemetryIdentity(options = {}) {
|
|
63994
|
+
try {
|
|
63995
|
+
rmSync(telemetryIdentityPath(options), { force: true });
|
|
63996
|
+
} catch {}
|
|
63997
|
+
}
|
|
63998
|
+
function readTelemetryNotice(options = {}) {
|
|
63999
|
+
const existing = readJson(telemetryNoticePath(options));
|
|
64000
|
+
if (existing?.shown === true && typeof existing.shownAt === "string" && isTelemetrySurface(existing.surface)) return {
|
|
64001
|
+
shown: true,
|
|
64002
|
+
shownAt: existing.shownAt,
|
|
64003
|
+
surface: existing.surface
|
|
64004
|
+
};
|
|
64005
|
+
return { shown: false };
|
|
64006
|
+
}
|
|
64007
|
+
function recordTelemetryNoticeShown(options) {
|
|
64008
|
+
const notice = {
|
|
64009
|
+
shown: true,
|
|
64010
|
+
shownAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
64011
|
+
surface: options.surface
|
|
64012
|
+
};
|
|
64013
|
+
writePrivateJson(telemetryNoticePath(options), notice);
|
|
64014
|
+
return notice;
|
|
64015
|
+
}
|
|
64016
|
+
function readTelemetryDeliveryHealth(options = {}) {
|
|
64017
|
+
const existing = readJson(telemetryDeliveryHealthPath(options));
|
|
64018
|
+
if (!isDeliveryHealth(existing)) return {};
|
|
64019
|
+
return existing;
|
|
64020
|
+
}
|
|
64021
|
+
function recordTelemetryDrop(options) {
|
|
64022
|
+
const health = readTelemetryDeliveryHealth(options);
|
|
64023
|
+
health[options.provider] = health[options.provider] ?? {};
|
|
64024
|
+
health[options.provider][options.reason] = (health[options.provider][options.reason] ?? 0) + 1;
|
|
64025
|
+
writePrivateJson(telemetryDeliveryHealthPath(options), health);
|
|
64026
|
+
}
|
|
64027
|
+
function writePrivateJson(path, value) {
|
|
64028
|
+
try {
|
|
64029
|
+
mkdirSync(dirname(path), {
|
|
64030
|
+
recursive: true,
|
|
64031
|
+
mode: 448
|
|
64032
|
+
});
|
|
64033
|
+
const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;
|
|
64034
|
+
writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, { mode: 384 });
|
|
64035
|
+
renameSync(tmp, path);
|
|
64036
|
+
return true;
|
|
64037
|
+
} catch {
|
|
64038
|
+
return false;
|
|
64039
|
+
}
|
|
64040
|
+
}
|
|
64041
|
+
function readJson(path) {
|
|
64042
|
+
if (!existsSync(path)) return void 0;
|
|
64043
|
+
try {
|
|
64044
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
64045
|
+
} catch {
|
|
64046
|
+
return;
|
|
64047
|
+
}
|
|
64048
|
+
}
|
|
64049
|
+
function stableId() {
|
|
64050
|
+
return `anon_${randomBytes(16).toString("hex")}`;
|
|
64051
|
+
}
|
|
64052
|
+
function ephemeralId() {
|
|
64053
|
+
return `ephemeral_${randomBytes(16).toString("hex")}`;
|
|
64054
|
+
}
|
|
64055
|
+
function isTelemetrySurface(value) {
|
|
64056
|
+
return value === "cli" || value === "serve" || value === "attach" || value === "daemon" || value === "native" || value === "code_mode";
|
|
64057
|
+
}
|
|
64058
|
+
function isDeliveryHealth(value) {
|
|
64059
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
64060
|
+
for (const provider of Object.values(value)) {
|
|
64061
|
+
if (!provider || typeof provider !== "object" || Array.isArray(provider)) return false;
|
|
64062
|
+
for (const count of Object.values(provider)) if (typeof count !== "number" || !Number.isInteger(count) || count < 0) return false;
|
|
64063
|
+
}
|
|
64064
|
+
return true;
|
|
64065
|
+
}
|
|
64066
|
+
//#endregion
|
|
64067
|
+
//#region src/telemetry/context.ts
|
|
64068
|
+
function resolveTelemetryState(options) {
|
|
64069
|
+
const env = options.env ?? process.env;
|
|
64070
|
+
const executionContext = classifyExecutionContext(env);
|
|
64071
|
+
const notice = readTelemetryNotice(options);
|
|
64072
|
+
const base = {
|
|
64073
|
+
surface: options.surface,
|
|
64074
|
+
visibility: options.visibility,
|
|
64075
|
+
executionContext,
|
|
64076
|
+
notice,
|
|
64077
|
+
stateDir: options.stateDir
|
|
64078
|
+
};
|
|
64079
|
+
if (options.debug) return {
|
|
64080
|
+
...base,
|
|
64081
|
+
status: "debug",
|
|
64082
|
+
decider: "debug"
|
|
64083
|
+
};
|
|
64084
|
+
if (env.CAPLETS_DISABLE_TELEMETRY === "1") return {
|
|
64085
|
+
...base,
|
|
64086
|
+
status: "disabled",
|
|
64087
|
+
decider: "env"
|
|
64088
|
+
};
|
|
64089
|
+
if (options.config?.telemetry === false) return {
|
|
64090
|
+
...base,
|
|
64091
|
+
status: "disabled",
|
|
64092
|
+
decider: "config"
|
|
64093
|
+
};
|
|
64094
|
+
if (isTestEnv(env)) return {
|
|
64095
|
+
...base,
|
|
64096
|
+
status: "disabled",
|
|
64097
|
+
decider: "test"
|
|
64098
|
+
};
|
|
64099
|
+
if (executionContext !== "ci" && !notice.shown && !options.allowWithoutNotice) return {
|
|
64100
|
+
...base,
|
|
64101
|
+
status: "suppressed",
|
|
64102
|
+
decider: "notice"
|
|
64103
|
+
};
|
|
64104
|
+
return {
|
|
64105
|
+
...base,
|
|
64106
|
+
status: "enabled",
|
|
64107
|
+
decider: "default",
|
|
64108
|
+
identity: readTelemetryIdentity({
|
|
64109
|
+
...options,
|
|
64110
|
+
create: options.createIdentity !== false
|
|
64111
|
+
})
|
|
64112
|
+
};
|
|
64113
|
+
}
|
|
64114
|
+
function classifyExecutionContext(env = process.env) {
|
|
64115
|
+
if (env.CI === "true" || env.GITHUB_ACTIONS === "true" || env.BUILDKITE === "true") return "ci";
|
|
64116
|
+
return process.stdout.isTTY || process.stderr.isTTY ? "interactive" : "noninteractive";
|
|
64117
|
+
}
|
|
64118
|
+
function isTestEnv(env) {
|
|
64119
|
+
return env.NODE_ENV === "test" || env.VITEST === "true" || env.VITEST_WORKER_ID !== void 0 || env.CAPLETS_TEST === "1";
|
|
64120
|
+
}
|
|
64121
|
+
//#endregion
|
|
64122
|
+
//#region src/telemetry/notice.ts
|
|
64123
|
+
const TELEMETRY_NOTICE = "Caplets collects anonymous telemetry for product usage and reliability. Disable it with CAPLETS_DISABLE_TELEMETRY=1 or `caplets telemetry disable`.\n";
|
|
64124
|
+
function maybePrintTelemetryNotice(options) {
|
|
64125
|
+
if (!options.stderrIsTTY) return false;
|
|
64126
|
+
if (readTelemetryNotice(options).shown) return false;
|
|
64127
|
+
options.writeErr(TELEMETRY_NOTICE);
|
|
64128
|
+
recordTelemetryNoticeShown({
|
|
64129
|
+
...options,
|
|
64130
|
+
surface: options.surface
|
|
64131
|
+
});
|
|
64132
|
+
return true;
|
|
64133
|
+
}
|
|
64134
|
+
//#endregion
|
|
64135
|
+
//#region src/telemetry/privacy.ts
|
|
64136
|
+
const ALLOWED_PROPERTY_KEYS = /* @__PURE__ */ new Set([
|
|
64137
|
+
"$process_person_profile",
|
|
64138
|
+
"$geoip_disable",
|
|
64139
|
+
"package",
|
|
64140
|
+
"version",
|
|
64141
|
+
"surface",
|
|
64142
|
+
"runtime_mode",
|
|
64143
|
+
"execution_context",
|
|
64144
|
+
"command_family",
|
|
64145
|
+
"operation_family",
|
|
64146
|
+
"outcome",
|
|
64147
|
+
"duration_bucket",
|
|
64148
|
+
"timeout_bucket",
|
|
64149
|
+
"integration",
|
|
64150
|
+
"exposure_mode",
|
|
64151
|
+
"backend_mcp_count",
|
|
64152
|
+
"backend_openapi_count",
|
|
64153
|
+
"backend_google_discovery_count",
|
|
64154
|
+
"backend_graphql_count",
|
|
64155
|
+
"backend_http_count",
|
|
64156
|
+
"backend_cli_count",
|
|
64157
|
+
"backend_caplets_count",
|
|
64158
|
+
"direct_count",
|
|
64159
|
+
"progressive_count",
|
|
64160
|
+
"code_mode_count",
|
|
64161
|
+
"session_category",
|
|
64162
|
+
"any_caplet_invoked",
|
|
64163
|
+
"provider",
|
|
64164
|
+
"reason",
|
|
64165
|
+
"count_bucket",
|
|
64166
|
+
"error_code",
|
|
64167
|
+
"diagnostic_category",
|
|
64168
|
+
"os_family",
|
|
64169
|
+
"arch",
|
|
64170
|
+
"node_major"
|
|
64171
|
+
]);
|
|
64172
|
+
const SAFE_STRING = /^[a-zA-Z0-9@._:-]{1,80}$/u;
|
|
64173
|
+
const SAFE_PACKAGE = /^@?[a-zA-Z0-9._-]+(?:\/[a-zA-Z0-9._-]+)?$/u;
|
|
64174
|
+
const SUSPICIOUS_VALUE = [
|
|
64175
|
+
/^\/|^[A-Za-z]:\\/u,
|
|
64176
|
+
/^https?:\/\//iu,
|
|
64177
|
+
/[a-z0-9-]+\.[a-z]{2,}/iu,
|
|
64178
|
+
/(?:^|[_.-])token(?:$|[_.=-])/iu,
|
|
64179
|
+
/(?:^|[_.-])secret(?:$|[_.=-])/iu,
|
|
64180
|
+
/(?:^|[_.-])key(?:$|[_.=-])/iu,
|
|
64181
|
+
/^sk-[a-z0-9]/iu,
|
|
64182
|
+
/^gh[pousr]_[a-z0-9]/iu,
|
|
64183
|
+
/^[A-Z_]{3,}=.+/u
|
|
64184
|
+
];
|
|
64185
|
+
const COMMAND_FAMILIES = /* @__PURE__ */ new Set([
|
|
64186
|
+
"init",
|
|
64187
|
+
"setup",
|
|
64188
|
+
"add",
|
|
64189
|
+
"install",
|
|
64190
|
+
"auth",
|
|
64191
|
+
"remote",
|
|
64192
|
+
"doctor",
|
|
64193
|
+
"serve",
|
|
64194
|
+
"attach",
|
|
64195
|
+
"daemon",
|
|
64196
|
+
"inspect",
|
|
64197
|
+
"check",
|
|
64198
|
+
"tools",
|
|
64199
|
+
"resources",
|
|
64200
|
+
"prompts",
|
|
64201
|
+
"complete",
|
|
64202
|
+
"code_mode",
|
|
64203
|
+
"native",
|
|
64204
|
+
"telemetry",
|
|
64205
|
+
"unknown"
|
|
64206
|
+
]);
|
|
64207
|
+
const STRING_VALUE_ALLOWLISTS = {
|
|
64208
|
+
surface: /* @__PURE__ */ new Set([
|
|
64209
|
+
"cli",
|
|
64210
|
+
"serve",
|
|
64211
|
+
"attach",
|
|
64212
|
+
"daemon",
|
|
64213
|
+
"native",
|
|
64214
|
+
"code_mode"
|
|
64215
|
+
]),
|
|
64216
|
+
runtime_mode: /* @__PURE__ */ new Set([
|
|
64217
|
+
"local",
|
|
64218
|
+
"remote",
|
|
64219
|
+
"cloud",
|
|
64220
|
+
"unknown"
|
|
64221
|
+
]),
|
|
64222
|
+
execution_context: /* @__PURE__ */ new Set([
|
|
64223
|
+
"interactive",
|
|
64224
|
+
"noninteractive",
|
|
64225
|
+
"ci"
|
|
64226
|
+
]),
|
|
64227
|
+
command_family: COMMAND_FAMILIES,
|
|
64228
|
+
operation_family: COMMAND_FAMILIES,
|
|
64229
|
+
outcome: /* @__PURE__ */ new Set([
|
|
64230
|
+
"success",
|
|
64231
|
+
"failure",
|
|
64232
|
+
"cancelled",
|
|
64233
|
+
"timeout",
|
|
64234
|
+
"suppressed"
|
|
64235
|
+
]),
|
|
64236
|
+
duration_bucket: /* @__PURE__ */ new Set([
|
|
64237
|
+
"lt_100ms",
|
|
64238
|
+
"lt_1s",
|
|
64239
|
+
"lt_5s",
|
|
64240
|
+
"lt_30s",
|
|
64241
|
+
"gte_30s"
|
|
64242
|
+
]),
|
|
64243
|
+
timeout_bucket: /* @__PURE__ */ new Set([
|
|
64244
|
+
"none",
|
|
64245
|
+
"lt_1s",
|
|
64246
|
+
"lt_10s",
|
|
64247
|
+
"lt_60s",
|
|
64248
|
+
"gte_60s"
|
|
64249
|
+
]),
|
|
64250
|
+
integration: /* @__PURE__ */ new Set([
|
|
64251
|
+
"opencode",
|
|
64252
|
+
"pi",
|
|
64253
|
+
"native",
|
|
64254
|
+
"unknown"
|
|
64255
|
+
]),
|
|
64256
|
+
exposure_mode: /* @__PURE__ */ new Set([
|
|
64257
|
+
"direct",
|
|
64258
|
+
"progressive",
|
|
64259
|
+
"code_mode",
|
|
64260
|
+
"mixed",
|
|
64261
|
+
"unknown"
|
|
64262
|
+
]),
|
|
64263
|
+
session_category: /* @__PURE__ */ new Set([
|
|
64264
|
+
"created",
|
|
64265
|
+
"reused",
|
|
64266
|
+
"none",
|
|
64267
|
+
"unknown"
|
|
64268
|
+
]),
|
|
64269
|
+
provider: /* @__PURE__ */ new Set(["posthog", "sentry"]),
|
|
64270
|
+
reason: /* @__PURE__ */ new Set(["not_configured", "send_failed"]),
|
|
64271
|
+
diagnostic_category: /* @__PURE__ */ new Set([
|
|
64272
|
+
"config",
|
|
64273
|
+
"auth",
|
|
64274
|
+
"network",
|
|
64275
|
+
"runtime",
|
|
64276
|
+
"validation",
|
|
64277
|
+
"code_mode",
|
|
64278
|
+
"provider",
|
|
64279
|
+
"unknown"
|
|
64280
|
+
])
|
|
64281
|
+
};
|
|
64282
|
+
function assertTelemetrySafeProperties(properties) {
|
|
64283
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
64284
|
+
if (!ALLOWED_PROPERTY_KEYS.has(key)) throw new Error(`unknown telemetry property: ${key}`);
|
|
64285
|
+
if (typeof value === "string") {
|
|
64286
|
+
const valueAllowlist = STRING_VALUE_ALLOWLISTS[key];
|
|
64287
|
+
if (valueAllowlist && !valueAllowlist.has(value)) throw new Error(`unsafe telemetry property ${key}`);
|
|
64288
|
+
if (key === "error_code" && !/^[A-Z_]{2,80}$/u.test(value)) throw new Error(`unsafe telemetry property ${key}`);
|
|
64289
|
+
if (!(key === "package" ? SAFE_PACKAGE.test(value) : SAFE_STRING.test(value)) || key !== "package" && key !== "version" && SUSPICIOUS_VALUE.some((pattern) => pattern.test(value))) throw new Error(`unsafe telemetry property ${key}`);
|
|
64290
|
+
continue;
|
|
64291
|
+
}
|
|
64292
|
+
if (typeof value === "number") {
|
|
64293
|
+
if (!Number.isFinite(value) || value < 0 || !Number.isInteger(value)) throw new Error(`unsafe telemetry property ${key}`);
|
|
64294
|
+
continue;
|
|
64295
|
+
}
|
|
64296
|
+
if (typeof value === "boolean") continue;
|
|
64297
|
+
throw new Error(`unsafe telemetry property ${key}`);
|
|
64298
|
+
}
|
|
64299
|
+
}
|
|
64300
|
+
function stripSentryEvent(event) {
|
|
64301
|
+
const stripped = {};
|
|
64302
|
+
if (event.tags && typeof event.tags === "object" && !Array.isArray(event.tags)) stripped.tags = event.tags;
|
|
64303
|
+
if (Array.isArray(event.fingerprint)) stripped.fingerprint = event.fingerprint;
|
|
64304
|
+
if (event.level) stripped.level = event.level;
|
|
64305
|
+
return stripped;
|
|
64306
|
+
}
|
|
64307
|
+
//#endregion
|
|
64308
|
+
//#region src/telemetry/events.ts
|
|
64309
|
+
const PRODUCT_EVENTS = /* @__PURE__ */ new Set([
|
|
64310
|
+
"caplets_cli_command",
|
|
64311
|
+
"caplets_tool_activation",
|
|
64312
|
+
"caplets_code_mode_outcome"
|
|
64313
|
+
]);
|
|
64314
|
+
const RELIABILITY_EVENTS = /* @__PURE__ */ new Set(["caplets_reliability_error"]);
|
|
64315
|
+
function buildProductTelemetryEvent(input) {
|
|
64316
|
+
if (!PRODUCT_EVENTS.has(input.name)) throw new Error(`unknown telemetry event: ${input.name}`);
|
|
64317
|
+
assertTelemetrySafeProperties(input.properties);
|
|
64318
|
+
return {
|
|
64319
|
+
provider: "posthog",
|
|
64320
|
+
name: input.name,
|
|
64321
|
+
distinctId: input.distinctId,
|
|
64322
|
+
properties: {
|
|
64323
|
+
...input.properties,
|
|
64324
|
+
$process_person_profile: false
|
|
64325
|
+
}
|
|
64326
|
+
};
|
|
64327
|
+
}
|
|
64328
|
+
function buildReliabilityTelemetryEvent(input) {
|
|
64329
|
+
if (!RELIABILITY_EVENTS.has(input.name)) throw new Error(`unknown telemetry event: ${input.name}`);
|
|
64330
|
+
assertTelemetrySafeProperties(input.properties);
|
|
64331
|
+
const tags = tagsFor(input.properties);
|
|
64332
|
+
return {
|
|
64333
|
+
provider: "sentry",
|
|
64334
|
+
name: input.name,
|
|
64335
|
+
tags,
|
|
64336
|
+
fingerprint: [
|
|
64337
|
+
tags.package ?? "unknown",
|
|
64338
|
+
tags.surface ?? "unknown",
|
|
64339
|
+
tags.command_family ?? "unknown",
|
|
64340
|
+
tags.runtime_mode ?? "unknown",
|
|
64341
|
+
tags.error_code ?? "unknown",
|
|
64342
|
+
tags.diagnostic_category ?? "unknown"
|
|
64343
|
+
]
|
|
64344
|
+
};
|
|
64345
|
+
}
|
|
64346
|
+
function durationBucket(ms) {
|
|
64347
|
+
if (ms < 100) return "lt_100ms";
|
|
64348
|
+
if (ms < 1e3) return "lt_1s";
|
|
64349
|
+
if (ms < 5e3) return "lt_5s";
|
|
64350
|
+
if (ms < 3e4) return "lt_30s";
|
|
64351
|
+
return "gte_30s";
|
|
64352
|
+
}
|
|
64353
|
+
function timeoutBucket(ms) {
|
|
64354
|
+
if (ms === void 0) return "none";
|
|
64355
|
+
if (ms < 1e3) return "lt_1s";
|
|
64356
|
+
if (ms < 1e4) return "lt_10s";
|
|
64357
|
+
if (ms < 6e4) return "lt_60s";
|
|
64358
|
+
return "gte_60s";
|
|
64359
|
+
}
|
|
64360
|
+
function tagsFor(properties) {
|
|
64361
|
+
return Object.fromEntries(Object.entries(properties).map(([key, value]) => [key, String(value)]));
|
|
64362
|
+
}
|
|
64363
|
+
//#endregion
|
|
64364
|
+
//#region src/telemetry/debug.ts
|
|
64365
|
+
var TelemetryDebugSink = class {
|
|
64366
|
+
records = [];
|
|
64367
|
+
capture(state, event) {
|
|
64368
|
+
this.records.push({
|
|
64369
|
+
state,
|
|
64370
|
+
event
|
|
64371
|
+
});
|
|
64372
|
+
}
|
|
64373
|
+
toJSON() {
|
|
64374
|
+
return this.records;
|
|
64375
|
+
}
|
|
64376
|
+
};
|
|
64377
|
+
//#endregion
|
|
64378
|
+
//#region src/telemetry/providers.ts
|
|
64379
|
+
function createTelemetryDispatcher(options = {}) {
|
|
64380
|
+
let posthog;
|
|
64381
|
+
let sentry;
|
|
64382
|
+
async function posthogClient() {
|
|
64383
|
+
const token = options.posthogToken ?? process.env.CAPLETS_POSTHOG_TOKEN ?? "phc_pUZ2ZCRtFkC5qCGDNYcoYEhxxjTaooH57Cj4PTRXovyB";
|
|
64384
|
+
if (!token) return void 0;
|
|
64385
|
+
posthog ??= Promise.resolve((options.factories?.createPostHog ?? defaultPostHogFactory)(token));
|
|
64386
|
+
return posthog;
|
|
64387
|
+
}
|
|
64388
|
+
async function sentryClient() {
|
|
64389
|
+
const dsn = options.sentryDsn ?? process.env.CAPLETS_SENTRY_DSN ?? "https://c66cfd76aad69209bcf44be4cd79f9b5@o4508042228006912.ingest.us.sentry.io/4511620382392320";
|
|
64390
|
+
if (!dsn) return void 0;
|
|
64391
|
+
sentry ??= Promise.resolve((options.factories?.createSentry ?? defaultSentryFactory)(dsn));
|
|
64392
|
+
return sentry;
|
|
64393
|
+
}
|
|
64394
|
+
return {
|
|
64395
|
+
async capture(state, event) {
|
|
64396
|
+
if (state.status !== "enabled") return;
|
|
64397
|
+
try {
|
|
64398
|
+
if (event.provider === "posthog") {
|
|
64399
|
+
await capturePostHog(await posthogClient(), event, state.stateDir ?? options.stateDir);
|
|
64400
|
+
return;
|
|
64401
|
+
}
|
|
64402
|
+
await captureSentry(await sentryClient(), event, state.stateDir ?? options.stateDir);
|
|
64403
|
+
} catch {
|
|
64404
|
+
recordTelemetryDrop({
|
|
64405
|
+
stateDir: state.stateDir ?? options.stateDir,
|
|
64406
|
+
provider: event.provider,
|
|
64407
|
+
reason: "send_failed"
|
|
64408
|
+
});
|
|
64409
|
+
}
|
|
64410
|
+
},
|
|
64411
|
+
async shutdown() {
|
|
64412
|
+
const clients = await Promise.allSettled([posthog, sentry]);
|
|
64413
|
+
for (const client of clients) {
|
|
64414
|
+
if (client.status !== "fulfilled" || !client.value) continue;
|
|
64415
|
+
if ("shutdown" in client.value) await Promise.resolve(client.value.shutdown()).catch(() => void 0);
|
|
64416
|
+
if ("flush" in client.value) await Promise.resolve(client.value.flush(2e3)).catch(() => void 0);
|
|
64417
|
+
}
|
|
64418
|
+
}
|
|
64419
|
+
};
|
|
64420
|
+
}
|
|
64421
|
+
async function capturePostHog(client, event, stateDir) {
|
|
64422
|
+
if (!client) {
|
|
64423
|
+
recordTelemetryDrop({
|
|
64424
|
+
stateDir,
|
|
64425
|
+
provider: "posthog",
|
|
64426
|
+
reason: "not_configured"
|
|
64427
|
+
});
|
|
64428
|
+
return;
|
|
64429
|
+
}
|
|
64430
|
+
client.capture({
|
|
64431
|
+
distinctId: event.distinctId,
|
|
64432
|
+
event: event.name,
|
|
64433
|
+
properties: {
|
|
64434
|
+
...event.properties,
|
|
64435
|
+
$geoip_disable: true
|
|
64436
|
+
}
|
|
64437
|
+
});
|
|
64438
|
+
}
|
|
64439
|
+
async function captureSentry(client, event, stateDir) {
|
|
64440
|
+
if (!client) {
|
|
64441
|
+
recordTelemetryDrop({
|
|
64442
|
+
stateDir,
|
|
64443
|
+
provider: "sentry",
|
|
64444
|
+
reason: "not_configured"
|
|
64445
|
+
});
|
|
64446
|
+
return;
|
|
64447
|
+
}
|
|
64448
|
+
client.captureEvent({
|
|
64449
|
+
level: "error",
|
|
64450
|
+
tags: event.tags,
|
|
64451
|
+
fingerprint: event.fingerprint
|
|
64452
|
+
});
|
|
64453
|
+
}
|
|
64454
|
+
async function defaultPostHogFactory(token) {
|
|
64455
|
+
const { PostHog } = await import("./node-BgWIvSVP.js");
|
|
64456
|
+
return new PostHog(token, {
|
|
64457
|
+
flushAt: 20,
|
|
64458
|
+
flushInterval: 1e4,
|
|
64459
|
+
disableGeoip: true,
|
|
64460
|
+
historicalMigration: false
|
|
64461
|
+
});
|
|
64462
|
+
}
|
|
64463
|
+
async function defaultSentryFactory(dsn) {
|
|
64464
|
+
const sentry = await import("./esm-Db9dhnIG.js");
|
|
64465
|
+
const options = {
|
|
64466
|
+
dsn,
|
|
64467
|
+
sendDefaultPii: false,
|
|
64468
|
+
defaultIntegrations: false,
|
|
64469
|
+
integrations: [],
|
|
64470
|
+
tracesSampleRate: 0,
|
|
64471
|
+
transport: sentry.makeNodeTransport,
|
|
64472
|
+
stackParser: sentry.defaultStackParser,
|
|
64473
|
+
beforeSend(event) {
|
|
64474
|
+
return stripSentryEvent(event);
|
|
64475
|
+
}
|
|
64476
|
+
};
|
|
64477
|
+
return new sentry.NodeClient(options);
|
|
64478
|
+
}
|
|
64479
|
+
//#endregion
|
|
64480
|
+
//#region package.json
|
|
64481
|
+
var version = "0.28.1";
|
|
64482
|
+
//#endregion
|
|
64483
|
+
//#region src/telemetry/runtime.ts
|
|
64484
|
+
function createRuntimeTelemetryContext(options) {
|
|
64485
|
+
return {
|
|
64486
|
+
...options,
|
|
64487
|
+
dispatcher: options.dispatcher ?? createTelemetryDispatcher({ stateDir: options.stateDir })
|
|
64488
|
+
};
|
|
64489
|
+
}
|
|
64490
|
+
async function captureRuntimeTelemetryEvent(context, name, properties) {
|
|
64491
|
+
const state = resolveTelemetryState({
|
|
64492
|
+
config: context.config,
|
|
64493
|
+
env: context.env,
|
|
64494
|
+
stateDir: context.stateDir,
|
|
64495
|
+
surface: context.surface,
|
|
64496
|
+
visibility: context.visibility,
|
|
64497
|
+
debug: context.debugSink !== void 0
|
|
64498
|
+
});
|
|
64499
|
+
if (state.status !== "enabled" && state.status !== "debug") return;
|
|
64500
|
+
const event = buildProductTelemetryEvent({
|
|
64501
|
+
name,
|
|
64502
|
+
distinctId: (state.identity ?? readTelemetryIdentity({
|
|
64503
|
+
stateDir: context.stateDir,
|
|
64504
|
+
create: false
|
|
64505
|
+
})).id,
|
|
64506
|
+
properties: {
|
|
64507
|
+
package: "@caplets/core",
|
|
64508
|
+
version,
|
|
64509
|
+
surface: context.surface,
|
|
64510
|
+
runtime_mode: context.runtimeMode ?? "unknown",
|
|
64511
|
+
execution_context: state.executionContext,
|
|
64512
|
+
...context.integration ? { integration: context.integration } : {},
|
|
64513
|
+
...properties
|
|
64514
|
+
}
|
|
64515
|
+
});
|
|
64516
|
+
if (state.status === "debug") {
|
|
64517
|
+
context.debugSink?.capture("debug", event);
|
|
64518
|
+
return;
|
|
64519
|
+
}
|
|
64520
|
+
await context.dispatcher.capture(state, event);
|
|
64521
|
+
}
|
|
64522
|
+
async function captureRuntimeReliabilityEvent(context, properties) {
|
|
64523
|
+
const state = resolveTelemetryState({
|
|
64524
|
+
config: context.config,
|
|
64525
|
+
env: context.env,
|
|
64526
|
+
stateDir: context.stateDir,
|
|
64527
|
+
surface: context.surface,
|
|
64528
|
+
visibility: context.visibility,
|
|
64529
|
+
debug: context.debugSink !== void 0
|
|
64530
|
+
});
|
|
64531
|
+
if (state.status !== "enabled" && state.status !== "debug") return;
|
|
64532
|
+
const event = buildReliabilityTelemetryEvent({
|
|
64533
|
+
name: "caplets_reliability_error",
|
|
64534
|
+
properties: {
|
|
64535
|
+
package: "@caplets/core",
|
|
64536
|
+
version,
|
|
64537
|
+
surface: context.surface,
|
|
64538
|
+
runtime_mode: context.runtimeMode ?? "unknown",
|
|
64539
|
+
execution_context: state.executionContext,
|
|
64540
|
+
...context.integration ? { integration: context.integration } : {},
|
|
64541
|
+
os_family: platform(),
|
|
64542
|
+
arch: arch(),
|
|
64543
|
+
node_major: Number(process.versions.node.split(".")[0] ?? 0),
|
|
64544
|
+
...properties
|
|
64545
|
+
}
|
|
64546
|
+
});
|
|
64547
|
+
if (state.status === "debug") {
|
|
64548
|
+
context.debugSink?.capture("debug", event);
|
|
64549
|
+
return;
|
|
64550
|
+
}
|
|
64551
|
+
await context.dispatcher.capture(state, event);
|
|
64552
|
+
}
|
|
64553
|
+
function backendFamilyCounts(config) {
|
|
64554
|
+
return {
|
|
64555
|
+
backend_mcp_count: enabledCount(config.mcpServers),
|
|
64556
|
+
backend_openapi_count: enabledCount(config.openapiEndpoints),
|
|
64557
|
+
backend_google_discovery_count: enabledCount(config.googleDiscoveryApis),
|
|
64558
|
+
backend_graphql_count: enabledCount(config.graphqlEndpoints),
|
|
64559
|
+
backend_http_count: enabledCount(config.httpApis),
|
|
64560
|
+
backend_cli_count: enabledCount(config.cliTools),
|
|
64561
|
+
backend_caplets_count: enabledCount(config.capletSets)
|
|
64562
|
+
};
|
|
64563
|
+
}
|
|
64564
|
+
function exposureModeCounts(config) {
|
|
64565
|
+
let direct = 0;
|
|
64566
|
+
let progressive = 0;
|
|
64567
|
+
let codeMode = 0;
|
|
64568
|
+
for (const caplet of allCaplets$1(config)) {
|
|
64569
|
+
if (caplet.disabled || caplet.setup || caplet.projectBinding?.required) continue;
|
|
64570
|
+
const exposure = resolveExposure(caplet.exposure, config.options.exposure);
|
|
64571
|
+
if (exposure.direct) direct += 1;
|
|
64572
|
+
if (exposure.progressive) progressive += 1;
|
|
64573
|
+
if (exposure.codeMode) codeMode += 1;
|
|
64574
|
+
}
|
|
64575
|
+
return {
|
|
64576
|
+
direct_count: direct,
|
|
64577
|
+
progressive_count: progressive,
|
|
64578
|
+
code_mode_count: codeMode
|
|
64579
|
+
};
|
|
64580
|
+
}
|
|
64581
|
+
function operationFamilyFromOperation(operation) {
|
|
64582
|
+
if (operation === "inspect") return "inspect";
|
|
64583
|
+
if (operation === "check") return "check";
|
|
64584
|
+
if (operation === "tools" || operation === "search_tools" || operation === "get_tool" || operation === "describe_tool" || operation === "call_tool") return "tools";
|
|
64585
|
+
if (operation === "resources" || operation === "resource_templates" || operation === "read_resource" || operation === "search_resources" || operation === "list_resources" || operation === "list_resource_templates" || operation === "search_resource_templates") return "resources";
|
|
64586
|
+
if (operation === "prompts" || operation === "get_prompt" || operation === "list_prompts" || operation === "search_prompts") return "prompts";
|
|
64587
|
+
if (operation === "complete") return "complete";
|
|
64588
|
+
if (operation === "code_mode") return "code_mode";
|
|
64589
|
+
return "unknown";
|
|
64590
|
+
}
|
|
64591
|
+
function outcomeFromResult(result) {
|
|
64592
|
+
if (isRecord$6(result) && result.isError === true) {
|
|
64593
|
+
if (errorCodeFromResult$1(result).toLowerCase().includes("timeout")) return "timeout";
|
|
64594
|
+
return "failure";
|
|
64595
|
+
}
|
|
64596
|
+
if (isRecord$6(result) && result.ok === false) {
|
|
64597
|
+
const code = errorCodeFromResult$1(result);
|
|
64598
|
+
if (typeof code === "string" && code.toLowerCase().includes("timeout")) return "timeout";
|
|
64599
|
+
return "failure";
|
|
64600
|
+
}
|
|
64601
|
+
return "success";
|
|
64602
|
+
}
|
|
64603
|
+
function codeModeTelemetryProperties(envelope, durationMs, timeoutMs) {
|
|
64604
|
+
const record = isRecord$6(envelope) ? envelope : {};
|
|
64605
|
+
const meta = isRecord$6(record.meta) ? record.meta : {};
|
|
64606
|
+
const sessionStatus = meta.sessionStatus;
|
|
64607
|
+
const effectiveTimeoutMs = timeoutMs ?? (typeof meta.timeoutMs === "number" ? meta.timeoutMs : void 0);
|
|
64608
|
+
return {
|
|
64609
|
+
command_family: "code_mode",
|
|
64610
|
+
outcome: outcomeFromResult(record),
|
|
64611
|
+
duration_bucket: durationBucket(durationMs),
|
|
64612
|
+
timeout_bucket: timeoutBucket(effectiveTimeoutMs),
|
|
64613
|
+
session_category: sessionStatus === "created" || sessionStatus === "reused" ? sessionStatus : sessionStatus === null ? "none" : "unknown",
|
|
64614
|
+
any_caplet_invoked: codeModeEnvelopeInvokedCaplet(record)
|
|
64615
|
+
};
|
|
64616
|
+
}
|
|
64617
|
+
function toolActivationProperties(input) {
|
|
64618
|
+
return {
|
|
64619
|
+
operation_family: operationFamilyFromOperation(input.operation),
|
|
64620
|
+
exposure_mode: input.exposureMode,
|
|
64621
|
+
outcome: outcomeFromResult(input.result),
|
|
64622
|
+
duration_bucket: durationBucket(input.durationMs),
|
|
64623
|
+
...backendFamilyCounts(input.config),
|
|
64624
|
+
...exposureModeCounts(input.config)
|
|
64625
|
+
};
|
|
64626
|
+
}
|
|
64627
|
+
function enabledCount(record) {
|
|
64628
|
+
return Object.values(record).filter((caplet) => !caplet.disabled).length;
|
|
64629
|
+
}
|
|
64630
|
+
function allCaplets$1(config) {
|
|
64631
|
+
return [
|
|
64632
|
+
...Object.values(config.mcpServers),
|
|
64633
|
+
...Object.values(config.openapiEndpoints),
|
|
64634
|
+
...Object.values(config.googleDiscoveryApis),
|
|
64635
|
+
...Object.values(config.graphqlEndpoints),
|
|
64636
|
+
...Object.values(config.httpApis),
|
|
64637
|
+
...Object.values(config.cliTools),
|
|
64638
|
+
...Object.values(config.capletSets)
|
|
64639
|
+
];
|
|
64640
|
+
}
|
|
64641
|
+
function isRecord$6(value) {
|
|
64642
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
64643
|
+
}
|
|
64644
|
+
function runtimeFailureTelemetryProperties(input) {
|
|
64645
|
+
const errorCode = errorCodeFromResult$1(input.result);
|
|
64646
|
+
return {
|
|
64647
|
+
operation_family: operationFamilyFromOperation(input.operation),
|
|
64648
|
+
exposure_mode: input.exposureMode,
|
|
64649
|
+
error_code: errorCode,
|
|
64650
|
+
diagnostic_category: diagnosticCategoryFromCode(errorCode)
|
|
64651
|
+
};
|
|
64652
|
+
}
|
|
64653
|
+
function errorCodeFromResult$1(result) {
|
|
64654
|
+
if (!isRecord$6(result)) return "UNKNOWN";
|
|
64655
|
+
const error = isRecord$6(result.error) ? result.error : isRecord$6(result.structuredContent) && isRecord$6(result.structuredContent.error) ? result.structuredContent.error : void 0;
|
|
64656
|
+
if (isRecord$6(error) && typeof error.code === "string") return error.code;
|
|
64657
|
+
return "UNKNOWN";
|
|
64658
|
+
}
|
|
64659
|
+
function diagnosticCategoryFromCode(code) {
|
|
64660
|
+
if (code.startsWith("CONFIG")) return "config";
|
|
64661
|
+
if (code.startsWith("AUTH")) return "auth";
|
|
64662
|
+
if (code.includes("NETWORK") || code.includes("UNAVAILABLE")) return "network";
|
|
64663
|
+
if (code.includes("VALID") || code.includes("REQUEST")) return "validation";
|
|
64664
|
+
if (code.includes("CODE_MODE") || code.includes("SANDBOX")) return "code_mode";
|
|
64665
|
+
return "runtime";
|
|
64666
|
+
}
|
|
64667
|
+
function codeModeEnvelopeInvokedCaplet(record) {
|
|
64668
|
+
const meta = isRecord$6(record.meta) ? record.meta : void 0;
|
|
64669
|
+
return hasBooleanTrue(meta, "anyCapletInvoked") || hasBooleanTrue(meta, "capletInvoked") || hasPositiveNumber(meta, "capletInvocationCount") || hasPositiveNumber(meta, "toolCallCount");
|
|
64670
|
+
}
|
|
64671
|
+
function hasBooleanTrue(record, key) {
|
|
64672
|
+
return record?.[key] === true;
|
|
64673
|
+
}
|
|
64674
|
+
function hasPositiveNumber(record, key) {
|
|
64675
|
+
const value = record?.[key];
|
|
64676
|
+
return typeof value === "number" && value > 0;
|
|
64677
|
+
}
|
|
64678
|
+
//#endregion
|
|
63948
64679
|
//#region src/engine.ts
|
|
63949
64680
|
var CapletsEngine = class {
|
|
63950
64681
|
registry;
|
|
@@ -63963,6 +64694,8 @@ var CapletsEngine = class {
|
|
|
63963
64694
|
observedOutputShapeStore;
|
|
63964
64695
|
observedOutputShapeScope;
|
|
63965
64696
|
projectFingerprint;
|
|
64697
|
+
telemetry;
|
|
64698
|
+
telemetryExecuteExposureMode;
|
|
63966
64699
|
reloadListeners = /* @__PURE__ */ new Set();
|
|
63967
64700
|
lastExposureSnapshot;
|
|
63968
64701
|
watchers = [];
|
|
@@ -63980,6 +64713,18 @@ var CapletsEngine = class {
|
|
|
63980
64713
|
this.configLoader = options.configLoader ?? runtimeConfigLoader(options.authDir, options.vaultRecoveryTarget);
|
|
63981
64714
|
const config = this.loadConfigWithWarnings();
|
|
63982
64715
|
this.registry = new ServerRegistry(config);
|
|
64716
|
+
this.telemetry = createRuntimeTelemetryContext({
|
|
64717
|
+
config: this.registry.config,
|
|
64718
|
+
env: options.telemetryEnv,
|
|
64719
|
+
stateDir: options.telemetryStateDir,
|
|
64720
|
+
surface: options.telemetrySurface ?? "serve",
|
|
64721
|
+
visibility: options.telemetryVisibility ?? "unknown",
|
|
64722
|
+
runtimeMode: options.telemetryRuntimeMode ?? runtimeModeFromEnv(options.telemetryEnv),
|
|
64723
|
+
integration: options.telemetryIntegration,
|
|
64724
|
+
debugSink: options.telemetryDebugSink,
|
|
64725
|
+
dispatcher: options.telemetryDispatcher
|
|
64726
|
+
});
|
|
64727
|
+
this.telemetryExecuteExposureMode = options.telemetrySurface === "code_mode" ? "code_mode" : "progressive";
|
|
63983
64728
|
this.downstream = new DownstreamManager(this.registry, selectAuthOptions(options.authDir));
|
|
63984
64729
|
this.openapi = new OpenApiManager(this.registry, selectHttpLikeOptions(options));
|
|
63985
64730
|
this.googleDiscovery = new GoogleDiscoveryManager(this.registry, selectHttpLikeOptions(options));
|
|
@@ -64044,44 +64789,73 @@ var CapletsEngine = class {
|
|
|
64044
64789
|
return await this.reloading;
|
|
64045
64790
|
}
|
|
64046
64791
|
async execute(serverId, request) {
|
|
64792
|
+
const started = Date.now();
|
|
64793
|
+
let caplet;
|
|
64047
64794
|
try {
|
|
64048
|
-
|
|
64795
|
+
caplet = this.registry.require(serverId);
|
|
64796
|
+
const result = await handleServerTool(caplet, request, this.registry, this.downstream, this.openapi, this.graphql, this.http, this.cli, this.capletSets, {
|
|
64049
64797
|
observedOutputShapeStore: this.observedOutputShapeStore,
|
|
64050
64798
|
observedOutputShapeScope: this.observedOutputShapeScope,
|
|
64051
64799
|
projectFingerprint: this.projectFingerprint
|
|
64052
64800
|
}, this.googleDiscovery);
|
|
64801
|
+
this.captureToolActivation(caplet, operationFromRequest(request), this.telemetryExecuteExposureMode, result, started);
|
|
64802
|
+
return result;
|
|
64053
64803
|
} catch (error) {
|
|
64054
|
-
|
|
64804
|
+
const result = errorResult(error);
|
|
64805
|
+
this.captureReliabilityError(operationFromRequest(request), this.telemetryExecuteExposureMode, result);
|
|
64806
|
+
this.captureToolActivation(caplet, operationFromRequest(request), this.telemetryExecuteExposureMode, result, started);
|
|
64807
|
+
return result;
|
|
64055
64808
|
}
|
|
64056
64809
|
}
|
|
64057
64810
|
async executeDirectTool(serverId, toolName, args) {
|
|
64811
|
+
const started = Date.now();
|
|
64812
|
+
let caplet;
|
|
64058
64813
|
try {
|
|
64059
|
-
|
|
64060
|
-
|
|
64814
|
+
caplet = this.registry.require(serverId);
|
|
64815
|
+
const annotated = annotateDirectResult(await this.callTool(caplet, toolName, args), caplet, toolName);
|
|
64816
|
+
this.captureToolActivation(caplet, "call_tool", "direct", annotated, started);
|
|
64817
|
+
return annotated;
|
|
64061
64818
|
} catch (error) {
|
|
64062
|
-
|
|
64819
|
+
const result = errorResult(error);
|
|
64820
|
+
this.captureReliabilityError("call_tool", "direct", result);
|
|
64821
|
+
this.captureToolActivation(caplet, "call_tool", "direct", result, started);
|
|
64822
|
+
return result;
|
|
64063
64823
|
}
|
|
64064
64824
|
}
|
|
64065
64825
|
async readDirectResource(serverId, downstreamUri) {
|
|
64826
|
+
const started = Date.now();
|
|
64827
|
+
let caplet;
|
|
64066
64828
|
try {
|
|
64067
|
-
|
|
64829
|
+
caplet = this.registry.require(serverId);
|
|
64068
64830
|
if (caplet.backend !== "mcp") throw new Error(`Caplet ${serverId} has no MCP resources`);
|
|
64069
|
-
|
|
64831
|
+
const annotated = annotateDirectResult(await this.downstream.readResource(caplet, downstreamUri), caplet, "read_resource");
|
|
64832
|
+
this.captureToolActivation(caplet, "read_resource", "direct", annotated, started);
|
|
64833
|
+
return annotated;
|
|
64070
64834
|
} catch (error) {
|
|
64071
|
-
|
|
64835
|
+
const result = errorResult(error);
|
|
64836
|
+
this.captureReliabilityError("read_resource", "direct", result);
|
|
64837
|
+
this.captureToolActivation(caplet, "read_resource", "direct", result, started);
|
|
64838
|
+
return result;
|
|
64072
64839
|
}
|
|
64073
64840
|
}
|
|
64074
64841
|
async getDirectPrompt(serverId, promptName, args) {
|
|
64842
|
+
const started = Date.now();
|
|
64843
|
+
let caplet;
|
|
64075
64844
|
try {
|
|
64076
|
-
|
|
64845
|
+
caplet = this.registry.require(serverId);
|
|
64077
64846
|
if (caplet.backend !== "mcp") throw new Error(`Caplet ${serverId} has no MCP prompts`);
|
|
64078
|
-
|
|
64847
|
+
const annotated = annotateDirectResult(await this.downstream.getPrompt(caplet, promptName, args), caplet, promptName);
|
|
64848
|
+
this.captureToolActivation(caplet, "get_prompt", "direct", annotated, started);
|
|
64849
|
+
return annotated;
|
|
64079
64850
|
} catch (error) {
|
|
64080
|
-
|
|
64851
|
+
const result = errorResult(error);
|
|
64852
|
+
this.captureReliabilityError("get_prompt", "direct", result);
|
|
64853
|
+
this.captureToolActivation(caplet, "get_prompt", "direct", result, started);
|
|
64854
|
+
return result;
|
|
64081
64855
|
}
|
|
64082
64856
|
}
|
|
64083
64857
|
async completeCliWords(words) {
|
|
64084
|
-
const { completeCliWords } = await import("./completion-
|
|
64858
|
+
const { completeCliWords } = await import("./completion-D9253pYs.js").then((n) => n.r);
|
|
64085
64859
|
return await completeCliWords(words, {
|
|
64086
64860
|
config: this.registry.config,
|
|
64087
64861
|
managers: {
|
|
@@ -64112,6 +64886,9 @@ var CapletsEngine = class {
|
|
|
64112
64886
|
}
|
|
64113
64887
|
});
|
|
64114
64888
|
}
|
|
64889
|
+
async captureCodeModeOutcome(envelope, options) {
|
|
64890
|
+
await captureRuntimeTelemetryEvent(this.telemetry, "caplets_code_mode_outcome", codeModeTelemetryProperties(envelope, Date.now() - options.started, options.timeoutMs));
|
|
64891
|
+
}
|
|
64115
64892
|
async close() {
|
|
64116
64893
|
this.closed = true;
|
|
64117
64894
|
try {
|
|
@@ -64128,6 +64905,7 @@ var CapletsEngine = class {
|
|
|
64128
64905
|
this.closeWatchers();
|
|
64129
64906
|
await this.downstream.close();
|
|
64130
64907
|
await this.capletSets.close();
|
|
64908
|
+
await this.telemetry.dispatcher.shutdown();
|
|
64131
64909
|
this.reloadListeners.clear();
|
|
64132
64910
|
}
|
|
64133
64911
|
}
|
|
@@ -64165,6 +64943,7 @@ var CapletsEngine = class {
|
|
|
64165
64943
|
const previousConfig = this.registry.config;
|
|
64166
64944
|
const nextRegistry = new ServerRegistry(nextConfig);
|
|
64167
64945
|
this.registry = nextRegistry;
|
|
64946
|
+
this.telemetry.config = nextConfig;
|
|
64168
64947
|
this.downstream.updateRegistry(nextRegistry);
|
|
64169
64948
|
this.openapi.updateRegistry(nextRegistry);
|
|
64170
64949
|
this.googleDiscovery.updateRegistry(nextRegistry);
|
|
@@ -64282,6 +65061,29 @@ var CapletsEngine = class {
|
|
|
64282
65061
|
if (!this.closed) this.resetWatchers();
|
|
64283
65062
|
}, this.watchDebounceMs);
|
|
64284
65063
|
}
|
|
65064
|
+
captureReliabilityError(operation, exposureMode, result) {
|
|
65065
|
+
captureRuntimeReliabilityEvent(this.telemetry, {
|
|
65066
|
+
command_family: commandFamilyForTelemetrySurface(this.telemetry.surface),
|
|
65067
|
+
...runtimeFailureTelemetryProperties({
|
|
65068
|
+
operation,
|
|
65069
|
+
exposureMode,
|
|
65070
|
+
result
|
|
65071
|
+
})
|
|
65072
|
+
}).catch(() => void 0);
|
|
65073
|
+
}
|
|
65074
|
+
captureToolActivation(caplet, operation, exposureMode, result, started) {
|
|
65075
|
+
captureRuntimeTelemetryEvent(this.telemetry, "caplets_tool_activation", {
|
|
65076
|
+
command_family: commandFamilyForTelemetrySurface(this.telemetry.surface),
|
|
65077
|
+
...toolActivationProperties({
|
|
65078
|
+
config: this.registry.config,
|
|
65079
|
+
caplet,
|
|
65080
|
+
operation,
|
|
65081
|
+
exposureMode,
|
|
65082
|
+
result,
|
|
65083
|
+
durationMs: Date.now() - started
|
|
65084
|
+
})
|
|
65085
|
+
}).catch(() => void 0);
|
|
65086
|
+
}
|
|
64285
65087
|
};
|
|
64286
65088
|
function runtimeConfigLoader(authDir, vaultRecoveryTarget) {
|
|
64287
65089
|
const vaultResolver = vaultResolverForAuthDir(authDir);
|
|
@@ -64384,7 +65186,7 @@ function annotateDirectResult(result, caplet, operation) {
|
|
|
64384
65186
|
return {
|
|
64385
65187
|
...result,
|
|
64386
65188
|
_meta: {
|
|
64387
|
-
...isRecord$
|
|
65189
|
+
...isRecord$5(existingMeta) ? existingMeta : {},
|
|
64388
65190
|
caplets: {
|
|
64389
65191
|
capletId: caplet.server,
|
|
64390
65192
|
backend: caplet.backend,
|
|
@@ -64397,9 +65199,25 @@ function annotateDirectResult(result, caplet, operation) {
|
|
|
64397
65199
|
function isUnsupportedCapability(error) {
|
|
64398
65200
|
return error instanceof CapletsError && error.code === "UNSUPPORTED_CAPABILITY";
|
|
64399
65201
|
}
|
|
64400
|
-
function isRecord$
|
|
65202
|
+
function isRecord$5(value) {
|
|
64401
65203
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
64402
65204
|
}
|
|
65205
|
+
function operationFromRequest(request) {
|
|
65206
|
+
return isRecord$5(request) ? request.operation : void 0;
|
|
65207
|
+
}
|
|
65208
|
+
function runtimeModeFromEnv(env) {
|
|
65209
|
+
const mode = env?.CAPLETS_MODE ?? process.env.CAPLETS_MODE;
|
|
65210
|
+
if (mode === "local" || mode === "remote" || mode === "cloud") return mode;
|
|
65211
|
+
return "unknown";
|
|
65212
|
+
}
|
|
65213
|
+
function commandFamilyForTelemetrySurface(surface) {
|
|
65214
|
+
if (surface === "serve") return "serve";
|
|
65215
|
+
if (surface === "attach") return "attach";
|
|
65216
|
+
if (surface === "daemon") return "daemon";
|
|
65217
|
+
if (surface === "code_mode") return "code_mode";
|
|
65218
|
+
if (surface === "native") return "native";
|
|
65219
|
+
return "tools";
|
|
65220
|
+
}
|
|
64403
65221
|
//#endregion
|
|
64404
65222
|
//#region src/code-mode/runtime-api.generated.ts
|
|
64405
65223
|
const CODE_MODE_RUNTIME_API_DECLARATION = "type JsonPrimitive=string|number|boolean|null;type JsonValue=JsonPrimitive|JsonValue[]|{[key:string]:JsonValue};interface CapletHandle<Id extends string>{readonly id:Id;/** Show this Caplet card,without tool/resource/prompt schemas. */ inspect():Promise<CapletCard<Id>>;/** Check backend readiness/auth;expected unavailable states return ok:false. */ check():Promise<CapletsResult<BackendCheckResult>>;/** List tool summaries for the discovery pass;may be empty. */ tools(input?:PageInput):Promise<Page<ToolSummary>>;/** Search tool summaries for the discovery pass;may be empty. */ searchTools(query:string,input?:PageInput):Promise<Page<ToolSummary>>;/** Get schema,callSignature,types,examples;prefer outputSchema/outputTypeScript over observed hints. */ describeTool(name:string):Promise<CapletsResult<ToolDescriptor>>;/** Call one tool;expected failures return ok:false. Filter bulky data in script before returning. */ callTool(name:string,args?:unknown):Promise<CapletsResult<unknown>>;/** List readable resources for the discovery pass;many backends expose none. */ resources(input?:PageInput):Promise<Page<ResourceSummary>>;/** Search readable resources for the discovery pass;many backends expose none. */ searchResources(query:string,input?:PageInput):Promise<Page<ResourceSummary>>;/** List resource templates for the discovery pass;many backends expose none. */ resourceTemplates(input?:PageInput):Promise<Page<ResourceTemplateSummary>>;/** Read one resource by URI;unsupported/missing resources return ok:false. */ readResource(uri:string):Promise<CapletsResult<ResourceReadResult>>;/** List reusable prompts for the discovery pass;many backends expose none. */ prompts(input?:PageInput):Promise<Page<PromptSummary>>;/** Search reusable prompts for the discovery pass;many backends expose none. */ searchPrompts(query:string,input?:PageInput):Promise<Page<PromptSummary>>;/** Get one prompt by name and args;unsupported/missing prompts return ok:false. */ getPrompt(name:string,args?:unknown):Promise<CapletsResult<PromptResult>>;/** Complete a prompt or resource-template argument. */ complete(input:CompleteInput):Promise<CapletsResult<CompleteResult>>;}interface DebugApi{readLogs(input:ReadLogsInput):Promise<ReadLogsResult>;readRecovery(input:ReadCodeModeRecoveryInput):Promise<ReadCodeModeRecoveryResult>;}type CapletCard<Id extends string>={id:Id;name:string;description:string;useWhen?:string;avoidWhen?:string;tags?:string[];backend?:unknown;};type PageInput={limit?:number;cursor?:string};type Page<T>={items:T[];nextCursor?:string;truncated?:boolean};type CapletsResult<T>=|{ok:true;data:T;meta?:CapletsMeta}|{ok:false;error:CapletsError;meta?:CapletsMeta};type CapletsMeta={[key:string]:unknown};type CapletsError={code:string;message:string;details?:unknown};type BackendCheckResult=unknown;type ToolSummary={/** Exact downstream tool identifier for describeTool(name)and callTool(name,args). */ name:string;title?:string;description?:string;/** Optional author-supplied hint for when to prefer this tool. */ useWhen?:string;/** Optional author-supplied hint for when to avoid this tool. */ avoidWhen?:string;/** True when the tool declares that it only reads data. */ readOnlyHint?:boolean;/** True when the tool declares that it may perform destructive writes. */ destructiveHint?:boolean;};type ToolDescriptor={id?:string;tool?:unknown;inputSchema?:unknown;outputSchema?:unknown;callSignature?:string;inputTypeScript?:string;outputTypeScript?:string;observedOutputShape?:ObservedOutputShape;examples?:unknown[];};type ObservedOutputShape={version:1;source:\"observed\";observedAt:string;sampleCount:number;typeScript:string;jsonShape:JsonShape;truncated:boolean;};type JsonShape=|{kind:\"null\"}|{kind:\"boolean\"}|{kind:\"number\"}|{kind:\"string\"}|{kind:\"unknown\"}|{kind:\"array\";element?:JsonShape;truncated?:boolean}|{kind:\"object\";fields:Record<string,{optional:boolean;shape:JsonShape}>;truncated?:boolean;}|{kind:\"union\";variants:JsonShape[]};type ResourceSummary={uri?:string;name?:string;title?:string;description?:string};type ResourceTemplateSummary={uriTemplate?:string;name?:string;title?:string;description?:string;};type ResourceReadResult=unknown;type PromptSummary={name?:string;title?:string;description?:string};type PromptResult=unknown;type CompleteInput={ref:{type:\"prompt\";name:string}|{type:\"resourceTemplate\";uri:string};argument:{name:string;value:string};};type CompleteResult=unknown;type ReadLogsInput={logRef:string;cursor?:string;limit?:number};type ReadLogsResult={entries:CodeModeLogEntry[];nextCursor?:string};type ReadCodeModeRecoveryInput={recoveryRef:string;cursor?:string;limit?:number};type CodeModeDiagnostic={code:string;message:string;severity:\"error\"|\"warning\"|\"info\";line?:number;column?:number;};type CodeModeRecoveryClassification=\"setup_like\"|\"side_effecting\"|\"unknown\";type CodeModeRecoveryEntry={timestamp:string;code:string;declarationHash:string;outcome:{ok:true}|{ok:false;code:string;message:string};diagnostics:Array<Pick<CodeModeDiagnostic,\"code\"|\"severity\"|\"message\">>;recoveryClassification:CodeModeRecoveryClassification;logsStored?:boolean;summary?:string;};type ReadCodeModeRecoveryResult={entries:CodeModeRecoveryEntry[];nextCursor?:string};type CodeModeLogEntry={level:\"log\"|\"info\"|\"warn\"|\"error\"|\"debug\";message:string;timestamp:string;};type CodeModeSessionStatus=\"created\"|\"reused\";type CodeModeRunMeta={runId:string;traceId:string;declarationHash:string;durationMs:number;timeoutMs:number;maxTimeoutMs:number;sessionId?:string|null;sessionStatus?:CodeModeSessionStatus|null;recoveryRef?:string|null;};interface Console{log(...values:unknown[]):void;info(...values:unknown[]):void;warn(...values:unknown[]):void;error(...values:unknown[]):void;debug(...values:unknown[]):void;}declare const console:Console;";
|
|
@@ -79924,9 +80742,11 @@ async function runCodeMode(input) {
|
|
|
79924
80742
|
const callable = listCodeModeCallableCaplets(input.service);
|
|
79925
80743
|
const declaration = generateCodeModeDeclarations({ caplets: callable });
|
|
79926
80744
|
const declarationHash = codeModeDeclarationHash(declaration);
|
|
80745
|
+
const platformRuntimeHash = codeModeDeclarationHash(CODE_MODE_PLATFORM_RUNTIME_SOURCE);
|
|
80746
|
+
let invokedCaplet = false;
|
|
79927
80747
|
const sessionCompatibility = {
|
|
79928
80748
|
declarationHash,
|
|
79929
|
-
platformRuntimeHash
|
|
80749
|
+
platformRuntimeHash,
|
|
79930
80750
|
runtimeScope: input.runtimeScope ?? "",
|
|
79931
80751
|
version: 1
|
|
79932
80752
|
};
|
|
@@ -79943,7 +80763,8 @@ async function runCodeMode(input) {
|
|
|
79943
80763
|
};
|
|
79944
80764
|
const meta = () => ({
|
|
79945
80765
|
...metaBase,
|
|
79946
|
-
durationMs: Date.now() - startedAt
|
|
80766
|
+
durationMs: Date.now() - startedAt,
|
|
80767
|
+
anyCapletInvoked: invokedCaplet
|
|
79947
80768
|
});
|
|
79948
80769
|
if (input.sessionId !== void 0 && !input.sessionManager) return {
|
|
79949
80770
|
ok: false,
|
|
@@ -80030,7 +80851,6 @@ async function runCodeMode(input) {
|
|
|
80030
80851
|
};
|
|
80031
80852
|
}
|
|
80032
80853
|
const capturedLogs = [];
|
|
80033
|
-
let invokedCaplet = false;
|
|
80034
80854
|
const api = createCodeModeCapletsApi({
|
|
80035
80855
|
service: input.service,
|
|
80036
80856
|
readLogs: async (readInput) => input.logStore?.read(readInput) ?? { entries: [] },
|
|
@@ -80336,6 +81156,7 @@ function emptyCodeModeRunMeta() {
|
|
|
80336
81156
|
durationMs: 0,
|
|
80337
81157
|
timeoutMs: 0,
|
|
80338
81158
|
maxTimeoutMs: 0,
|
|
81159
|
+
anyCapletInvoked: false,
|
|
80339
81160
|
sessionId: null,
|
|
80340
81161
|
sessionStatus: null,
|
|
80341
81162
|
recoveryRef: null
|
|
@@ -80595,18 +81416,28 @@ function resolveNativeCapletsServiceOptions(input = {}, env = process.env) {
|
|
|
80595
81416
|
...remoteFetch ? { fetch: remoteFetch } : {}
|
|
80596
81417
|
}, env);
|
|
80597
81418
|
const cloud = resolveNativeCloudPresence(input.remote?.cloud, env);
|
|
81419
|
+
const requestInit = mode.mode === "cloud" && cloud ? { headers: { Authorization: `Bearer ${cloud.accessToken}` } } : server.requestInit;
|
|
80598
81420
|
return {
|
|
80599
81421
|
mode: mode.mode,
|
|
80600
81422
|
remote: {
|
|
80601
81423
|
url: server.attachUrl,
|
|
80602
81424
|
auth: nativeAuthFromRemoteAuth$1(server.auth),
|
|
80603
81425
|
pollIntervalMs: parsePollInterval(input.remote?.pollIntervalMs),
|
|
80604
|
-
requestInit:
|
|
81426
|
+
requestInit: withRequestHeaders(requestInit, input.remote?.requestHeaders),
|
|
80605
81427
|
...cloud ? { cloud } : {},
|
|
80606
81428
|
...server.fetch ? { fetch: server.fetch } : {}
|
|
80607
81429
|
}
|
|
80608
81430
|
};
|
|
80609
81431
|
}
|
|
81432
|
+
function withRequestHeaders(requestInit, requestHeaders) {
|
|
81433
|
+
if (!requestHeaders) return requestInit;
|
|
81434
|
+
const headers = new Headers(requestInit.headers);
|
|
81435
|
+
for (const [name, value] of Object.entries(requestHeaders)) headers.set(name, value);
|
|
81436
|
+
return {
|
|
81437
|
+
...requestInit,
|
|
81438
|
+
headers
|
|
81439
|
+
};
|
|
81440
|
+
}
|
|
80610
81441
|
function resolveNativeHostedCloudRemote(url, workspace, fetch) {
|
|
80611
81442
|
return resolveHostedCloudRemote({
|
|
80612
81443
|
url,
|
|
@@ -81021,7 +81852,382 @@ function projectSyncFiles(projectRoot) {
|
|
|
81021
81852
|
}));
|
|
81022
81853
|
}
|
|
81023
81854
|
//#endregion
|
|
81855
|
+
//#region src/attach/api.ts
|
|
81856
|
+
const CAPLETS_ATTACH_SESSION_HEADER = "caplets-attach-session-id";
|
|
81857
|
+
async function buildAttachProjection(engine) {
|
|
81858
|
+
const snapshot = await engine.exposureSnapshot();
|
|
81859
|
+
const partial = sortAttachProjectionInput({
|
|
81860
|
+
caplets: snapshot.progressiveCaplets.map(progressiveCapletExport),
|
|
81861
|
+
tools: snapshot.directTools.map(toolExport),
|
|
81862
|
+
resources: snapshot.directResources.map(resourceExport),
|
|
81863
|
+
resourceTemplates: snapshot.directResourceTemplates.map(resourceTemplateExport),
|
|
81864
|
+
prompts: snapshot.directPrompts.map(promptExport),
|
|
81865
|
+
completions: completionExports(snapshot),
|
|
81866
|
+
codeModeCaplets: snapshot.codeModeCaplets.map(codeModeCapletExport),
|
|
81867
|
+
diagnostics: snapshot.hiddenCaplets.map((hidden) => ({
|
|
81868
|
+
code: `ATTACH_CAPLET_${hidden.reason.toUpperCase()}`,
|
|
81869
|
+
message: `Caplet ${hidden.capletId} is not exported: ${hidden.reason}.`,
|
|
81870
|
+
capletId: hidden.capletId,
|
|
81871
|
+
...hidden.error ? { details: hidden.error } : {}
|
|
81872
|
+
}))
|
|
81873
|
+
});
|
|
81874
|
+
const revision = revisionFor(partial);
|
|
81875
|
+
const manifest = {
|
|
81876
|
+
version: 1,
|
|
81877
|
+
revision,
|
|
81878
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
81879
|
+
...withRevisionExportIds(revision, partial)
|
|
81880
|
+
};
|
|
81881
|
+
return {
|
|
81882
|
+
manifest,
|
|
81883
|
+
routes: routesFor(manifest)
|
|
81884
|
+
};
|
|
81885
|
+
}
|
|
81886
|
+
async function buildNativeAttachProjection(service) {
|
|
81887
|
+
const tools = service.listTools();
|
|
81888
|
+
const partial = sortAttachProjectionInput({
|
|
81889
|
+
caplets: nativeProgressiveCaplets(tools),
|
|
81890
|
+
tools: nativeDirectTools(tools),
|
|
81891
|
+
resources: [],
|
|
81892
|
+
resourceTemplates: [],
|
|
81893
|
+
prompts: [],
|
|
81894
|
+
completions: [],
|
|
81895
|
+
codeModeCaplets: nativeCodeModeCaplets(tools),
|
|
81896
|
+
diagnostics: []
|
|
81897
|
+
});
|
|
81898
|
+
const revision = revisionFor(partial);
|
|
81899
|
+
const manifest = {
|
|
81900
|
+
version: 1,
|
|
81901
|
+
revision,
|
|
81902
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
81903
|
+
...withRevisionExportIds(revision, partial)
|
|
81904
|
+
};
|
|
81905
|
+
return {
|
|
81906
|
+
manifest,
|
|
81907
|
+
routes: routesFor(manifest)
|
|
81908
|
+
};
|
|
81909
|
+
}
|
|
81910
|
+
function nativeProgressiveCaplets(tools) {
|
|
81911
|
+
return tools.filter((tool) => tool.codeModeRun !== true && !nativeDirectToolOperation(tool)).map((tool) => ({
|
|
81912
|
+
stableId: `native:${tool.caplet}`,
|
|
81913
|
+
kind: "caplet",
|
|
81914
|
+
name: tool.caplet,
|
|
81915
|
+
title: tool.title,
|
|
81916
|
+
description: tool.description,
|
|
81917
|
+
inputSchema: tool.inputSchema,
|
|
81918
|
+
outputSchema: tool.outputSchema,
|
|
81919
|
+
annotations: tool.annotations,
|
|
81920
|
+
schemaHash: schemaHash(tool.inputSchema ?? null),
|
|
81921
|
+
capletId: tool.caplet,
|
|
81922
|
+
shadowing: tool.shadowing ?? "forbid"
|
|
81923
|
+
}));
|
|
81924
|
+
}
|
|
81925
|
+
function nativeDirectTools(tools) {
|
|
81926
|
+
return tools.flatMap((tool) => {
|
|
81927
|
+
const operation = nativeDirectToolOperation(tool);
|
|
81928
|
+
if (!operation || tool.codeModeRun === true || !tool.sourceCaplet) return [];
|
|
81929
|
+
return [{
|
|
81930
|
+
stableId: `native-tool:${tool.caplet}`,
|
|
81931
|
+
kind: "tool",
|
|
81932
|
+
name: tool.caplet,
|
|
81933
|
+
downstreamName: operation,
|
|
81934
|
+
title: tool.title,
|
|
81935
|
+
description: tool.description,
|
|
81936
|
+
inputSchema: tool.inputSchema,
|
|
81937
|
+
outputSchema: tool.outputSchema,
|
|
81938
|
+
annotations: tool.annotations,
|
|
81939
|
+
schemaHash: schemaHash({
|
|
81940
|
+
input: tool.inputSchema,
|
|
81941
|
+
output: tool.outputSchema
|
|
81942
|
+
}),
|
|
81943
|
+
capletId: tool.sourceCaplet,
|
|
81944
|
+
shadowing: tool.shadowing ?? "forbid"
|
|
81945
|
+
}];
|
|
81946
|
+
});
|
|
81947
|
+
}
|
|
81948
|
+
function nativeDirectToolOperation(tool) {
|
|
81949
|
+
if (!tool.sourceCaplet || !tool.caplet.startsWith(`${tool.sourceCaplet}__`)) return;
|
|
81950
|
+
return tool.caplet.slice(tool.sourceCaplet.length + 2);
|
|
81951
|
+
}
|
|
81952
|
+
function nativeCodeModeCaplets(tools) {
|
|
81953
|
+
return tools.flatMap((tool) => (tool.codeModeCaplets ?? []).map((caplet) => ({
|
|
81954
|
+
stableId: `native-code-mode:${caplet.id}`,
|
|
81955
|
+
kind: "caplet",
|
|
81956
|
+
name: caplet.name,
|
|
81957
|
+
title: caplet.name,
|
|
81958
|
+
description: caplet.description,
|
|
81959
|
+
schemaHash: null,
|
|
81960
|
+
capletId: caplet.id,
|
|
81961
|
+
shadowing: caplet.shadowing ?? "forbid"
|
|
81962
|
+
})));
|
|
81963
|
+
}
|
|
81964
|
+
async function invokeNativeAttachExport(service, projection, request) {
|
|
81965
|
+
if (request.revision !== projection.manifest.revision) throw new CapletsError("ATTACH_MANIFEST_STALE", "Attach manifest revision is stale.");
|
|
81966
|
+
const route = projection.routes.get(request.exportId);
|
|
81967
|
+
if (!route || route.kind !== request.kind) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach export was not found.");
|
|
81968
|
+
if (route.kind !== "caplet") {
|
|
81969
|
+
if (route.kind === "tool") return await service.execute(`${route.capletId}__${route.downstreamName}`, request.input);
|
|
81970
|
+
throw new CapletsError("REQUEST_INVALID", "Native attach sessions only support Caplet and tool exports.");
|
|
81971
|
+
}
|
|
81972
|
+
return await service.execute(route.capletId, request.input);
|
|
81973
|
+
}
|
|
81974
|
+
async function invokeAttachExport$1(engine, projection, request) {
|
|
81975
|
+
if (request.revision !== projection.manifest.revision) throw new CapletsError("ATTACH_MANIFEST_STALE", "Attach manifest revision is stale.");
|
|
81976
|
+
const route = projection.routes.get(request.exportId);
|
|
81977
|
+
if (!route || route.kind !== request.kind) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach export was not found.");
|
|
81978
|
+
if (route.kind === "caplet") return await engine.execute(route.capletId, request.input);
|
|
81979
|
+
if (route.kind === "tool") return await engine.executeDirectTool(route.capletId, route.downstreamName, isRecord$4(request.input) ? request.input : {});
|
|
81980
|
+
if (route.kind === "resource") return await engine.readDirectResource(route.capletId, route.downstreamUri);
|
|
81981
|
+
if (route.kind === "resourceTemplate") {
|
|
81982
|
+
const uri = isRecord$4(request.input) && typeof request.input.uri === "string" ? request.input.uri : void 0;
|
|
81983
|
+
if (!uri) throw new CapletsError("REQUEST_INVALID", "Attach resource template invoke requires input.uri.");
|
|
81984
|
+
const downstreamUri = downstreamResourceUri$1(route.capletId, uri);
|
|
81985
|
+
if (!directResourceUriMatchesTemplate(downstreamUri, route.downstreamUriTemplate)) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach resource URI does not match the exported resource template.");
|
|
81986
|
+
return await engine.readDirectResource(route.capletId, downstreamUri);
|
|
81987
|
+
}
|
|
81988
|
+
if (route.kind === "prompt") return await engine.getDirectPrompt(route.capletId, route.downstreamName, isRecord$4(request.input) ? stringifyRecord(request.input) : {});
|
|
81989
|
+
if (route.kind === "completion") return await engine.execute(route.capletId, {
|
|
81990
|
+
...normalizeCompletionInput(projection.manifest, route.capletId, request.input),
|
|
81991
|
+
operation: "complete"
|
|
81992
|
+
});
|
|
81993
|
+
throw new CapletsError("REQUEST_INVALID", "Attach export kind is not invokable via /v1/attach/invoke.");
|
|
81994
|
+
}
|
|
81995
|
+
function attachErrorResponse(error) {
|
|
81996
|
+
const safe = toSafeError(error, "INTERNAL_ERROR");
|
|
81997
|
+
return {
|
|
81998
|
+
status: safe.code === "ATTACH_MANIFEST_STALE" ? 409 : safe.code === "ATTACH_EXPORT_NOT_FOUND" ? 404 : safe.code === "REQUEST_INVALID" ? 400 : 500,
|
|
81999
|
+
body: {
|
|
82000
|
+
ok: false,
|
|
82001
|
+
error: safe
|
|
82002
|
+
}
|
|
82003
|
+
};
|
|
82004
|
+
}
|
|
82005
|
+
function progressiveCapletExport(entry) {
|
|
82006
|
+
const inputSchema = generatedToolInputJsonSchemaForCaplet(entry.caplet);
|
|
82007
|
+
return {
|
|
82008
|
+
stableId: `progressive:${entry.caplet.server}`,
|
|
82009
|
+
kind: "caplet",
|
|
82010
|
+
name: entry.caplet.server,
|
|
82011
|
+
title: entry.caplet.name,
|
|
82012
|
+
description: entry.caplet.description,
|
|
82013
|
+
inputSchema,
|
|
82014
|
+
schemaHash: schemaHash(inputSchema),
|
|
82015
|
+
capletId: entry.caplet.server,
|
|
82016
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82017
|
+
};
|
|
82018
|
+
}
|
|
82019
|
+
function codeModeCapletExport(entry) {
|
|
82020
|
+
return {
|
|
82021
|
+
stableId: `code_mode:${entry.caplet.server}`,
|
|
82022
|
+
kind: "caplet",
|
|
82023
|
+
name: entry.caplet.name,
|
|
82024
|
+
title: entry.caplet.name,
|
|
82025
|
+
description: entry.caplet.description,
|
|
82026
|
+
schemaHash: null,
|
|
82027
|
+
capletId: entry.caplet.server,
|
|
82028
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82029
|
+
};
|
|
82030
|
+
}
|
|
82031
|
+
function toolExport(entry) {
|
|
82032
|
+
return {
|
|
82033
|
+
stableId: `tool:${entry.caplet.server}:${entry.downstreamName}`,
|
|
82034
|
+
kind: "tool",
|
|
82035
|
+
name: entry.name,
|
|
82036
|
+
downstreamName: entry.downstreamName,
|
|
82037
|
+
title: entry.tool.name,
|
|
82038
|
+
description: entry.tool.description,
|
|
82039
|
+
inputSchema: entry.tool.inputSchema,
|
|
82040
|
+
outputSchema: entry.tool.outputSchema,
|
|
82041
|
+
annotations: entry.tool.annotations,
|
|
82042
|
+
schemaHash: schemaHash({
|
|
82043
|
+
input: entry.tool.inputSchema,
|
|
82044
|
+
output: entry.tool.outputSchema
|
|
82045
|
+
}),
|
|
82046
|
+
capletId: entry.caplet.server,
|
|
82047
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82048
|
+
};
|
|
82049
|
+
}
|
|
82050
|
+
function resourceExport(entry) {
|
|
82051
|
+
return {
|
|
82052
|
+
stableId: `resource:${entry.caplet.server}:${entry.downstreamUri}`,
|
|
82053
|
+
kind: "resource",
|
|
82054
|
+
uri: entry.uri,
|
|
82055
|
+
downstreamUri: entry.downstreamUri,
|
|
82056
|
+
title: entry.resource.name,
|
|
82057
|
+
description: entry.resource.description,
|
|
82058
|
+
...entry.resource.mimeType ? { mimeType: entry.resource.mimeType } : {},
|
|
82059
|
+
...typeof entry.resource.size === "number" ? { size: entry.resource.size } : {},
|
|
82060
|
+
schemaHash: null,
|
|
82061
|
+
capletId: entry.caplet.server,
|
|
82062
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82063
|
+
};
|
|
82064
|
+
}
|
|
82065
|
+
function resourceTemplateExport(entry) {
|
|
82066
|
+
return {
|
|
82067
|
+
stableId: `resourceTemplate:${entry.caplet.server}:${entry.downstreamUriTemplate}`,
|
|
82068
|
+
kind: "resourceTemplate",
|
|
82069
|
+
uriTemplate: entry.uriTemplate,
|
|
82070
|
+
downstreamUriTemplate: entry.downstreamUriTemplate,
|
|
82071
|
+
title: entry.resourceTemplate.name,
|
|
82072
|
+
description: entry.resourceTemplate.description,
|
|
82073
|
+
...entry.resourceTemplate.mimeType ? { mimeType: entry.resourceTemplate.mimeType } : {},
|
|
82074
|
+
schemaHash: null,
|
|
82075
|
+
capletId: entry.caplet.server,
|
|
82076
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82077
|
+
};
|
|
82078
|
+
}
|
|
82079
|
+
function promptExport(entry) {
|
|
82080
|
+
const inputSchema = { arguments: entry.prompt.arguments ?? [] };
|
|
82081
|
+
return {
|
|
82082
|
+
stableId: `prompt:${entry.caplet.server}:${entry.downstreamName}`,
|
|
82083
|
+
kind: "prompt",
|
|
82084
|
+
name: entry.name,
|
|
82085
|
+
downstreamName: entry.downstreamName,
|
|
82086
|
+
title: entry.prompt.name,
|
|
82087
|
+
description: entry.prompt.description,
|
|
82088
|
+
inputSchema,
|
|
82089
|
+
schemaHash: schemaHash(inputSchema),
|
|
82090
|
+
capletId: entry.caplet.server,
|
|
82091
|
+
shadowing: shadowingPolicy(entry.caplet)
|
|
82092
|
+
};
|
|
82093
|
+
}
|
|
82094
|
+
function completionExports(snapshot) {
|
|
82095
|
+
return [...new Map([...snapshot.directPrompts, ...snapshot.directResourceTemplates].map((entry) => [entry.caplet.server, entry.caplet])).entries()].sort(([left], [right]) => left.localeCompare(right)).map(([capletId, caplet]) => ({
|
|
82096
|
+
stableId: `completion:${capletId}`,
|
|
82097
|
+
kind: "completion",
|
|
82098
|
+
name: `${capletId}:complete`,
|
|
82099
|
+
title: "Complete",
|
|
82100
|
+
description: `MCP completion for ${capletId}.`,
|
|
82101
|
+
schemaHash: null,
|
|
82102
|
+
capletId,
|
|
82103
|
+
shadowing: shadowingPolicy(caplet)
|
|
82104
|
+
}));
|
|
82105
|
+
}
|
|
82106
|
+
function shadowingPolicy(caplet) {
|
|
82107
|
+
return caplet.shadowing ?? "forbid";
|
|
82108
|
+
}
|
|
82109
|
+
function sortAttachProjectionInput(partial) {
|
|
82110
|
+
return {
|
|
82111
|
+
caplets: sortByStableId(partial.caplets),
|
|
82112
|
+
tools: sortByStableId(partial.tools),
|
|
82113
|
+
resources: sortByStableId(partial.resources),
|
|
82114
|
+
resourceTemplates: sortByStableId(partial.resourceTemplates),
|
|
82115
|
+
prompts: sortByStableId(partial.prompts),
|
|
82116
|
+
completions: sortByStableId(partial.completions),
|
|
82117
|
+
codeModeCaplets: sortByStableId(partial.codeModeCaplets),
|
|
82118
|
+
diagnostics: [...partial.diagnostics].sort((left, right) => diagnosticSortKey(left).localeCompare(diagnosticSortKey(right)))
|
|
82119
|
+
};
|
|
82120
|
+
}
|
|
82121
|
+
function sortByStableId(entries) {
|
|
82122
|
+
return [...entries].sort((left, right) => left.stableId.localeCompare(right.stableId));
|
|
82123
|
+
}
|
|
82124
|
+
function diagnosticSortKey(diagnostic) {
|
|
82125
|
+
return stableJsonStringify({
|
|
82126
|
+
code: diagnostic.code,
|
|
82127
|
+
capletId: diagnostic.capletId ?? "",
|
|
82128
|
+
message: diagnostic.message
|
|
82129
|
+
});
|
|
82130
|
+
}
|
|
82131
|
+
function revisionFor(value) {
|
|
82132
|
+
return `sha256:${createHash("sha256").update(stableJsonStringify(value)).digest("hex")}`;
|
|
82133
|
+
}
|
|
82134
|
+
function withRevisionExportIds(revision, partial) {
|
|
82135
|
+
return {
|
|
82136
|
+
...partial,
|
|
82137
|
+
caplets: partial.caplets.map((entry) => withExportId(revision, entry)),
|
|
82138
|
+
tools: partial.tools.map((entry) => withExportId(revision, entry)),
|
|
82139
|
+
resources: partial.resources.map((entry) => withExportId(revision, entry)),
|
|
82140
|
+
resourceTemplates: partial.resourceTemplates.map((entry) => withExportId(revision, entry)),
|
|
82141
|
+
prompts: partial.prompts.map((entry) => withExportId(revision, entry)),
|
|
82142
|
+
completions: partial.completions.map((entry) => withExportId(revision, entry)),
|
|
82143
|
+
codeModeCaplets: partial.codeModeCaplets.map((entry) => withExportId(revision, entry))
|
|
82144
|
+
};
|
|
82145
|
+
}
|
|
82146
|
+
function withExportId(revision, entry) {
|
|
82147
|
+
return {
|
|
82148
|
+
...entry,
|
|
82149
|
+
exportId: `${revision}:${entry.stableId}`
|
|
82150
|
+
};
|
|
82151
|
+
}
|
|
82152
|
+
function routesFor(manifest) {
|
|
82153
|
+
const routes = /* @__PURE__ */ new Map();
|
|
82154
|
+
for (const entry of manifest.caplets) routes.set(entry.exportId, {
|
|
82155
|
+
kind: "caplet",
|
|
82156
|
+
capletId: entry.capletId
|
|
82157
|
+
});
|
|
82158
|
+
for (const entry of manifest.tools) routes.set(entry.exportId, {
|
|
82159
|
+
kind: "tool",
|
|
82160
|
+
capletId: entry.capletId,
|
|
82161
|
+
downstreamName: entry.downstreamName
|
|
82162
|
+
});
|
|
82163
|
+
for (const entry of manifest.resources) routes.set(entry.exportId, {
|
|
82164
|
+
kind: "resource",
|
|
82165
|
+
capletId: entry.capletId,
|
|
82166
|
+
downstreamUri: entry.downstreamUri
|
|
82167
|
+
});
|
|
82168
|
+
for (const entry of manifest.resourceTemplates) routes.set(entry.exportId, {
|
|
82169
|
+
kind: "resourceTemplate",
|
|
82170
|
+
capletId: entry.capletId,
|
|
82171
|
+
downstreamUriTemplate: entry.downstreamUriTemplate
|
|
82172
|
+
});
|
|
82173
|
+
for (const entry of manifest.prompts) routes.set(entry.exportId, {
|
|
82174
|
+
kind: "prompt",
|
|
82175
|
+
capletId: entry.capletId,
|
|
82176
|
+
downstreamName: entry.downstreamName
|
|
82177
|
+
});
|
|
82178
|
+
for (const entry of manifest.completions) routes.set(entry.exportId, {
|
|
82179
|
+
kind: "completion",
|
|
82180
|
+
capletId: entry.capletId
|
|
82181
|
+
});
|
|
82182
|
+
for (const entry of manifest.codeModeCaplets) routes.set(entry.exportId, {
|
|
82183
|
+
kind: "caplet",
|
|
82184
|
+
capletId: entry.capletId
|
|
82185
|
+
});
|
|
82186
|
+
return routes;
|
|
82187
|
+
}
|
|
82188
|
+
function normalizeCompletionInput(manifest, capletId, input) {
|
|
82189
|
+
if (!isRecord$4(input)) return {};
|
|
82190
|
+
const ref = input.ref;
|
|
82191
|
+
if (!isRecord$4(ref)) return input;
|
|
82192
|
+
if (ref.type === "prompt" && typeof ref.name === "string") {
|
|
82193
|
+
const prompt = manifest.prompts.find((entry) => entry.capletId === capletId && (entry.name === ref.name || entry.downstreamName === ref.name));
|
|
82194
|
+
if (!prompt) return input;
|
|
82195
|
+
return {
|
|
82196
|
+
...input,
|
|
82197
|
+
ref: {
|
|
82198
|
+
...ref,
|
|
82199
|
+
name: prompt.downstreamName
|
|
82200
|
+
}
|
|
82201
|
+
};
|
|
82202
|
+
}
|
|
82203
|
+
if (ref.type === "resourceTemplate" && typeof ref.uri === "string") {
|
|
82204
|
+
const resourceTemplate = manifest.resourceTemplates.find((entry) => entry.capletId === capletId && (entry.uriTemplate === ref.uri || entry.downstreamUriTemplate === ref.uri));
|
|
82205
|
+
if (!resourceTemplate) return input;
|
|
82206
|
+
return {
|
|
82207
|
+
...input,
|
|
82208
|
+
ref: {
|
|
82209
|
+
...ref,
|
|
82210
|
+
uri: resourceTemplate.downstreamUriTemplate
|
|
82211
|
+
}
|
|
82212
|
+
};
|
|
82213
|
+
}
|
|
82214
|
+
return input;
|
|
82215
|
+
}
|
|
82216
|
+
function isRecord$4(value) {
|
|
82217
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
82218
|
+
}
|
|
82219
|
+
function stringifyRecord(record) {
|
|
82220
|
+
return Object.fromEntries(Object.entries(record).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)]));
|
|
82221
|
+
}
|
|
82222
|
+
function downstreamResourceUri$1(capletId, uri) {
|
|
82223
|
+
if (!uri.startsWith("caplets://")) return uri;
|
|
82224
|
+
const decoded = decodeDirectResourceUri(uri);
|
|
82225
|
+
if (decoded.capletId !== capletId) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach resource template URI belongs to a different Caplet.");
|
|
82226
|
+
return decoded.downstreamUri;
|
|
82227
|
+
}
|
|
82228
|
+
//#endregion
|
|
81024
82229
|
//#region src/native/remote.ts
|
|
82230
|
+
const ATTACH_SESSION_UNSUPPORTED_RETRY_MS = 6e4;
|
|
81025
82231
|
function createSdkRemoteCapletsClient(options) {
|
|
81026
82232
|
const listeners = /* @__PURE__ */ new Set();
|
|
81027
82233
|
let manifest;
|
|
@@ -81029,18 +82235,50 @@ function createSdkRemoteCapletsClient(options) {
|
|
|
81029
82235
|
let eventsAbort;
|
|
81030
82236
|
let eventsStartInFlight;
|
|
81031
82237
|
let eventsReconnectTimer;
|
|
82238
|
+
let attachSessionId;
|
|
82239
|
+
let attachSessionInFlight;
|
|
82240
|
+
let attachSessionsUnsupportedUntil = 0;
|
|
81032
82241
|
let closed = false;
|
|
81033
82242
|
const resolveRuntimeOptions = async () => {
|
|
81034
82243
|
return options.resolveRuntimeOptions ? await options.resolveRuntimeOptions() : options;
|
|
81035
82244
|
};
|
|
81036
82245
|
const fetchFor = (runtimeOptions) => runtimeOptions.fetch ?? fetch;
|
|
81037
82246
|
const fetchCurrentManifest = async () => {
|
|
81038
|
-
|
|
81039
|
-
|
|
82247
|
+
return await withAttachSessionRetry(async (runtimeOptions, sessionId) => {
|
|
82248
|
+
return await fetchAttachManifest(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions));
|
|
82249
|
+
});
|
|
81040
82250
|
};
|
|
81041
82251
|
const invokeCurrentExport = async (body) => {
|
|
82252
|
+
return await withAttachSessionRetry(async (runtimeOptions, sessionId) => {
|
|
82253
|
+
return await invokeAttachExport(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions), body);
|
|
82254
|
+
});
|
|
82255
|
+
};
|
|
82256
|
+
const ensureAttachSession = async (runtimeOptions) => {
|
|
82257
|
+
if (!options.attachSessionMetadata) return void 0;
|
|
82258
|
+
if (attachSessionsUnsupportedUntil > Date.now()) return void 0;
|
|
82259
|
+
attachSessionsUnsupportedUntil = 0;
|
|
82260
|
+
if (attachSessionId) return attachSessionId;
|
|
82261
|
+
if (attachSessionInFlight) return await attachSessionInFlight;
|
|
82262
|
+
attachSessionInFlight = createAttachSession(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), options.attachSessionMetadata);
|
|
82263
|
+
try {
|
|
82264
|
+
attachSessionId = await attachSessionInFlight;
|
|
82265
|
+
if (!attachSessionId) attachSessionsUnsupportedUntil = Date.now() + ATTACH_SESSION_UNSUPPORTED_RETRY_MS;
|
|
82266
|
+
return attachSessionId;
|
|
82267
|
+
} finally {
|
|
82268
|
+
attachSessionInFlight = void 0;
|
|
82269
|
+
}
|
|
82270
|
+
};
|
|
82271
|
+
const withAttachSessionRetry = async (operation) => {
|
|
81042
82272
|
const runtimeOptions = await resolveRuntimeOptions();
|
|
81043
|
-
|
|
82273
|
+
const sessionId = await ensureAttachSession(runtimeOptions);
|
|
82274
|
+
if (closed) throw new CapletsError("SERVER_UNAVAILABLE", "Remote Caplets client is closed.");
|
|
82275
|
+
try {
|
|
82276
|
+
return await operation(runtimeOptions, sessionId);
|
|
82277
|
+
} catch (error) {
|
|
82278
|
+
if (!options.attachSessionMetadata || attachSessionsUnsupportedUntil > Date.now() || !sessionId || !isAttachSessionNotFound(error)) throw error;
|
|
82279
|
+
if (attachSessionId === sessionId) attachSessionId = void 0;
|
|
82280
|
+
return await operation(runtimeOptions, await ensureAttachSession(runtimeOptions));
|
|
82281
|
+
}
|
|
81044
82282
|
};
|
|
81045
82283
|
const clearEventsReconnectTimer = () => {
|
|
81046
82284
|
if (eventsReconnectTimer) {
|
|
@@ -81060,7 +82298,9 @@ function createSdkRemoteCapletsClient(options) {
|
|
|
81060
82298
|
try {
|
|
81061
82299
|
const runtimeOptions = await resolveRuntimeOptions();
|
|
81062
82300
|
if (closed || eventsAbort || listeners.size === 0) return;
|
|
81063
|
-
|
|
82301
|
+
const sessionId = await ensureAttachSession(runtimeOptions);
|
|
82302
|
+
if (closed || eventsAbort || listeners.size === 0) return;
|
|
82303
|
+
eventsAbort = startAttachEvents(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions), listeners, (closedAbort, retry) => {
|
|
81064
82304
|
if (eventsAbort !== closedAbort) return;
|
|
81065
82305
|
eventsAbort = void 0;
|
|
81066
82306
|
if (!retry || closedAbort.signal.aborted || listeners.size === 0) return;
|
|
@@ -81142,6 +82382,13 @@ function createSdkRemoteCapletsClient(options) {
|
|
|
81142
82382
|
eventsAbort?.abort();
|
|
81143
82383
|
eventsAbort = void 0;
|
|
81144
82384
|
listeners.clear();
|
|
82385
|
+
const pendingSessionId = await attachSessionInFlight?.catch(() => void 0);
|
|
82386
|
+
const sessionId = attachSessionId ?? pendingSessionId;
|
|
82387
|
+
attachSessionId = void 0;
|
|
82388
|
+
if (sessionId) await (async () => {
|
|
82389
|
+
const runtimeOptions = await resolveRuntimeOptions();
|
|
82390
|
+
await closeAttachSession(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), sessionId);
|
|
82391
|
+
})().catch(() => void 0);
|
|
81145
82392
|
}
|
|
81146
82393
|
};
|
|
81147
82394
|
}
|
|
@@ -81338,17 +82585,63 @@ function remoteCodeModeCallableNativeTools$1(tools) {
|
|
|
81338
82585
|
function nativeToolRouteId(tool) {
|
|
81339
82586
|
return tool.codeModeRun ? nativeCodeModeToolId : tool.name;
|
|
81340
82587
|
}
|
|
81341
|
-
async function fetchAttachManifest(attachUrl, requestInit, fetchImpl) {
|
|
82588
|
+
async function fetchAttachManifest(attachUrl, requestInit, attachSessionId, fetchImpl) {
|
|
82589
|
+
const headers = attachHeaders(requestInit, attachSessionId);
|
|
81342
82590
|
const response = await fetchImpl(new URL("manifest", slashUrl(attachUrl)), {
|
|
81343
82591
|
...requestInit,
|
|
81344
|
-
method: "GET"
|
|
82592
|
+
method: "GET",
|
|
82593
|
+
headers
|
|
81345
82594
|
});
|
|
81346
|
-
if (!response.ok)
|
|
82595
|
+
if (!response.ok) {
|
|
82596
|
+
let payload;
|
|
82597
|
+
try {
|
|
82598
|
+
payload = await response.json();
|
|
82599
|
+
} catch {
|
|
82600
|
+
payload = { error: { message: `Caplets attach manifest returned HTTP ${response.status}.` } };
|
|
82601
|
+
}
|
|
82602
|
+
throw attachPayloadError(payload, response.status, "manifest");
|
|
82603
|
+
}
|
|
81347
82604
|
return await response.json();
|
|
81348
82605
|
}
|
|
81349
|
-
async function
|
|
82606
|
+
async function createAttachSession(attachUrl, requestInit, fetchImpl, metadata) {
|
|
81350
82607
|
const headers = new Headers(requestInit?.headers);
|
|
81351
82608
|
headers.set("content-type", "application/json");
|
|
82609
|
+
const response = await fetchImpl(new URL("sessions", slashUrl(attachUrl)), {
|
|
82610
|
+
...requestInit,
|
|
82611
|
+
method: "POST",
|
|
82612
|
+
headers,
|
|
82613
|
+
body: JSON.stringify(metadata)
|
|
82614
|
+
});
|
|
82615
|
+
if (!response.ok) {
|
|
82616
|
+
if (response.status === 404) return void 0;
|
|
82617
|
+
let payload;
|
|
82618
|
+
try {
|
|
82619
|
+
payload = await response.json();
|
|
82620
|
+
} catch {
|
|
82621
|
+
payload = void 0;
|
|
82622
|
+
}
|
|
82623
|
+
if (response.status === 400 && isAttachSessionProjectContextRejected(payload)) return;
|
|
82624
|
+
throw new CapletsError("SERVER_UNAVAILABLE", `Caplets attach session returned HTTP ${response.status}.`);
|
|
82625
|
+
}
|
|
82626
|
+
const payload = await response.json();
|
|
82627
|
+
if (!isPlainObject(payload) || typeof payload.sessionId !== "string") throw new CapletsError("SERVER_UNAVAILABLE", "Caplets attach session response was invalid.");
|
|
82628
|
+
return payload.sessionId;
|
|
82629
|
+
}
|
|
82630
|
+
async function closeAttachSession(attachUrl, requestInit, fetchImpl, attachSessionId) {
|
|
82631
|
+
await fetchImpl(new URL(`sessions/${encodeURIComponent(attachSessionId)}`, slashUrl(attachUrl)), {
|
|
82632
|
+
...requestInit,
|
|
82633
|
+
method: "DELETE",
|
|
82634
|
+
headers: attachHeaders(requestInit, attachSessionId)
|
|
82635
|
+
});
|
|
82636
|
+
}
|
|
82637
|
+
function attachHeaders(requestInit, attachSessionId) {
|
|
82638
|
+
const headers = new Headers(requestInit?.headers);
|
|
82639
|
+
if (attachSessionId) headers.set(CAPLETS_ATTACH_SESSION_HEADER, attachSessionId);
|
|
82640
|
+
return headers;
|
|
82641
|
+
}
|
|
82642
|
+
async function invokeAttachExport(attachUrl, requestInit, attachSessionId, fetchImpl, body) {
|
|
82643
|
+
const headers = attachHeaders(requestInit, attachSessionId);
|
|
82644
|
+
headers.set("content-type", "application/json");
|
|
81352
82645
|
const response = await fetchImpl(new URL("invoke", slashUrl(attachUrl)), {
|
|
81353
82646
|
...requestInit,
|
|
81354
82647
|
method: "POST",
|
|
@@ -81359,10 +82652,10 @@ async function invokeAttachExport(attachUrl, requestInit, fetchImpl, body) {
|
|
|
81359
82652
|
try {
|
|
81360
82653
|
payload = await response.json();
|
|
81361
82654
|
} catch (error) {
|
|
81362
|
-
if (!response.ok) throw attachPayloadError({ error: { message: `Caplets attach invoke returned HTTP ${response.status}.` } }, response.status);
|
|
82655
|
+
if (!response.ok) throw attachPayloadError({ error: { message: `Caplets attach invoke returned HTTP ${response.status}.` } }, response.status, "invoke");
|
|
81363
82656
|
throw error;
|
|
81364
82657
|
}
|
|
81365
|
-
if (!response.ok) throw attachPayloadError(payload, response.status);
|
|
82658
|
+
if (!response.ok) throw attachPayloadError(payload, response.status, "invoke");
|
|
81366
82659
|
if (isPlainObject(payload) && payload.ok === true && "data" in payload) return payload.data;
|
|
81367
82660
|
return payload;
|
|
81368
82661
|
}
|
|
@@ -81619,9 +82912,9 @@ function slashUrl(url) {
|
|
|
81619
82912
|
next.pathname = next.pathname.endsWith("/") ? next.pathname : `${next.pathname}/`;
|
|
81620
82913
|
return next;
|
|
81621
82914
|
}
|
|
81622
|
-
function attachPayloadError(payload, status) {
|
|
82915
|
+
function attachPayloadError(payload, status, endpoint) {
|
|
81623
82916
|
const error = isPlainObject(payload) && isPlainObject(payload.error) ? payload.error : void 0;
|
|
81624
|
-
const message = typeof error?.message === "string" ? error.message : `Caplets attach
|
|
82917
|
+
const message = typeof error?.message === "string" ? error.message : `Caplets attach ${endpoint} returned HTTP ${status}.`;
|
|
81625
82918
|
const thrown = new Error(message);
|
|
81626
82919
|
thrown.status = status;
|
|
81627
82920
|
if (error && "code" in error) thrown.code = error.code;
|
|
@@ -81630,14 +82923,23 @@ function attachPayloadError(payload, status) {
|
|
|
81630
82923
|
function isAttachManifestStale(error) {
|
|
81631
82924
|
return isPlainObject(error) && error.code === "ATTACH_MANIFEST_STALE";
|
|
81632
82925
|
}
|
|
81633
|
-
function
|
|
82926
|
+
function isAttachSessionNotFound(error) {
|
|
82927
|
+
return error.code === "REQUEST_INVALID" && /\battach session was not found\b/iu.test(errorMessage$1(error));
|
|
82928
|
+
}
|
|
82929
|
+
function isAttachSessionProjectContextRejected(payload) {
|
|
82930
|
+
const error = isPlainObject(payload) && isPlainObject(payload.error) ? payload.error : void 0;
|
|
82931
|
+
return error?.code === "REQUEST_INVALID" && typeof error.message === "string" && /\bproject context is only accepted by loopback runtimes\b/iu.test(error.message);
|
|
82932
|
+
}
|
|
82933
|
+
function startAttachEvents(attachUrl, requestInit, attachSessionId, fetchImpl, listeners, onClose) {
|
|
81634
82934
|
const abort = new AbortController();
|
|
81635
82935
|
let retry = true;
|
|
81636
82936
|
(async () => {
|
|
81637
82937
|
try {
|
|
82938
|
+
const headers = attachHeaders(requestInit, attachSessionId);
|
|
81638
82939
|
const response = await fetchImpl(new URL("events", slashUrl(attachUrl)), {
|
|
81639
82940
|
...requestInit,
|
|
81640
82941
|
method: "GET",
|
|
82942
|
+
headers,
|
|
81641
82943
|
signal: abort.signal
|
|
81642
82944
|
});
|
|
81643
82945
|
if (!response.ok) {
|
|
@@ -83018,7 +84320,11 @@ var DefaultNativeCapletsService = class {
|
|
|
83018
84320
|
this.writeErr = options.writeErr ?? (() => void 0);
|
|
83019
84321
|
this.engine = new CapletsEngine({
|
|
83020
84322
|
...options,
|
|
83021
|
-
writeErr: this.writeErr
|
|
84323
|
+
writeErr: this.writeErr,
|
|
84324
|
+
telemetrySurface: options.telemetrySurface ?? "native",
|
|
84325
|
+
telemetryVisibility: options.telemetryVisibility ?? "hidden",
|
|
84326
|
+
telemetryRuntimeMode: options.telemetryRuntimeMode ?? runtimeModeFromNativeOptions(options),
|
|
84327
|
+
telemetryIntegration: options.telemetryIntegration ?? "native"
|
|
83022
84328
|
});
|
|
83023
84329
|
this.postReloadRefresh = this.refreshExposureSnapshot({ emitToolsChanged: this.hasSnapshotBackedDirectExposure() });
|
|
83024
84330
|
this.unsubscribeEngineReload = this.engine.onReload(() => {
|
|
@@ -83049,7 +84355,16 @@ var DefaultNativeCapletsService = class {
|
|
|
83049
84355
|
];
|
|
83050
84356
|
}
|
|
83051
84357
|
async execute(capletId, request) {
|
|
83052
|
-
if (capletId === "code_mode")
|
|
84358
|
+
if (capletId === "code_mode") {
|
|
84359
|
+
const started = Date.now();
|
|
84360
|
+
const envelope = await executeCodeModeRunNative(this.codeModeDelegate(), request, this.codeModeSessions);
|
|
84361
|
+
const parsed = codeModeRunInputSchema.safeParse(request);
|
|
84362
|
+
this.engine.captureCodeModeOutcome(envelope, {
|
|
84363
|
+
started,
|
|
84364
|
+
...parsed.success && parsed.data.timeoutMs !== void 0 ? { timeoutMs: parsed.data.timeoutMs } : {}
|
|
84365
|
+
}).catch(() => void 0);
|
|
84366
|
+
return envelope;
|
|
84367
|
+
}
|
|
83053
84368
|
const route = this.directToolRoutes.get(capletId);
|
|
83054
84369
|
if (route) {
|
|
83055
84370
|
if (isMcpPrimitiveRoute(route.operationName)) return await this.engine.execute(route.capletId, nativeMcpPrimitiveRequest(route.operationName, request));
|
|
@@ -83057,6 +84372,9 @@ var DefaultNativeCapletsService = class {
|
|
|
83057
84372
|
}
|
|
83058
84373
|
return await this.engine.execute(capletId, request);
|
|
83059
84374
|
}
|
|
84375
|
+
async captureCodeModeOutcome(envelope, options) {
|
|
84376
|
+
await this.engine.captureCodeModeOutcome(envelope, options);
|
|
84377
|
+
}
|
|
83060
84378
|
codeModeService() {
|
|
83061
84379
|
return this.codeModeDelegate();
|
|
83062
84380
|
}
|
|
@@ -83277,9 +84595,39 @@ function nativeMcpPrimitiveRequest(operationName, request) {
|
|
|
83277
84595
|
};
|
|
83278
84596
|
return { operation: operationName };
|
|
83279
84597
|
}
|
|
84598
|
+
function operationFromNativeRequest(request) {
|
|
84599
|
+
return isRecord(request) ? request.operation : void 0;
|
|
84600
|
+
}
|
|
83280
84601
|
function isRecord(value) {
|
|
83281
84602
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
83282
84603
|
}
|
|
84604
|
+
function runtimeModeFromNativeOptions(options) {
|
|
84605
|
+
if (options.mode === "local") return "local";
|
|
84606
|
+
if (options.mode === "remote") return "remote";
|
|
84607
|
+
if (options.mode === "cloud") return "cloud";
|
|
84608
|
+
if (options.remote?.url) return "remote";
|
|
84609
|
+
const envMode = options.telemetryEnv?.CAPLETS_MODE ?? process.env.CAPLETS_MODE;
|
|
84610
|
+
if (envMode === "remote" || envMode === "cloud" || envMode === "local") return envMode;
|
|
84611
|
+
return "local";
|
|
84612
|
+
}
|
|
84613
|
+
function telemetryConfigFromNativeOptions(options) {
|
|
84614
|
+
const configPath = resolveConfigPath(options.configPath);
|
|
84615
|
+
const config = createLocalOverlayConfigLoader(options)(configPath, options.projectConfigPath ?? resolveProjectConfigPath());
|
|
84616
|
+
const explicitTelemetry = readTelemetryOnlyConfig(configPath);
|
|
84617
|
+
return explicitTelemetry === void 0 ? config : {
|
|
84618
|
+
...config,
|
|
84619
|
+
telemetry: explicitTelemetry
|
|
84620
|
+
};
|
|
84621
|
+
}
|
|
84622
|
+
function readTelemetryOnlyConfig(path) {
|
|
84623
|
+
if (!existsSync(path)) return void 0;
|
|
84624
|
+
try {
|
|
84625
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
84626
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? typeof parsed.telemetry === "boolean" ? parsed.telemetry : void 0 : void 0;
|
|
84627
|
+
} catch {
|
|
84628
|
+
return;
|
|
84629
|
+
}
|
|
84630
|
+
}
|
|
83283
84631
|
function codeModeRunNativeTool(capletTools) {
|
|
83284
84632
|
const codeModeCaplets = capletTools.map((tool) => ({
|
|
83285
84633
|
id: tool.caplet,
|
|
@@ -83373,7 +84721,7 @@ function createCompositeRemoteParts(remoteOptions, local, options, authKind, res
|
|
|
83373
84721
|
authKind,
|
|
83374
84722
|
...options.writeErr ? { writeErr: options.writeErr } : {}
|
|
83375
84723
|
});
|
|
83376
|
-
const presence = createProjectBindingSessionManager(remoteOptions.cloud, local, options);
|
|
84724
|
+
const presence = createProjectBindingSessionManager(remoteOptions.cloud, remoteOptions, local, options);
|
|
83377
84725
|
return {
|
|
83378
84726
|
remote,
|
|
83379
84727
|
...presence ? { presence } : {}
|
|
@@ -83381,13 +84729,33 @@ function createCompositeRemoteParts(remoteOptions, local, options, authKind, res
|
|
|
83381
84729
|
}
|
|
83382
84730
|
function createRemoteClient(remoteOptions, options, authKind, resolveRuntimeRemoteOptions) {
|
|
83383
84731
|
if (options.remoteClientFactory) return options.remoteClientFactory(remoteOptions);
|
|
84732
|
+
const attachSessionMetadata = isLoopbackRemote(remoteOptions) ? attachSessionMetadataForOptions(options) : void 0;
|
|
83384
84733
|
return createSdkRemoteCapletsClient({
|
|
83385
84734
|
...remoteOptions,
|
|
83386
84735
|
authKind,
|
|
83387
84736
|
...options.writeErr ? { writeErr: options.writeErr } : {},
|
|
84737
|
+
...attachSessionMetadata ? { attachSessionMetadata } : {},
|
|
83388
84738
|
...resolveRuntimeRemoteOptions ? { resolveRuntimeOptions: resolveRuntimeRemoteOptions } : {}
|
|
83389
84739
|
});
|
|
83390
84740
|
}
|
|
84741
|
+
function attachSessionMetadataForOptions(options) {
|
|
84742
|
+
if (!options.projectRoot) return void 0;
|
|
84743
|
+
const projectRoot = canonicalProjectRootForMetadata(options.projectRoot);
|
|
84744
|
+
return {
|
|
84745
|
+
projectRoot,
|
|
84746
|
+
projectConfigPath: resolve(projectRoot, ".caplets", "config.json")
|
|
84747
|
+
};
|
|
84748
|
+
}
|
|
84749
|
+
function canonicalProjectRootForMetadata(projectRoot) {
|
|
84750
|
+
try {
|
|
84751
|
+
return realpathSync(projectRoot);
|
|
84752
|
+
} catch {
|
|
84753
|
+
return projectRoot;
|
|
84754
|
+
}
|
|
84755
|
+
}
|
|
84756
|
+
function isLoopbackRemote(remoteOptions) {
|
|
84757
|
+
return remoteOptions.url.protocol === "http:" && isLoopbackHost(remoteOptions.url.hostname);
|
|
84758
|
+
}
|
|
83391
84759
|
var ProfileBackedNativeCapletsService = class {
|
|
83392
84760
|
options;
|
|
83393
84761
|
baseRemote;
|
|
@@ -83564,6 +84932,8 @@ var CompositeNativeCapletsService = class {
|
|
|
83564
84932
|
closed = false;
|
|
83565
84933
|
batchingReload = false;
|
|
83566
84934
|
codeModeSessions = new CodeModeSessionManager();
|
|
84935
|
+
telemetry;
|
|
84936
|
+
ownsTelemetryDispatcher;
|
|
83567
84937
|
constructor(remote, local, options, remoteIdentity, presence) {
|
|
83568
84938
|
this.remote = remote;
|
|
83569
84939
|
this.local = local;
|
|
@@ -83572,6 +84942,18 @@ var CompositeNativeCapletsService = class {
|
|
|
83572
84942
|
this.presence = presence;
|
|
83573
84943
|
this.unsubscribeRemote = this.remote.onToolsChanged(() => this.updateMergedTools());
|
|
83574
84944
|
this.unsubscribeLocal = this.local.onToolsChanged(() => this.updateMergedTools());
|
|
84945
|
+
this.ownsTelemetryDispatcher = options.telemetryDispatcher === void 0;
|
|
84946
|
+
this.telemetry = createRuntimeTelemetryContext({
|
|
84947
|
+
config: telemetryConfigFromNativeOptions(options),
|
|
84948
|
+
env: options.telemetryEnv,
|
|
84949
|
+
stateDir: options.telemetryStateDir,
|
|
84950
|
+
surface: options.telemetrySurface ?? "native",
|
|
84951
|
+
visibility: options.telemetryVisibility ?? "hidden",
|
|
84952
|
+
runtimeMode: options.telemetryRuntimeMode ?? runtimeModeFromNativeOptions(options),
|
|
84953
|
+
integration: options.telemetryIntegration ?? "native",
|
|
84954
|
+
debugSink: options.telemetryDebugSink,
|
|
84955
|
+
dispatcher: options.telemetryDispatcher
|
|
84956
|
+
});
|
|
83575
84957
|
const merged = this.mergeTools();
|
|
83576
84958
|
this.tools = merged.tools;
|
|
83577
84959
|
this.routes = merged.routes;
|
|
@@ -83585,10 +84967,10 @@ var CompositeNativeCapletsService = class {
|
|
|
83585
84967
|
if (capletId === "code_mode") return await executeCodeModeRunNative(this, request, this.codeModeSessions);
|
|
83586
84968
|
const route = this.routes.get(capletId);
|
|
83587
84969
|
if (route?.service === "local") return await this.local.execute(route.capletId, request);
|
|
83588
|
-
if (route?.service === "remote") return await this.
|
|
84970
|
+
if (route?.service === "remote") return await this.executeRemote(route.capletId, request);
|
|
83589
84971
|
const diagnostic = this.namespaceDiagnostics.get(capletId);
|
|
83590
84972
|
if (diagnostic) throw new CapletsError("CAPLET_NAMESPACE_COLLISION", diagnostic.hint, diagnostic);
|
|
83591
|
-
return await this.
|
|
84973
|
+
return await this.executeRemote(capletId, request);
|
|
83592
84974
|
}
|
|
83593
84975
|
codeModeService() {
|
|
83594
84976
|
return {
|
|
@@ -83608,6 +84990,8 @@ var CompositeNativeCapletsService = class {
|
|
|
83608
84990
|
this.batchingReload = false;
|
|
83609
84991
|
if (remoteReloaded === void 0 || localReloaded === void 0) return false;
|
|
83610
84992
|
if (localReloaded) await this.presence?.updateAllowedCapletIds(this.local.listTools().map((tool) => tool.caplet));
|
|
84993
|
+
this.telemetry.config = telemetryConfigFromNativeOptions(this.options);
|
|
84994
|
+
this.startPresence();
|
|
83611
84995
|
this.updateMergedTools();
|
|
83612
84996
|
return remoteReloaded || localReloaded;
|
|
83613
84997
|
}
|
|
@@ -83625,7 +85009,8 @@ var CompositeNativeCapletsService = class {
|
|
|
83625
85009
|
await Promise.all([
|
|
83626
85010
|
this.remote.close(),
|
|
83627
85011
|
this.local.close(),
|
|
83628
|
-
this.presence?.close()
|
|
85012
|
+
this.presence?.close(),
|
|
85013
|
+
this.ownsTelemetryDispatcher ? this.telemetry.dispatcher.shutdown() : void 0
|
|
83629
85014
|
]);
|
|
83630
85015
|
}
|
|
83631
85016
|
async replaceRemote(remote, remoteIdentityOrPresence, presence) {
|
|
@@ -83664,6 +85049,42 @@ var CompositeNativeCapletsService = class {
|
|
|
83664
85049
|
writeErr(this.options, `Caplets tools-changed listener failed: ${errorMessage(error)}\n`);
|
|
83665
85050
|
}
|
|
83666
85051
|
}
|
|
85052
|
+
async executeRemote(capletId, request) {
|
|
85053
|
+
const started = Date.now();
|
|
85054
|
+
try {
|
|
85055
|
+
const result = await this.remote.execute(capletId, request);
|
|
85056
|
+
this.captureRemoteToolActivation(request, result, started);
|
|
85057
|
+
return result;
|
|
85058
|
+
} catch (error) {
|
|
85059
|
+
const result = errorResult(error);
|
|
85060
|
+
this.captureRemoteReliabilityError(request, result);
|
|
85061
|
+
this.captureRemoteToolActivation(request, result, started);
|
|
85062
|
+
throw error;
|
|
85063
|
+
}
|
|
85064
|
+
}
|
|
85065
|
+
captureRemoteToolActivation(request, result, started) {
|
|
85066
|
+
captureRuntimeTelemetryEvent(this.telemetry, "caplets_tool_activation", {
|
|
85067
|
+
command_family: "native",
|
|
85068
|
+
...toolActivationProperties({
|
|
85069
|
+
config: this.telemetry.config,
|
|
85070
|
+
caplet: void 0,
|
|
85071
|
+
operation: operationFromNativeRequest(request),
|
|
85072
|
+
exposureMode: "direct",
|
|
85073
|
+
result,
|
|
85074
|
+
durationMs: Date.now() - started
|
|
85075
|
+
})
|
|
85076
|
+
}).catch(() => void 0);
|
|
85077
|
+
}
|
|
85078
|
+
captureRemoteReliabilityError(request, result) {
|
|
85079
|
+
captureRuntimeReliabilityEvent(this.telemetry, {
|
|
85080
|
+
command_family: "native",
|
|
85081
|
+
...runtimeFailureTelemetryProperties({
|
|
85082
|
+
operation: operationFromNativeRequest(request),
|
|
85083
|
+
exposureMode: "direct",
|
|
85084
|
+
result
|
|
85085
|
+
})
|
|
85086
|
+
}).catch(() => void 0);
|
|
85087
|
+
}
|
|
83667
85088
|
mergeTools() {
|
|
83668
85089
|
const allLocalTools = this.local.listTools();
|
|
83669
85090
|
const allRemoteTools = this.remote.listTools();
|
|
@@ -83772,7 +85193,7 @@ var CompositeNativeCapletsService = class {
|
|
|
83772
85193
|
}
|
|
83773
85194
|
startPresence() {
|
|
83774
85195
|
this.presence?.start().catch((error) => {
|
|
83775
|
-
writeErr(this.options, `Could not
|
|
85196
|
+
writeErr(this.options, `Could not start upstream Project Binding: ${errorMessage(error)}\n`);
|
|
83776
85197
|
});
|
|
83777
85198
|
}
|
|
83778
85199
|
};
|
|
@@ -83856,27 +85277,173 @@ function remoteCodeModeCallableNativeTools(tools) {
|
|
|
83856
85277
|
function remoteSuppressedCapletIds(allRemoteTools, remoteCodeModeTools = remoteCodeModeCallableNativeTools(allRemoteTools)) {
|
|
83857
85278
|
return new Set([...allRemoteTools.filter((tool) => tool.codeModeRun !== true && (tool.shadowing ?? "forbid") === "forbid").map((tool) => tool.sourceCaplet ?? tool.caplet), ...remoteCodeModeTools.filter((tool) => (tool.shadowing ?? "forbid") === "forbid").map((tool) => tool.caplet)].filter((caplet) => caplet !== nativeCodeModeToolId));
|
|
83858
85279
|
}
|
|
83859
|
-
function createProjectBindingSessionManager(cloud, local, options) {
|
|
83860
|
-
|
|
83861
|
-
|
|
83862
|
-
|
|
83863
|
-
|
|
83864
|
-
|
|
83865
|
-
|
|
83866
|
-
|
|
83867
|
-
|
|
83868
|
-
|
|
83869
|
-
|
|
83870
|
-
|
|
83871
|
-
|
|
83872
|
-
|
|
83873
|
-
|
|
83874
|
-
|
|
83875
|
-
|
|
83876
|
-
|
|
83877
|
-
|
|
85280
|
+
function createProjectBindingSessionManager(cloud, remoteOptions, local, options) {
|
|
85281
|
+
const allowedCapletIds = local.listTools().map((tool) => tool.caplet);
|
|
85282
|
+
if (cloud) {
|
|
85283
|
+
const projectRoot = cloud.projectRoot ?? findProjectRoot();
|
|
85284
|
+
const cloudFetch = options.remote?.fetch;
|
|
85285
|
+
return new ProjectBindingSessionManager({
|
|
85286
|
+
client: new CapletsCloudClient({
|
|
85287
|
+
baseUrl: cloud.url,
|
|
85288
|
+
accessToken: cloud.accessToken,
|
|
85289
|
+
...cloudFetch ? { fetch: cloudFetch } : {}
|
|
85290
|
+
}),
|
|
85291
|
+
workspaceId: cloud.workspaceId,
|
|
85292
|
+
projectRoot,
|
|
85293
|
+
projectFingerprint: fingerprintProjectRoot(projectRoot),
|
|
85294
|
+
projectFiles: projectSyncFiles(projectRoot),
|
|
85295
|
+
allowedCapletIds,
|
|
85296
|
+
heartbeatIntervalMs: cloud.heartbeatIntervalMs,
|
|
85297
|
+
onError: (error) => {
|
|
85298
|
+
writeErr(options, `Caplets Cloud Project Binding heartbeat failed: ${errorMessage(error)}\n`);
|
|
85299
|
+
}
|
|
85300
|
+
});
|
|
85301
|
+
}
|
|
85302
|
+
if (!options.projectRoot || !isLoopbackRemote(remoteOptions)) return;
|
|
85303
|
+
return new RemoteProjectBindingSessionManager({
|
|
85304
|
+
attachUrl: remoteOptions.url,
|
|
85305
|
+
requestInit: remoteOptions.requestInit,
|
|
85306
|
+
fetch: remoteOptions.fetch,
|
|
85307
|
+
projectRoot: options.projectRoot,
|
|
85308
|
+
allowedCapletIds,
|
|
85309
|
+
heartbeatIntervalMs: 3e4,
|
|
85310
|
+
writeErr: options.writeErr
|
|
83878
85311
|
});
|
|
83879
85312
|
}
|
|
85313
|
+
var RemoteProjectBindingSessionManager = class {
|
|
85314
|
+
options;
|
|
85315
|
+
bindingId;
|
|
85316
|
+
sessionId;
|
|
85317
|
+
allowedCapletIds;
|
|
85318
|
+
heartbeatTimer;
|
|
85319
|
+
startPromise;
|
|
85320
|
+
unsupported = false;
|
|
85321
|
+
constructor(options) {
|
|
85322
|
+
this.options = options;
|
|
85323
|
+
this.allowedCapletIds = [...options.allowedCapletIds];
|
|
85324
|
+
}
|
|
85325
|
+
async start() {
|
|
85326
|
+
if (this.unsupported) return;
|
|
85327
|
+
if (!this.startPromise) {
|
|
85328
|
+
const start = this.register();
|
|
85329
|
+
this.startPromise = start;
|
|
85330
|
+
start.catch((error) => {
|
|
85331
|
+
if (isUnsupportedProjectBinding(error)) this.unsupported = true;
|
|
85332
|
+
if (this.startPromise === start) this.startPromise = void 0;
|
|
85333
|
+
});
|
|
85334
|
+
}
|
|
85335
|
+
return await this.startPromise;
|
|
85336
|
+
}
|
|
85337
|
+
async close() {
|
|
85338
|
+
await this.startPromise?.catch(() => void 0);
|
|
85339
|
+
this.stopHeartbeat();
|
|
85340
|
+
const bindingId = this.bindingId;
|
|
85341
|
+
this.bindingId = void 0;
|
|
85342
|
+
const sessionId = this.sessionId;
|
|
85343
|
+
this.sessionId = void 0;
|
|
85344
|
+
if (!bindingId || !sessionId) return;
|
|
85345
|
+
await this.fetchJson(projectBindingUrl(this.options.attachUrl, bindingId, "session"), {
|
|
85346
|
+
method: "DELETE",
|
|
85347
|
+
body: {
|
|
85348
|
+
sessionId,
|
|
85349
|
+
terminalReason: {
|
|
85350
|
+
code: "completed",
|
|
85351
|
+
message: "Binding Session completed."
|
|
85352
|
+
}
|
|
85353
|
+
}
|
|
85354
|
+
}).catch(() => void 0);
|
|
85355
|
+
}
|
|
85356
|
+
async updateAllowedCapletIds(allowedCapletIds) {
|
|
85357
|
+
this.allowedCapletIds = [...allowedCapletIds];
|
|
85358
|
+
await this.startPromise?.catch(() => void 0);
|
|
85359
|
+
if (!this.bindingId || !this.sessionId) return;
|
|
85360
|
+
await this.heartbeat().catch(() => void 0);
|
|
85361
|
+
}
|
|
85362
|
+
async register() {
|
|
85363
|
+
const projectFingerprint = fingerprintProjectRoot(this.options.projectRoot);
|
|
85364
|
+
const response = await this.fetchJson(projectBindingUrl(this.options.attachUrl, "sessions"), {
|
|
85365
|
+
method: "POST",
|
|
85366
|
+
body: {
|
|
85367
|
+
projectRoot: this.options.projectRoot,
|
|
85368
|
+
projectFingerprint,
|
|
85369
|
+
allowedCapletIds: this.allowedCapletIds
|
|
85370
|
+
}
|
|
85371
|
+
});
|
|
85372
|
+
if (!response.binding?.bindingId || !response.sessionId) throw new CapletsError("SERVER_UNAVAILABLE", "Project Binding session response was invalid.");
|
|
85373
|
+
this.bindingId = response.binding.bindingId;
|
|
85374
|
+
this.sessionId = response.sessionId;
|
|
85375
|
+
this.startHeartbeat();
|
|
85376
|
+
}
|
|
85377
|
+
startHeartbeat() {
|
|
85378
|
+
this.stopHeartbeat();
|
|
85379
|
+
this.heartbeatTimer = setInterval(() => {
|
|
85380
|
+
this.heartbeat().catch((error) => {
|
|
85381
|
+
this.disconnect();
|
|
85382
|
+
this.options.writeErr?.(`Remote Project Binding heartbeat failed: ${errorMessage(error)}\n`);
|
|
85383
|
+
});
|
|
85384
|
+
}, this.options.heartbeatIntervalMs);
|
|
85385
|
+
this.heartbeatTimer.unref?.();
|
|
85386
|
+
}
|
|
85387
|
+
stopHeartbeat() {
|
|
85388
|
+
if (!this.heartbeatTimer) return;
|
|
85389
|
+
clearInterval(this.heartbeatTimer);
|
|
85390
|
+
this.heartbeatTimer = void 0;
|
|
85391
|
+
}
|
|
85392
|
+
disconnect() {
|
|
85393
|
+
this.stopHeartbeat();
|
|
85394
|
+
this.bindingId = void 0;
|
|
85395
|
+
this.sessionId = void 0;
|
|
85396
|
+
this.startPromise = void 0;
|
|
85397
|
+
}
|
|
85398
|
+
async heartbeat() {
|
|
85399
|
+
if (!this.bindingId || !this.sessionId) return;
|
|
85400
|
+
await this.fetchJson(projectBindingUrl(this.options.attachUrl, this.bindingId, "heartbeat"), {
|
|
85401
|
+
method: "POST",
|
|
85402
|
+
body: {
|
|
85403
|
+
sessionId: this.sessionId,
|
|
85404
|
+
state: "ready",
|
|
85405
|
+
syncState: "idle",
|
|
85406
|
+
allowedCapletIds: this.allowedCapletIds
|
|
85407
|
+
}
|
|
85408
|
+
});
|
|
85409
|
+
}
|
|
85410
|
+
async fetchJson(url, input) {
|
|
85411
|
+
const headers = new Headers(this.options.requestInit.headers);
|
|
85412
|
+
headers.set("content-type", "application/json");
|
|
85413
|
+
const response = await (this.options.fetch ?? fetch)(url, {
|
|
85414
|
+
...this.options.requestInit,
|
|
85415
|
+
method: input.method,
|
|
85416
|
+
headers,
|
|
85417
|
+
body: JSON.stringify(input.body)
|
|
85418
|
+
});
|
|
85419
|
+
if (!response.ok) {
|
|
85420
|
+
let payload;
|
|
85421
|
+
try {
|
|
85422
|
+
payload = await response.json();
|
|
85423
|
+
} catch {
|
|
85424
|
+
payload = void 0;
|
|
85425
|
+
}
|
|
85426
|
+
const error = isRecord(payload) && isRecord(payload.error) ? payload.error : void 0;
|
|
85427
|
+
if (error?.code === "UNSUPPORTED_CAPABILITY" && typeof error.message === "string") throw new CapletsError("UNSUPPORTED_CAPABILITY", error.message);
|
|
85428
|
+
throw new CapletsError("SERVER_UNAVAILABLE", `Project Binding request failed (${response.status}).`);
|
|
85429
|
+
}
|
|
85430
|
+
return await response.json().catch(() => ({}));
|
|
85431
|
+
}
|
|
85432
|
+
};
|
|
85433
|
+
function isUnsupportedProjectBinding(error) {
|
|
85434
|
+
return isRecord(error) && error.code === "UNSUPPORTED_CAPABILITY";
|
|
85435
|
+
}
|
|
85436
|
+
function projectBindingUrl(attachUrl, ...segments) {
|
|
85437
|
+
const url = new URL(attachUrl);
|
|
85438
|
+
url.pathname = [
|
|
85439
|
+
url.pathname.replace(/\/+$/u, ""),
|
|
85440
|
+
"project-bindings",
|
|
85441
|
+
...segments.map(encodeURIComponent)
|
|
85442
|
+
].join("/");
|
|
85443
|
+
url.search = "";
|
|
85444
|
+
url.hash = "";
|
|
85445
|
+
return url;
|
|
85446
|
+
}
|
|
83880
85447
|
function createLocalOverlayConfigLoader(options) {
|
|
83881
85448
|
let hasLoaded = false;
|
|
83882
85449
|
let previousWarnings = /* @__PURE__ */ new Set();
|
|
@@ -83913,4 +85480,4 @@ function errorMessage(error) {
|
|
|
83913
85480
|
return error instanceof Error ? error.message : String(error);
|
|
83914
85481
|
}
|
|
83915
85482
|
//#endregion
|
|
83916
|
-
export {
|
|
85483
|
+
export { redactCodeModeLogText as $, getParseErrorMessage as $n, readTokenBundle as $t, resolveRemoteMode as A, GetPromptRequestSchema as An, loadProjectConfig as At, nativeCodeModeToolId as B, LoggingLevelSchema as Bn, discoverCapletFiles as Bt, CapletsCloudClient as C, CreateMessageResultSchema as Cn, ServerRegistry as Ct, normalizeRemoteProfileHostUrl as D, ElicitResultSchema as Dn, loadConfigWithSources as Dt, isCapletsCloudUrl as E, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as En, loadConfig as Et, resolveCapletsServer as F, ListPromptsRequestSchema as Fn, FileVaultStore as Ft, runCodeMode as G, assertCompleteRequestPrompt as Gn, markdownStructuredContent as Gt, codeModeRunInputSchema as H, ReadResourceRequestSchema as Hn, loadCapletFilesFromMap as Ht, nativeCapletPromptGuidance as I, ListResourceTemplatesRequestSchema as In, VAULT_MAX_VALUE_BYTES as It, diagnoseCodeModeTypeScript as J, isJSONRPCErrorResponse as Jn, runOAuthFlow as Jt, CodeModeSessionManager as K, assertCompleteRequestResourceTemplate as Kn, refreshOAuthTokenBundle as Kt, nativeCapletToolDescription as L, ListResourcesRequestSchema as Ln, validateVaultKeyName as Lt, controlUrlForBase as M, InitializedNotificationSchema as Mn, vaultBootstrapResolver as Mt, isLoopbackHost as N, JSONRPCMessageSchema as Nn, vaultResolverForAuthDir as Nt, resolveCapletsRemote as O, EmptyResultSchema as On, loadGlobalConfig as Ot, parseServerBaseUrl as P, LATEST_PROTOCOL_VERSION as Pn, vaultStoreForAuthDir as Pt, CodeModeLogStore as Q, getObjectShape as Qn, isTokenBundleExpired as Qt, nativeCapletToolName as R, ListRootsResultSchema as Rn, decryptVaultValue as Rt, buildProjectSyncManifest as S, CompleteRequestSchema as Sn, handleServerTool as St, hostedCloudWorkspaceFromRemoteUrl as T, CreateTaskResultSchema as Tn, GoogleDiscoveryManager as Tt, codeModeRunParamsSchema as U, SUPPORTED_PROTOCOL_VERSIONS as Un, hasRenderableStructuredContent as Ut, nativeCodeModeToolName as V, McpError as Vn, validateCapletFile as Vt, emptyCodeModeRunMeta as W, SetLevelRequestSchema as Wn, markdownCallToolResultContent as Wt, listCodeModeCallableCaplets as X, isJSONRPCResultResponse as Xn, startOAuthFlow as Xt, createCodeModeCapletsApi as Y, isJSONRPCRequest as Yn, startGenericOAuthFlow as Yt, CodeModeJournalStore as Z, getLiteralValue as Zn, deleteTokenBundle as Zt, attachErrorResponse as _, Protocol as _n, rotateTelemetryIdentity as _t, CloudAuthStore as a, defaultConfigPath as an, safeParse as ar, version as at, invokeAttachExport$1 as b, CallToolRequestSchema as bn, findProjectRoot as bt, redactedCloudAuthStatus as c, resolveCapletsRoot as cn, buildProductTelemetryEvent as ct, projectBindingError as d, resolveProjectConfigPath as dn, maybePrintTelemetryNotice as dt, DEFAULT_AUTH_DIR as en, getSchemaDescription as er, codeModeDeclarationHash as et, projectBindingRecovery as f, ReadBuffer as fn, resolveTelemetryState as ft, CAPLETS_ATTACH_SESSION_HEADER as g, AjvJsonSchemaValidator as gn, readTelemetryNotice as gt, createSdkRemoteCapletsClient as h, assertToolsCallTaskCapability as hn, readTelemetryIdentity as ht, createRemoteProfileStore as i, defaultConfigBaseDir as in, objectFromShape as ir, CapletsEngine as it, appendBasePath as j, InitializeRequestSchema as jn, parseConfig as jt, resolveHostedCloudRemote as k, ErrorCode as kn, loadLocalOverlayConfigWithSources as kt, PROJECT_BINDING_ERROR_CODES as l, resolveConfigPath as ln, buildReliabilityTelemetryEvent as lt, RemoteNativeCapletsService as m, assertClientRequestTaskCapability as mn, readTelemetryDeliveryHealth as mt, resolveRemoteSelection as n, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as nn, isZ4Schema as nr, generateCodeModeRunToolDescription as nt, cloudAuthPath as o, defaultStateBaseDir as on, safeParseAsync as or, createTelemetryDispatcher as ot, CloudAuthClient as p, serializeMessage as pn, deleteTelemetryIdentity as pt, QuickJsCodeModeSandbox as q, isInitializeRequest as qn, runGenericOAuthFlow as qt, cloudCredentialsFromRemoteProfile as r, defaultCacheBaseDir as rn, normalizeObjectSchema as rr, minifyCodeModeDeclarationText as rt, migrateCredentials as s, defaultTelemetryStateDir as sn, TelemetryDebugSink as st, createNativeCapletsService as t, DEFAULT_COMPLETION_CACHE_DIR as tn, isSchemaOptional as tr, generateCodeModeDeclarations as tt, ProjectBindingError as u, resolveProjectCapletsRoot as un, durationBucket as ut, buildAttachProjection as v, mergeCapabilities as vn, resolveExposure as vt, resolveNativeCapletsServiceOptions as w, CreateMessageResultWithToolsSchema as wn, capabilityDescription as wt, invokeNativeAttachExport as x, CallToolResultSchema as xn, fingerprintProjectRoot as xt, buildNativeAttachProjection as y, toJsonSchemaCompat as yn, decodeDirectResourceUri as yt, nativeCapletsSystemGuidance as z, ListToolsRequestSchema as zn, encryptVaultValue as zt };
|