@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.
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/THIRD-PARTY-INVENTORY.json +65 -0
- package/THIRD-PARTY-NOTICES.md +103 -0
- package/dist/disclosure.d.ts +3431 -0
- package/dist/disclosure.js +873 -0
- package/dist/kay-agent-testing.d.ts +3294 -0
- package/dist/kay-agent-testing.js +88 -0
- package/dist/kay-agent.d.ts +5286 -0
- package/dist/kay-agent.js +1341 -0
- package/dist/kay-app.d.ts +6303 -0
- package/dist/kay-app.js +424 -0
- package/dist/phase-shift.d.ts +127 -0
- package/dist/phase-shift.js +180 -0
- package/dist/transcript.d.ts +60 -0
- package/dist/transcript.js +23 -0
- package/package.json +59 -0
- package/skills/directory-plugin-authoring/SKILL.md +252 -0
package/dist/kay-app.js
ADDED
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
// packages/plugin-sdk/dist/jev.js
|
|
2
|
+
function createFallbackOnlyWithJev() {
|
|
3
|
+
return async (_use, fallback, options = {}) => {
|
|
4
|
+
if (typeof fallback !== "function") {
|
|
5
|
+
throw new TypeError("withJev requires a `fallback` function as its second argument.");
|
|
6
|
+
}
|
|
7
|
+
const { signal, deadlineAt } = options;
|
|
8
|
+
if (deadlineAt !== void 0 && !Number.isFinite(deadlineAt)) {
|
|
9
|
+
throw new TypeError("withJev's `deadlineAt` must be a finite epoch-ms timestamp.");
|
|
10
|
+
}
|
|
11
|
+
const assertWithinBoundaries = () => {
|
|
12
|
+
if (signal?.aborted === true) {
|
|
13
|
+
throw signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
14
|
+
}
|
|
15
|
+
if (deadlineAt !== void 0 && Date.now() >= deadlineAt) {
|
|
16
|
+
throw new Error("withJev's deadline has passed.");
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
assertWithinBoundaries();
|
|
20
|
+
let timer;
|
|
21
|
+
let onAbort;
|
|
22
|
+
const stopped = new Promise((_resolve, reject) => {
|
|
23
|
+
if (signal !== void 0) {
|
|
24
|
+
onAbort = () => reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
|
|
25
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
26
|
+
}
|
|
27
|
+
if (deadlineAt !== void 0) {
|
|
28
|
+
const checkDeadline = () => {
|
|
29
|
+
const remaining = deadlineAt - Date.now();
|
|
30
|
+
if (remaining <= 0) {
|
|
31
|
+
reject(new Error("withJev's deadline has passed."));
|
|
32
|
+
} else {
|
|
33
|
+
timer = setTimeout(checkDeadline, Math.min(remaining, 2147483647));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
checkDeadline();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
try {
|
|
40
|
+
const result = await Promise.race([
|
|
41
|
+
Promise.resolve().then(() => {
|
|
42
|
+
assertWithinBoundaries();
|
|
43
|
+
return fallback();
|
|
44
|
+
}),
|
|
45
|
+
stopped
|
|
46
|
+
]);
|
|
47
|
+
assertWithinBoundaries();
|
|
48
|
+
return result;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
assertWithinBoundaries();
|
|
51
|
+
throw error;
|
|
52
|
+
} finally {
|
|
53
|
+
if (timer !== void 0)
|
|
54
|
+
clearTimeout(timer);
|
|
55
|
+
if (signal !== void 0 && onAbort !== void 0) {
|
|
56
|
+
signal.removeEventListener("abort", onAbort);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// packages/plugin-sdk/dist/signals.js
|
|
63
|
+
import { z } from "zod";
|
|
64
|
+
function createFallbackOnlySignals() {
|
|
65
|
+
const noStore = { status: "unavailable", reason: "no-store" };
|
|
66
|
+
return {
|
|
67
|
+
observe: (input) => Promise.resolve(invalidObservation(input) ?? {
|
|
68
|
+
status: "unavailable",
|
|
69
|
+
reason: "no-jev-lane",
|
|
70
|
+
detector: { ...input.detector, rubricDigest: "" },
|
|
71
|
+
source: input.source,
|
|
72
|
+
stored: false,
|
|
73
|
+
deduplicated: false,
|
|
74
|
+
inputDigest: "",
|
|
75
|
+
recordedAtMs: Date.now()
|
|
76
|
+
}),
|
|
77
|
+
listDetectors: () => Promise.resolve(noStore),
|
|
78
|
+
list: () => Promise.resolve(noStore)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
var SIGNAL_TIME_MAX_MS = 864e13;
|
|
82
|
+
var MAX_CHOICE_LABELS = 64;
|
|
83
|
+
var MAX_NAME = 64;
|
|
84
|
+
var MAX_POINTER = 256;
|
|
85
|
+
var MAX_QUESTIONS = 64;
|
|
86
|
+
var DETECTOR_ID = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
87
|
+
var VERSION = /^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/u;
|
|
88
|
+
var QUESTION_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/u;
|
|
89
|
+
var POINTER = /^[^\s\p{C}/?#]+$/u;
|
|
90
|
+
var LABEL = /^[^\s,@\p{C}]+(?: [^\s,@\p{C}]+)*$/u;
|
|
91
|
+
var RUN_ID = /^\P{Cc}+$/u;
|
|
92
|
+
var POINTER_RULE = `1 to ${MAX_POINTER} characters with no whitespace, \`/\`, \`?\`, \`#\`, or control or invisible character`;
|
|
93
|
+
var ObserveShape = z.looseObject({
|
|
94
|
+
detector: z.looseObject({ id: z.string(), version: z.string() }),
|
|
95
|
+
source: z.looseObject({
|
|
96
|
+
sessionId: z.string(),
|
|
97
|
+
entryId: z.string(),
|
|
98
|
+
openerEntryId: z.string().optional(),
|
|
99
|
+
runId: z.string().optional(),
|
|
100
|
+
occurredAtMs: z.unknown().optional()
|
|
101
|
+
}),
|
|
102
|
+
questions: z.record(z.string(), z.unknown())
|
|
103
|
+
});
|
|
104
|
+
var ChoiceQuestion = z.looseObject({
|
|
105
|
+
type: z.literal("choice"),
|
|
106
|
+
criteria: z.record(z.string(), z.unknown())
|
|
107
|
+
});
|
|
108
|
+
var fits = (value, grammar) => value.length <= MAX_NAME && grammar.test(value);
|
|
109
|
+
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")}`);
|
|
110
|
+
function grammarProblem(input) {
|
|
111
|
+
const shape = ObserveShape.safeParse(input);
|
|
112
|
+
if (!shape.success) {
|
|
113
|
+
const field = shape.error.issues[0]?.path.join(".") ?? "";
|
|
114
|
+
return field === "" ? "`observe` takes an object with `detector`, `source`, `state`, and `questions`." : `\`${field}\` is missing or has the wrong type.`;
|
|
115
|
+
}
|
|
116
|
+
const { detector, source, questions } = shape.data;
|
|
117
|
+
if (!fits(detector.id, DETECTOR_ID)) {
|
|
118
|
+
return "`detector.id` must be a lowercase slug of at most 64 characters: a-z and 0-9 in words joined by single hyphens.";
|
|
119
|
+
}
|
|
120
|
+
if (!fits(detector.version, VERSION)) {
|
|
121
|
+
return "`detector.version` must be at most 64 characters: letters and digits in parts joined by single `.`, `-`, or `_`.";
|
|
122
|
+
}
|
|
123
|
+
for (const [field, grammar, rule] of [
|
|
124
|
+
["sessionId", POINTER, POINTER_RULE],
|
|
125
|
+
["entryId", POINTER, POINTER_RULE],
|
|
126
|
+
["openerEntryId", POINTER, POINTER_RULE],
|
|
127
|
+
[
|
|
128
|
+
"runId",
|
|
129
|
+
RUN_ID,
|
|
130
|
+
`1 to ${MAX_POINTER} characters with no control character`
|
|
131
|
+
]
|
|
132
|
+
]) {
|
|
133
|
+
const id = source[field];
|
|
134
|
+
if (id !== void 0 && !(id.length <= MAX_POINTER && grammar.test(id))) {
|
|
135
|
+
return `\`source.${field}\` must be ${rule}.`;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const occurredAtMs = source.occurredAtMs;
|
|
139
|
+
if (occurredAtMs !== void 0 && !(typeof occurredAtMs === "number" && Number.isSafeInteger(occurredAtMs) && occurredAtMs >= 0 && occurredAtMs <= SIGNAL_TIME_MAX_MS)) {
|
|
140
|
+
return `\`source.occurredAtMs\` must be whole epoch milliseconds from 0 to ${SIGNAL_TIME_MAX_MS}.`;
|
|
141
|
+
}
|
|
142
|
+
const names = Object.keys(questions);
|
|
143
|
+
if (names.length === 0 || names.length > MAX_QUESTIONS) {
|
|
144
|
+
return `\`questions\` must ask 1 to ${MAX_QUESTIONS} questions.`;
|
|
145
|
+
}
|
|
146
|
+
for (const name of names) {
|
|
147
|
+
if (!fits(name, QUESTION_NAME)) {
|
|
148
|
+
return `The question name ${quoted(name)} must be an identifier of at most 64 characters: letters, digits, and \`_\`, not starting with a digit.`;
|
|
149
|
+
}
|
|
150
|
+
const choice = ChoiceQuestion.safeParse(questions[name]);
|
|
151
|
+
if (!choice.success)
|
|
152
|
+
continue;
|
|
153
|
+
const labels = Object.keys(choice.data.criteria);
|
|
154
|
+
if (labels.length > MAX_CHOICE_LABELS) {
|
|
155
|
+
return `The choice question \`${name}\` offers ${labels.length} labels; at most ${MAX_CHOICE_LABELS}.`;
|
|
156
|
+
}
|
|
157
|
+
const bad = labels.find((label) => !fits(label, LABEL));
|
|
158
|
+
if (bad !== void 0) {
|
|
159
|
+
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.`;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return void 0;
|
|
163
|
+
}
|
|
164
|
+
var EchoText = z.string().catch("");
|
|
165
|
+
var Echo = z.object({
|
|
166
|
+
detector: z.object({ id: EchoText, version: EchoText }).catch({ id: "", version: "" }),
|
|
167
|
+
source: z.object({ sessionId: EchoText, entryId: EchoText }).catch({ sessionId: "", entryId: "" })
|
|
168
|
+
}).catch({
|
|
169
|
+
detector: { id: "", version: "" },
|
|
170
|
+
source: { sessionId: "", entryId: "" }
|
|
171
|
+
});
|
|
172
|
+
function invalidObservation(input) {
|
|
173
|
+
const reason = grammarProblem(input);
|
|
174
|
+
if (reason === void 0)
|
|
175
|
+
return void 0;
|
|
176
|
+
const { detector, source } = Echo.parse(input);
|
|
177
|
+
return {
|
|
178
|
+
status: "invalid",
|
|
179
|
+
reason,
|
|
180
|
+
detector: { ...detector, rubricDigest: "" },
|
|
181
|
+
source,
|
|
182
|
+
stored: false,
|
|
183
|
+
deduplicated: false,
|
|
184
|
+
inputDigest: "",
|
|
185
|
+
recordedAtMs: Date.now()
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// packages/herd-uri/dist/errors.js
|
|
190
|
+
var UriError = class extends Error {
|
|
191
|
+
};
|
|
192
|
+
var CONFLICT_MESSAGES = {
|
|
193
|
+
changed: "This resource changed since this session last read it. Read it again before modifying it.",
|
|
194
|
+
unwitnessed: "This resource was not read in this session. Read it before modifying it.",
|
|
195
|
+
unknown: "This resource changed or was not read in this session. Read it again before modifying it."
|
|
196
|
+
};
|
|
197
|
+
var UriConflictError = class extends UriError {
|
|
198
|
+
_tag = "UriConflictError";
|
|
199
|
+
reason;
|
|
200
|
+
constructor(reason) {
|
|
201
|
+
super(CONFLICT_MESSAGES[reason ?? "unknown"]);
|
|
202
|
+
this.name = "UriConflictError";
|
|
203
|
+
this.reason = reason;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var UriValidationError = class extends UriError {
|
|
207
|
+
_tag = "UriValidationError";
|
|
208
|
+
constructor(message) {
|
|
209
|
+
super(message);
|
|
210
|
+
this.name = "UriValidationError";
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
var UriProviderError = class extends UriError {
|
|
214
|
+
_tag = "UriProviderError";
|
|
215
|
+
moduleId;
|
|
216
|
+
operation;
|
|
217
|
+
uri;
|
|
218
|
+
status;
|
|
219
|
+
providerCode;
|
|
220
|
+
retryable;
|
|
221
|
+
/** Provider-directed delay before retrying, in milliseconds. */
|
|
222
|
+
retryAfterMs;
|
|
223
|
+
constructor(options) {
|
|
224
|
+
super(options.message);
|
|
225
|
+
this.name = "UriProviderError";
|
|
226
|
+
this.moduleId = options.moduleId;
|
|
227
|
+
this.operation = options.operation;
|
|
228
|
+
this.uri = options.uri;
|
|
229
|
+
if (options.status !== void 0)
|
|
230
|
+
this.status = options.status;
|
|
231
|
+
if (options.providerCode !== void 0)
|
|
232
|
+
this.providerCode = options.providerCode;
|
|
233
|
+
if (options.retryable !== void 0)
|
|
234
|
+
this.retryable = options.retryable;
|
|
235
|
+
if (options.retryAfterMs !== void 0) {
|
|
236
|
+
if (!Number.isInteger(options.retryAfterMs) || options.retryAfterMs < 0) {
|
|
237
|
+
throw new TypeError("retryAfterMs must be a nonnegative integer.");
|
|
238
|
+
}
|
|
239
|
+
this.retryAfterMs = options.retryAfterMs;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
var UriNotFoundError = class extends UriError {
|
|
244
|
+
uri;
|
|
245
|
+
hint;
|
|
246
|
+
_tag = "UriNotFoundError";
|
|
247
|
+
constructor(uri, hint) {
|
|
248
|
+
super(hint !== void 0 ? `No resource found at '${uri}'. ${hint}` : `No resource found at '${uri}'.`);
|
|
249
|
+
this.uri = uri;
|
|
250
|
+
this.hint = hint;
|
|
251
|
+
this.name = "UriNotFoundError";
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
var UriUnsupportedOperationError = class extends UriError {
|
|
255
|
+
operation;
|
|
256
|
+
moduleId;
|
|
257
|
+
uri;
|
|
258
|
+
_tag = "UriUnsupportedOperationError";
|
|
259
|
+
constructor(operation, moduleId, uri, message) {
|
|
260
|
+
super(message ?? `URI module '${moduleId}' does not support '${operation}' for '${uri}'.`);
|
|
261
|
+
this.operation = operation;
|
|
262
|
+
this.moduleId = moduleId;
|
|
263
|
+
this.uri = uri;
|
|
264
|
+
this.name = "UriUnsupportedOperationError";
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
// packages/herd-uri/dist/operations.js
|
|
269
|
+
import { z as z2 } from "zod";
|
|
270
|
+
var URI_OPERATIONS = [
|
|
271
|
+
"help",
|
|
272
|
+
"read",
|
|
273
|
+
"write",
|
|
274
|
+
"edit",
|
|
275
|
+
"list",
|
|
276
|
+
"search",
|
|
277
|
+
"delete"
|
|
278
|
+
];
|
|
279
|
+
var UriOperationSchema = z2.enum(URI_OPERATIONS);
|
|
280
|
+
|
|
281
|
+
// packages/herd-uri/dist/help-schema.js
|
|
282
|
+
import { z as z3 } from "zod";
|
|
283
|
+
var UriContractJsonSchema = z3.record(z3.string(), z3.unknown());
|
|
284
|
+
var UriParameterSchema = z3.strictObject({
|
|
285
|
+
name: z3.string().min(1),
|
|
286
|
+
in: z3.enum(["uri", "query", "selector"]),
|
|
287
|
+
required: z3.boolean(),
|
|
288
|
+
description: z3.string().optional(),
|
|
289
|
+
schema: UriContractJsonSchema,
|
|
290
|
+
examples: z3.array(z3.unknown()).optional()
|
|
291
|
+
});
|
|
292
|
+
var UriPayloadContractSchema = z3.strictObject({
|
|
293
|
+
name: z3.string().min(1),
|
|
294
|
+
mediaType: z3.string().optional(),
|
|
295
|
+
description: z3.string().optional(),
|
|
296
|
+
schema: UriContractJsonSchema.optional(),
|
|
297
|
+
semanticConstraints: z3.array(z3.string().min(1)).min(1).optional(),
|
|
298
|
+
examples: z3.array(z3.unknown()).optional()
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
// packages/herd-uri/dist/text-edit.js
|
|
302
|
+
import { z as z4 } from "zod";
|
|
303
|
+
var findReplaceArm = z4.strictObject({
|
|
304
|
+
find: z4.string().min(1),
|
|
305
|
+
replace: z4.string(),
|
|
306
|
+
all: z4.boolean().optional()
|
|
307
|
+
});
|
|
308
|
+
var oldNewEntry = z4.strictObject({
|
|
309
|
+
oldText: z4.string().min(1),
|
|
310
|
+
newText: z4.string()
|
|
311
|
+
});
|
|
312
|
+
var uriTextEditPayloadArms = z4.union([
|
|
313
|
+
findReplaceArm,
|
|
314
|
+
z4.strictObject({ edits: z4.array(oldNewEntry).min(1) }),
|
|
315
|
+
oldNewEntry,
|
|
316
|
+
z4.array(oldNewEntry).min(1)
|
|
317
|
+
]);
|
|
318
|
+
|
|
319
|
+
// packages/herd-uri/dist/schema/to-json-schema.js
|
|
320
|
+
import { z as z5 } from "zod";
|
|
321
|
+
function toJsonSchema(schema) {
|
|
322
|
+
if (schema instanceof z5.ZodType) {
|
|
323
|
+
const { $schema: _dialect, ...value } = z5.toJSONSchema(schema, {
|
|
324
|
+
// `io: "input"` describes what a caller may SEND, which is what a parameter and an
|
|
325
|
+
// `accepts` payload advertise: a field with a Zod default is optional on the wire even
|
|
326
|
+
// though the parsed value always carries it. Strictness still survives where the validator
|
|
327
|
+
// really enforces it — `z.strictObject` emits `additionalProperties: false`, while a plain
|
|
328
|
+
// `z.object` correctly does not, because it TOLERATES unknown keys and silently strips
|
|
329
|
+
// them. A `returns` payload derived from a Zod schema is described in the same input terms;
|
|
330
|
+
// no module does that today, and a faithful output projection would need its own seam.
|
|
331
|
+
io: "input",
|
|
332
|
+
// Inline every reused sub-schema rather than emitting `$ref`s into a `$defs` block. A
|
|
333
|
+
// contract schema is a FRAGMENT: it gets embedded in a payload contract, and callers
|
|
334
|
+
// legitimately lift one arm of a union out of it. A `$ref` only resolves relative to the
|
|
335
|
+
// root that carries `$defs`, so the moment the fragment moves, the reference dangles.
|
|
336
|
+
// Self-contained is worth the repetition at these sizes.
|
|
337
|
+
reused: "inline",
|
|
338
|
+
// Recursion (`z.lazy`) has no self-contained form: zod's default is to emit a
|
|
339
|
+
// `$defs` block with `$ref` pointers, which dangle the moment the fragment is
|
|
340
|
+
// embedded. Throw instead, so a contract that needs recursion has to disclose a
|
|
341
|
+
// non-recursive shape (see skill-module's metadata disclosure) rather than ship a
|
|
342
|
+
// reference nothing can resolve.
|
|
343
|
+
cycles: "throw"
|
|
344
|
+
});
|
|
345
|
+
return value;
|
|
346
|
+
}
|
|
347
|
+
return structuredClone(schema);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// packages/herd-uri/dist/schema/helpers.js
|
|
351
|
+
function payload(name, schema, options = {}) {
|
|
352
|
+
return {
|
|
353
|
+
name,
|
|
354
|
+
...options.mediaType === void 0 ? {} : { mediaType: options.mediaType },
|
|
355
|
+
...options.description === void 0 ? {} : { description: options.description },
|
|
356
|
+
schema: toJsonSchema(schema),
|
|
357
|
+
...options.semanticConstraints === void 0 ? {} : { semanticConstraints: options.semanticConstraints },
|
|
358
|
+
...options.examples === void 0 ? {} : { examples: options.examples }
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// packages/plugin-sdk/dist/kay-app/transcript-text.js
|
|
363
|
+
function transcriptMessageTexts(entries) {
|
|
364
|
+
return entries.flatMap((entry) => {
|
|
365
|
+
if (entry.type !== "message")
|
|
366
|
+
return [];
|
|
367
|
+
const role = entry.message.role;
|
|
368
|
+
if (role !== "user" && role !== "assistant")
|
|
369
|
+
return [];
|
|
370
|
+
const text = transcriptMessageText(entry.message);
|
|
371
|
+
return text === "" ? [] : [{ role, text }];
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function transcriptMessageText(message) {
|
|
375
|
+
if (typeof message.content === "string")
|
|
376
|
+
return message.content.trim();
|
|
377
|
+
if (!Array.isArray(message.content))
|
|
378
|
+
return "";
|
|
379
|
+
return message.content.flatMap((part) => {
|
|
380
|
+
if (typeof part !== "object" || part === null)
|
|
381
|
+
return [];
|
|
382
|
+
const candidate = part;
|
|
383
|
+
return candidate.type === "text" && typeof candidate.text === "string" ? [candidate.text] : [];
|
|
384
|
+
}).join("").trim();
|
|
385
|
+
}
|
|
386
|
+
function transcriptRoleLabel(role) {
|
|
387
|
+
return role === "user" ? "User" : "Assistant";
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// packages/plugin-protocol/dist/app-data.js
|
|
391
|
+
var KAY_APP_DATA_SNAPSHOT_MAX_BYTES = 16 * 1024 * 1024;
|
|
392
|
+
var KAY_APP_DATA_CHANGE_MAX_BYTES = 256 * 1024;
|
|
393
|
+
var KAY_APP_DATA_READ_REQUEST_MAX_BYTES = 64 * 1024;
|
|
394
|
+
var KAY_APP_DATA_READ_RESULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
395
|
+
|
|
396
|
+
// packages/plugin-sdk/dist/kay-app/index.js
|
|
397
|
+
function isRetryable(result) {
|
|
398
|
+
return result.status === "not-ready";
|
|
399
|
+
}
|
|
400
|
+
var KAY_APP_AUTOMATION_CONDITION_KINDS = [
|
|
401
|
+
"time",
|
|
402
|
+
"uri-change",
|
|
403
|
+
"occurrence",
|
|
404
|
+
"delayed-occurrence"
|
|
405
|
+
];
|
|
406
|
+
export {
|
|
407
|
+
KAY_APP_AUTOMATION_CONDITION_KINDS,
|
|
408
|
+
KAY_APP_DATA_CHANGE_MAX_BYTES,
|
|
409
|
+
MAX_CHOICE_LABELS,
|
|
410
|
+
SIGNAL_TIME_MAX_MS,
|
|
411
|
+
UriConflictError,
|
|
412
|
+
UriNotFoundError,
|
|
413
|
+
UriProviderError,
|
|
414
|
+
UriUnsupportedOperationError,
|
|
415
|
+
UriValidationError,
|
|
416
|
+
createFallbackOnlySignals,
|
|
417
|
+
createFallbackOnlyWithJev,
|
|
418
|
+
invalidObservation,
|
|
419
|
+
isRetryable,
|
|
420
|
+
payload,
|
|
421
|
+
transcriptMessageText,
|
|
422
|
+
transcriptMessageTexts,
|
|
423
|
+
transcriptRoleLabel
|
|
424
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export declare const PHASE_SHIFT_CUSTOM_TYPE = "ext:kay.phase-shift:observation";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The custom-entry type a SURFACE reads phase shifts from: the derived
|
|
7
|
+
* {@link PhaseShiftTimelineRecord} stream, one record per accepted check.
|
|
8
|
+
*
|
|
9
|
+
* Never written to a session log. The detector records
|
|
10
|
+
* {@link PHASE_SHIFT_CUSTOM_TYPE} observations, which stay daemon bookkeeping
|
|
11
|
+
* because a surface cannot validate them: custom entries reach a surface
|
|
12
|
+
* without their entry ids, a tool call carries no entry id at all, and the
|
|
13
|
+
* observation's source ids routinely name tool-result entries. The daemon
|
|
14
|
+
* therefore folds the branch itself and hands a surface only what it can place.
|
|
15
|
+
*/
|
|
16
|
+
export declare const PHASE_SHIFT_TIMELINE_CUSTOM_TYPE = "ext:kay.phase-shift:timeline";
|
|
17
|
+
|
|
18
|
+
declare type PhaseShiftCost = z.infer<typeof phaseShiftCostSchema>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* What one check cost: the detector's OWN model call, priced by the same
|
|
22
|
+
* accounting as any other direct completion.
|
|
23
|
+
*
|
|
24
|
+
* It lives on the observation because nothing else can carry it. A detector
|
|
25
|
+
* call is a direct completion, not a turn, so it writes no `herd.cost_fact`
|
|
26
|
+
* and never reaches the session's usage ledger; the daemon's telemetry knows
|
|
27
|
+
* it, but a surface reading the session log does not. Recording it here is how
|
|
28
|
+
* the feature accounts for itself.
|
|
29
|
+
*
|
|
30
|
+
* Absent on a record written before the detector accounted for itself, and on
|
|
31
|
+
* a call no attempt priced — absence means "not recorded", never zero.
|
|
32
|
+
*/
|
|
33
|
+
declare const phaseShiftCostSchema: z.ZodObject<{
|
|
34
|
+
amountUsd: z.ZodNumber;
|
|
35
|
+
amountBasis: z.ZodEnum<{
|
|
36
|
+
unknown: "unknown";
|
|
37
|
+
measured: "measured";
|
|
38
|
+
"list-estimate": "list-estimate";
|
|
39
|
+
}>;
|
|
40
|
+
inputTokens: z.ZodNumber;
|
|
41
|
+
outputTokens: z.ZodNumber;
|
|
42
|
+
attempts: z.ZodNumber;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
|
|
45
|
+
/** One accepted transition, placed in time. */
|
|
46
|
+
export declare interface PhaseShiftTimelineChange {
|
|
47
|
+
readonly startEntryId: string;
|
|
48
|
+
/** When the new work began — the onset entry's own timestamp, not the judgment's. */
|
|
49
|
+
readonly startedAt: string;
|
|
50
|
+
readonly relation: "outcome" | "phase";
|
|
51
|
+
readonly reason: string;
|
|
52
|
+
readonly purposeAfter: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A session's phase-shift timeline, read from its FLAT entry log.
|
|
57
|
+
*
|
|
58
|
+
* The one entry point for a consumer holding a whole log rather than a branch:
|
|
59
|
+
* it walks the tree to the active branch itself (a `leaf` marker moves the
|
|
60
|
+
* chain, so the last entry is not the branch tip after a rewind), folds the
|
|
61
|
+
* branch through {@link acceptedPhaseShiftObservations}, and resolves a
|
|
62
|
+
* version-1 record's source timestamps from the entries it referenced. Those
|
|
63
|
+
* references are branch-validated by the fold, so the resolution is total.
|
|
64
|
+
*/
|
|
65
|
+
export declare function phaseShiftTimelineFromEntries(entries: readonly TranscriptSourceEntry[]): readonly PhaseShiftTimelineRecord[];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* One accepted detector check, as a surface reads it.
|
|
69
|
+
*
|
|
70
|
+
* A record is evidence about the span it names and nothing else: time outside
|
|
71
|
+
* every record's `[windowStartAt, throughAt]` is unobserved, which is not the
|
|
72
|
+
* same as unchanged. An empty `changes` is the opposite — a check that ran and
|
|
73
|
+
* found no transition.
|
|
74
|
+
*/
|
|
75
|
+
export declare interface PhaseShiftTimelineRecord {
|
|
76
|
+
readonly version: 1;
|
|
77
|
+
readonly detectorVersion: string;
|
|
78
|
+
/** The model that judged, as resolved after any provider recovery. */
|
|
79
|
+
readonly modelReference: string;
|
|
80
|
+
/** When the detector RECOGNIZED this, which can trail the onsets it names. */
|
|
81
|
+
readonly observedAt: string;
|
|
82
|
+
readonly windowStartEntryId: string;
|
|
83
|
+
readonly windowStartAt: string;
|
|
84
|
+
readonly throughEntryId: string;
|
|
85
|
+
readonly throughAt: string;
|
|
86
|
+
/** The purpose standing after this check. */
|
|
87
|
+
readonly purpose: string;
|
|
88
|
+
/** Accepted transitions in onset order; empty means none was found. */
|
|
89
|
+
readonly changes: readonly PhaseShiftTimelineChange[];
|
|
90
|
+
/**
|
|
91
|
+
* What running this check cost. Absent means the cost was not recorded (every
|
|
92
|
+
* record written before the detector accounted for itself, and every version-1
|
|
93
|
+
* record), which is never the same as a check that cost nothing.
|
|
94
|
+
*/
|
|
95
|
+
readonly cost?: PhaseShiftCost;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** The fields the customType selector needs off a session entry. */
|
|
99
|
+
declare interface TranscriptEntry {
|
|
100
|
+
readonly id: string;
|
|
101
|
+
readonly type: string;
|
|
102
|
+
readonly customType?: string;
|
|
103
|
+
/** Opaque. Never parsed or validated here — a feature's own schema owns that. */
|
|
104
|
+
readonly data?: unknown;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* A tree entry plus the ISO timestamp the timeline projections read alongside
|
|
109
|
+
* the walk result (`turnSegments`, `phaseShiftTimelineFromEntries`).
|
|
110
|
+
*/
|
|
111
|
+
declare interface TranscriptSourceEntry extends TranscriptTreeEntry {
|
|
112
|
+
readonly timestamp: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* A session entry as {@link branchEntryIds} reads it: the fields above plus the
|
|
117
|
+
* tree links the walk follows to find the active branch. No timestamp: the walk
|
|
118
|
+
* never reads one, and a live v2 entry carries epoch milliseconds where a raw
|
|
119
|
+
* v3 log carries an ISO string, so requiring either shape here would force one
|
|
120
|
+
* class of caller to convert entries it only wants walked.
|
|
121
|
+
*/
|
|
122
|
+
declare interface TranscriptTreeEntry extends TranscriptEntry {
|
|
123
|
+
readonly parentId?: string | null;
|
|
124
|
+
readonly targetId?: string | null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { }
|