@yaklabs-ai/plugin-sdk 0.8.4

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.
@@ -0,0 +1,1341 @@
1
+ // packages/herd-uri/dist/errors.js
2
+ var UriError = class extends Error {
3
+ };
4
+ var CONFLICT_MESSAGES = {
5
+ changed: "This resource changed since this session last read it. Read it again before modifying it.",
6
+ unwitnessed: "This resource was not read in this session. Read it before modifying it.",
7
+ unknown: "This resource changed or was not read in this session. Read it again before modifying it."
8
+ };
9
+ var UriConflictError = class extends UriError {
10
+ _tag = "UriConflictError";
11
+ reason;
12
+ constructor(reason) {
13
+ super(CONFLICT_MESSAGES[reason ?? "unknown"]);
14
+ this.name = "UriConflictError";
15
+ this.reason = reason;
16
+ }
17
+ };
18
+ var UriValidationError = class extends UriError {
19
+ _tag = "UriValidationError";
20
+ constructor(message) {
21
+ super(message);
22
+ this.name = "UriValidationError";
23
+ }
24
+ };
25
+ var UriProviderError = class extends UriError {
26
+ _tag = "UriProviderError";
27
+ moduleId;
28
+ operation;
29
+ uri;
30
+ status;
31
+ providerCode;
32
+ retryable;
33
+ /** Provider-directed delay before retrying, in milliseconds. */
34
+ retryAfterMs;
35
+ constructor(options) {
36
+ super(options.message);
37
+ this.name = "UriProviderError";
38
+ this.moduleId = options.moduleId;
39
+ this.operation = options.operation;
40
+ this.uri = options.uri;
41
+ if (options.status !== void 0)
42
+ this.status = options.status;
43
+ if (options.providerCode !== void 0)
44
+ this.providerCode = options.providerCode;
45
+ if (options.retryable !== void 0)
46
+ this.retryable = options.retryable;
47
+ if (options.retryAfterMs !== void 0) {
48
+ if (!Number.isInteger(options.retryAfterMs) || options.retryAfterMs < 0) {
49
+ throw new TypeError("retryAfterMs must be a nonnegative integer.");
50
+ }
51
+ this.retryAfterMs = options.retryAfterMs;
52
+ }
53
+ }
54
+ };
55
+ var UriNotFoundError = class extends UriError {
56
+ uri;
57
+ hint;
58
+ _tag = "UriNotFoundError";
59
+ constructor(uri, hint) {
60
+ super(hint !== void 0 ? `No resource found at '${uri}'. ${hint}` : `No resource found at '${uri}'.`);
61
+ this.uri = uri;
62
+ this.hint = hint;
63
+ this.name = "UriNotFoundError";
64
+ }
65
+ };
66
+ var UriUnsupportedOperationError = class extends UriError {
67
+ operation;
68
+ moduleId;
69
+ uri;
70
+ _tag = "UriUnsupportedOperationError";
71
+ constructor(operation, moduleId, uri, message) {
72
+ super(message ?? `URI module '${moduleId}' does not support '${operation}' for '${uri}'.`);
73
+ this.operation = operation;
74
+ this.moduleId = moduleId;
75
+ this.uri = uri;
76
+ this.name = "UriUnsupportedOperationError";
77
+ }
78
+ };
79
+
80
+ // packages/herd-uri/dist/connection.js
81
+ var CONNECTION_SELECTOR_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*:\/\/)@([^/]+)(?:\/(.*))?$/;
82
+ function parseUriConnectionSelector(input) {
83
+ const match = CONNECTION_SELECTOR_RE.exec(input.trim());
84
+ if (match?.[1] === void 0 || match[2] === void 0) {
85
+ return { rest: input };
86
+ }
87
+ return { selector: match[2], rest: `${match[1]}${match[3] ?? ""}` };
88
+ }
89
+
90
+ // packages/herd-uri/dist/resource-witness.js
91
+ import { createHash } from "node:crypto";
92
+ function contentDigest(content) {
93
+ const hash = createHash("sha256");
94
+ hash.update(typeof content === "string" ? new TextEncoder().encode(content) : content);
95
+ return `${DIGEST_PREFIX}${hash.digest("base64url")}`;
96
+ }
97
+ function assertResourceUnchanged(ctx, current) {
98
+ const expected = ctx.expectedRevision;
99
+ if (expected === void 0)
100
+ return;
101
+ if (current.revision !== void 0 && current.revision === expected)
102
+ return;
103
+ if (current.content !== void 0) {
104
+ const digest = contentDigest(current.content);
105
+ if (digest === expected)
106
+ return;
107
+ if (filesystemStampDigest(expected) === digest.slice(DIGEST_PREFIX.length))
108
+ return;
109
+ }
110
+ throw new UriConflictError("changed");
111
+ }
112
+ var DIGEST_PREFIX = "sha256:";
113
+ function filesystemStampDigest(revision) {
114
+ const parts = revision.split(":");
115
+ return parts.length === 6 ? parts[5] : void 0;
116
+ }
117
+
118
+ // packages/herd-uri/dist/template-route.js
119
+ var PLACEHOLDER_RE = /<([^<>]+)>/g;
120
+ var REST_SUFFIX = "...";
121
+ var SCHEME_RE = /^([a-zA-Z][a-zA-Z0-9+.-]*):(?:\/\/)?(.*)$/s;
122
+ function parseRoute(address) {
123
+ const trimmed = address.trim();
124
+ const match = SCHEME_RE.exec(trimmed);
125
+ const scheme = match?.[1]?.toLowerCase() ?? "";
126
+ const rest = match?.[2] ?? trimmed;
127
+ const [rawPath = "", rawQuery] = splitQuery(rest);
128
+ const path = rawPath.replace(/^\/+/, "").replace(/\/+$/, "");
129
+ const query = /* @__PURE__ */ new Map();
130
+ if (rawQuery !== void 0) {
131
+ for (const pair of rawQuery.split("&")) {
132
+ if (pair.length === 0)
133
+ continue;
134
+ const eq = pair.indexOf("=");
135
+ const key = eq === -1 ? pair : pair.slice(0, eq);
136
+ const value = eq === -1 ? "" : pair.slice(eq + 1);
137
+ if (key.length === 0)
138
+ continue;
139
+ if (!query.has(key) || isPlaceholder(value))
140
+ query.set(key, value);
141
+ }
142
+ }
143
+ return { scheme, path, query };
144
+ }
145
+ function splitQuery(rest) {
146
+ const hash = rest.indexOf("#");
147
+ const withoutFragment = hash === -1 ? rest : rest.slice(0, hash);
148
+ const q = withoutFragment.indexOf("?");
149
+ return q === -1 ? [withoutFragment, void 0] : [withoutFragment.slice(0, q), withoutFragment.slice(q + 1)];
150
+ }
151
+ function isPlaceholder(value) {
152
+ return /^<[^<>]+>$/.test(value);
153
+ }
154
+ function selectorPlaceholder(templateUri) {
155
+ const selector = parseUriConnectionSelector(templateUri).selector;
156
+ if (selector === void 0)
157
+ return void 0;
158
+ const match = /^<([^<>]+)>$/.exec(selector);
159
+ return match?.[1];
160
+ }
161
+ function isRestPlaceholder(name) {
162
+ return name.endsWith(REST_SUFFIX);
163
+ }
164
+ function placeholderParameterName(name) {
165
+ return isRestPlaceholder(name) ? name.slice(0, -REST_SUFFIX.length) : name;
166
+ }
167
+ function templateAddressProblem(templateUri) {
168
+ const parsed = parseRoute(stripUriSelector(templateUri));
169
+ for (const match of parsed.path.matchAll(PLACEHOLDER_RE)) {
170
+ const name = match[1] ?? "";
171
+ if (name.includes("/")) {
172
+ return `placeholder <${name}> contains a slash; use <${name.split("/")[0] ?? "path"}...> as the last segment for a rest-of-path placeholder`;
173
+ }
174
+ if (isRestPlaceholder(name) && match.index + match[0].length !== parsed.path.length) {
175
+ return `rest-of-path placeholder <${name}> must be the last path segment`;
176
+ }
177
+ }
178
+ return void 0;
179
+ }
180
+ function stripUriSelector(address) {
181
+ return parseUriConnectionSelector(address).rest;
182
+ }
183
+ function templatePlaceholders(templateUri) {
184
+ return deriveTemplateParameters({ uri: templateUri, description: "" }).map((parameter) => parameter.name);
185
+ }
186
+ function deriveTemplateParameters(template) {
187
+ const authored = new Map((template.parameters ?? []).map((parameter) => [parameter.name, parameter]));
188
+ const parsed = parseRoute(stripUriSelector(template.uri));
189
+ const derived = [];
190
+ const selector = selectorPlaceholder(template.uri);
191
+ if (selector !== void 0) {
192
+ derived.push(authored.get(selector) ?? {
193
+ name: selector,
194
+ in: "selector",
195
+ required: false,
196
+ schema: { type: "string" }
197
+ });
198
+ }
199
+ for (const match of parsed.path.matchAll(PLACEHOLDER_RE)) {
200
+ const name = placeholderParameterName(match[1] ?? "");
201
+ if (name.length === 0 || derived.some((p) => p.name === name))
202
+ continue;
203
+ derived.push(authored.get(name) ?? {
204
+ name,
205
+ in: "uri",
206
+ required: true,
207
+ schema: { type: "string" }
208
+ });
209
+ }
210
+ for (const [key, value] of parsed.query) {
211
+ if (derived.some((p) => p.name === key))
212
+ continue;
213
+ const schema = isPlaceholder(value) ? { type: "string" } : { type: "string", enum: value.split("|").filter((v) => v.length > 0) };
214
+ derived.push(authored.get(key) ?? {
215
+ name: key,
216
+ in: "query",
217
+ required: false,
218
+ schema
219
+ });
220
+ }
221
+ const derivedNames = new Set(derived.map((parameter) => parameter.name));
222
+ const extra = (template.parameters ?? []).filter((parameter) => !derivedNames.has(parameter.name));
223
+ return [...derived, ...extra];
224
+ }
225
+
226
+ // packages/herd-uri/dist/template-lint.js
227
+ function lintUriTemplate(template) {
228
+ const findings = [];
229
+ const addressProblem = templateAddressProblem(template.uri);
230
+ if (addressProblem !== void 0) {
231
+ findings.push({
232
+ rule: "template-address-unmatchable",
233
+ uri: template.uri,
234
+ message: `${template.uri} can never be matched by help: ${addressProblem}.`
235
+ });
236
+ }
237
+ const operations = template.operations ?? [];
238
+ if (operations.filter((operation) => operation !== "help").length === 0) {
239
+ findings.push({
240
+ rule: "template-operations-missing",
241
+ uri: template.uri,
242
+ message: `${template.uri} lists no operations; a route must declare the verbs it supports.`
243
+ });
244
+ }
245
+ for (const operation of operations) {
246
+ if ((operation === "write" || operation === "edit") && template.accepts?.[operation] === void 0) {
247
+ findings.push({
248
+ rule: "template-accepts-missing",
249
+ uri: template.uri,
250
+ operation,
251
+ message: `${template.uri} lists ${operation} but declares no accepts.${operation} payload contract (use payload() from the handler's validator, or an explicit contract without a schema for an unstructured body).`
252
+ });
253
+ }
254
+ if (operation === "delete" && template.deleteEffect === void 0) {
255
+ findings.push({
256
+ rule: "template-delete-effect-missing",
257
+ uri: template.uri,
258
+ operation,
259
+ message: `${template.uri} lists delete but declares no deleteEffect (trash, permanent, or conditional).`
260
+ });
261
+ }
262
+ if (operation === "help")
263
+ continue;
264
+ const sentence = template.operationDocs?.[operation];
265
+ const soleVerb = operations.filter((candidate) => candidate !== "help").length === 1;
266
+ if (sentence === void 0 && !soleVerb) {
267
+ findings.push({
268
+ rule: "template-operation-docs-missing",
269
+ uri: template.uri,
270
+ operation,
271
+ message: `${template.uri} lists ${operation} alongside other verbs and has no operationDocs.${operation} sentence.`
272
+ });
273
+ }
274
+ }
275
+ const placeholders = new Set(templatePlaceholders(template.uri));
276
+ for (const parameter of template.parameters ?? []) {
277
+ if (placeholders.has(parameter.name))
278
+ continue;
279
+ findings.push({
280
+ rule: "template-parameter-unknown",
281
+ uri: template.uri,
282
+ parameter: parameter.name,
283
+ message: `${template.uri} authors parameter "${parameter.name}" but the address has no <${parameter.name}> placeholder.`
284
+ });
285
+ }
286
+ return findings;
287
+ }
288
+ function lintUriHelpContracts(help) {
289
+ return (help.templates ?? []).flatMap((template) => lintUriTemplate(template));
290
+ }
291
+
292
+ // packages/herd-uri/dist/operations.js
293
+ import { z } from "zod";
294
+ var URI_OPERATIONS = [
295
+ "help",
296
+ "read",
297
+ "write",
298
+ "edit",
299
+ "list",
300
+ "search",
301
+ "delete"
302
+ ];
303
+ var UriOperationSchema = z.enum(URI_OPERATIONS);
304
+
305
+ // packages/herd-uri/dist/help-schema.js
306
+ import { z as z2 } from "zod";
307
+ var UriContractJsonSchema = z2.record(z2.string(), z2.unknown());
308
+ var UriParameterSchema = z2.strictObject({
309
+ name: z2.string().min(1),
310
+ in: z2.enum(["uri", "query", "selector"]),
311
+ required: z2.boolean(),
312
+ description: z2.string().optional(),
313
+ schema: UriContractJsonSchema,
314
+ examples: z2.array(z2.unknown()).optional()
315
+ });
316
+ var UriPayloadContractSchema = z2.strictObject({
317
+ name: z2.string().min(1),
318
+ mediaType: z2.string().optional(),
319
+ description: z2.string().optional(),
320
+ schema: UriContractJsonSchema.optional(),
321
+ semanticConstraints: z2.array(z2.string().min(1)).min(1).optional(),
322
+ examples: z2.array(z2.unknown()).optional()
323
+ });
324
+
325
+ // packages/herd-uri/dist/observation.js
326
+ var OBSERVATION_MIME = "application/vnd.kay.observation+json";
327
+
328
+ // packages/herd-uri/dist/text-edit.js
329
+ import { z as z3 } from "zod";
330
+ var findReplaceArm = z3.strictObject({
331
+ find: z3.string().min(1),
332
+ replace: z3.string(),
333
+ all: z3.boolean().optional()
334
+ });
335
+ var oldNewEntry = z3.strictObject({
336
+ oldText: z3.string().min(1),
337
+ newText: z3.string()
338
+ });
339
+ var uriTextEditPayloadArms = z3.union([
340
+ findReplaceArm,
341
+ z3.strictObject({ edits: z3.array(oldNewEntry).min(1) }),
342
+ oldNewEntry,
343
+ z3.array(oldNewEntry).min(1)
344
+ ]);
345
+ var uriTextEditPayloadSchema = uriTextEditPayloadArms;
346
+ var URI_TEXT_EDIT_SHAPE_SUMMARY = `{"find": string, "replace": string, "all"?: boolean} (one exact-text replacement), or the edit tool's {"edits": [{"oldText", "newText"}, ...]}`;
347
+ function parseUriTextEditPayload(payload2) {
348
+ const parsed = uriTextEditPayloadArms.safeParse(payload2);
349
+ if (!parsed.success)
350
+ return { ok: false };
351
+ const data = parsed.data;
352
+ if (!Array.isArray(data) && "find" in data) {
353
+ return {
354
+ ok: true,
355
+ grammar: "find",
356
+ edits: [
357
+ { find: data.find, replace: data.replace, all: data.all ?? false }
358
+ ]
359
+ };
360
+ }
361
+ const entries = Array.isArray(data) ? data : "edits" in data ? data.edits : [data];
362
+ return {
363
+ ok: true,
364
+ grammar: "edits",
365
+ edits: entries.map((entry) => ({
366
+ find: entry.oldText,
367
+ replace: entry.newText,
368
+ all: false
369
+ }))
370
+ };
371
+ }
372
+ function occurrencePositions(content, find) {
373
+ const positions = [];
374
+ let cursor = content.indexOf(find);
375
+ while (cursor !== -1) {
376
+ positions.push(cursor);
377
+ cursor = content.indexOf(find, cursor + find.length);
378
+ }
379
+ return positions;
380
+ }
381
+ function applyUriTextEdits(content, edits) {
382
+ const ranges = [];
383
+ for (const [index, edit] of edits.entries()) {
384
+ const positions = occurrencePositions(content, edit.find);
385
+ if (positions.length === 0) {
386
+ return { ok: false, failure: { kind: "no-match", index } };
387
+ }
388
+ if (positions.length > 1 && !edit.all) {
389
+ return {
390
+ ok: false,
391
+ failure: { kind: "ambiguous", index, occurrences: positions.length }
392
+ };
393
+ }
394
+ const applied = edit.all ? positions : positions.slice(0, 1);
395
+ for (const start of applied) {
396
+ ranges.push({
397
+ start,
398
+ end: start + edit.find.length,
399
+ replace: edit.replace,
400
+ editIndex: index
401
+ });
402
+ }
403
+ }
404
+ ranges.sort((a, b) => a.start - b.start || a.editIndex - b.editIndex);
405
+ for (let i = 1; i < ranges.length; i++) {
406
+ if (ranges[i].start < ranges[i - 1].end) {
407
+ return {
408
+ ok: false,
409
+ failure: {
410
+ kind: "overlap",
411
+ index: Math.max(ranges[i].editIndex, ranges[i - 1].editIndex)
412
+ }
413
+ };
414
+ }
415
+ }
416
+ let text = "";
417
+ let cursor = 0;
418
+ for (const range of ranges) {
419
+ text += content.slice(cursor, range.start) + range.replace;
420
+ cursor = range.end;
421
+ }
422
+ text += content.slice(cursor);
423
+ if (text === content) {
424
+ return { ok: false, failure: { kind: "no-change" } };
425
+ }
426
+ return { ok: true, text, replaced: ranges.length };
427
+ }
428
+ function describeUriTextEditTarget(grammar, index, count) {
429
+ if (grammar === "find")
430
+ return "The find text";
431
+ return count === 1 ? "The oldText" : `edits[${String(index)}].oldText`;
432
+ }
433
+
434
+ // packages/herd-uri/dist/line-selector.js
435
+ var RAW_TOKEN = /^raw$/i;
436
+ function parseRangeListToken(token) {
437
+ if (token.length === 0)
438
+ return void 0;
439
+ const ranges = [];
440
+ for (const part of token.split(",")) {
441
+ const range = parseSingleRange(part);
442
+ if (range === void 0)
443
+ return void 0;
444
+ ranges.push(range);
445
+ }
446
+ return ranges;
447
+ }
448
+ function toInt(value) {
449
+ if (!/^\d+$/.test(value))
450
+ return void 0;
451
+ const n = Number.parseInt(value, 10);
452
+ return Number.isSafeInteger(n) && n >= 1 ? n : void 0;
453
+ }
454
+ function parseSingleRange(part) {
455
+ const plus = part.indexOf("+");
456
+ if (plus >= 0) {
457
+ const start2 = toInt(part.slice(0, plus));
458
+ const count = toInt(part.slice(plus + 1));
459
+ if (start2 === void 0 || count === void 0)
460
+ return void 0;
461
+ return { start: start2, end: start2 + count - 1 };
462
+ }
463
+ const dash = part.indexOf("-");
464
+ if (dash >= 0) {
465
+ const start2 = toInt(part.slice(0, dash));
466
+ const endRaw = part.slice(dash + 1);
467
+ if (start2 === void 0)
468
+ return void 0;
469
+ if (endRaw.length === 0)
470
+ return { start: start2, end: Number.POSITIVE_INFINITY };
471
+ const end = toInt(endRaw);
472
+ if (end === void 0 || end < start2)
473
+ return void 0;
474
+ return { start: start2, end };
475
+ }
476
+ const start = toInt(part);
477
+ if (start === void 0)
478
+ return void 0;
479
+ return { start, end: Number.POSITIVE_INFINITY };
480
+ }
481
+ function mergeRanges(ranges) {
482
+ const sorted = [...ranges].sort((a, b) => a.start - b.start);
483
+ const merged = [];
484
+ for (const range of sorted) {
485
+ const last = merged[merged.length - 1];
486
+ if (last !== void 0 && range.start <= last.end) {
487
+ if (range.end > last.end) {
488
+ merged[merged.length - 1] = { start: last.start, end: range.end };
489
+ }
490
+ continue;
491
+ }
492
+ merged.push(range);
493
+ }
494
+ return merged;
495
+ }
496
+ function parseLineSelector(input) {
497
+ let address = input;
498
+ let raw = false;
499
+ let ranges;
500
+ for (let i = 0; i < 2; i += 1) {
501
+ const colon = address.lastIndexOf(":");
502
+ if (colon < 0)
503
+ break;
504
+ const token = address.slice(colon + 1);
505
+ if (RAW_TOKEN.test(token)) {
506
+ if (raw)
507
+ break;
508
+ raw = true;
509
+ address = address.slice(0, colon);
510
+ continue;
511
+ }
512
+ const parsed = parseRangeListToken(token);
513
+ if (parsed === void 0)
514
+ break;
515
+ if (ranges !== void 0)
516
+ break;
517
+ ranges = parsed;
518
+ address = address.slice(0, colon);
519
+ }
520
+ return {
521
+ address,
522
+ selector: { ranges: ranges ? mergeRanges(ranges) : [], raw }
523
+ };
524
+ }
525
+
526
+ // packages/herd-uri/dist/schema/to-json-schema.js
527
+ import { z as z4 } from "zod";
528
+ function toJsonSchema(schema) {
529
+ if (schema instanceof z4.ZodType) {
530
+ const { $schema: _dialect, ...value } = z4.toJSONSchema(schema, {
531
+ // `io: "input"` describes what a caller may SEND, which is what a parameter and an
532
+ // `accepts` payload advertise: a field with a Zod default is optional on the wire even
533
+ // though the parsed value always carries it. Strictness still survives where the validator
534
+ // really enforces it — `z.strictObject` emits `additionalProperties: false`, while a plain
535
+ // `z.object` correctly does not, because it TOLERATES unknown keys and silently strips
536
+ // them. A `returns` payload derived from a Zod schema is described in the same input terms;
537
+ // no module does that today, and a faithful output projection would need its own seam.
538
+ io: "input",
539
+ // Inline every reused sub-schema rather than emitting `$ref`s into a `$defs` block. A
540
+ // contract schema is a FRAGMENT: it gets embedded in a payload contract, and callers
541
+ // legitimately lift one arm of a union out of it. A `$ref` only resolves relative to the
542
+ // root that carries `$defs`, so the moment the fragment moves, the reference dangles.
543
+ // Self-contained is worth the repetition at these sizes.
544
+ reused: "inline",
545
+ // Recursion (`z.lazy`) has no self-contained form: zod's default is to emit a
546
+ // `$defs` block with `$ref` pointers, which dangle the moment the fragment is
547
+ // embedded. Throw instead, so a contract that needs recursion has to disclose a
548
+ // non-recursive shape (see skill-module's metadata disclosure) rather than ship a
549
+ // reference nothing can resolve.
550
+ cycles: "throw"
551
+ });
552
+ return value;
553
+ }
554
+ return structuredClone(schema);
555
+ }
556
+
557
+ // packages/herd-uri/dist/schema/helpers.js
558
+ function uriParam(name, schema, description, options = {}) {
559
+ return {
560
+ name,
561
+ in: "uri",
562
+ required: options.required ?? true,
563
+ ...description === void 0 ? {} : { description },
564
+ schema: toJsonSchema(schema),
565
+ ...options.examples === void 0 ? {} : { examples: options.examples }
566
+ };
567
+ }
568
+ function payload(name, schema, options = {}) {
569
+ return {
570
+ name,
571
+ ...options.mediaType === void 0 ? {} : { mediaType: options.mediaType },
572
+ ...options.description === void 0 ? {} : { description: options.description },
573
+ schema: toJsonSchema(schema),
574
+ ...options.semanticConstraints === void 0 ? {} : { semanticConstraints: options.semanticConstraints },
575
+ ...options.examples === void 0 ? {} : { examples: options.examples }
576
+ };
577
+ }
578
+ function capability(spec) {
579
+ return { ...spec };
580
+ }
581
+
582
+ // packages/plugin-sdk/dist/jev.js
583
+ function createFallbackOnlyWithJev() {
584
+ return async (_use, fallback, options = {}) => {
585
+ if (typeof fallback !== "function") {
586
+ throw new TypeError("withJev requires a `fallback` function as its second argument.");
587
+ }
588
+ const { signal, deadlineAt } = options;
589
+ if (deadlineAt !== void 0 && !Number.isFinite(deadlineAt)) {
590
+ throw new TypeError("withJev's `deadlineAt` must be a finite epoch-ms timestamp.");
591
+ }
592
+ const assertWithinBoundaries = () => {
593
+ if (signal?.aborted === true) {
594
+ throw signal.reason ?? new DOMException("Aborted", "AbortError");
595
+ }
596
+ if (deadlineAt !== void 0 && Date.now() >= deadlineAt) {
597
+ throw new Error("withJev's deadline has passed.");
598
+ }
599
+ };
600
+ assertWithinBoundaries();
601
+ let timer;
602
+ let onAbort;
603
+ const stopped = new Promise((_resolve, reject) => {
604
+ if (signal !== void 0) {
605
+ onAbort = () => reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
606
+ signal.addEventListener("abort", onAbort, { once: true });
607
+ }
608
+ if (deadlineAt !== void 0) {
609
+ const checkDeadline = () => {
610
+ const remaining = deadlineAt - Date.now();
611
+ if (remaining <= 0) {
612
+ reject(new Error("withJev's deadline has passed."));
613
+ } else {
614
+ timer = setTimeout(checkDeadline, Math.min(remaining, 2147483647));
615
+ }
616
+ };
617
+ checkDeadline();
618
+ }
619
+ });
620
+ try {
621
+ const result = await Promise.race([
622
+ Promise.resolve().then(() => {
623
+ assertWithinBoundaries();
624
+ return fallback();
625
+ }),
626
+ stopped
627
+ ]);
628
+ assertWithinBoundaries();
629
+ return result;
630
+ } catch (error) {
631
+ assertWithinBoundaries();
632
+ throw error;
633
+ } finally {
634
+ if (timer !== void 0)
635
+ clearTimeout(timer);
636
+ if (signal !== void 0 && onAbort !== void 0) {
637
+ signal.removeEventListener("abort", onAbort);
638
+ }
639
+ }
640
+ };
641
+ }
642
+
643
+ // packages/herd-uri-extensions/dist/limits.js
644
+ var MAX_BYTES = 50 * 1024 * 1024;
645
+ var MAX_OUTPUT_CHARS = 5e5;
646
+
647
+ // packages/herd-uri-extensions/dist/markdown.js
648
+ function finalizeOutput(content, maxChars = MAX_OUTPUT_CHARS) {
649
+ const cleaned = content.replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
650
+ const truncated = cleaned.length > maxChars;
651
+ return {
652
+ content: truncated ? cleaned.slice(0, maxChars) : cleaned,
653
+ truncated
654
+ };
655
+ }
656
+
657
+ // packages/herd-uri-extensions/dist/help.js
658
+ function basicUriHelp(options) {
659
+ return {
660
+ uri: options.uri,
661
+ title: options.title,
662
+ summary: options.summary,
663
+ capabilities: options.operations.map((operation) => ({
664
+ rel: operation,
665
+ operation,
666
+ uri: options.uri,
667
+ title: `${operation} ${options.uri}`
668
+ })),
669
+ ...options.templates !== void 0 ? { templates: options.templates } : {},
670
+ ...options.examples !== void 0 ? { examples: options.examples } : {},
671
+ ...options.notes !== void 0 ? { notes: options.notes } : {}
672
+ };
673
+ }
674
+ function tryParseJson(text) {
675
+ try {
676
+ return JSON.parse(text);
677
+ } catch {
678
+ return void 0;
679
+ }
680
+ }
681
+ function formatNumber(n) {
682
+ if (n >= 1e6)
683
+ return `${(n / 1e6).toFixed(1)}M`;
684
+ if (n >= 1e3)
685
+ return `${(n / 1e3).toFixed(1)}K`;
686
+ return String(n);
687
+ }
688
+ function formatIsoDate(value) {
689
+ if (value == null)
690
+ return "";
691
+ try {
692
+ return new Date(value).toISOString().split("T")[0] ?? "";
693
+ } catch {
694
+ return "";
695
+ }
696
+ }
697
+ function jsonResource(uri, value) {
698
+ return {
699
+ uri,
700
+ content: JSON.stringify(value, null, 2),
701
+ mimeType: "application/json"
702
+ };
703
+ }
704
+ function markdownResource(uri, md, notes = []) {
705
+ const capped = finalizeOutput(md);
706
+ if (capped.truncated)
707
+ notes.push("Output truncated to size limit.");
708
+ const content = capped.content;
709
+ return {
710
+ uri,
711
+ content: content.length === 0 ? "(empty)" : content,
712
+ mimeType: "text/markdown",
713
+ ...notes.length > 0 ? { metadata: { notes } } : {}
714
+ };
715
+ }
716
+ function observationResource(uri, material) {
717
+ return {
718
+ uri,
719
+ content: JSON.stringify(material, null, 2),
720
+ mimeType: OBSERVATION_MIME
721
+ };
722
+ }
723
+ function accountQualifiedUri(scheme, accountId, path) {
724
+ if (accountId.length === 0 || accountId.includes("/")) {
725
+ throw new Error(`accountQualifiedUri: accountId must be non-empty and contain no "/" (selector-parse would truncate it), got ${JSON.stringify(accountId)}`);
726
+ }
727
+ return `${scheme}://@${accountId}/${path}`;
728
+ }
729
+ function isOptionalString(value) {
730
+ return value === void 0 || typeof value === "string";
731
+ }
732
+ function isOptionalStringArray(value) {
733
+ return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
734
+ }
735
+ function observationFromResource(resource) {
736
+ if (resource.mimeType !== OBSERVATION_MIME)
737
+ return void 0;
738
+ if (typeof resource.content !== "string")
739
+ return void 0;
740
+ const parsed = tryParseJson(resource.content);
741
+ if (parsed === void 0 || typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
742
+ return void 0;
743
+ }
744
+ const value = parsed;
745
+ if (typeof value.uri !== "string" || typeof value.kind !== "string") {
746
+ return void 0;
747
+ }
748
+ if (!isOptionalString(value.title) || !isOptionalStringArray(value.text) || !isOptionalString(value.createdAt) || !isOptionalString(value.updatedAt) || !isOptionalString(value.version)) {
749
+ return void 0;
750
+ }
751
+ return value;
752
+ }
753
+
754
+ // packages/herd-agent/dist/core/extensions/auth/scheme.js
755
+ var ACCOUNT_ID_PARAM = "accountId";
756
+ function authContextOf(ctx) {
757
+ return ctx.auth;
758
+ }
759
+ function authFailureResult(failure) {
760
+ return {
761
+ content: [{ type: "text", text: failure.message }],
762
+ details: void 0
763
+ };
764
+ }
765
+ function withAccountIdParam(parameters) {
766
+ if (parameters === null || typeof parameters !== "object" || parameters.type !== "object") {
767
+ return parameters;
768
+ }
769
+ const schema = parameters;
770
+ if (schema.properties?.[ACCOUNT_ID_PARAM] !== void 0) {
771
+ return parameters;
772
+ }
773
+ return {
774
+ ...schema,
775
+ properties: {
776
+ ...schema.properties,
777
+ [ACCOUNT_ID_PARAM]: {
778
+ type: "string",
779
+ description: "Optional account id to use for this call instead of the session-active account."
780
+ }
781
+ }
782
+ };
783
+ }
784
+ function withResolvedAuth(definition, binding, body) {
785
+ return {
786
+ ...definition,
787
+ requiresAuth: binding,
788
+ parameters: withAccountIdParam(definition.parameters),
789
+ async execute(toolCallId, params, signal, onUpdate, ctx) {
790
+ const auth = authContextOf(ctx);
791
+ if (auth === void 0) {
792
+ return authFailureResult({
793
+ ok: false,
794
+ reason: "no-connection",
795
+ message: `Auth is not available in this context for ${binding.serviceId}.`
796
+ });
797
+ }
798
+ const override = params?.[ACCOUNT_ID_PARAM];
799
+ const result = await auth.resolveToken({
800
+ serviceId: binding.serviceId,
801
+ ...binding.schemeId === void 0 ? {} : { schemeId: binding.schemeId },
802
+ ...typeof override === "string" && override.length > 0 ? { accountId: override } : {},
803
+ ...binding.requiredScopes === void 0 ? {} : { requiredScopes: binding.requiredScopes },
804
+ ...binding.scopeRequirement === void 0 ? {} : { scopeRequirement: binding.scopeRequirement },
805
+ ...binding.connectServiceId === void 0 ? {} : { connectServiceId: binding.connectServiceId }
806
+ });
807
+ if (!result.ok) {
808
+ return authFailureResult(result);
809
+ }
810
+ return body(toolCallId, params, signal, onUpdate, ctx, result.auth);
811
+ }
812
+ };
813
+ }
814
+
815
+ // packages/herd-agent/dist/core/web/search/types.js
816
+ var SearchProviderError = class extends Error {
817
+ provider;
818
+ status;
819
+ constructor(provider, message, status) {
820
+ super(message);
821
+ this.provider = provider;
822
+ this.status = status;
823
+ this.name = "SearchProviderError";
824
+ }
825
+ };
826
+
827
+ // packages/herd-agent/dist/core/web/search/with-resolved-search-provider.js
828
+ function withResolvedSearchProvider(definition, binding, body) {
829
+ return {
830
+ id: definition.id,
831
+ label: definition.label,
832
+ providerId: definition.providerId ?? "",
833
+ requiresAuth: binding,
834
+ async isAvailable(ctx) {
835
+ const auth = ctx?.auth;
836
+ if (auth === void 0)
837
+ return false;
838
+ const result = await auth.resolveToken(binding);
839
+ return result.ok;
840
+ },
841
+ async search(params, signal, ctx) {
842
+ const auth = ctx?.auth;
843
+ if (auth === void 0) {
844
+ throw new SearchProviderError(definition.id, `Auth is not available in this context for ${binding.serviceId}.`);
845
+ }
846
+ const result = await auth.resolveToken(binding);
847
+ if (!result.ok) {
848
+ throw new SearchProviderError(definition.id, result.message);
849
+ }
850
+ return body(params, signal, result.auth);
851
+ }
852
+ };
853
+ }
854
+
855
+ // packages/herd-agent/dist/core/tools/tool-parameters.js
856
+ import { z as z5 } from "zod";
857
+ var URI_PAYLOAD_MARKER = "x-kay-uri-payload";
858
+ var URI_PAYLOAD_WIRE_TYPES = [
859
+ "string",
860
+ "object",
861
+ "array",
862
+ "number",
863
+ "boolean",
864
+ "null"
865
+ ];
866
+ var uriPayloadSchema = z5.union([
867
+ z5.string(),
868
+ z5.record(z5.string(), z5.unknown()),
869
+ z5.array(z5.unknown()),
870
+ z5.number(),
871
+ z5.boolean(),
872
+ z5.null()
873
+ ]).meta({ [URI_PAYLOAD_MARKER]: true });
874
+ function toToolParameters(schema) {
875
+ const jsonSchema = z5.toJSONSchema(schema, {
876
+ io: "input",
877
+ override(ctx) {
878
+ const node = ctx.jsonSchema;
879
+ if (node[URI_PAYLOAD_MARKER] === true) {
880
+ delete node[URI_PAYLOAD_MARKER];
881
+ delete node["anyOf"];
882
+ node["type"] = [...URI_PAYLOAD_WIRE_TYPES];
883
+ }
884
+ }
885
+ });
886
+ const { $schema: _schema, $id: _id, ...rest } = jsonSchema;
887
+ return rest;
888
+ }
889
+
890
+ // packages/plugin-primitives/dist/results.js
891
+ function textResult(text, details) {
892
+ const content = [{ type: "text", text }];
893
+ return { content, details };
894
+ }
895
+ function contentResult(content, details) {
896
+ return { content: [...content], details };
897
+ }
898
+
899
+ // packages/plugin-primitives/dist/transfer.js
900
+ var MAX_BYTES2 = 50 * 1024 * 1024;
901
+ async function readBodyWithByteCap(response, maxBytes) {
902
+ const reader = response.body?.getReader();
903
+ if (!reader)
904
+ return void 0;
905
+ const chunks = [];
906
+ let totalSize = 0;
907
+ let capped = false;
908
+ while (true) {
909
+ const { done, value } = await reader.read();
910
+ if (done)
911
+ break;
912
+ if (value) {
913
+ chunks.push(value);
914
+ totalSize += value.length;
915
+ if (totalSize > maxBytes) {
916
+ capped = true;
917
+ await reader.cancel();
918
+ break;
919
+ }
920
+ }
921
+ }
922
+ const bodyBuffer = Buffer.concat(chunks);
923
+ const bytes = new Uint8Array(bodyBuffer.buffer, bodyBuffer.byteOffset, bodyBuffer.byteLength);
924
+ return { bytes, capped };
925
+ }
926
+
927
+ // packages/plugin-sdk/dist/kay-agent/index.js
928
+ import { z as z6 } from "zod";
929
+
930
+ // packages/plugin-sdk/dist/kay-agent/http-client.js
931
+ var PluginApiError = class extends Error {
932
+ status;
933
+ url;
934
+ bodyText;
935
+ constructor(init) {
936
+ super(`Request to ${init.url} failed with status ${init.status}`);
937
+ this.name = "PluginApiError";
938
+ this.status = init.status;
939
+ this.url = init.url;
940
+ this.bodyText = init.bodyText;
941
+ }
942
+ };
943
+ async function readErrorBodyText(response) {
944
+ return response.text().catch(() => "");
945
+ }
946
+ async function readCappedErrorBodyText(response, maxBytes) {
947
+ const result = await readBodyWithByteCap(response, maxBytes).catch(() => void 0);
948
+ return result === void 0 ? "" : new TextDecoder().decode(result.bytes.slice(0, maxBytes));
949
+ }
950
+ function mergeHeaders(defaults, overrides) {
951
+ const headers = new Headers(defaults);
952
+ if (overrides !== void 0) {
953
+ for (const [key, value] of Object.entries(overrides))
954
+ headers.set(key, value);
955
+ }
956
+ return headers;
957
+ }
958
+ function withQueryParams(url, params) {
959
+ if (params === void 0)
960
+ return url;
961
+ const target = new URL(url);
962
+ for (const [key, value] of Object.entries(params)) {
963
+ if (value !== void 0)
964
+ target.searchParams.set(key, String(value));
965
+ }
966
+ return target.toString();
967
+ }
968
+ async function getBytes(url, options, fetchImpl = globalThis.fetch) {
969
+ const response = await fetchImpl(url, {
970
+ headers: mergeHeaders(void 0, options.headers),
971
+ ...options.signal !== void 0 ? { signal: options.signal } : {}
972
+ });
973
+ if (!response.ok) {
974
+ throw new PluginApiError({
975
+ status: response.status,
976
+ url,
977
+ bodyText: await readCappedErrorBodyText(response, options.maxBytes)
978
+ });
979
+ }
980
+ const capRead = await readBodyWithByteCap(response, options.maxBytes);
981
+ return {
982
+ status: response.status,
983
+ headers: response.headers,
984
+ bytes: capRead?.bytes ?? new Uint8Array(0),
985
+ capped: capRead?.capped ?? false
986
+ };
987
+ }
988
+ function createJsonApiClient(options = {}) {
989
+ const fetchImpl = options.fetch ?? globalThis.fetch;
990
+ async function requestJson(url, init) {
991
+ const response = await fetchImpl(url, init);
992
+ if (!response.ok) {
993
+ throw new PluginApiError({
994
+ status: response.status,
995
+ url,
996
+ bodyText: await readErrorBodyText(response)
997
+ });
998
+ }
999
+ const body = await response.json();
1000
+ return { status: response.status, headers: response.headers, body };
1001
+ }
1002
+ return {
1003
+ getJson: (url, callOptions) => requestJson(withQueryParams(url, callOptions?.params), {
1004
+ method: "GET",
1005
+ headers: mergeHeaders(void 0, callOptions?.headers),
1006
+ ...callOptions?.signal !== void 0 ? { signal: callOptions.signal } : {}
1007
+ }),
1008
+ postJson: (url, payload2, callOptions) => requestJson(withQueryParams(url, callOptions?.params), {
1009
+ method: "POST",
1010
+ headers: mergeHeaders({ "content-type": "application/json" }, callOptions?.headers),
1011
+ body: JSON.stringify(payload2),
1012
+ ...callOptions?.signal !== void 0 ? { signal: callOptions.signal } : {}
1013
+ }),
1014
+ getBytes: (url, byteOptions) => getBytes(url, byteOptions, fetchImpl)
1015
+ };
1016
+ }
1017
+
1018
+ // packages/plugin-sdk/dist/kay-agent/readers.js
1019
+ function asRecord(value) {
1020
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
1021
+ }
1022
+ function asArray(value) {
1023
+ return Array.isArray(value) ? value : [];
1024
+ }
1025
+ function str(record, key) {
1026
+ const value = record?.[key];
1027
+ return typeof value === "string" && value !== "" ? value : void 0;
1028
+ }
1029
+ function num(record, key) {
1030
+ const value = record?.[key];
1031
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1032
+ }
1033
+ function numLike(record, key) {
1034
+ const value = record?.[key];
1035
+ if (typeof value === "number" && Number.isFinite(value))
1036
+ return value;
1037
+ if (typeof value === "string" && value.trim() !== "") {
1038
+ const parsed = Number(value);
1039
+ return Number.isFinite(parsed) ? parsed : void 0;
1040
+ }
1041
+ return void 0;
1042
+ }
1043
+
1044
+ // packages/plugin-sdk/dist/kay-agent/base64.js
1045
+ var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1046
+ function bytesToBase64(bytes) {
1047
+ let output = "";
1048
+ for (let i = 0; i < bytes.length; i += 3) {
1049
+ const b0 = bytes[i] ?? 0;
1050
+ const b1 = bytes[i + 1] ?? 0;
1051
+ const b2 = bytes[i + 2] ?? 0;
1052
+ const triple = b0 << 16 | b1 << 8 | b2;
1053
+ output += BASE64_ALPHABET.charAt(triple >> 18 & 63);
1054
+ output += BASE64_ALPHABET.charAt(triple >> 12 & 63);
1055
+ output += i + 1 < bytes.length ? BASE64_ALPHABET.charAt(triple >> 6 & 63) : "=";
1056
+ output += i + 2 < bytes.length ? BASE64_ALPHABET.charAt(triple & 63) : "=";
1057
+ }
1058
+ return output;
1059
+ }
1060
+
1061
+ // packages/plugin-sdk/dist/kay-agent/advertisement.js
1062
+ function defineKayAgentAdvertisement(advertisement) {
1063
+ return advertisement;
1064
+ }
1065
+ function rejectDuplicate(category, id, seen) {
1066
+ if (seen.has(id)) {
1067
+ throw new Error(`Duplicate advertised ${category} '${id}'.`);
1068
+ }
1069
+ seen.add(id);
1070
+ }
1071
+ function rejectImplementationFields(category, value, fields) {
1072
+ for (const field of fields) {
1073
+ if (field in value) {
1074
+ throw new Error(`Advertised ${category} cannot include implementation field '${field}'.`);
1075
+ }
1076
+ }
1077
+ }
1078
+ function snapshotAdvertisementValue(value, seen = /* @__PURE__ */ new WeakMap()) {
1079
+ if ((typeof value !== "object" || value === null) && typeof value !== "function") {
1080
+ return value;
1081
+ }
1082
+ if (typeof value === "function") {
1083
+ return value;
1084
+ }
1085
+ const existing = seen.get(value);
1086
+ if (existing !== void 0)
1087
+ return existing;
1088
+ if (Array.isArray(value)) {
1089
+ const copy2 = [];
1090
+ seen.set(value, copy2);
1091
+ for (const entry of value) {
1092
+ copy2.push(snapshotAdvertisementValue(entry, seen));
1093
+ }
1094
+ return Object.freeze(copy2);
1095
+ }
1096
+ const copy = /* @__PURE__ */ Object.create(null);
1097
+ seen.set(value, copy);
1098
+ const copiedKeys = /* @__PURE__ */ new Set();
1099
+ let source = value;
1100
+ while (source !== null && source !== Object.prototype) {
1101
+ for (const key of Reflect.ownKeys(source)) {
1102
+ if (key === "constructor" || copiedKeys.has(key))
1103
+ continue;
1104
+ copiedKeys.add(key);
1105
+ copy[key] = snapshotAdvertisementValue(Reflect.get(value, key), seen);
1106
+ }
1107
+ source = Object.getPrototypeOf(source);
1108
+ }
1109
+ return Object.freeze(copy);
1110
+ }
1111
+ function snapshotDelegatedServiceSource(source) {
1112
+ return () => {
1113
+ const entries = source();
1114
+ if (!Array.isArray(entries)) {
1115
+ throw new Error("An advertised delegated service source must return an array synchronously.");
1116
+ }
1117
+ return Object.freeze(entries.map((entry) => {
1118
+ rejectImplementationFields("delegated service source scheme", entry.scheme, ["connect", "refresh"]);
1119
+ return snapshotAdvertisementValue(entry);
1120
+ }));
1121
+ };
1122
+ }
1123
+ function collectKayAgentAdvertisement(advertisement) {
1124
+ const tools = [];
1125
+ const uriModules = [];
1126
+ const searchProviders = [];
1127
+ const converters = [];
1128
+ const services = [];
1129
+ const oauthPkceSchemes = [];
1130
+ const apiKeySchemes = [];
1131
+ const externalCliSchemes = [];
1132
+ const delegatedSchemes = [];
1133
+ const delegatedServiceSources = [];
1134
+ const toolNames = /* @__PURE__ */ new Set();
1135
+ const moduleIds = /* @__PURE__ */ new Set();
1136
+ const providerIds = /* @__PURE__ */ new Set();
1137
+ const converterIds = /* @__PURE__ */ new Set();
1138
+ let collecting = true;
1139
+ const assertCollecting = () => {
1140
+ if (!collecting) {
1141
+ throw new Error("The kay.agent advertisement API cannot be used after advertise() returns.");
1142
+ }
1143
+ };
1144
+ const auth = {
1145
+ advertiseService: (descriptor) => {
1146
+ assertCollecting();
1147
+ services.push(snapshotAdvertisementValue(descriptor));
1148
+ },
1149
+ declareOAuthPkceScheme: (serviceId, scheme) => {
1150
+ assertCollecting();
1151
+ rejectImplementationFields("OAuth PKCE scheme", scheme, [
1152
+ "resolveAccountId",
1153
+ "resolveAccounts"
1154
+ ]);
1155
+ oauthPkceSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1156
+ },
1157
+ declareApiKeyScheme: (serviceId, scheme) => {
1158
+ assertCollecting();
1159
+ rejectImplementationFields("API key scheme", scheme, ["validate"]);
1160
+ apiKeySchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1161
+ },
1162
+ declareExternalCliScheme: (serviceId, scheme) => {
1163
+ assertCollecting();
1164
+ externalCliSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1165
+ },
1166
+ declareDelegatedScheme: (serviceId, scheme) => {
1167
+ assertCollecting();
1168
+ rejectImplementationFields("delegated scheme", scheme, [
1169
+ "connect",
1170
+ "refresh"
1171
+ ]);
1172
+ delegatedSchemes.push(snapshotAdvertisementValue({ serviceId, scheme }));
1173
+ },
1174
+ registerDelegatedServiceSource: (source) => {
1175
+ assertCollecting();
1176
+ delegatedServiceSources.push(Object.freeze({ source: snapshotDelegatedServiceSource(source) }));
1177
+ }
1178
+ };
1179
+ const api = {
1180
+ uri: {
1181
+ registerModule: (module) => {
1182
+ assertCollecting();
1183
+ rejectImplementationFields("URI module", module, [
1184
+ "locate",
1185
+ "read",
1186
+ "help",
1187
+ "write",
1188
+ "edit",
1189
+ "list",
1190
+ "search",
1191
+ "delete"
1192
+ ]);
1193
+ const snapshot = snapshotAdvertisementValue(module);
1194
+ rejectDuplicate("URI module id", snapshot.id, moduleIds);
1195
+ uriModules.push(snapshot);
1196
+ }
1197
+ },
1198
+ registerTool: (definition) => {
1199
+ assertCollecting();
1200
+ rejectImplementationFields("tool", definition, ["execute"]);
1201
+ const snapshot = snapshotAdvertisementValue(definition);
1202
+ rejectDuplicate("tool name", snapshot.name, toolNames);
1203
+ tools.push(snapshot);
1204
+ },
1205
+ registerSearchProvider: (provider) => {
1206
+ assertCollecting();
1207
+ rejectImplementationFields("search provider", provider, [
1208
+ "isAvailable",
1209
+ "search"
1210
+ ]);
1211
+ const snapshot = snapshotAdvertisementValue(provider);
1212
+ rejectDuplicate("search provider id", snapshot.id, providerIds);
1213
+ searchProviders.push(snapshot);
1214
+ },
1215
+ registerConverter: (converter) => {
1216
+ assertCollecting();
1217
+ rejectImplementationFields("converter", converter, ["convert"]);
1218
+ const snapshot = snapshotAdvertisementValue(converter);
1219
+ rejectDuplicate("converter id", snapshot.id, converterIds);
1220
+ converters.push(snapshot);
1221
+ },
1222
+ auth
1223
+ };
1224
+ let result;
1225
+ try {
1226
+ result = advertisement.advertise(api);
1227
+ } finally {
1228
+ collecting = false;
1229
+ }
1230
+ if (result !== void 0) {
1231
+ void Promise.resolve(result).catch(() => void 0);
1232
+ throw new Error("A kay.agent advertisement must finish synchronously and return undefined.");
1233
+ }
1234
+ return Object.freeze({
1235
+ tools: Object.freeze([...tools]),
1236
+ uriModules: Object.freeze([...uriModules]),
1237
+ searchProviders: Object.freeze([...searchProviders]),
1238
+ converters: Object.freeze([...converters]),
1239
+ auth: Object.freeze({
1240
+ services: Object.freeze([...services]),
1241
+ oauthPkceSchemes: Object.freeze([...oauthPkceSchemes]),
1242
+ apiKeySchemes: Object.freeze([...apiKeySchemes]),
1243
+ externalCliSchemes: Object.freeze([...externalCliSchemes]),
1244
+ delegatedSchemes: Object.freeze([...delegatedSchemes]),
1245
+ delegatedServiceSources: Object.freeze([...delegatedServiceSources])
1246
+ })
1247
+ });
1248
+ }
1249
+
1250
+ // packages/plugin-sdk/dist/kay-agent/index.js
1251
+ function toolParameters(schema) {
1252
+ return toToolParameters(schema);
1253
+ }
1254
+ function defineTool(definition) {
1255
+ return definition;
1256
+ }
1257
+ function defineAuthedTool(definition, schema, binding, body) {
1258
+ return withResolvedAuth({ ...definition, parameters: toolParameters(schema) }, binding, (toolCallId, rawParams, signal, onUpdate, ctx, resolvedAuth) => body(toolCallId, schema.parse(rawParams), signal, onUpdate, ctx, resolvedAuth));
1259
+ }
1260
+ var KayAgentFilesystemError = class extends Error {
1261
+ code;
1262
+ constructor(code, message) {
1263
+ super(message);
1264
+ this.name = "KayAgentFilesystemError";
1265
+ this.code = code;
1266
+ }
1267
+ };
1268
+ var KayAgentCapabilityError = class extends Error {
1269
+ refusal;
1270
+ constructor(refusal, message) {
1271
+ super(message ?? refusal.message);
1272
+ this.name = "KayAgentCapabilityError";
1273
+ this.refusal = refusal;
1274
+ }
1275
+ };
1276
+ var KayAgentWebSessionError = class extends Error {
1277
+ code;
1278
+ status;
1279
+ constructor(code, message, status) {
1280
+ super(message);
1281
+ this.code = code;
1282
+ this.status = status;
1283
+ this.name = "KayAgentWebSessionError";
1284
+ }
1285
+ };
1286
+ export {
1287
+ KayAgentCapabilityError,
1288
+ KayAgentFilesystemError,
1289
+ KayAgentWebSessionError,
1290
+ OBSERVATION_MIME,
1291
+ PluginApiError,
1292
+ SearchProviderError,
1293
+ URI_TEXT_EDIT_SHAPE_SUMMARY,
1294
+ UriConflictError,
1295
+ UriNotFoundError,
1296
+ UriProviderError,
1297
+ UriUnsupportedOperationError,
1298
+ UriValidationError,
1299
+ accountQualifiedUri,
1300
+ applyUriTextEdits,
1301
+ asArray,
1302
+ asRecord,
1303
+ assertResourceUnchanged,
1304
+ basicUriHelp,
1305
+ bytesToBase64,
1306
+ capability,
1307
+ collectKayAgentAdvertisement,
1308
+ contentDigest,
1309
+ contentResult,
1310
+ createFallbackOnlyWithJev,
1311
+ createJsonApiClient,
1312
+ defineAuthedTool,
1313
+ defineKayAgentAdvertisement,
1314
+ defineTool,
1315
+ describeUriTextEditTarget,
1316
+ formatIsoDate,
1317
+ formatNumber,
1318
+ getBytes,
1319
+ jsonResource,
1320
+ lintUriHelpContracts,
1321
+ lintUriTemplate,
1322
+ markdownResource,
1323
+ num,
1324
+ numLike,
1325
+ observationFromResource,
1326
+ observationResource,
1327
+ parseLineSelector,
1328
+ parseUriConnectionSelector,
1329
+ parseUriTextEditPayload,
1330
+ payload,
1331
+ readBodyWithByteCap,
1332
+ str,
1333
+ textResult,
1334
+ toJsonSchema,
1335
+ toolParameters,
1336
+ uriParam,
1337
+ uriTextEditPayloadSchema,
1338
+ withResolvedAuth,
1339
+ withResolvedSearchProvider,
1340
+ z6 as z
1341
+ };