@caplets/core 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/caplet-files-bundle.d.ts +24 -9
  2. package/dist/caplet-source.js +368 -4588
  3. package/dist/cli/auth.d.ts +40 -2
  4. package/dist/cli/cloud-add.d.ts +8 -0
  5. package/dist/cli/code-mode.d.ts +16 -0
  6. package/dist/cli/commands.d.ts +3 -1
  7. package/dist/cli/doctor.d.ts +3 -0
  8. package/dist/cli/setup.d.ts +7 -0
  9. package/dist/cli-tools.d.ts +1 -1
  10. package/dist/cli.d.ts +1 -0
  11. package/dist/cloud-auth/client.d.ts +15 -0
  12. package/dist/cloud-auth/types.d.ts +2 -1
  13. package/dist/code-mode/api.d.ts +32 -0
  14. package/dist/code-mode/declarations.d.ts +5 -0
  15. package/dist/code-mode/diagnostics.d.ts +8 -0
  16. package/dist/code-mode/index.d.ts +4 -0
  17. package/dist/code-mode/logs.d.ts +21 -0
  18. package/dist/code-mode/runner.d.ts +15 -0
  19. package/dist/code-mode/runtime-api.generated.d.ts +1 -0
  20. package/dist/code-mode/sandbox.d.ts +28 -0
  21. package/dist/code-mode/static-analysis.d.ts +2 -0
  22. package/dist/code-mode/tool.d.ts +11 -0
  23. package/dist/code-mode/types.d.ts +120 -0
  24. package/dist/code-mode.js +147855 -0
  25. package/dist/{completion-brgziz4L.js → completion-CbazRAiL.js} +5 -2
  26. package/dist/config/paths.d.ts +2 -0
  27. package/dist/config-runtime.d.ts +13 -4
  28. package/dist/config-runtime.js +31 -2
  29. package/dist/config.d.ts +34 -9
  30. package/dist/downstream.d.ts +20 -2
  31. package/dist/engine.d.ts +20 -0
  32. package/dist/exposure/direct-names.d.ts +9 -0
  33. package/dist/exposure/discovery.d.ts +75 -0
  34. package/dist/exposure/policy.d.ts +8 -0
  35. package/dist/generated-tool-input-schema.d.ts +89 -59
  36. package/dist/generated-tool-input-schema.js +38 -27
  37. package/dist/graphql.d.ts +1 -1
  38. package/dist/http-actions.d.ts +1 -1
  39. package/dist/index.d.ts +13 -0
  40. package/dist/index.js +1096 -154
  41. package/dist/native/service.d.ts +6 -0
  42. package/dist/native/tools.d.ts +2 -0
  43. package/dist/native.d.ts +1 -1
  44. package/dist/native.js +2 -2
  45. package/dist/observed-output-shapes/extract.d.ts +5 -0
  46. package/dist/observed-output-shapes/file-store.d.ts +17 -0
  47. package/dist/observed-output-shapes/index.d.ts +7 -0
  48. package/dist/observed-output-shapes/key.d.ts +14 -0
  49. package/dist/observed-output-shapes/merge.d.ts +2 -0
  50. package/dist/observed-output-shapes/pure.d.ts +5 -0
  51. package/dist/observed-output-shapes/pure.js +241 -0
  52. package/dist/observed-output-shapes/schema.d.ts +1 -0
  53. package/dist/observed-output-shapes/types.d.ts +84 -0
  54. package/dist/observed-output-shapes/typescript.d.ts +7 -0
  55. package/dist/observed-output-shapes-uzAMQPhg.js +485 -0
  56. package/dist/observed-output-shapes.js +2 -0
  57. package/dist/openapi.d.ts +1 -1
  58. package/dist/project-binding/index.d.ts +2 -0
  59. package/dist/project-binding.js +22 -0
  60. package/dist/redaction.d.ts +14 -0
  61. package/dist/redaction.js +30 -0
  62. package/dist/registry.d.ts +4 -0
  63. package/dist/remote/options.d.ts +2 -0
  64. package/dist/remote-control/types.d.ts +1 -1
  65. package/dist/runtime-plan/resources.d.ts +2 -0
  66. package/dist/runtime-plan.js +8 -2
  67. package/dist/schemas-1HZ0kFpx.js +4270 -0
  68. package/dist/serve/session.d.ts +15 -3
  69. package/dist/{service-BXcE4Rv8.js → service-D0MwLNyb.js} +29175 -26499
  70. package/dist/stable-json.d.ts +3 -0
  71. package/dist/stable-json.js +26 -0
  72. package/dist/tools.d.ts +22 -11
  73. package/dist/{validation-BBG4skZf.js → validation-CdqbI2zN.js} +25 -4
  74. package/package.json +29 -3
@@ -0,0 +1,485 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ //#region src/observed-output-shapes/types.ts
5
+ const OBSERVED_OUTPUT_SHAPE_VERSION = 1;
6
+ const OBSERVED_OUTPUT_SHAPE_LIMITS = {
7
+ maxDepth: 6,
8
+ maxObjectFields: 40,
9
+ maxArrayElements: 20,
10
+ maxUnionVariants: 4,
11
+ maxTypeScriptChars: 4e3,
12
+ maxStoredJsonBytes: 16e3,
13
+ ttlMs: 720 * 60 * 60 * 1e3,
14
+ maxLocalEntries: 2e3
15
+ };
16
+ //#endregion
17
+ //#region src/stable-json.ts
18
+ function stableJsonValue(value) {
19
+ if (Array.isArray(value)) return value.map((item) => stableJsonValue(item));
20
+ if (isPlainObject$2(value)) {
21
+ const sorted = {};
22
+ for (const key of Object.keys(value).sort()) {
23
+ const item = value[key];
24
+ if (item !== void 0) sorted[key] = stableJsonValue(item);
25
+ }
26
+ return sorted;
27
+ }
28
+ return value;
29
+ }
30
+ function stableJsonStringify(value) {
31
+ return JSON.stringify(stableJsonValue(value));
32
+ }
33
+ function isPlainObject$2(value) {
34
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
35
+ }
36
+ //#endregion
37
+ //#region src/schema-hash.ts
38
+ function schemaHash(schema) {
39
+ if (schema === void 0 || schema === null) return null;
40
+ const json = stableJsonStringify(schema);
41
+ return `sha256:${createHash("sha256").update(json).digest("hex")}`;
42
+ }
43
+ //#endregion
44
+ //#region src/observed-output-shapes/key.ts
45
+ function observedOutputShapeStorageKey(key) {
46
+ return stableHash(key);
47
+ }
48
+ function observedOutputShapeKey(input) {
49
+ const toolDescriptorHash = input.toolDescriptor ? stableHash(input.toolDescriptor) : void 0;
50
+ const outputSchemaHash = schemaHash(input.outputSchema) ?? void 0;
51
+ return {
52
+ scope: input.scope,
53
+ ...input.workspaceId ? { workspaceId: input.workspaceId } : {},
54
+ ...input.projectFingerprint ? { projectFingerprint: input.projectFingerprint } : {},
55
+ capletId: input.caplet.server,
56
+ backendKind: input.caplet.backend,
57
+ backendFingerprint: backendFingerprint(input.caplet),
58
+ toolName: input.toolName,
59
+ ...toolDescriptorHash ? { toolDescriptorHash } : {},
60
+ ...outputSchemaHash ? { outputSchemaHash } : {},
61
+ resultVersion: 1
62
+ };
63
+ }
64
+ function backendFingerprint(caplet) {
65
+ return stableHash(nonSecretBackendIdentity(caplet));
66
+ }
67
+ function stableHash(value) {
68
+ return createHash("sha256").update(stableJsonStringify(value)).digest("hex");
69
+ }
70
+ function nonSecretBackendIdentity(caplet) {
71
+ switch (caplet.backend) {
72
+ case "mcp": return caplet.transport === "stdio" ? {
73
+ backend: caplet.backend,
74
+ server: caplet.server,
75
+ transport: caplet.transport,
76
+ command: caplet.command,
77
+ args: caplet.args,
78
+ cwd: caplet.cwd
79
+ } : {
80
+ backend: caplet.backend,
81
+ server: caplet.server,
82
+ transport: caplet.transport,
83
+ url: caplet.url
84
+ };
85
+ case "openapi": return {
86
+ backend: caplet.backend,
87
+ server: caplet.server,
88
+ specPath: caplet.specPath,
89
+ specUrl: caplet.specUrl,
90
+ baseUrl: caplet.baseUrl
91
+ };
92
+ case "graphql": return {
93
+ backend: caplet.backend,
94
+ server: caplet.server,
95
+ endpointUrl: caplet.endpointUrl,
96
+ schemaPath: caplet.schemaPath,
97
+ schemaUrl: caplet.schemaUrl,
98
+ introspection: caplet.introspection,
99
+ operations: caplet.operations
100
+ };
101
+ case "http": return {
102
+ backend: caplet.backend,
103
+ server: caplet.server,
104
+ baseUrl: caplet.baseUrl,
105
+ actions: Object.fromEntries(Object.entries(caplet.actions).map(([name, action]) => [name, {
106
+ method: action.method,
107
+ path: action.path,
108
+ query: action.query,
109
+ hasJsonBody: action.jsonBody !== void 0
110
+ }]))
111
+ };
112
+ case "cli": return {
113
+ backend: caplet.backend,
114
+ server: caplet.server,
115
+ cwd: caplet.cwd,
116
+ actions: Object.fromEntries(Object.entries(caplet.actions).map(([name, action]) => [name, {
117
+ command: action.command,
118
+ args: action.args,
119
+ cwd: action.cwd,
120
+ output: action.output
121
+ }]))
122
+ };
123
+ case "caplets": return {
124
+ backend: caplet.backend,
125
+ server: caplet.server,
126
+ configPath: caplet.configPath,
127
+ capletsRoot: caplet.capletsRoot
128
+ };
129
+ }
130
+ }
131
+ //#endregion
132
+ //#region src/observed-output-shapes/file-store.ts
133
+ var FileObservedOutputShapeStore = class {
134
+ cacheDir;
135
+ options;
136
+ constructor(cacheDir, options = {}) {
137
+ this.cacheDir = cacheDir;
138
+ this.options = options;
139
+ }
140
+ async read(key) {
141
+ try {
142
+ const parsed = JSON.parse(readFileSync(this.pathFor(key), "utf8"));
143
+ if (Date.now() > Date.parse(parsed.expiresAt)) return void 0;
144
+ if (!isObservedOutputShape(parsed.shape)) return void 0;
145
+ return parsed.shape;
146
+ } catch {
147
+ return;
148
+ }
149
+ }
150
+ async write(key, shape) {
151
+ const payload = {
152
+ key,
153
+ shape,
154
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
155
+ expiresAt: new Date(Date.now() + this.ttlMs()).toISOString()
156
+ };
157
+ if (new TextEncoder().encode(JSON.stringify(payload)).byteLength > OBSERVED_OUTPUT_SHAPE_LIMITS.maxStoredJsonBytes) return;
158
+ mkdirSync(this.cacheDir, { recursive: true });
159
+ const path = this.pathFor(key);
160
+ const tempPath = `${path}.${process.pid}.tmp`;
161
+ writeFileSync(tempPath, JSON.stringify(payload), { mode: 384 });
162
+ renameSync(tempPath, path);
163
+ this.prune().catch(() => void 0);
164
+ }
165
+ async prune(now = /* @__PURE__ */ new Date()) {
166
+ if (!existsSync(this.cacheDir)) return {
167
+ removed: 0,
168
+ remaining: 0
169
+ };
170
+ const files = this.entries();
171
+ let removed = 0;
172
+ const live = [];
173
+ for (const file of files) try {
174
+ const parsed = JSON.parse(readFileSync(file.path, "utf8"));
175
+ const expiresAt = Date.parse(parsed.expiresAt);
176
+ if (!Number.isFinite(expiresAt) || now.getTime() > expiresAt || !isObservedOutputShape(parsed.shape)) {
177
+ rmSync(file.path, { force: true });
178
+ removed++;
179
+ continue;
180
+ }
181
+ live.push({
182
+ path: file.path,
183
+ expiresAt,
184
+ mtimeMs: file.mtimeMs
185
+ });
186
+ } catch {
187
+ rmSync(file.path, { force: true });
188
+ removed++;
189
+ }
190
+ const maxEntries = this.maxEntries();
191
+ const overflow = Math.max(0, live.length - maxEntries);
192
+ if (overflow > 0) for (const entry of live.sort((a, b) => a.mtimeMs - b.mtimeMs).slice(0, overflow)) {
193
+ rmSync(entry.path, { force: true });
194
+ removed++;
195
+ }
196
+ return {
197
+ removed,
198
+ remaining: Math.max(0, live.length - overflow)
199
+ };
200
+ }
201
+ async health() {
202
+ try {
203
+ mkdirSync(this.cacheDir, { recursive: true });
204
+ const probe = join(this.cacheDir, `.health-${process.pid}.json`);
205
+ writeFileSync(probe, "{}", { mode: 384 });
206
+ rmSync(probe, { force: true });
207
+ const prune = await this.prune();
208
+ return {
209
+ path: this.cacheDir,
210
+ readable: true,
211
+ writable: true,
212
+ entryCount: this.entries().length,
213
+ prune
214
+ };
215
+ } catch (error) {
216
+ return {
217
+ path: this.cacheDir,
218
+ readable: false,
219
+ writable: false,
220
+ error: error instanceof Error ? error.message : String(error)
221
+ };
222
+ }
223
+ }
224
+ pathFor(key) {
225
+ return join(this.cacheDir, `${observedOutputShapeStorageKey(key)}.json`);
226
+ }
227
+ entries() {
228
+ try {
229
+ return readdirSync(this.cacheDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => {
230
+ const path = join(this.cacheDir, entry.name);
231
+ return {
232
+ path,
233
+ mtimeMs: readMtimeMs(path)
234
+ };
235
+ });
236
+ } catch {
237
+ return [];
238
+ }
239
+ }
240
+ ttlMs() {
241
+ return this.options.ttlMs ?? OBSERVED_OUTPUT_SHAPE_LIMITS.ttlMs;
242
+ }
243
+ maxEntries() {
244
+ return this.options.maxEntries ?? OBSERVED_OUTPUT_SHAPE_LIMITS.maxLocalEntries;
245
+ }
246
+ };
247
+ function readMtimeMs(path) {
248
+ try {
249
+ return statSync(path).mtimeMs;
250
+ } catch {
251
+ return 0;
252
+ }
253
+ }
254
+ function isObservedOutputShape(value) {
255
+ return Boolean(value && typeof value === "object" && value.version === 1 && value.source === "observed" && typeof value.typeScript === "string" && typeof value.sampleCount === "number");
256
+ }
257
+ //#endregion
258
+ //#region src/observed-output-shapes/merge.ts
259
+ function mergeJsonShapes(left, right) {
260
+ if (left.kind === "unknown" || right.kind === "unknown") return { kind: "unknown" };
261
+ if (left.kind === right.kind) {
262
+ if (left.kind === "object" && right.kind === "object") return mergeObjects(left, right);
263
+ if (left.kind === "array" && right.kind === "array") return mergeArrays(left, right);
264
+ if (left.kind === "union" && right.kind === "union") return boundedUnion([...left.variants, ...right.variants]);
265
+ return left;
266
+ }
267
+ return boundedUnion([...left.kind === "union" ? left.variants : [left], ...right.kind === "union" ? right.variants : [right]]);
268
+ }
269
+ function mergeObjects(left, right) {
270
+ const fields = {};
271
+ const keys = [...new Set([...Object.keys(left.fields), ...Object.keys(right.fields)])].sort();
272
+ let truncated = left.truncated === true || right.truncated === true;
273
+ const selected = keys.slice(0, OBSERVED_OUTPUT_SHAPE_LIMITS.maxObjectFields);
274
+ truncated = truncated || keys.length > selected.length;
275
+ for (const key of selected) {
276
+ const leftField = left.fields[key];
277
+ const rightField = right.fields[key];
278
+ if (leftField && rightField) fields[key] = {
279
+ optional: true,
280
+ shape: mergeJsonShapes(leftField.shape, rightField.shape)
281
+ };
282
+ else fields[key] = {
283
+ optional: true,
284
+ shape: (leftField ?? rightField).shape
285
+ };
286
+ }
287
+ return {
288
+ kind: "object",
289
+ fields,
290
+ ...truncated ? { truncated: true } : {}
291
+ };
292
+ }
293
+ function mergeArrays(left, right) {
294
+ const element = left.element && right.element ? mergeJsonShapes(left.element, right.element) : left.element ?? right.element;
295
+ return {
296
+ kind: "array",
297
+ ...element ? { element } : {},
298
+ ...left.truncated === true || right.truncated === true ? { truncated: true } : {}
299
+ };
300
+ }
301
+ function boundedUnion(variants) {
302
+ const flattened = variants.flatMap((variant) => variant.kind === "union" ? variant.variants : [variant]);
303
+ const unique = [];
304
+ for (const variant of flattened) {
305
+ if (variant.kind === "unknown") return { kind: "unknown" };
306
+ const key = JSON.stringify(variant);
307
+ if (!unique.some((existing) => JSON.stringify(existing) === key)) unique.push(variant);
308
+ }
309
+ if (unique.length === 1) return unique[0];
310
+ if (unique.length > OBSERVED_OUTPUT_SHAPE_LIMITS.maxUnionVariants) return { kind: "unknown" };
311
+ return {
312
+ kind: "union",
313
+ variants: unique.sort((a, b) => a.kind.localeCompare(b.kind))
314
+ };
315
+ }
316
+ //#endregion
317
+ //#region src/observed-output-shapes/typescript.ts
318
+ function shapeToTypeScript(shape, typeName = "ObservedOutput", maxChars = OBSERVED_OUTPUT_SHAPE_LIMITS.maxTypeScriptChars) {
319
+ const typeScript = `type ${typeName} = ${shapeType(shape)};`;
320
+ if (typeScript.length <= maxChars) return {
321
+ typeScript,
322
+ truncated: hasTruncatedShape(shape)
323
+ };
324
+ return {
325
+ typeScript: `type ${typeName} = unknown;`,
326
+ truncated: true
327
+ };
328
+ }
329
+ function shapeType(shape) {
330
+ switch (shape.kind) {
331
+ case "null": return "null";
332
+ case "boolean": return "boolean";
333
+ case "number": return "number";
334
+ case "string": return "string";
335
+ case "unknown": return "unknown";
336
+ case "array": return `${shape.element ? wrapArrayElement(shapeType(shape.element)) : "unknown"}[]`;
337
+ case "object": return objectType(shape);
338
+ case "union": return unionType(shape.variants);
339
+ }
340
+ }
341
+ function hasTruncatedShape(shape) {
342
+ if ("truncated" in shape && shape.truncated === true) return true;
343
+ if (shape.kind === "array") return shape.element ? hasTruncatedShape(shape.element) : false;
344
+ if (shape.kind === "object") return Object.values(shape.fields).some((field) => hasTruncatedShape(field.shape));
345
+ if (shape.kind === "union") return shape.variants.some((variant) => hasTruncatedShape(variant));
346
+ return false;
347
+ }
348
+ function objectType(shape) {
349
+ const entries = Object.entries(shape.fields);
350
+ if (entries.length === 0) return "Record<string, unknown>";
351
+ return `{ ${entries.map(([key, field]) => `${propertyName(key)}?: ${shapeType(field.shape)};`).join(" ")} }`;
352
+ }
353
+ function unionType(variants) {
354
+ const rendered = [...new Set(variants.map((variant) => shapeType(variant)))];
355
+ return rendered.length === 0 ? "unknown" : rendered.join(" | ");
356
+ }
357
+ function wrapArrayElement(value) {
358
+ return value.includes(" | ") ? `(${value})` : value;
359
+ }
360
+ function propertyName(key) {
361
+ return /^[A-Za-z_$][\w$]*$/u.test(key) ? key : JSON.stringify(key);
362
+ }
363
+ //#endregion
364
+ //#region src/observed-output-shapes/extract.ts
365
+ function observeOutputShape(input) {
366
+ const shape = extractJsonShape(input.value);
367
+ if (!shape) return void 0;
368
+ const merged = input.existing ? mergeJsonShapes(input.existing.jsonShape, shape) : shape;
369
+ const emitted = shapeToTypeScript(merged);
370
+ const observed = {
371
+ version: 1,
372
+ source: "observed",
373
+ observedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
374
+ sampleCount: (input.existing?.sampleCount ?? 0) + 1,
375
+ typeScript: emitted.typeScript,
376
+ jsonShape: merged,
377
+ truncated: emitted.truncated || hasTruncatedShape(merged)
378
+ };
379
+ return storedBytes(observed) > OBSERVED_OUTPUT_SHAPE_LIMITS.maxStoredJsonBytes ? {
380
+ ...observed,
381
+ typeScript: "type ObservedOutput = unknown;",
382
+ jsonShape: { kind: "unknown" },
383
+ truncated: true
384
+ } : observed;
385
+ }
386
+ function extractJsonShape(value) {
387
+ if (!isShapeableJsonRoot(value)) return void 0;
388
+ return shapeFor(value, 0);
389
+ }
390
+ function parseShapeableJsonText(value) {
391
+ if (!isPlainObject$1(value) || !Array.isArray(value.content) || value.content.length !== 1) return;
392
+ const [item] = value.content;
393
+ if (!isPlainObject$1(item) || item.type !== "text" || typeof item.text !== "string") return;
394
+ const text = item.text.trim();
395
+ if (!text || !text.startsWith("{") && !text.startsWith("[")) return void 0;
396
+ try {
397
+ const parsed = JSON.parse(text);
398
+ return isShapeableJsonRoot(parsed) ? parsed : void 0;
399
+ } catch {
400
+ return;
401
+ }
402
+ }
403
+ function normalizedObservableValue(result) {
404
+ if (isPlainObject$1(result)) {
405
+ const structured = result.structuredContent;
406
+ if (structured !== void 0) {
407
+ if (isPlainObject$1(structured) && "caplets" in structured && "result" in structured) return isShapeableJsonRoot(structured.result) ? structured.result : void 0;
408
+ return isShapeableJsonRoot(structured) ? structured : void 0;
409
+ }
410
+ }
411
+ return parseShapeableJsonText(result);
412
+ }
413
+ function shapeFor(value, depth) {
414
+ if (depth >= OBSERVED_OUTPUT_SHAPE_LIMITS.maxDepth) return { kind: "unknown" };
415
+ if (value === null) return { kind: "null" };
416
+ if (typeof value === "boolean") return { kind: "boolean" };
417
+ if (typeof value === "number") return { kind: "number" };
418
+ if (typeof value === "string") return { kind: "string" };
419
+ if (Array.isArray(value)) return arrayShape(value, depth);
420
+ if (isPlainObject$1(value)) return objectShape(value, depth);
421
+ return { kind: "unknown" };
422
+ }
423
+ function arrayShape(value, depth) {
424
+ const sampled = value.slice(0, OBSERVED_OUTPUT_SHAPE_LIMITS.maxArrayElements);
425
+ let element;
426
+ for (const item of sampled) {
427
+ const itemShape = shapeFor(item, depth + 1);
428
+ element = element ? mergeJsonShapes(element, itemShape) : itemShape;
429
+ }
430
+ return {
431
+ kind: "array",
432
+ ...element ? { element } : {},
433
+ ...value.length > sampled.length ? { truncated: true } : {}
434
+ };
435
+ }
436
+ function objectShape(value, depth) {
437
+ const keys = Object.keys(value).sort();
438
+ const selected = keys.slice(0, OBSERVED_OUTPUT_SHAPE_LIMITS.maxObjectFields);
439
+ const fields = {};
440
+ for (const key of selected) fields[key] = {
441
+ optional: true,
442
+ shape: shapeFor(value[key], depth + 1)
443
+ };
444
+ return {
445
+ kind: "object",
446
+ fields,
447
+ ...keys.length > selected.length ? { truncated: true } : {}
448
+ };
449
+ }
450
+ function isShapeableJsonRoot(value) {
451
+ return Array.isArray(value) || isPlainObject$1(value);
452
+ }
453
+ function isPlainObject$1(value) {
454
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
455
+ }
456
+ function storedBytes(value) {
457
+ return new TextEncoder().encode(JSON.stringify(value)).byteLength;
458
+ }
459
+ //#endregion
460
+ //#region src/observed-output-shapes/schema.ts
461
+ function usefulOutputSchema(schema) {
462
+ if (!isPlainObject(schema)) return false;
463
+ if (Object.keys(schema).length === 0) return false;
464
+ if ("const" in schema || Array.isArray(schema.enum)) return true;
465
+ const type = schema.type;
466
+ if (Array.isArray(type)) return type.some((item) => usefulOutputSchema({
467
+ ...schema,
468
+ type: item
469
+ }));
470
+ if (type === "object" || isPlainObject(schema.properties)) {
471
+ if (isPlainObject(schema.properties) && Object.keys(schema.properties).length > 0) return true;
472
+ if (schema.additionalProperties === false) return true;
473
+ if (isPlainObject(schema.additionalProperties)) return true;
474
+ return false;
475
+ }
476
+ if (type === "array") return usefulOutputSchema(schema.items);
477
+ if (typeof type === "string") return true;
478
+ if (Array.isArray(schema.oneOf) || Array.isArray(schema.anyOf) || Array.isArray(schema.allOf)) return true;
479
+ return false;
480
+ }
481
+ function isPlainObject(value) {
482
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
483
+ }
484
+ //#endregion
485
+ export { parseShapeableJsonText as a, shapeType as c, backendFingerprint as d, observedOutputShapeKey as f, OBSERVED_OUTPUT_SHAPE_VERSION as g, OBSERVED_OUTPUT_SHAPE_LIMITS as h, observeOutputShape as i, mergeJsonShapes as l, stableHash as m, extractJsonShape as n, hasTruncatedShape as o, observedOutputShapeStorageKey as p, normalizedObservableValue as r, shapeToTypeScript as s, usefulOutputSchema as t, FileObservedOutputShapeStore as u };
@@ -0,0 +1,2 @@
1
+ import { a as parseShapeableJsonText, c as shapeType, d as backendFingerprint, f as observedOutputShapeKey, g as OBSERVED_OUTPUT_SHAPE_VERSION, h as OBSERVED_OUTPUT_SHAPE_LIMITS, i as observeOutputShape, l as mergeJsonShapes, m as stableHash, n as extractJsonShape, o as hasTruncatedShape, p as observedOutputShapeStorageKey, r as normalizedObservableValue, s as shapeToTypeScript, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-uzAMQPhg.js";
2
+ export { FileObservedOutputShapeStore, OBSERVED_OUTPUT_SHAPE_LIMITS, OBSERVED_OUTPUT_SHAPE_VERSION, backendFingerprint, extractJsonShape, hasTruncatedShape, mergeJsonShapes, normalizedObservableValue, observeOutputShape, observedOutputShapeKey, observedOutputShapeStorageKey, parseShapeableJsonText, shapeToTypeScript, shapeType, stableHash, usefulOutputSchema };
package/dist/openapi.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { CompatibilityCallToolResult, Tool } from "@modelcontextprotocol/sdk/types";
2
2
  import type { OpenApiEndpointConfig } from "./config";
3
- import type { CompactTool } from "./downstream";
3
+ import { type CompactTool } from "./downstream";
4
4
  import type { ServerRegistry } from "./registry";
5
5
  export declare class OpenApiManager {
6
6
  private registry;
@@ -0,0 +1,2 @@
1
+ export { PROJECT_BINDING_STATES, PROJECT_BINDING_SYNC_STATES } from "./types";
2
+ export type { BindingTerminalReason, ProjectBindingLease, ProjectBindingSetupReceipt, ProjectBindingState, ProjectBindingSyncState, ProjectBindingWorkspaceMetadata, } from "./types";
@@ -0,0 +1,22 @@
1
+ //#region src/project-binding/types.ts
2
+ const PROJECT_BINDING_STATES = [
3
+ "not_attached",
4
+ "attaching",
5
+ "syncing",
6
+ "ready",
7
+ "degraded",
8
+ "blocked",
9
+ "offline",
10
+ "cleaning_up",
11
+ "ended",
12
+ "expired"
13
+ ];
14
+ const PROJECT_BINDING_SYNC_STATES = [
15
+ "not_started",
16
+ "pending",
17
+ "syncing",
18
+ "idle",
19
+ "failed"
20
+ ];
21
+ //#endregion
22
+ export { PROJECT_BINDING_STATES, PROJECT_BINDING_SYNC_STATES };
@@ -0,0 +1,14 @@
1
+ export declare const SECRET_KEY_PATTERN: RegExp;
2
+ export declare const SECRET_TEXT_PATTERNS: readonly [RegExp, RegExp, RegExp];
3
+ export type RedactionResult = {
4
+ text: string;
5
+ redacted: boolean;
6
+ };
7
+ export type RedactionOptions = {
8
+ patterns?: readonly RegExp[] | undefined;
9
+ additionalSecrets?: readonly string[] | undefined;
10
+ replacement?: string | undefined;
11
+ };
12
+ export declare function isSecretKey(key: string): boolean;
13
+ export declare function redactSecretText(value: string, options?: RedactionOptions): RedactionResult;
14
+ export declare function redactUnknownSecrets<T>(value: T, options?: RedactionOptions): T;
@@ -0,0 +1,30 @@
1
+ //#region src/redaction.ts
2
+ const SECRET_KEY_PATTERN = /(token|secret|authorization|auth|api[-_]?key|password|credential|clientsecret|client_secret|code|refresh)/iu;
3
+ const SECRET_TEXT_PATTERNS = [
4
+ /(Authorization:\s*Bearer\s+)[0-9A-Za-z._~+/=-]+/giu,
5
+ /(bearer\s+)[a-z0-9._~+/=-]+/giu,
6
+ /([?&](?:access_token|refresh_token|token|code)=)[^&\s]+/giu
7
+ ];
8
+ function isSecretKey(key) {
9
+ return SECRET_KEY_PATTERN.test(key);
10
+ }
11
+ function redactSecretText(value, options = {}) {
12
+ const replacement = options.replacement ?? "[REDACTED]";
13
+ let text = value;
14
+ for (const pattern of [...options.patterns ?? [], ...SECRET_TEXT_PATTERNS]) text = text.replace(pattern, (...args) => {
15
+ return `${typeof args[1] === "string" ? args[1] : ""}${replacement}`;
16
+ });
17
+ for (const secret of options.additionalSecrets?.filter(Boolean) ?? []) text = text.split(secret).join(replacement);
18
+ return {
19
+ text,
20
+ redacted: text !== value
21
+ };
22
+ }
23
+ function redactUnknownSecrets(value, options = {}) {
24
+ if (typeof value === "string") return redactSecretText(value, options).text;
25
+ if (Array.isArray(value)) return value.map((item) => redactUnknownSecrets(item, options));
26
+ if (!value || typeof value !== "object") return value;
27
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, isSecretKey(key) ? "[REDACTED]" : redactUnknownSecrets(entry, options)]));
28
+ }
29
+ //#endregion
30
+ export { SECRET_KEY_PATTERN, SECRET_TEXT_PATTERNS, isSecretKey, redactSecretText, redactUnknownSecrets };
@@ -6,6 +6,8 @@ export type CapletServerSummary = {
6
6
  id: string;
7
7
  name: string;
8
8
  description: string;
9
+ useWhen?: string;
10
+ avoidWhen?: string;
9
11
  disabled?: boolean;
10
12
  status: ServerStatus;
11
13
  lastError?: SafeErrorSummary;
@@ -14,6 +16,8 @@ export type CapletServerDetail = {
14
16
  id: string;
15
17
  name: string;
16
18
  description: string;
19
+ useWhen?: string;
20
+ avoidWhen?: string;
17
21
  tags?: string[];
18
22
  backend: {
19
23
  type: "mcp";
@@ -38,5 +38,7 @@ export declare function resolveRemoteMode(input?: CapletsRemoteModeInput, env?:
38
38
  mode: CapletsRemoteMode;
39
39
  };
40
40
  export declare function resolveCapletsRemote(input?: CapletsRemoteInput, env?: CapletsRemoteEnv): ResolvedCapletsRemote;
41
+ export declare function resolveHostedCloudRemote(input?: CapletsRemoteInput, env?: CapletsRemoteEnv): ResolvedCapletsRemote;
42
+ export declare function hostedCloudWorkspaceFromRemoteUrl(value: string): string | undefined;
41
43
  export declare function projectBindingWebSocketUrlForBase(baseUrl: URL): URL;
42
44
  export declare function isCapletsCloudUrl(value: string): boolean;
@@ -1,5 +1,5 @@
1
1
  import type { CapletsErrorCode } from "../errors";
2
- export type RemoteCliCommand = "list" | "inspect" | "check_backend" | "list_tools" | "search_tools" | "get_tool" | "call_tool" | "list_resources" | "search_resources" | "list_resource_templates" | "read_resource" | "list_prompts" | "search_prompts" | "get_prompt" | "complete" | "init" | "add" | "install" | "complete_cli" | "auth_login_start" | "auth_login_complete" | "auth_logout" | "auth_list";
2
+ export type RemoteCliCommand = "list" | "inspect" | "check" | "tools" | "search_tools" | "describe_tool" | "call_tool" | "resources" | "search_resources" | "resource_templates" | "read_resource" | "prompts" | "search_prompts" | "get_prompt" | "complete" | "init" | "add" | "install" | "complete_cli" | "auth_login_start" | "auth_login_complete" | "auth_logout" | "auth_list";
3
3
  export type RemoteCliRequest = {
4
4
  command: RemoteCliCommand;
5
5
  arguments: Record<string, unknown>;
@@ -1,4 +1,6 @@
1
1
  import type { HostedRuntimeResourceClass, RuntimeResourcePolicy, RuntimeResourceResolution } from "./types";
2
+ export declare function resourceClassRank(value: string): number;
3
+ export declare function isRuntimeResourceClassAllowed(requested: string, maximum: string): boolean;
2
4
  type ResourceInput = {
3
5
  backend?: string | undefined;
4
6
  features: string[];
@@ -171,6 +171,12 @@ const rank = {
171
171
  large: 2,
172
172
  heavy: 3
173
173
  };
174
+ function resourceClassRank(value) {
175
+ return rank[value] ?? 0;
176
+ }
177
+ function isRuntimeResourceClassAllowed(requested, maximum) {
178
+ return resourceClassRank(requested) <= resourceClassRank(maximum);
179
+ }
174
180
  function resolveRuntimeResources(inputOrCaplet, features, policy) {
175
181
  const caplet = inputOrCaplet;
176
182
  const input = features === void 0 ? inputOrCaplet : {
@@ -205,7 +211,7 @@ function explicitResourceClass$1(caplet) {
205
211
  }
206
212
  function capClass(requested, maxClass) {
207
213
  if (!maxClass) return requested;
208
- return (rank[requested] ?? 0) > (rank[maxClass] ?? 0) ? maxClass : requested;
214
+ return isRuntimeResourceClassAllowed(requested, maxClass) ? requested : maxClass;
209
215
  }
210
216
  //#endregion
211
217
  //#region src/runtime-plan/planner.ts
@@ -272,4 +278,4 @@ function explicitResourceClass(caplet) {
272
278
  return value === "small" || value === "medium" || value === "standard" || value === "large" || value === "heavy" ? value : void 0;
273
279
  }
274
280
  //#endregion
275
- export { HIDDEN_REASON_CODES, classifyCapletRuntimeRoute, inferRuntimeFeatures, planCapletRuntimeRoute, planCapletRuntimeRoutes, resolveRuntimeResources };
281
+ export { HIDDEN_REASON_CODES, classifyCapletRuntimeRoute, inferRuntimeFeatures, isRuntimeResourceClassAllowed, planCapletRuntimeRoute, planCapletRuntimeRoutes, resolveRuntimeResources, resourceClassRank };