@yaklabs-ai/plugin-sdk 0.48.0 → 0.49.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-app.js CHANGED
@@ -1,3 +1,313 @@
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
+ function requireWriteContent(payload2, uri) {
26
+ if (payload2 === void 0) {
27
+ throw new UriValidationError(`Writing ${uri} needs \`content\` (or a \`source\` to copy from): pass the payload this address takes, which its help names.`);
28
+ }
29
+ if (payload2 instanceof Uint8Array) {
30
+ throw new UriValidationError(`${uri} stores text only, so it cannot take raw bytes. Copy the file to an address that accepts bytes.`);
31
+ }
32
+ return payload2;
33
+ }
34
+ var UriProviderError = class extends UriError {
35
+ _tag = "UriProviderError";
36
+ moduleId;
37
+ operation;
38
+ uri;
39
+ status;
40
+ providerCode;
41
+ retryable;
42
+ /** Provider-directed delay before retrying, in milliseconds. */
43
+ retryAfterMs;
44
+ /** See {@link UriProviderErrorOptions.effect}. */
45
+ effect;
46
+ /** See {@link UriProviderErrorOptions.refusalMessage}. */
47
+ refusalMessage;
48
+ constructor(options) {
49
+ super(options.message);
50
+ this.name = "UriProviderError";
51
+ this.moduleId = options.moduleId;
52
+ this.operation = options.operation;
53
+ this.uri = options.uri;
54
+ if (options.status !== void 0)
55
+ this.status = options.status;
56
+ if (options.providerCode !== void 0)
57
+ this.providerCode = options.providerCode;
58
+ if (options.retryable !== void 0)
59
+ this.retryable = options.retryable;
60
+ if (options.retryAfterMs !== void 0) {
61
+ if (!Number.isInteger(options.retryAfterMs) || options.retryAfterMs < 0) {
62
+ throw new TypeError("retryAfterMs must be a nonnegative integer.");
63
+ }
64
+ this.retryAfterMs = options.retryAfterMs;
65
+ }
66
+ if (options.effect !== void 0)
67
+ this.effect = options.effect;
68
+ if (options.refusalMessage !== void 0) {
69
+ if (options.effect !== "none") {
70
+ throw new TypeError('refusalMessage requires effect: "none".');
71
+ }
72
+ this.refusalMessage = options.refusalMessage;
73
+ }
74
+ }
75
+ };
76
+ var UriNotFoundError = class extends UriError {
77
+ uri;
78
+ hint;
79
+ _tag = "UriNotFoundError";
80
+ constructor(uri, hint) {
81
+ super(hint !== void 0 ? `No resource found at '${uri}'. ${hint}` : `No resource found at '${uri}'.`);
82
+ this.uri = uri;
83
+ this.hint = hint;
84
+ this.name = "UriNotFoundError";
85
+ }
86
+ };
87
+ var UriUnsupportedOperationError = class extends UriError {
88
+ operation;
89
+ moduleId;
90
+ uri;
91
+ _tag = "UriUnsupportedOperationError";
92
+ constructor(operation, moduleId, uri, message) {
93
+ super(message ?? `URI module '${moduleId}' does not support '${operation}' for '${uri}'.`);
94
+ this.operation = operation;
95
+ this.moduleId = moduleId;
96
+ this.uri = uri;
97
+ this.name = "UriUnsupportedOperationError";
98
+ }
99
+ };
100
+
101
+ // packages/herd-uri/dist/resource-witness.js
102
+ import { createHash } from "node:crypto";
103
+ function contentDigest(content) {
104
+ const hash = createHash("sha256");
105
+ hash.update(typeof content === "string" ? new TextEncoder().encode(content) : content);
106
+ return `${DIGEST_PREFIX}${hash.digest("base64url")}`;
107
+ }
108
+ var DIGEST_PREFIX = "sha256:";
109
+
110
+ // packages/herd-uri/dist/operations.js
111
+ import { z } from "zod";
112
+ var URI_OPERATIONS = [
113
+ "help",
114
+ "read",
115
+ "write",
116
+ "edit",
117
+ "list",
118
+ "search",
119
+ "delete"
120
+ ];
121
+ var UriOperationSchema = z.enum(URI_OPERATIONS);
122
+
123
+ // packages/herd-uri/dist/help-schema.js
124
+ import { z as z2 } from "zod";
125
+ var UriContractJsonSchema = z2.record(z2.string(), z2.unknown());
126
+ var UriParameterSchema = z2.strictObject({
127
+ name: z2.string().min(1),
128
+ in: z2.enum(["uri", "query", "selector"]),
129
+ required: z2.boolean(),
130
+ description: z2.string().optional(),
131
+ schema: UriContractJsonSchema,
132
+ examples: z2.array(z2.unknown()).optional()
133
+ });
134
+ var UriPayloadContractSchema = z2.strictObject({
135
+ name: z2.string().min(1),
136
+ mediaType: z2.string().optional(),
137
+ description: z2.string().optional(),
138
+ schema: UriContractJsonSchema.optional(),
139
+ semanticConstraints: z2.array(z2.string().min(1)).min(1).optional(),
140
+ examples: z2.array(z2.unknown()).optional()
141
+ });
142
+
143
+ // packages/herd-uri/dist/text-edit.js
144
+ import { z as z3 } from "zod";
145
+ var findReplaceArm = z3.strictObject({
146
+ find: z3.string().min(1),
147
+ replace: z3.string(),
148
+ all: z3.boolean().optional()
149
+ });
150
+ var oldNewEntry = z3.strictObject({
151
+ oldText: z3.string().min(1),
152
+ newText: z3.string()
153
+ });
154
+ var uriTextEditPayloadArms = z3.union([
155
+ findReplaceArm,
156
+ z3.strictObject({ edits: z3.array(oldNewEntry).min(1) }),
157
+ oldNewEntry,
158
+ z3.array(oldNewEntry).min(1)
159
+ ]);
160
+
161
+ // packages/herd-uri/dist/line-selector.js
162
+ var RAW_TOKEN = /^raw$/i;
163
+ function parseRangeListToken(token) {
164
+ if (token.length === 0)
165
+ return void 0;
166
+ const ranges = [];
167
+ for (const part of token.split(",")) {
168
+ const range = parseSingleRange(part);
169
+ if (range === void 0)
170
+ return void 0;
171
+ ranges.push(range);
172
+ }
173
+ return ranges;
174
+ }
175
+ function toInt(value) {
176
+ if (!/^\d+$/.test(value))
177
+ return void 0;
178
+ const n = Number.parseInt(value, 10);
179
+ return Number.isSafeInteger(n) && n >= 1 ? n : void 0;
180
+ }
181
+ function parseSingleRange(part) {
182
+ const plus = part.indexOf("+");
183
+ if (plus >= 0) {
184
+ const start2 = toInt(part.slice(0, plus));
185
+ const count = toInt(part.slice(plus + 1));
186
+ if (start2 === void 0 || count === void 0)
187
+ return void 0;
188
+ return { start: start2, end: start2 + count - 1 };
189
+ }
190
+ const dash = part.indexOf("-");
191
+ if (dash >= 0) {
192
+ const start2 = toInt(part.slice(0, dash));
193
+ const endRaw = part.slice(dash + 1);
194
+ if (start2 === void 0)
195
+ return void 0;
196
+ if (endRaw.length === 0)
197
+ return { start: start2, end: Number.POSITIVE_INFINITY };
198
+ const end = toInt(endRaw);
199
+ if (end === void 0 || end < start2)
200
+ return void 0;
201
+ return { start: start2, end };
202
+ }
203
+ const start = toInt(part);
204
+ if (start === void 0)
205
+ return void 0;
206
+ return { start, end: Number.POSITIVE_INFINITY };
207
+ }
208
+ function mergeRanges(ranges) {
209
+ const sorted = [...ranges].sort((a, b) => a.start - b.start);
210
+ const merged = [];
211
+ for (const range of sorted) {
212
+ const last = merged[merged.length - 1];
213
+ if (last !== void 0 && range.start <= last.end) {
214
+ if (range.end > last.end) {
215
+ merged[merged.length - 1] = { start: last.start, end: range.end };
216
+ }
217
+ continue;
218
+ }
219
+ merged.push(range);
220
+ }
221
+ return merged;
222
+ }
223
+ function parseLineSelector(input) {
224
+ let address = input;
225
+ let raw = false;
226
+ let ranges;
227
+ for (let i = 0; i < 2; i += 1) {
228
+ const colon = address.lastIndexOf(":");
229
+ if (colon < 0)
230
+ break;
231
+ const token = address.slice(colon + 1);
232
+ if (RAW_TOKEN.test(token)) {
233
+ if (raw)
234
+ break;
235
+ raw = true;
236
+ address = address.slice(0, colon);
237
+ continue;
238
+ }
239
+ const parsed = parseRangeListToken(token);
240
+ if (parsed === void 0)
241
+ break;
242
+ if (ranges !== void 0)
243
+ break;
244
+ ranges = parsed;
245
+ address = address.slice(0, colon);
246
+ }
247
+ return {
248
+ address,
249
+ selector: { ranges: ranges ? mergeRanges(ranges) : [], raw }
250
+ };
251
+ }
252
+
253
+ // packages/herd-uri/dist/schema/to-json-schema.js
254
+ import { z as z4 } from "zod";
255
+ function toJsonSchema(schema) {
256
+ if (schema instanceof z4.ZodType) {
257
+ const { $schema: _dialect, ...value } = z4.toJSONSchema(schema, {
258
+ // `io: "input"` describes what a caller may SEND, which is what a parameter and an
259
+ // `accepts` payload advertise: a field with a Zod default is optional on the wire even
260
+ // though the parsed value always carries it. Strictness still survives where the validator
261
+ // really enforces it - `z.strictObject` emits `additionalProperties: false`, while a plain
262
+ // `z.object` correctly does not, because it TOLERATES unknown keys and silently strips
263
+ // them. A `returns` payload derived from a Zod schema is described in the same input terms;
264
+ // no module does that today, and a faithful output projection would need its own seam.
265
+ io: "input",
266
+ // Inline every reused sub-schema rather than emitting `$ref`s into a `$defs` block. A
267
+ // contract schema is a FRAGMENT: it gets embedded in a payload contract, and callers
268
+ // legitimately lift one arm of a union out of it. A `$ref` only resolves relative to the
269
+ // root that carries `$defs`, so the moment the fragment moves, the reference dangles.
270
+ // Self-contained is worth the repetition at these sizes.
271
+ reused: "inline",
272
+ // Recursion (`z.lazy`) has no self-contained form: zod's default is to emit a
273
+ // `$defs` block with `$ref` pointers, which dangle the moment the fragment is
274
+ // embedded. Throw instead, so a contract that needs recursion has to disclose a
275
+ // non-recursive shape (see skill-module's metadata disclosure) rather than ship a
276
+ // reference nothing can resolve.
277
+ cycles: "throw"
278
+ });
279
+ return value;
280
+ }
281
+ return structuredClone(schema);
282
+ }
283
+
284
+ // packages/herd-uri/dist/schema/helpers.js
285
+ function payload(name, schema, options = {}) {
286
+ return {
287
+ name,
288
+ ...options.mediaType === void 0 ? {} : { mediaType: options.mediaType },
289
+ ...options.description === void 0 ? {} : { description: options.description },
290
+ schema: toJsonSchema(schema),
291
+ ...options.semanticConstraints === void 0 ? {} : { semanticConstraints: options.semanticConstraints },
292
+ ...options.examples === void 0 ? {} : { examples: options.examples }
293
+ };
294
+ }
295
+
296
+ // packages/plugin-sdk/dist/uri.js
297
+ function createUnavailableUriCaller(message) {
298
+ const unavailable = async () => {
299
+ throw new Error(message);
300
+ };
301
+ return {
302
+ read: unavailable,
303
+ list: unavailable,
304
+ search: unavailable,
305
+ write: unavailable,
306
+ edit: unavailable,
307
+ delete: unavailable
308
+ };
309
+ }
310
+
1
311
  // packages/plugin-protocol/dist/plugin-signal-limits.js
2
312
  var PLUGIN_EVENT_REFUSED_ERROR_NAME = "PluginEventRefusedError";
3
313
  var PLUGIN_SIGNAL_KINDS = [
@@ -58,17 +368,17 @@ function isCredentialShapedText(value) {
58
368
  }
59
369
 
60
370
  // packages/plugin-protocol/dist/json.js
61
- import { z } from "zod";
62
- var JsonValue = z.lazy(() => z.union([
63
- z.string(),
64
- z.number(),
65
- z.boolean(),
66
- z.null(),
67
- z.array(JsonValue),
68
- z.record(z.string(), JsonValue)
371
+ import { z as z5 } from "zod";
372
+ var JsonValue = z5.lazy(() => z5.union([
373
+ z5.string(),
374
+ z5.number(),
375
+ z5.boolean(),
376
+ z5.null(),
377
+ z5.array(JsonValue),
378
+ z5.record(z5.string(), JsonValue)
69
379
  ]));
70
- var JsonObject = z.record(z.string(), JsonValue);
71
- var JsonSchema = z.record(z.string(), JsonValue);
380
+ var JsonObject = z5.record(z5.string(), JsonValue);
381
+ var JsonSchema = z5.record(z5.string(), JsonValue);
72
382
 
73
383
  // packages/plugin-sdk/dist/kay-app/card-layout.js
74
384
  function element(type, props) {
@@ -104,559 +414,273 @@ function field(type, name, options) {
104
414
  function textField(name, options) {
105
415
  return field("Field", name, options);
106
416
  }
107
- function textArea(name, options) {
108
- return field("TextArea", name, options);
109
- }
110
- function select(name, options) {
111
- return field("Select", name, options);
112
- }
113
- function multiSelect(name, options) {
114
- return field("MultiSelect", name, options);
115
- }
116
- function switchField(name, options) {
117
- return field("Switch", name, options);
118
- }
119
- function submit(label) {
120
- return {
121
- root: "root",
122
- elements: {
123
- root: {
124
- type: "Button",
125
- props: { label },
126
- on: { press: { action: "submit" } }
127
- }
128
- }
129
- };
130
- }
131
-
132
- // packages/plugin-sdk/dist/signals.js
133
- import { z as z2 } from "zod";
134
- function createFallbackOnlySignals() {
135
- const noStore = { status: "unavailable", reason: "no-store" };
136
- return {
137
- observe: (input) => Promise.resolve(invalidObservation(input) ?? {
138
- status: "unavailable",
139
- reason: "no-system-one",
140
- detector: { ...input.detector, rubricDigest: "" },
141
- source: input.source,
142
- stored: false,
143
- deduplicated: false,
144
- inputDigest: "",
145
- recordedAtMs: Date.now()
146
- }),
147
- listDetectors: () => Promise.resolve(noStore),
148
- list: () => Promise.resolve(noStore)
149
- };
150
- }
151
- var SIGNAL_TIME_MAX_MS = 864e13;
152
- var MAX_CHOICE_LABELS = 64;
153
- var MAX_NAME = 64;
154
- var MAX_POINTER = 256;
155
- var MAX_QUESTIONS = 64;
156
- var DETECTOR_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
157
- var VERSION = /^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/u;
158
- var QUESTION_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
159
- var POINTER = /^[^\s\p{C}/?#]+$/u;
160
- var LABEL = /^[^\s,@\p{C}]+(?: [^\s,@\p{C}]+)*$/u;
161
- var RUN_ID = /^\P{Cc}+$/u;
162
- var POINTER_RULE = `1 to ${MAX_POINTER} characters with no whitespace, \`/\`, \`?\`, \`#\`, or control or invisible character`;
163
- var ObserveShape = z2.looseObject({
164
- detector: z2.looseObject({ id: z2.string(), version: z2.string() }),
165
- subject: z2.looseObject({ kind: z2.string(), key: z2.string().optional() }).optional(),
166
- after: z2.looseObject({ observationId: z2.unknown() }).optional(),
167
- reuse: z2.looseObject({ maxAgeMs: z2.unknown() }).optional(),
168
- source: z2.looseObject({
169
- sessionId: z2.string(),
170
- entryId: z2.string(),
171
- openerEntryId: z2.string().optional(),
172
- runId: z2.string().optional(),
173
- occurredAtMs: z2.unknown().optional()
174
- }),
175
- questions: z2.record(z2.string(), z2.unknown())
176
- });
177
- var ChoiceQuestion = z2.looseObject({
178
- type: z2.literal("choice"),
179
- criteria: z2.record(z2.string(), z2.unknown())
180
- });
181
- var fits = (value, grammar) => value.length <= MAX_NAME && grammar.test(value);
182
- var isWhole = (value, min) => typeof value === "number" && Number.isSafeInteger(value) && value >= min && value <= SIGNAL_TIME_MAX_MS;
183
- var quoted = (value) => JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}\u2026` : value).replace(/(?! )[\s\p{C}]/gu, (char) => `\\u${char.codePointAt(0).toString(16).padStart(4, "0")}`);
184
- function grammarProblem(input) {
185
- const shape = ObserveShape.safeParse(input);
186
- if (!shape.success) {
187
- const field2 = shape.error.issues[0]?.path.join(".") ?? "";
188
- return field2 === "" ? "`observe` takes an object with `detector`, `source`, `state`, and `questions`." : `\`${field2}\` is missing or has the wrong type.`;
189
- }
190
- const { detector, source, questions, subject, after, reuse } = shape.data;
191
- const { state } = input;
192
- if (typeof state !== "object" || state === null || Array.isArray(state)) {
193
- return "`state` must be a JSON object.";
194
- }
195
- if (!fits(detector.id, DETECTOR_ID)) {
196
- return "`detector.id` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
197
- }
198
- if (!fits(detector.version, VERSION)) {
199
- return "`detector.version` must be at most 64 characters: letters and digits in parts joined by single `.`, `-`, or `_`.";
200
- }
201
- for (const [field2, grammar, rule] of [
202
- ["sessionId", POINTER, POINTER_RULE],
203
- ["entryId", POINTER, POINTER_RULE],
204
- ["openerEntryId", POINTER, POINTER_RULE],
205
- [
206
- "runId",
207
- RUN_ID,
208
- `1 to ${MAX_POINTER} characters with no control character`
209
- ]
210
- ]) {
211
- const id = source[field2];
212
- if (id !== void 0 && !(id.length <= MAX_POINTER && grammar.test(id))) {
213
- return `\`source.${field2}\` must be ${rule}.`;
214
- }
215
- }
216
- const occurredAtMs = source.occurredAtMs;
217
- if (occurredAtMs !== void 0 && !(typeof occurredAtMs === "number" && Number.isSafeInteger(occurredAtMs) && occurredAtMs >= 0 && occurredAtMs <= SIGNAL_TIME_MAX_MS)) {
218
- return `\`source.occurredAtMs\` must be whole epoch milliseconds from 0 to ${SIGNAL_TIME_MAX_MS}.`;
219
- }
220
- if (subject !== void 0 && !fits(subject.kind, DETECTOR_ID)) {
221
- return "`subject.kind` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
222
- }
223
- if (subject?.key !== void 0 && !(subject.key.length <= MAX_POINTER && POINTER.test(subject.key))) {
224
- return `\`subject.key\` must be ${POINTER_RULE}.`;
225
- }
226
- if (after !== void 0 && !isWhole(after.observationId, 1)) {
227
- return "`after.observationId` must be a positive whole number: the id of a stored signal.";
228
- }
229
- if (reuse !== void 0) {
230
- if (!isWhole(reuse.maxAgeMs, 1)) {
231
- return `\`reuse.maxAgeMs\` must be whole milliseconds from 1 to ${SIGNAL_TIME_MAX_MS}.`;
232
- }
233
- if (subject?.key === void 0) {
234
- return "`reuse` needs `subject.key`: a stored answer is reused only for the same subject.";
235
- }
236
- }
237
- const names = Object.keys(questions);
238
- if (names.length === 0 || names.length > MAX_QUESTIONS) {
239
- return `\`questions\` must ask 1 to ${MAX_QUESTIONS} questions.`;
240
- }
241
- for (const name of names) {
242
- if (!fits(name, QUESTION_NAME)) {
243
- return `The question name ${quoted(name)} must be an identifier of at most 64 characters: letters, digits, and \`_\`, not starting with a digit.`;
244
- }
245
- const choice = ChoiceQuestion.safeParse(questions[name]);
246
- if (!choice.success)
247
- continue;
248
- const labels = Object.keys(choice.data.criteria);
249
- if (labels.length > MAX_CHOICE_LABELS) {
250
- return `The choice question \`${name}\` offers ${labels.length} labels; at most ${MAX_CHOICE_LABELS}.`;
251
- }
252
- const bad = labels.find((label) => !fits(label, LABEL));
253
- if (bad !== void 0) {
254
- return `The choice question \`${name}\` offers the label ${quoted(bad)}, which a \`where\` filter cannot name: a label is 1 to 64 characters with no \`,\`, \`@\`, or control or invisible character, and no whitespace but single spaces between words.`;
255
- }
256
- }
257
- return void 0;
258
- }
259
- var EchoText = z2.string().catch("");
260
- var Echo = z2.object({
261
- detector: z2.object({ id: EchoText, version: EchoText }).catch({ id: "", version: "" }),
262
- source: z2.object({ sessionId: EchoText, entryId: EchoText }).catch({ sessionId: "", entryId: "" })
263
- }).catch({
264
- detector: { id: "", version: "" },
265
- source: { sessionId: "", entryId: "" }
266
- });
267
- function invalidObservation(input) {
268
- const reason = grammarProblem(input);
269
- if (reason === void 0)
270
- return void 0;
271
- const { detector, source } = Echo.parse(input);
272
- return {
273
- status: "invalid",
274
- reason,
275
- detector: { ...detector, rubricDigest: "" },
276
- source,
277
- stored: false,
278
- deduplicated: false,
279
- inputDigest: "",
280
- recordedAtMs: Date.now()
281
- };
282
- }
283
-
284
- // packages/herd-transcript/dist/record-kinds.js
285
- var STORED_TRANSCRIPT_MESSAGE_KINDS = [
286
- "user",
287
- "assistant",
288
- "tool_result",
289
- "custom_message:*",
290
- "compaction",
291
- "branch_summary"
292
- ];
293
- var NAMED_KINDS = /* @__PURE__ */ new Set([
294
- "user",
295
- "assistant",
296
- "tool_result",
297
- "compaction",
298
- "branch_summary",
299
- "other",
300
- "unreadable"
301
- ]);
302
- var ROLE_KINDS = {
303
- user: "user",
304
- assistant: "assistant",
305
- toolResult: "tool_result"
306
- };
307
- function storedTranscriptKindOf(record) {
308
- if (!("entry" in record))
309
- return "unreadable";
310
- const entry = record.entry;
311
- switch (entry.type) {
312
- case "message": {
313
- const message = entry.message;
314
- if (message.role === "custom") {
315
- return `custom_message:${typeof message.customType === "string" ? message.customType : ""}`;
316
- }
317
- return (typeof message.role === "string" ? ROLE_KINDS[message.role] : void 0) ?? "other";
318
- }
319
- case "custom":
320
- return `custom:${entry.customType}`;
321
- case "compaction":
322
- return "compaction";
323
- case "branch_summary":
324
- return "branch_summary";
325
- default:
326
- return "other";
327
- }
417
+ function textArea(name, options) {
418
+ return field("TextArea", name, options);
328
419
  }
329
- function parseStoredTranscriptKindFilter(tokens) {
330
- const exact = /* @__PURE__ */ new Set();
331
- const families = /* @__PURE__ */ new Set();
332
- let all = false;
333
- for (const raw of tokens) {
334
- const token = raw.trim();
335
- if (token === "all") {
336
- all = true;
337
- } else if (token === "messages") {
338
- for (const kind of STORED_TRANSCRIPT_MESSAGE_KINDS)
339
- addToken(kind);
340
- } else if (!addToken(token)) {
341
- return { ok: false, invalid: raw };
342
- }
343
- }
420
+ function select(name, options) {
421
+ return field("Select", name, options);
422
+ }
423
+ function multiSelect(name, options) {
424
+ return field("MultiSelect", name, options);
425
+ }
426
+ function switchField(name, options) {
427
+ return field("Switch", name, options);
428
+ }
429
+ function submit(label) {
344
430
  return {
345
- ok: true,
346
- filter: {
347
- includes: (kind) => all || exact.has(kind) || families.has(kind.slice(0, kind.indexOf(":") + 1))
431
+ root: "root",
432
+ elements: {
433
+ root: {
434
+ type: "Button",
435
+ props: { label },
436
+ on: { press: { action: "submit" } }
437
+ }
348
438
  }
349
439
  };
350
- function addToken(token) {
351
- if (NAMED_KINDS.has(token)) {
352
- exact.add(token);
353
- return true;
354
- }
355
- const family = /^(custom|custom_message):(.+)$/.exec(token);
356
- if (family === null)
357
- return false;
358
- if (family[2] === "*")
359
- families.add(`${family[1]}:`);
360
- else
361
- exact.add(token);
362
- return true;
363
- }
364
440
  }
365
- var STORED_TRANSCRIPT_MESSAGE_FILTER = (() => {
366
- const parsed = parseStoredTranscriptKindFilter(STORED_TRANSCRIPT_MESSAGE_KINDS);
367
- if (!parsed.ok)
368
- throw new Error(`invalid default kinds: ${parsed.invalid}`);
369
- return parsed.filter;
370
- })();
371
-
372
- // packages/plugin-sdk/dist/kay-app/index.js
373
- import { pathToFileURL } from "node:url";
374
441
 
375
- // packages/herd-uri/dist/errors.js
376
- var UriError = class extends Error {
377
- };
378
- var CONFLICT_MESSAGES = {
379
- changed: "This resource changed since this session last read it. Read it again before modifying it.",
380
- unwitnessed: "This resource was not read in this session. Read it before modifying it.",
381
- unknown: "This resource changed or was not read in this session. Read it again before modifying it."
382
- };
383
- var UriConflictError = class extends UriError {
384
- _tag = "UriConflictError";
385
- reason;
386
- constructor(reason) {
387
- super(CONFLICT_MESSAGES[reason ?? "unknown"]);
388
- this.name = "UriConflictError";
389
- this.reason = reason;
442
+ // packages/plugin-sdk/dist/signals.js
443
+ import { z as z6 } from "zod";
444
+ function createFallbackOnlySignals() {
445
+ const noStore = { status: "unavailable", reason: "no-store" };
446
+ return {
447
+ observe: (input) => Promise.resolve(invalidObservation(input) ?? {
448
+ status: "unavailable",
449
+ reason: "no-system-one",
450
+ detector: { ...input.detector, rubricDigest: "" },
451
+ source: input.source,
452
+ stored: false,
453
+ deduplicated: false,
454
+ inputDigest: "",
455
+ recordedAtMs: Date.now()
456
+ }),
457
+ listDetectors: () => Promise.resolve(noStore),
458
+ list: () => Promise.resolve(noStore)
459
+ };
460
+ }
461
+ var SIGNAL_TIME_MAX_MS = 864e13;
462
+ var MAX_CHOICE_LABELS = 64;
463
+ var MAX_NAME = 64;
464
+ var MAX_POINTER = 256;
465
+ var MAX_QUESTIONS = 64;
466
+ var DETECTOR_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
467
+ var VERSION = /^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/u;
468
+ var QUESTION_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
469
+ var POINTER = /^[^\s\p{C}/?#]+$/u;
470
+ var LABEL = /^[^\s,@\p{C}]+(?: [^\s,@\p{C}]+)*$/u;
471
+ var RUN_ID = /^\P{Cc}+$/u;
472
+ var POINTER_RULE = `1 to ${MAX_POINTER} characters with no whitespace, \`/\`, \`?\`, \`#\`, or control or invisible character`;
473
+ var ObserveShape = z6.looseObject({
474
+ detector: z6.looseObject({ id: z6.string(), version: z6.string() }),
475
+ subject: z6.looseObject({ kind: z6.string(), key: z6.string().optional() }).optional(),
476
+ after: z6.looseObject({ observationId: z6.unknown() }).optional(),
477
+ reuse: z6.looseObject({ maxAgeMs: z6.unknown() }).optional(),
478
+ source: z6.looseObject({
479
+ sessionId: z6.string(),
480
+ entryId: z6.string(),
481
+ openerEntryId: z6.string().optional(),
482
+ runId: z6.string().optional(),
483
+ occurredAtMs: z6.unknown().optional()
484
+ }),
485
+ questions: z6.record(z6.string(), z6.unknown())
486
+ });
487
+ var ChoiceQuestion = z6.looseObject({
488
+ type: z6.literal("choice"),
489
+ criteria: z6.record(z6.string(), z6.unknown())
490
+ });
491
+ var fits = (value, grammar) => value.length <= MAX_NAME && grammar.test(value);
492
+ var isWhole = (value, min) => typeof value === "number" && Number.isSafeInteger(value) && value >= min && value <= SIGNAL_TIME_MAX_MS;
493
+ var quoted = (value) => JSON.stringify(value.length > 40 ? `${value.slice(0, 40)}\u2026` : value).replace(/(?! )[\s\p{C}]/gu, (char) => `\\u${char.codePointAt(0).toString(16).padStart(4, "0")}`);
494
+ function grammarProblem(input) {
495
+ const shape = ObserveShape.safeParse(input);
496
+ if (!shape.success) {
497
+ const field2 = shape.error.issues[0]?.path.join(".") ?? "";
498
+ return field2 === "" ? "`observe` takes an object with `detector`, `source`, `state`, and `questions`." : `\`${field2}\` is missing or has the wrong type.`;
390
499
  }
391
- };
392
- var UriValidationError = class extends UriError {
393
- _tag = "UriValidationError";
394
- constructor(message) {
395
- super(message);
396
- this.name = "UriValidationError";
500
+ const { detector, source, questions, subject, after, reuse } = shape.data;
501
+ const { state } = input;
502
+ if (typeof state !== "object" || state === null || Array.isArray(state)) {
503
+ return "`state` must be a JSON object.";
397
504
  }
398
- };
399
- function requireWriteContent(payload2, uri) {
400
- if (payload2 === void 0) {
401
- throw new UriValidationError(`Writing ${uri} needs \`content\` (or a \`source\` to copy from): pass the payload this address takes, which its help names.`);
505
+ if (!fits(detector.id, DETECTOR_ID)) {
506
+ return "`detector.id` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
402
507
  }
403
- if (payload2 instanceof Uint8Array) {
404
- throw new UriValidationError(`${uri} stores text only, so it cannot take raw bytes. Copy the file to an address that accepts bytes.`);
508
+ if (!fits(detector.version, VERSION)) {
509
+ return "`detector.version` must be at most 64 characters: letters and digits in parts joined by single `.`, `-`, or `_`.";
405
510
  }
406
- return payload2;
407
- }
408
- var UriProviderError = class extends UriError {
409
- _tag = "UriProviderError";
410
- moduleId;
411
- operation;
412
- uri;
413
- status;
414
- providerCode;
415
- retryable;
416
- /** Provider-directed delay before retrying, in milliseconds. */
417
- retryAfterMs;
418
- /** See {@link UriProviderErrorOptions.effect}. */
419
- effect;
420
- /** See {@link UriProviderErrorOptions.refusalMessage}. */
421
- refusalMessage;
422
- constructor(options) {
423
- super(options.message);
424
- this.name = "UriProviderError";
425
- this.moduleId = options.moduleId;
426
- this.operation = options.operation;
427
- this.uri = options.uri;
428
- if (options.status !== void 0)
429
- this.status = options.status;
430
- if (options.providerCode !== void 0)
431
- this.providerCode = options.providerCode;
432
- if (options.retryable !== void 0)
433
- this.retryable = options.retryable;
434
- if (options.retryAfterMs !== void 0) {
435
- if (!Number.isInteger(options.retryAfterMs) || options.retryAfterMs < 0) {
436
- throw new TypeError("retryAfterMs must be a nonnegative integer.");
437
- }
438
- this.retryAfterMs = options.retryAfterMs;
439
- }
440
- if (options.effect !== void 0)
441
- this.effect = options.effect;
442
- if (options.refusalMessage !== void 0) {
443
- if (options.effect !== "none") {
444
- throw new TypeError('refusalMessage requires effect: "none".');
445
- }
446
- this.refusalMessage = options.refusalMessage;
511
+ for (const [field2, grammar, rule] of [
512
+ ["sessionId", POINTER, POINTER_RULE],
513
+ ["entryId", POINTER, POINTER_RULE],
514
+ ["openerEntryId", POINTER, POINTER_RULE],
515
+ [
516
+ "runId",
517
+ RUN_ID,
518
+ `1 to ${MAX_POINTER} characters with no control character`
519
+ ]
520
+ ]) {
521
+ const id = source[field2];
522
+ if (id !== void 0 && !(id.length <= MAX_POINTER && grammar.test(id))) {
523
+ return `\`source.${field2}\` must be ${rule}.`;
447
524
  }
448
525
  }
449
- };
450
- var UriNotFoundError = class extends UriError {
451
- uri;
452
- hint;
453
- _tag = "UriNotFoundError";
454
- constructor(uri, hint) {
455
- super(hint !== void 0 ? `No resource found at '${uri}'. ${hint}` : `No resource found at '${uri}'.`);
456
- this.uri = uri;
457
- this.hint = hint;
458
- this.name = "UriNotFoundError";
459
- }
460
- };
461
- var UriUnsupportedOperationError = class extends UriError {
462
- operation;
463
- moduleId;
464
- uri;
465
- _tag = "UriUnsupportedOperationError";
466
- constructor(operation, moduleId, uri, message) {
467
- super(message ?? `URI module '${moduleId}' does not support '${operation}' for '${uri}'.`);
468
- this.operation = operation;
469
- this.moduleId = moduleId;
470
- this.uri = uri;
471
- this.name = "UriUnsupportedOperationError";
472
- }
473
- };
474
-
475
- // packages/herd-uri/dist/operations.js
476
- import { z as z3 } from "zod";
477
- var URI_OPERATIONS = [
478
- "help",
479
- "read",
480
- "write",
481
- "edit",
482
- "list",
483
- "search",
484
- "delete"
485
- ];
486
- var UriOperationSchema = z3.enum(URI_OPERATIONS);
487
-
488
- // packages/herd-uri/dist/help-schema.js
489
- import { z as z4 } from "zod";
490
- var UriContractJsonSchema = z4.record(z4.string(), z4.unknown());
491
- var UriParameterSchema = z4.strictObject({
492
- name: z4.string().min(1),
493
- in: z4.enum(["uri", "query", "selector"]),
494
- required: z4.boolean(),
495
- description: z4.string().optional(),
496
- schema: UriContractJsonSchema,
497
- examples: z4.array(z4.unknown()).optional()
498
- });
499
- var UriPayloadContractSchema = z4.strictObject({
500
- name: z4.string().min(1),
501
- mediaType: z4.string().optional(),
502
- description: z4.string().optional(),
503
- schema: UriContractJsonSchema.optional(),
504
- semanticConstraints: z4.array(z4.string().min(1)).min(1).optional(),
505
- examples: z4.array(z4.unknown()).optional()
506
- });
507
-
508
- // packages/herd-uri/dist/text-edit.js
509
- import { z as z5 } from "zod";
510
- var findReplaceArm = z5.strictObject({
511
- find: z5.string().min(1),
512
- replace: z5.string(),
513
- all: z5.boolean().optional()
514
- });
515
- var oldNewEntry = z5.strictObject({
516
- oldText: z5.string().min(1),
517
- newText: z5.string()
518
- });
519
- var uriTextEditPayloadArms = z5.union([
520
- findReplaceArm,
521
- z5.strictObject({ edits: z5.array(oldNewEntry).min(1) }),
522
- oldNewEntry,
523
- z5.array(oldNewEntry).min(1)
524
- ]);
525
-
526
- // packages/herd-uri/dist/line-selector.js
527
- var RAW_TOKEN = /^raw$/i;
528
- function parseRangeListToken(token) {
529
- if (token.length === 0)
530
- return void 0;
531
- const ranges = [];
532
- for (const part of token.split(",")) {
533
- const range = parseSingleRange(part);
534
- if (range === void 0)
535
- return void 0;
536
- ranges.push(range);
537
- }
538
- return ranges;
539
- }
540
- function toInt(value) {
541
- if (!/^\d+$/.test(value))
542
- return void 0;
543
- const n = Number.parseInt(value, 10);
544
- return Number.isSafeInteger(n) && n >= 1 ? n : void 0;
545
- }
546
- function parseSingleRange(part) {
547
- const plus = part.indexOf("+");
548
- if (plus >= 0) {
549
- const start2 = toInt(part.slice(0, plus));
550
- const count = toInt(part.slice(plus + 1));
551
- if (start2 === void 0 || count === void 0)
552
- return void 0;
553
- return { start: start2, end: start2 + count - 1 };
526
+ const occurredAtMs = source.occurredAtMs;
527
+ if (occurredAtMs !== void 0 && !(typeof occurredAtMs === "number" && Number.isSafeInteger(occurredAtMs) && occurredAtMs >= 0 && occurredAtMs <= SIGNAL_TIME_MAX_MS)) {
528
+ return `\`source.occurredAtMs\` must be whole epoch milliseconds from 0 to ${SIGNAL_TIME_MAX_MS}.`;
554
529
  }
555
- const dash = part.indexOf("-");
556
- if (dash >= 0) {
557
- const start2 = toInt(part.slice(0, dash));
558
- const endRaw = part.slice(dash + 1);
559
- if (start2 === void 0)
560
- return void 0;
561
- if (endRaw.length === 0)
562
- return { start: start2, end: Number.POSITIVE_INFINITY };
563
- const end = toInt(endRaw);
564
- if (end === void 0 || end < start2)
565
- return void 0;
566
- return { start: start2, end };
530
+ if (subject !== void 0 && !fits(subject.kind, DETECTOR_ID)) {
531
+ return "`subject.kind` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
567
532
  }
568
- const start = toInt(part);
569
- if (start === void 0)
570
- return void 0;
571
- return { start, end: Number.POSITIVE_INFINITY };
572
- }
573
- function mergeRanges(ranges) {
574
- const sorted = [...ranges].sort((a, b) => a.start - b.start);
575
- const merged = [];
576
- for (const range of sorted) {
577
- const last = merged[merged.length - 1];
578
- if (last !== void 0 && range.start <= last.end) {
579
- if (range.end > last.end) {
580
- merged[merged.length - 1] = { start: last.start, end: range.end };
581
- }
582
- continue;
533
+ if (subject?.key !== void 0 && !(subject.key.length <= MAX_POINTER && POINTER.test(subject.key))) {
534
+ return `\`subject.key\` must be ${POINTER_RULE}.`;
535
+ }
536
+ if (after !== void 0 && !isWhole(after.observationId, 1)) {
537
+ return "`after.observationId` must be a positive whole number: the id of a stored signal.";
538
+ }
539
+ if (reuse !== void 0) {
540
+ if (!isWhole(reuse.maxAgeMs, 1)) {
541
+ return `\`reuse.maxAgeMs\` must be whole milliseconds from 1 to ${SIGNAL_TIME_MAX_MS}.`;
542
+ }
543
+ if (subject?.key === void 0) {
544
+ return "`reuse` needs `subject.key`: a stored answer is reused only for the same subject.";
583
545
  }
584
- merged.push(range);
585
546
  }
586
- return merged;
587
- }
588
- function parseLineSelector(input) {
589
- let address = input;
590
- let raw = false;
591
- let ranges;
592
- for (let i = 0; i < 2; i += 1) {
593
- const colon = address.lastIndexOf(":");
594
- if (colon < 0)
595
- break;
596
- const token = address.slice(colon + 1);
597
- if (RAW_TOKEN.test(token)) {
598
- if (raw)
599
- break;
600
- raw = true;
601
- address = address.slice(0, colon);
547
+ const names = Object.keys(questions);
548
+ if (names.length === 0 || names.length > MAX_QUESTIONS) {
549
+ return `\`questions\` must ask 1 to ${MAX_QUESTIONS} questions.`;
550
+ }
551
+ for (const name of names) {
552
+ if (!fits(name, QUESTION_NAME)) {
553
+ return `The question name ${quoted(name)} must be an identifier of at most 64 characters: letters, digits, and \`_\`, not starting with a digit.`;
554
+ }
555
+ const choice = ChoiceQuestion.safeParse(questions[name]);
556
+ if (!choice.success)
602
557
  continue;
558
+ const labels = Object.keys(choice.data.criteria);
559
+ if (labels.length > MAX_CHOICE_LABELS) {
560
+ return `The choice question \`${name}\` offers ${labels.length} labels; at most ${MAX_CHOICE_LABELS}.`;
561
+ }
562
+ const bad = labels.find((label) => !fits(label, LABEL));
563
+ if (bad !== void 0) {
564
+ return `The choice question \`${name}\` offers the label ${quoted(bad)}, which a \`where\` filter cannot name: a label is 1 to 64 characters with no \`,\`, \`@\`, or control or invisible character, and no whitespace but single spaces between words.`;
603
565
  }
604
- const parsed = parseRangeListToken(token);
605
- if (parsed === void 0)
606
- break;
607
- if (ranges !== void 0)
608
- break;
609
- ranges = parsed;
610
- address = address.slice(0, colon);
611
566
  }
567
+ return void 0;
568
+ }
569
+ var EchoText = z6.string().catch("");
570
+ var Echo = z6.object({
571
+ detector: z6.object({ id: EchoText, version: EchoText }).catch({ id: "", version: "" }),
572
+ source: z6.object({ sessionId: EchoText, entryId: EchoText }).catch({ sessionId: "", entryId: "" })
573
+ }).catch({
574
+ detector: { id: "", version: "" },
575
+ source: { sessionId: "", entryId: "" }
576
+ });
577
+ function invalidObservation(input) {
578
+ const reason = grammarProblem(input);
579
+ if (reason === void 0)
580
+ return void 0;
581
+ const { detector, source } = Echo.parse(input);
612
582
  return {
613
- address,
614
- selector: { ranges: ranges ? mergeRanges(ranges) : [], raw }
583
+ status: "invalid",
584
+ reason,
585
+ detector: { ...detector, rubricDigest: "" },
586
+ source,
587
+ stored: false,
588
+ deduplicated: false,
589
+ inputDigest: "",
590
+ recordedAtMs: Date.now()
615
591
  };
616
592
  }
617
593
 
618
- // packages/herd-uri/dist/schema/to-json-schema.js
619
- import { z as z6 } from "zod";
620
- function toJsonSchema(schema) {
621
- if (schema instanceof z6.ZodType) {
622
- const { $schema: _dialect, ...value } = z6.toJSONSchema(schema, {
623
- // `io: "input"` describes what a caller may SEND, which is what a parameter and an
624
- // `accepts` payload advertise: a field with a Zod default is optional on the wire even
625
- // though the parsed value always carries it. Strictness still survives where the validator
626
- // really enforces it - `z.strictObject` emits `additionalProperties: false`, while a plain
627
- // `z.object` correctly does not, because it TOLERATES unknown keys and silently strips
628
- // them. A `returns` payload derived from a Zod schema is described in the same input terms;
629
- // no module does that today, and a faithful output projection would need its own seam.
630
- io: "input",
631
- // Inline every reused sub-schema rather than emitting `$ref`s into a `$defs` block. A
632
- // contract schema is a FRAGMENT: it gets embedded in a payload contract, and callers
633
- // legitimately lift one arm of a union out of it. A `$ref` only resolves relative to the
634
- // root that carries `$defs`, so the moment the fragment moves, the reference dangles.
635
- // Self-contained is worth the repetition at these sizes.
636
- reused: "inline",
637
- // Recursion (`z.lazy`) has no self-contained form: zod's default is to emit a
638
- // `$defs` block with `$ref` pointers, which dangle the moment the fragment is
639
- // embedded. Throw instead, so a contract that needs recursion has to disclose a
640
- // non-recursive shape (see skill-module's metadata disclosure) rather than ship a
641
- // reference nothing can resolve.
642
- cycles: "throw"
643
- });
644
- return value;
594
+ // packages/herd-transcript/dist/record-kinds.js
595
+ var STORED_TRANSCRIPT_MESSAGE_KINDS = [
596
+ "user",
597
+ "assistant",
598
+ "tool_result",
599
+ "custom_message:*",
600
+ "compaction",
601
+ "branch_summary"
602
+ ];
603
+ var NAMED_KINDS = /* @__PURE__ */ new Set([
604
+ "user",
605
+ "assistant",
606
+ "tool_result",
607
+ "compaction",
608
+ "branch_summary",
609
+ "other",
610
+ "unreadable"
611
+ ]);
612
+ var ROLE_KINDS = {
613
+ user: "user",
614
+ assistant: "assistant",
615
+ toolResult: "tool_result"
616
+ };
617
+ function storedTranscriptKindOf(record) {
618
+ if (!("entry" in record))
619
+ return "unreadable";
620
+ const entry = record.entry;
621
+ switch (entry.type) {
622
+ case "message": {
623
+ const message = entry.message;
624
+ if (message.role === "custom") {
625
+ return `custom_message:${typeof message.customType === "string" ? message.customType : ""}`;
626
+ }
627
+ return (typeof message.role === "string" ? ROLE_KINDS[message.role] : void 0) ?? "other";
628
+ }
629
+ case "custom":
630
+ return `custom:${entry.customType}`;
631
+ case "compaction":
632
+ return "compaction";
633
+ case "branch_summary":
634
+ return "branch_summary";
635
+ default:
636
+ return "other";
645
637
  }
646
- return structuredClone(schema);
647
638
  }
648
-
649
- // packages/herd-uri/dist/schema/helpers.js
650
- function payload(name, schema, options = {}) {
639
+ function parseStoredTranscriptKindFilter(tokens) {
640
+ const exact = /* @__PURE__ */ new Set();
641
+ const families = /* @__PURE__ */ new Set();
642
+ let all = false;
643
+ for (const raw of tokens) {
644
+ const token = raw.trim();
645
+ if (token === "all") {
646
+ all = true;
647
+ } else if (token === "messages") {
648
+ for (const kind of STORED_TRANSCRIPT_MESSAGE_KINDS)
649
+ addToken(kind);
650
+ } else if (!addToken(token)) {
651
+ return { ok: false, invalid: raw };
652
+ }
653
+ }
651
654
  return {
652
- name,
653
- ...options.mediaType === void 0 ? {} : { mediaType: options.mediaType },
654
- ...options.description === void 0 ? {} : { description: options.description },
655
- schema: toJsonSchema(schema),
656
- ...options.semanticConstraints === void 0 ? {} : { semanticConstraints: options.semanticConstraints },
657
- ...options.examples === void 0 ? {} : { examples: options.examples }
655
+ ok: true,
656
+ filter: {
657
+ includes: (kind) => all || exact.has(kind) || families.has(kind.slice(0, kind.indexOf(":") + 1))
658
+ }
658
659
  };
660
+ function addToken(token) {
661
+ if (NAMED_KINDS.has(token)) {
662
+ exact.add(token);
663
+ return true;
664
+ }
665
+ const family = /^(custom|custom_message):(.+)$/.exec(token);
666
+ if (family === null)
667
+ return false;
668
+ if (family[2] === "*")
669
+ families.add(`${family[1]}:`);
670
+ else
671
+ exact.add(token);
672
+ return true;
673
+ }
659
674
  }
675
+ var STORED_TRANSCRIPT_MESSAGE_FILTER = (() => {
676
+ const parsed = parseStoredTranscriptKindFilter(STORED_TRANSCRIPT_MESSAGE_KINDS);
677
+ if (!parsed.ok)
678
+ throw new Error(`invalid default kinds: ${parsed.invalid}`);
679
+ return parsed.filter;
680
+ })();
681
+
682
+ // packages/plugin-sdk/dist/kay-app/index.js
683
+ import { pathToFileURL } from "node:url";
660
684
 
661
685
  // packages/plugin-sdk/dist/kay-app/auth.js
662
686
  var KayAppCredentialRejectedError = class extends Error {
@@ -880,6 +904,60 @@ function refusedCountOf(error) {
880
904
  return typeof count === "number" && Number.isSafeInteger(count) && count > 0 ? count : 1;
881
905
  }
882
906
 
907
+ // packages/plugin-sdk/dist/kay-agent/declared-tool.js
908
+ function declaredToolPermission(permission) {
909
+ const { kind, ruleKey, resourceArgs, scheme, resourcePrefix, resourceTrim, defaultPermission, classificationRules } = permission;
910
+ return {
911
+ kind,
912
+ ...scheme === void 0 ? {} : { scheme },
913
+ ...ruleKey === void 0 ? {} : { ruleKey },
914
+ ...defaultPermission === void 0 ? {} : { defaultPermission },
915
+ ...classificationRules === void 0 ? {} : {
916
+ deriveClassification: (input) => {
917
+ const rule = classificationRules.find((candidate) => candidate.when.every((condition) => {
918
+ const value = Object.hasOwn(input, condition.arg) ? input[condition.arg] : void 0;
919
+ return "equals" in condition ? value === condition.equals : value !== void 0 === condition.present;
920
+ }));
921
+ return rule === void 0 ? void 0 : {
922
+ kind: rule.kind,
923
+ ...rule.ruleKey === void 0 ? {} : { ruleKey: rule.ruleKey }
924
+ };
925
+ }
926
+ },
927
+ ...resourceArgs === void 0 ? {} : {
928
+ deriveResources: (input) => resourceArgs.flatMap((arg) => {
929
+ const value = input[arg];
930
+ return typeof value === "string" ? [
931
+ `${resourcePrefix ?? ""}${resourceTrim === true ? value.trim() : value}`
932
+ ] : [];
933
+ })
934
+ }
935
+ };
936
+ }
937
+
938
+ // packages/plugin-sdk/dist/kay-app/declared-tool.js
939
+ function declaredAppToolDefinition(tool, implementation) {
940
+ if (tool.parameters === void 0 || tool.description === void 0) {
941
+ throw new Error(`Tool '${tool.toolName}' declares no parameters or description.`);
942
+ }
943
+ const { permission: preview, label: _label, description: _description, parameters: _parameters, executionMode: _executionMode, promptSnippet: _promptSnippet, promptGuidelines: _promptGuidelines, ...callbacks } = implementation;
944
+ return {
945
+ ...callbacks,
946
+ label: tool.displayName ?? tool.toolName,
947
+ description: tool.description,
948
+ parameters: tool.parameters,
949
+ ...tool.executionMode === void 0 ? {} : { executionMode: tool.executionMode },
950
+ ...tool.promptSnippet === void 0 ? {} : { promptSnippet: tool.promptSnippet },
951
+ ...tool.promptGuidelines === void 0 ? {} : { promptGuidelines: tool.promptGuidelines },
952
+ ...tool.permission === void 0 ? {} : {
953
+ permission: {
954
+ ...declaredToolPermission(tool.permission),
955
+ ...preview?.describePreview === void 0 ? {} : { describePreview: preview.describePreview }
956
+ }
957
+ }
958
+ };
959
+ }
960
+
883
961
  // packages/plugin-sdk/dist/kay-app/sealing.js
884
962
  var KAY_APP_SEALING_MAX_BYTES = 1048576;
885
963
  function createUnavailableSealing(message) {
@@ -1024,13 +1102,16 @@ export {
1024
1102
  UriUnsupportedOperationError,
1025
1103
  UriValidationError,
1026
1104
  card,
1105
+ contentDigest,
1027
1106
  createConsoleKayPluginLog,
1028
1107
  createFallbackOnlySignals,
1029
1108
  createKayPluginLog,
1030
1109
  createUnavailableSealing,
1031
1110
  createUnavailableSkills,
1032
1111
  createUnavailableTools,
1112
+ createUnavailableUriCaller,
1033
1113
  createUnavailableUsage,
1114
+ declaredAppToolDefinition,
1034
1115
  definePoller,
1035
1116
  failedRunCause,
1036
1117
  invalidObservation,