@yaklabs-ai/plugin-sdk 0.15.3 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/kay-agent.js CHANGED
@@ -18,57 +18,111 @@ function compileUriClaim(claim) {
18
18
  };
19
19
  }
20
20
  const pattern = compileRoutePattern(claim.pattern);
21
+ const normalizeTo = claim.normalizeTo === void 0 ? void 0 : compileTemplate(claim.normalizeTo);
22
+ const sourceUrl = claim.kind === "uriPattern" && claim.sourceUrl !== void 0 ? compileTemplate(claim.sourceUrl) : void 0;
23
+ const matchAt = (target, selector) => {
24
+ const parsed = parsePatternInput(target);
25
+ if (parsed === void 0)
26
+ return void 0;
27
+ const captures = matchRoute(pattern, parsed);
28
+ if (captures === void 0)
29
+ return void 0;
30
+ const restCaptures = pattern.restCaptures ?? [];
31
+ const normalized = normalizeTo === void 0 ? void 0 : fillTemplate(normalizeTo, captures, restCaptures);
32
+ if (normalizeTo !== void 0 && normalized === void 0)
33
+ return void 0;
34
+ const filledSourceUrl = sourceUrl === void 0 ? void 0 : fillTemplate(sourceUrl, captures, restCaptures);
35
+ return {
36
+ claimKind: claim.kind,
37
+ ...Object.keys(captures).length > 0 ? { captures } : {},
38
+ ...normalized !== void 0 ? {
39
+ normalizedUri: withSelector(withInputSearch(claim, pattern, parsed, normalized), parsed.protocol, selector)
40
+ } : {},
41
+ ...claim.route !== void 0 ? { route: claim.route } : {},
42
+ ...filledSourceUrl !== void 0 ? { sourceUrl: filledSourceUrl } : {},
43
+ ...claim.kind === "uriPattern" && claim.title !== void 0 ? { title: fillTitle(claim.title, captures) } : {}
44
+ };
45
+ };
21
46
  return {
22
47
  claim,
23
48
  match(input) {
24
- const parsed = parsePatternInput(input);
25
- if (parsed === void 0)
26
- return void 0;
27
- const captures = matchRoute(pattern, parsed);
28
- if (captures === void 0)
29
- return void 0;
30
- return {
31
- claimKind: claim.kind,
32
- ...Object.keys(captures).length > 0 ? { captures } : {},
33
- ...claim.normalizeTo !== void 0 ? {
34
- normalizedUri: withInputSearch(claim, pattern, parsed, interpolateNormalizeTo(claim.normalizeTo, captures, pattern.restCaptures ?? []))
35
- } : {}
36
- };
49
+ if (claim.kind === "uriPattern") {
50
+ const { selector, rest } = parseUriConnectionSelector(input);
51
+ if (selector !== void 0) {
52
+ const match = matchAt(rest, selector);
53
+ if (match !== void 0)
54
+ return match;
55
+ }
56
+ }
57
+ return matchAt(input, void 0);
37
58
  }
38
59
  };
39
60
  }
61
+ function fillTitle(template, captures) {
62
+ return template.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, (written, name) => captures[name] ?? written);
63
+ }
64
+ var CONNECTION_SELECTOR_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)@([^/]+)(?:\/(.*))?$/;
65
+ function parseUriConnectionSelector(input) {
66
+ const match = CONNECTION_SELECTOR_RE.exec(input.trim());
67
+ if (match?.[1] === void 0 || match[2] === void 0) {
68
+ return { rest: input };
69
+ }
70
+ return { selector: match[2], rest: `${match[1]}${match[3] ?? ""}` };
71
+ }
72
+ function withSelector(normalized, inputProtocol, selector) {
73
+ if (selector === void 0)
74
+ return normalized;
75
+ if (templateProtocol(normalized) !== inputProtocol)
76
+ return normalized;
77
+ const schemeEnd = normalized.indexOf("://") + 3;
78
+ return `${normalized.slice(0, schemeEnd)}@${selector}/${normalized.slice(schemeEnd)}`;
79
+ }
40
80
  function normalizeProtocol(value) {
41
81
  return value.replace(/:$/, "").toLowerCase();
42
82
  }
43
83
  function parsePatternInput(input) {
84
+ const trimmed = input.trim();
85
+ let url;
44
86
  try {
45
- const url = new URL(input.trim());
46
- return {
47
- protocol: normalizeProtocol(url.protocol),
48
- hostname: url.hostname.toLowerCase(),
49
- pathname: url.pathname,
50
- search: url.search.startsWith("?") ? url.search.slice(1) : url.search
51
- };
87
+ url = new URL(trimmed);
52
88
  } catch {
53
- return void 0;
89
+ if (!trimmed.includes(" "))
90
+ return void 0;
91
+ try {
92
+ url = new URL(trimmed.replaceAll(" ", "%20"));
93
+ } catch {
94
+ return void 0;
95
+ }
54
96
  }
97
+ return {
98
+ protocol: normalizeProtocol(url.protocol),
99
+ // A web host arrives lowercased; a custom scheme's keeps its case, so a capture of it
100
+ // (`projects://Acme`) names it as written. Literal host parts match either case.
101
+ hostname: url.hostname,
102
+ pathname: url.pathname,
103
+ search: url.search.startsWith("?") ? url.search.slice(1) : url.search
104
+ };
55
105
  }
56
106
  function compileRoutePattern(pattern) {
57
107
  const pathname = pattern.pathname !== void 0 ? compileParts(pattern.pathname, "/", { allowRest: true }) : void 0;
58
108
  return {
59
109
  ...pattern.protocol !== void 0 ? { protocol: normalizeProtocol(pattern.protocol) } : {},
60
- ...pattern.hostname !== void 0 ? { hostname: compileParts(pattern.hostname.toLowerCase(), ".") } : {},
110
+ ...pattern.hostname !== void 0 ? {
111
+ hostname: compileParts(pattern.hostname.toLowerCase(), LONE_CAPTURE_RE.test(pattern.hostname) ? void 0 : ".")
112
+ } : {},
61
113
  ...pathname !== void 0 ? { pathname } : {},
114
+ ...pattern.pathname?.endsWith("/") === true ? { pathnameEndsInSlash: true } : {},
62
115
  ...pathname !== void 0 ? {
63
116
  restCaptures: pathname.filter((part) => part.rest === true).map((part) => part.capture)
64
117
  } : {},
65
118
  ...pattern.search !== void 0 ? { search: compileParts(pattern.search.replace(/^\?/, ""), "&") } : {}
66
119
  };
67
120
  }
121
+ var LONE_CAPTURE_RE = /^:[A-Za-z_][A-Za-z0-9_]*(?:\([^()|]*\))?$/;
68
122
  function compileParts(value, separator, options = {}) {
69
123
  if (value === "")
70
124
  return [];
71
- const parts = value.split(separator);
125
+ const parts = separator === void 0 ? [value] : value.split(separator);
72
126
  return parts.map((part, index) => {
73
127
  const restMatch = REST_CAPTURE_RE.exec(part);
74
128
  if (restMatch !== null) {
@@ -108,19 +162,30 @@ function matchRoute(pattern, input) {
108
162
  return void 0;
109
163
  }
110
164
  const captures = {};
111
- if (pattern.hostname !== void 0 && !matchParts(pattern.hostname, input.hostname, ".", captures)) {
165
+ if (pattern.hostname !== void 0 && !matchParts(pattern.hostname, input.hostname, isLoneCapture(pattern.hostname) ? void 0 : ".", captures, true)) {
112
166
  return void 0;
113
167
  }
114
- if (pattern.pathname !== void 0 && !matchParts(pattern.pathname, input.pathname, "/", captures)) {
168
+ if (pattern.pathname !== void 0 && !matchParts(pattern.pathname, pattern.pathnameEndsInSlash === true ? input.pathname : withoutTrailingSlash(input), "/", captures)) {
115
169
  return void 0;
116
170
  }
117
- if (pattern.search !== void 0 && !matchParts(pattern.search, input.search, "&", captures)) {
171
+ if (pattern.search !== void 0 && (pattern.search.length === 0 ? input.search !== "" : !matchParts(pattern.search, input.search, "&", captures))) {
118
172
  return void 0;
119
173
  }
120
174
  return captures;
121
175
  }
122
- function matchParts(pattern, value, separator, captures) {
123
- const parts = value.split(separator);
176
+ function withoutTrailingSlash(input) {
177
+ const { hostname, pathname } = input;
178
+ if (!pathname.endsWith("/") || pathname.endsWith("//"))
179
+ return pathname;
180
+ if (pathname === "/" && hostname === "")
181
+ return pathname;
182
+ return pathname.slice(0, -1);
183
+ }
184
+ function isLoneCapture(pattern) {
185
+ return pattern.length === 1 && pattern[0].capture !== void 0 && pattern[0].rest !== true;
186
+ }
187
+ function matchParts(pattern, value, separator, captures, foldLiterals = false) {
188
+ const parts = separator === void 0 ? [value] : value.split(separator);
124
189
  let partIndex = 0;
125
190
  for (let i = 0; i < pattern.length; i += 1) {
126
191
  const expected = pattern[i];
@@ -128,7 +193,7 @@ function matchParts(pattern, value, separator, captures) {
128
193
  const remaining = parts.slice(partIndex);
129
194
  if (remaining.every((part) => part === ""))
130
195
  return false;
131
- captures[expected.capture] = remaining.join(separator);
196
+ captures[expected.capture] = remaining.join(separator ?? "");
132
197
  return true;
133
198
  }
134
199
  if (partIndex >= parts.length)
@@ -143,8 +208,9 @@ function matchParts(pattern, value, separator, captures) {
143
208
  partIndex += 1;
144
209
  continue;
145
210
  }
146
- if (expected.literal !== actual)
211
+ if (expected.literal !== (foldLiterals ? actual.toLowerCase() : actual)) {
147
212
  return false;
213
+ }
148
214
  partIndex += 1;
149
215
  }
150
216
  return partIndex === parts.length;
@@ -165,31 +231,116 @@ function withInputSearch(claim, pattern, input, normalized) {
165
231
  function templateProtocol(template) {
166
232
  return SCHEME_RE.exec(template)?.[1]?.toLowerCase();
167
233
  }
168
- function interpolateNormalizeTo(template, captures, restCaptures) {
169
- return template.replace(/:([A-Za-z_][A-Za-z0-9_]*)/g, (full, name, offset) => {
170
- const value = captures[name];
171
- if (value === void 0)
172
- return full;
173
- return encodeCaptureValue({
174
- template,
175
- offset,
176
- value,
177
- rest: restCaptures.includes(name)
178
- });
179
- });
180
- }
181
- function encodeCaptureValue({ template, offset, value, rest }) {
182
- const normalized = isAuthorityCapture(template, offset) ? value.toLowerCase() : value;
183
- if (!rest)
184
- return encodeURIComponent(normalized);
185
- return normalized.split("/").join("/");
234
+ var TEMPLATE_TOKEN_RE = /\{([A-Za-z][A-Za-z0-9]*)\(([^)]*)\)\}|:([A-Za-z_][A-Za-z0-9_]*)/g;
235
+ var TRANSFORMS = {
236
+ base64: (value) => {
237
+ const bytes = new TextEncoder().encode(value);
238
+ let binary = "";
239
+ for (const byte of bytes)
240
+ binary += String.fromCharCode(byte);
241
+ return btoa(binary).replace(/=+$/, "");
242
+ },
243
+ slackTimestamp: (value) => {
244
+ const match = /^p(\d+)(\d{6})$/.exec(value);
245
+ return match === null ? void 0 : `${match[1]}.${match[2]}`;
246
+ }
247
+ };
248
+ function isTransform(name) {
249
+ return Object.prototype.hasOwnProperty.call(TRANSFORMS, name);
250
+ }
251
+ function compileTemplate(template) {
252
+ const parts = [];
253
+ let last = 0;
254
+ for (const token of template.matchAll(TEMPLATE_TOKEN_RE)) {
255
+ const offset = token.index;
256
+ if (offset > last)
257
+ parts.push({ literal: template.slice(last, offset) });
258
+ const position = templatePosition(template, offset);
259
+ const [full, transform = "", inner = "", capture] = token;
260
+ if (capture !== void 0) {
261
+ parts.push({ capture, position });
262
+ } else {
263
+ if (!isTransform(transform)) {
264
+ throw new Error(`Unknown URI claim template transform '${transform}'.`);
265
+ }
266
+ parts.push({
267
+ transform,
268
+ inner: compileTransformInput(inner),
269
+ position
270
+ });
271
+ }
272
+ last = offset + full.length;
273
+ }
274
+ if (last < template.length)
275
+ parts.push({ literal: template.slice(last) });
276
+ return parts;
277
+ }
278
+ function compileTransformInput(text) {
279
+ const parts = [];
280
+ let last = 0;
281
+ for (const token of text.matchAll(/:([A-Za-z_][A-Za-z0-9_]*)/g)) {
282
+ if (token.index > last)
283
+ parts.push({ literal: text.slice(last, token.index) });
284
+ parts.push({ capture: token[1] });
285
+ last = token.index + token[0].length;
286
+ }
287
+ if (last < text.length)
288
+ parts.push({ literal: text.slice(last) });
289
+ return parts;
290
+ }
291
+ function fillTemplate(parts, captures, restCaptures) {
292
+ let out = "";
293
+ for (const part of parts) {
294
+ if ("literal" in part) {
295
+ out += part.literal;
296
+ continue;
297
+ }
298
+ if ("capture" in part) {
299
+ const value = captures[part.capture];
300
+ if (value === void 0) {
301
+ out += `:${part.capture}`;
302
+ continue;
303
+ }
304
+ const escaped = restCaptures.includes(part.capture) ? escapeRestCapture(value) : escapeForPosition(value, part.position);
305
+ if (escaped === void 0)
306
+ return void 0;
307
+ out += escaped;
308
+ continue;
309
+ }
310
+ let raw = "";
311
+ for (const inner of part.inner) {
312
+ raw += "literal" in inner ? inner.literal : captures[inner.capture] ?? `:${inner.capture}`;
313
+ }
314
+ const transformed = TRANSFORMS[part.transform](raw);
315
+ if (transformed === void 0)
316
+ return void 0;
317
+ out += escapeForPosition(transformed, part.position);
318
+ }
319
+ return out;
186
320
  }
187
- function isAuthorityCapture(template, offset) {
321
+ function templatePosition(template, offset) {
188
322
  const prefix = template.slice(0, offset);
323
+ if (prefix.includes("#"))
324
+ return "fragment";
325
+ if (prefix.includes("?"))
326
+ return "query";
189
327
  const schemeIndex = prefix.lastIndexOf("://");
190
- if (schemeIndex === -1)
191
- return false;
192
- return !/[/?#]/.test(prefix.slice(schemeIndex + 3));
328
+ if (schemeIndex !== -1 && !prefix.slice(schemeIndex + 3).includes("/")) {
329
+ return "host";
330
+ }
331
+ return "path";
332
+ }
333
+ function escapeForPosition(value, position) {
334
+ if (position === "host")
335
+ return encodeURIComponent(value.toLowerCase());
336
+ return encodeURIComponent(value).replace(/%(?:3A|40)/gi, (code) => decodeURIComponent(code));
337
+ }
338
+ function escapeRestCapture(value) {
339
+ const segments = value.split("/").map(safeDecode);
340
+ if (segments.some((segment) => segment === "." || segment === "..")) {
341
+ return void 0;
342
+ }
343
+ return segments.map(encodeURIComponent).join("/");
193
344
  }
194
345
 
195
346
  // packages/herd-uri/dist/errors.js
@@ -216,6 +367,15 @@ var UriValidationError = class extends UriError {
216
367
  this.name = "UriValidationError";
217
368
  }
218
369
  };
370
+ function requireWriteContent(payload2, uri) {
371
+ if (payload2 === void 0) {
372
+ throw new UriValidationError(`Writing ${uri} needs \`content\` (or a \`source\` to copy from): pass the payload this address takes, which its help names.`);
373
+ }
374
+ if (payload2 instanceof Uint8Array) {
375
+ throw new UriValidationError(`${uri} stores text only, so it cannot take raw bytes. Copy the file to an address that accepts bytes.`);
376
+ }
377
+ return payload2;
378
+ }
219
379
  var UriProviderError = class extends UriError {
220
380
  _tag = "UriProviderError";
221
381
  moduleId;
@@ -228,6 +388,8 @@ var UriProviderError = class extends UriError {
228
388
  retryAfterMs;
229
389
  /** See {@link UriProviderErrorOptions.effect}. */
230
390
  effect;
391
+ /** See {@link UriProviderErrorOptions.refusalMessage}. */
392
+ refusalMessage;
231
393
  constructor(options) {
232
394
  super(options.message);
233
395
  this.name = "UriProviderError";
@@ -248,6 +410,12 @@ var UriProviderError = class extends UriError {
248
410
  }
249
411
  if (options.effect !== void 0)
250
412
  this.effect = options.effect;
413
+ if (options.refusalMessage !== void 0) {
414
+ if (options.effect !== "none") {
415
+ throw new TypeError('refusalMessage requires effect: "none".');
416
+ }
417
+ this.refusalMessage = options.refusalMessage;
418
+ }
251
419
  }
252
420
  };
253
421
  var UriNotFoundError = class extends UriError {
@@ -275,16 +443,6 @@ var UriUnsupportedOperationError = class extends UriError {
275
443
  }
276
444
  };
277
445
 
278
- // packages/herd-uri/dist/connection.js
279
- var CONNECTION_SELECTOR_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)@([^/]+)(?:\/(.*))?$/;
280
- function parseUriConnectionSelector(input) {
281
- const match = CONNECTION_SELECTOR_RE.exec(input.trim());
282
- if (match?.[1] === void 0 || match[2] === void 0) {
283
- return { rest: input };
284
- }
285
- return { selector: match[2], rest: `${match[1]}${match[3] ?? ""}` };
286
- }
287
-
288
446
  // packages/herd-uri/dist/resource-witness.js
289
447
  import { createHash } from "node:crypto";
290
448
  function contentDigest(content) {
@@ -542,6 +700,13 @@ var UriPayloadContractSchema = z2.strictObject({
542
700
 
543
701
  // packages/herd-uri/dist/observation.js
544
702
  var OBSERVATION_MIME = "application/vnd.kay.observation+json";
703
+ var isOptionalString = (value) => value === void 0 || typeof value === "string";
704
+ function isObservationMaterial(value) {
705
+ if (typeof value !== "object" || value === null || Array.isArray(value))
706
+ return false;
707
+ const material = value;
708
+ return typeof material.uri === "string" && typeof material.kind === "string" && isOptionalString(material.title) && (material.text === void 0 || Array.isArray(material.text) && material.text.every((piece) => typeof piece === "string")) && isOptionalString(material.createdAt) && isOptionalString(material.updatedAt) && isOptionalString(material.version) && (material.retainForMs === void 0 || typeof material.retainForMs === "number" && Number.isFinite(material.retainForMs));
709
+ }
545
710
 
546
711
  // packages/herd-uri/dist/text-edit.js
547
712
  import { z as z3 } from "zod";
@@ -749,7 +914,7 @@ function toJsonSchema(schema) {
749
914
  // `io: "input"` describes what a caller may SEND, which is what a parameter and an
750
915
  // `accepts` payload advertise: a field with a Zod default is optional on the wire even
751
916
  // though the parsed value always carries it. Strictness still survives where the validator
752
- // really enforces it — `z.strictObject` emits `additionalProperties: false`, while a plain
917
+ // really enforces it - `z.strictObject` emits `additionalProperties: false`, while a plain
753
918
  // `z.object` correctly does not, because it TOLERATES unknown keys and silently strips
754
919
  // them. A `returns` payload derived from a Zod schema is described in the same input terms;
755
920
  // no module does that today, and a faithful output projection would need its own seam.
@@ -883,29 +1048,45 @@ function accountQualifiedUri(scheme, accountId, path) {
883
1048
  }
884
1049
  return `${scheme}://@${accountId}/${path}`;
885
1050
  }
886
- function isOptionalString(value) {
887
- return value === void 0 || typeof value === "string";
888
- }
889
- function isOptionalStringArray(value) {
890
- return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
891
- }
892
1051
  function observationFromResource(resource) {
893
1052
  if (resource.mimeType !== OBSERVATION_MIME)
894
1053
  return void 0;
895
1054
  if (typeof resource.content !== "string")
896
1055
  return void 0;
897
1056
  const parsed = tryParseJson(resource.content);
898
- if (parsed === void 0 || typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1057
+ return isObservationMaterial(parsed) ? parsed : void 0;
1058
+ }
1059
+
1060
+ // packages/herd-uri-extensions/dist/secure-transport.js
1061
+ var SecureTransportError = class extends Error {
1062
+ name = "SecureTransportError";
1063
+ };
1064
+ function isLoopbackHostname(hostname) {
1065
+ const host = hostname.toLowerCase();
1066
+ if (host === "localhost" || host === "[::1]")
1067
+ return true;
1068
+ const octets = host.split(".");
1069
+ return octets.length === 4 && octets[0] === "127" && octets.every((octet) => /^\d{1,3}$/.test(octet) && Number(octet) <= 255);
1070
+ }
1071
+ function secureTransportViolation(url) {
1072
+ let parsed;
1073
+ try {
1074
+ parsed = typeof url === "string" ? new URL(url) : url;
1075
+ } catch {
899
1076
  return void 0;
900
1077
  }
901
- const value = parsed;
902
- if (typeof value.uri !== "string" || typeof value.kind !== "string") {
1078
+ if (parsed.protocol !== "http:" && parsed.protocol !== "ws:")
903
1079
  return void 0;
904
- }
905
- if (!isOptionalString(value.title) || !isOptionalStringArray(value.text) || !isOptionalString(value.createdAt) || !isOptionalString(value.updatedAt) || !isOptionalString(value.version)) {
1080
+ if (isLoopbackHostname(parsed.hostname))
906
1081
  return void 0;
907
- }
908
- return value;
1082
+ const secure = parsed.protocol === "ws:" ? "wss://" : "https://";
1083
+ return `Plain HTTP is only allowed to this computer (localhost, 127.0.0.1 or ::1); use ${secure} for ${parsed.host}.`;
1084
+ }
1085
+ function assertSecureTransport(url, label) {
1086
+ const violation = secureTransportViolation(url);
1087
+ if (violation === void 0)
1088
+ return;
1089
+ throw new SecureTransportError(label === void 0 ? violation : `${label}: ${violation}`);
909
1090
  }
910
1091
 
911
1092
  // packages/plugin-primitives/dist/results.js
@@ -982,15 +1163,6 @@ function toToolParameters(schema) {
982
1163
 
983
1164
  // packages/plugin-primitives/dist/auth-scheme.js
984
1165
  var ACCOUNT_ID_PARAM = "accountId";
985
- function authContextOf(ctx) {
986
- return ctx.auth;
987
- }
988
- function authFailureResult(failure) {
989
- return {
990
- content: [{ type: "text", text: failure.message }],
991
- details: void 0
992
- };
993
- }
994
1166
  function withAccountIdParam(parameters) {
995
1167
  if (parameters === null || typeof parameters !== "object" || parameters.type !== "object") {
996
1168
  return parameters;
@@ -1016,27 +1188,18 @@ function withResolvedAuth(definition, binding, body) {
1016
1188
  requiresAuth: binding,
1017
1189
  parameters: withAccountIdParam(definition.parameters),
1018
1190
  async execute(toolCallId, params, signal, onUpdate, ctx) {
1019
- const auth = authContextOf(ctx);
1020
- if (auth === void 0) {
1021
- return authFailureResult({
1022
- ok: false,
1023
- reason: "no-connection",
1024
- message: `Auth is not available in this context for ${binding.serviceId}.`
1025
- });
1191
+ if (ctx.credential === void 0) {
1192
+ return {
1193
+ content: [
1194
+ {
1195
+ type: "text",
1196
+ text: `Auth is not available in this context for ${binding.serviceId}.`
1197
+ }
1198
+ ],
1199
+ details: void 0
1200
+ };
1026
1201
  }
1027
- const override = params?.[ACCOUNT_ID_PARAM];
1028
- const result = await auth.resolveToken({
1029
- serviceId: binding.serviceId,
1030
- ...binding.schemeId === void 0 ? {} : { schemeId: binding.schemeId },
1031
- ...typeof override === "string" && override.length > 0 ? { accountId: override } : {},
1032
- ...binding.requiredScopes === void 0 ? {} : { requiredScopes: binding.requiredScopes },
1033
- ...binding.scopeRequirement === void 0 ? {} : { scopeRequirement: binding.scopeRequirement },
1034
- ...binding.connectServiceId === void 0 ? {} : { connectServiceId: binding.connectServiceId }
1035
- });
1036
- if (!result.ok) {
1037
- return authFailureResult(result);
1038
- }
1039
- return body(toolCallId, params, signal, onUpdate, ctx, result.auth);
1202
+ return body(toolCallId, params, signal, onUpdate, ctx, ctx.credential);
1040
1203
  }
1041
1204
  };
1042
1205
  }
@@ -1058,23 +1221,14 @@ function withResolvedSearchProvider(definition, binding, body) {
1058
1221
  label: definition.label,
1059
1222
  providerId: definition.providerId ?? "",
1060
1223
  requiresAuth: binding,
1061
- async isAvailable(ctx) {
1062
- const auth = ctx?.auth;
1063
- if (auth === void 0)
1064
- return false;
1065
- const result = await auth.resolveToken(binding);
1066
- return result.ok;
1224
+ isAvailable(ctx) {
1225
+ return ctx?.credential !== void 0;
1067
1226
  },
1068
1227
  async search(params, signal, ctx) {
1069
- const auth = ctx?.auth;
1070
- if (auth === void 0) {
1228
+ if (ctx?.credential === void 0) {
1071
1229
  throw new SearchProviderError(definition.id, `Auth is not available in this context for ${binding.serviceId}.`);
1072
1230
  }
1073
- const result = await auth.resolveToken(binding);
1074
- if (!result.ok) {
1075
- throw new SearchProviderError(definition.id, result.message);
1076
- }
1077
- return body(params, signal, result.auth);
1231
+ return body(params, signal, ctx.credential);
1078
1232
  }
1079
1233
  };
1080
1234
  }
@@ -1286,6 +1440,27 @@ function bytesToBase64(bytes) {
1286
1440
  return output;
1287
1441
  }
1288
1442
 
1443
+ // packages/plugin-sdk/dist/kay-agent/known-resources-view.js
1444
+ function knownResourcesView(result) {
1445
+ return { ...result, knownResourcesView: true };
1446
+ }
1447
+
1448
+ // packages/plugin-sdk/dist/kay-agent/compiler.js
1449
+ function createUnavailableCompiler(message) {
1450
+ return {
1451
+ bundleBrowser: async () => {
1452
+ throw new Error(message);
1453
+ }
1454
+ };
1455
+ }
1456
+
1457
+ // packages/plugin-sdk/dist/kay-agent/endpoints.js
1458
+ function createUnavailableEndpoints(message) {
1459
+ return {
1460
+ invoke: async () => ({ ok: false, reason: "unavailable", message })
1461
+ };
1462
+ }
1463
+
1289
1464
  // packages/plugin-sdk/dist/kay-agent/osascript.js
1290
1465
  import { z as z6 } from "zod";
1291
1466
  var OSASCRIPT_TIMEOUT_MS = 3e4;
@@ -1443,204 +1618,21 @@ function fenced(text) {
1443
1618
  return [`${fence}text`, text, fence];
1444
1619
  }
1445
1620
 
1446
- // packages/plugin-sdk/dist/kay-agent/advertisement.js
1447
- function defineKayAgentAdvertisement(advertisement) {
1448
- return advertisement;
1449
- }
1450
- function rejectDuplicate(category, id, seen) {
1451
- if (seen.has(id)) {
1452
- throw new Error(`Duplicate advertised ${category} '${id}'.`);
1453
- }
1454
- seen.add(id);
1455
- }
1456
- function rejectImplementationFields(category, value, fields) {
1457
- for (const field of fields) {
1458
- if (field in value) {
1459
- throw new Error(`Advertised ${category} cannot include implementation field '${field}'.`);
1460
- }
1461
- }
1462
- }
1463
- function snapshotAdvertisementValue(value, seen = /* @__PURE__ */ new WeakMap()) {
1464
- if ((typeof value !== "object" || value === null) && typeof value !== "function") {
1465
- return value;
1466
- }
1467
- if (typeof value === "function") {
1468
- return value;
1469
- }
1470
- const existing = seen.get(value);
1471
- if (existing !== void 0)
1472
- return existing;
1473
- if (Array.isArray(value)) {
1474
- const copy2 = [];
1475
- seen.set(value, copy2);
1476
- for (const entry of value) {
1477
- copy2.push(snapshotAdvertisementValue(entry, seen));
1478
- }
1479
- return Object.freeze(copy2);
1480
- }
1481
- const copy = /* @__PURE__ */ Object.create(null);
1482
- seen.set(value, copy);
1483
- const copiedKeys = /* @__PURE__ */ new Set();
1484
- let source = value;
1485
- while (source !== null && source !== Object.prototype) {
1486
- for (const key of Reflect.ownKeys(source)) {
1487
- if (key === "constructor" || copiedKeys.has(key))
1488
- continue;
1489
- copiedKeys.add(key);
1490
- copy[key] = snapshotAdvertisementValue(Reflect.get(value, key), seen);
1491
- }
1492
- source = Object.getPrototypeOf(source);
1493
- }
1494
- return Object.freeze(copy);
1495
- }
1496
- function snapshotDelegatedServiceSource(source) {
1497
- return () => {
1498
- const entries = source();
1499
- if (!Array.isArray(entries)) {
1500
- throw new Error("An advertised delegated service source must return an array synchronously.");
1501
- }
1502
- return Object.freeze(entries.map((entry) => {
1503
- rejectImplementationFields("delegated service source scheme", entry.scheme, ["connect", "refresh"]);
1504
- return snapshotAdvertisementValue(entry);
1505
- }));
1506
- };
1507
- }
1508
- function collectKayAgentAdvertisement(advertisement) {
1509
- const tools = [];
1510
- const uriModules = [];
1511
- const searchProviders = [];
1512
- const converters = [];
1513
- const services = [];
1514
- const oauthPkceSchemes = [];
1515
- const apiKeySchemes = [];
1516
- const externalCliSchemes = [];
1517
- const delegatedSchemes = [];
1518
- const delegatedServiceSources = [];
1519
- const toolNames = /* @__PURE__ */ new Set();
1520
- const moduleIds = /* @__PURE__ */ new Set();
1521
- const providerIds = /* @__PURE__ */ new Set();
1522
- const converterIds = /* @__PURE__ */ new Set();
1523
- let collecting = true;
1524
- const assertCollecting = () => {
1525
- if (!collecting) {
1526
- throw new Error("The kay.agent advertisement API cannot be used after advertise() returns.");
1527
- }
1528
- };
1529
- const auth = {
1530
- advertiseService: (descriptor) => {
1531
- assertCollecting();
1532
- services.push(snapshotAdvertisementValue(descriptor));
1533
- },
1534
- declareOAuthPkceScheme: (serviceId, scheme) => {
1535
- assertCollecting();
1536
- rejectImplementationFields("OAuth PKCE scheme", scheme, [
1537
- "resolveAccountId",
1538
- "resolveAccounts"
1539
- ]);
1540
- oauthPkceSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1541
- },
1542
- declareApiKeyScheme: (serviceId, scheme) => {
1543
- assertCollecting();
1544
- rejectImplementationFields("API key scheme", scheme, ["validate"]);
1545
- apiKeySchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1546
- },
1547
- declareExternalCliScheme: (serviceId, scheme) => {
1548
- assertCollecting();
1549
- externalCliSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1550
- },
1551
- declareDelegatedScheme: (serviceId, scheme) => {
1552
- assertCollecting();
1553
- rejectImplementationFields("delegated scheme", scheme, [
1554
- "connect",
1555
- "refresh"
1556
- ]);
1557
- delegatedSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1558
- },
1559
- registerDelegatedServiceSource: (source) => {
1560
- assertCollecting();
1561
- delegatedServiceSources.push(Object.freeze({ source: snapshotDelegatedServiceSource(source) }));
1562
- }
1563
- };
1564
- const api = {
1565
- uri: {
1566
- registerModule: (module) => {
1567
- assertCollecting();
1568
- rejectImplementationFields("URI module", module, [
1569
- "locate",
1570
- "read",
1571
- "help",
1572
- "write",
1573
- "edit",
1574
- "list",
1575
- "search",
1576
- "delete"
1577
- ]);
1578
- const snapshot = snapshotAdvertisementValue(module);
1579
- rejectDuplicate("URI module id", snapshot.id, moduleIds);
1580
- uriModules.push(snapshot);
1581
- }
1582
- },
1583
- registerTool: (definition) => {
1584
- assertCollecting();
1585
- rejectImplementationFields("tool", definition, ["execute"]);
1586
- const snapshot = snapshotAdvertisementValue(definition);
1587
- rejectDuplicate("tool name", snapshot.name, toolNames);
1588
- tools.push(snapshot);
1589
- },
1590
- registerSearchProvider: (provider) => {
1591
- assertCollecting();
1592
- rejectImplementationFields("search provider", provider, [
1593
- "isAvailable",
1594
- "search"
1595
- ]);
1596
- const snapshot = snapshotAdvertisementValue(provider);
1597
- rejectDuplicate("search provider id", snapshot.id, providerIds);
1598
- searchProviders.push(snapshot);
1599
- },
1600
- registerConverter: (converter) => {
1601
- assertCollecting();
1602
- rejectImplementationFields("converter", converter, ["convert"]);
1603
- const snapshot = snapshotAdvertisementValue(converter);
1604
- rejectDuplicate("converter id", snapshot.id, converterIds);
1605
- converters.push(snapshot);
1606
- },
1607
- auth
1608
- };
1609
- let result;
1610
- try {
1611
- result = advertisement.advertise(api);
1612
- } finally {
1613
- collecting = false;
1614
- }
1615
- if (result !== void 0) {
1616
- void Promise.resolve(result).catch(() => void 0);
1617
- throw new Error("A kay.agent advertisement must finish synchronously and return undefined.");
1618
- }
1619
- return Object.freeze({
1620
- tools: Object.freeze([...tools]),
1621
- uriModules: Object.freeze([...uriModules]),
1622
- searchProviders: Object.freeze([...searchProviders]),
1623
- converters: Object.freeze([...converters]),
1624
- auth: Object.freeze({
1625
- services: Object.freeze([...services]),
1626
- oauthPkceSchemes: Object.freeze([...oauthPkceSchemes]),
1627
- apiKeySchemes: Object.freeze([...apiKeySchemes]),
1628
- externalCliSchemes: Object.freeze([...externalCliSchemes]),
1629
- delegatedSchemes: Object.freeze([...delegatedSchemes]),
1630
- delegatedServiceSources: Object.freeze([...delegatedServiceSources])
1631
- })
1632
- });
1633
- }
1634
-
1635
1621
  // packages/plugin-sdk/dist/kay-agent/index.js
1636
1622
  function toolParameters(schema) {
1637
1623
  return toToolParameters(schema);
1638
1624
  }
1625
+ function manifestToolParameters(schema) {
1626
+ return toToolParameters(schema);
1627
+ }
1628
+ function toolExecute(schema, body) {
1629
+ return async (toolCallId, params, signal, onUpdate, ctx) => body(toolCallId, schema.parse(params), signal, onUpdate, ctx);
1630
+ }
1639
1631
  function defineTool(definition) {
1640
1632
  return definition;
1641
1633
  }
1642
1634
  function defineAuthedTool(definition, schema, binding, body) {
1643
- return withResolvedAuth({ ...definition, parameters: toolParameters(schema) }, binding, (toolCallId, rawParams, signal, onUpdate, ctx, resolvedAuth) => body(toolCallId, schema.parse(rawParams), signal, onUpdate, ctx, resolvedAuth));
1635
+ return withResolvedAuth({ ...definition, parameters: toolParameters(schema) }, binding, (toolCallId, rawParams, signal, onUpdate, ctx, credential) => body(toolCallId, schema.parse(rawParams), signal, onUpdate, ctx, credential));
1644
1636
  }
1645
1637
  var DELEGATED_REFRESH_REJECTED = Symbol.for("kay.plugin-sdk.delegated-refresh-rejected");
1646
1638
  var DelegatedRefreshRejectedError = class extends Error {
@@ -1681,6 +1673,7 @@ export {
1681
1673
  OSASCRIPT_TIMEOUT_MS,
1682
1674
  PluginApiError,
1683
1675
  SearchProviderError,
1676
+ SecureTransportError,
1684
1677
  URI_TEXT_EDIT_SHAPE_SUMMARY,
1685
1678
  UriConflictError,
1686
1679
  UriNotFoundError,
@@ -1692,18 +1685,19 @@ export {
1692
1685
  asArray,
1693
1686
  asRecord,
1694
1687
  assertResourceUnchanged,
1688
+ assertSecureTransport,
1695
1689
  basicUriHelp,
1696
1690
  bytesToBase64,
1697
1691
  capability,
1698
- collectKayAgentAdvertisement,
1699
1692
  compileUriClaim,
1700
1693
  contentDigest,
1701
1694
  contentResult,
1702
1695
  createJsonApiClient,
1703
1696
  createOsascriptRunner,
1697
+ createUnavailableCompiler,
1698
+ createUnavailableEndpoints,
1704
1699
  declareProducedResources,
1705
1700
  defineAuthedTool,
1706
- defineKayAgentAdvertisement,
1707
1701
  defineTool,
1708
1702
  describeUriTextEditTarget,
1709
1703
  fenced,
@@ -1711,11 +1705,14 @@ export {
1711
1705
  formatNumber,
1712
1706
  getBytes,
1713
1707
  isDelegatedRefreshRejected,
1708
+ isLoopbackHostname,
1714
1709
  jsonResource,
1710
+ knownResourcesView,
1715
1711
  labelOf,
1716
1712
  lineOf,
1717
1713
  lintUriHelpContracts,
1718
1714
  lintUriTemplate,
1715
+ manifestToolParameters,
1719
1716
  markdownResource,
1720
1717
  markdownText,
1721
1718
  num,
@@ -1730,9 +1727,12 @@ export {
1730
1727
  payload,
1731
1728
  readBodyWithByteCap,
1732
1729
  readOsascriptOutput,
1730
+ requireWriteContent,
1731
+ secureTransportViolation,
1733
1732
  str,
1734
1733
  textResult,
1735
1734
  toJsonSchema,
1735
+ toolExecute,
1736
1736
  toolParameters,
1737
1737
  unavailableInteractionSurface,
1738
1738
  unavailableInteractionSurfaces,