@yaklabs-ai/plugin-sdk 0.52.1 → 0.54.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.
@@ -133,6 +133,268 @@ function readProducedResourceDeclarations(details) {
133
133
  return MALFORMED;
134
134
  return { kind: "declared", resources: claimed };
135
135
  }
136
+
137
+ // packages/plugin-protocol/dist/turn-packet.js
138
+ var RUN_STARTED = "session_run_started";
139
+ function textOf(entry) {
140
+ const content = entry.message?.content;
141
+ if (typeof content === "string")
142
+ return content;
143
+ if (!Array.isArray(content))
144
+ return "";
145
+ return content.map((part) => typeof part === "object" && part !== null && part.type === "text" && typeof part.text === "string" ? part.text : "").join("");
146
+ }
147
+ function turnMessageOrigin(entry) {
148
+ const m = entry.message;
149
+ if (m === void 0 || typeof m.clientIntentId !== "string")
150
+ return "unknown";
151
+ const details = m.details;
152
+ const deliveryId = typeof details === "object" && details !== null ? details.deliveryId : void 0;
153
+ return typeof deliveryId === "string" ? "human-verified" : "unknown";
154
+ }
155
+ function turnPacket(entries, settleEntryId, options = {}) {
156
+ const branch = branchEntryIds(entries);
157
+ const live = entries.filter((e) => branch.has(e.id));
158
+ const anchorIndex = live.findIndex((e) => e.id === settleEntryId);
159
+ const searchFrom = anchorIndex === -1 ? live.length - 1 : anchorIndex;
160
+ let runStart = -1;
161
+ for (let i = searchFrom; i >= 0; i -= 1) {
162
+ if (live[i]?.type === "custom" && live[i]?.customType === RUN_STARTED) {
163
+ runStart = i;
164
+ break;
165
+ }
166
+ }
167
+ let spanStart = runStart;
168
+ if (runStart === -1) {
169
+ spanStart = 0;
170
+ for (let i = searchFrom; i >= 0; i -= 1) {
171
+ if (live[i]?.type === "message" && live[i]?.message?.role === "user") {
172
+ spanStart = i;
173
+ break;
174
+ }
175
+ }
176
+ }
177
+ const span = live.slice(spanStart, searchFrom + 1);
178
+ const messages = span.filter((e) => e.type === "message" && e.message?.role !== void 0);
179
+ const people = messages.filter((e) => e.message?.role === "user");
180
+ const assistants = messages.filter((e) => e.message?.role === "assistant");
181
+ const opener = people[0];
182
+ if (opener === void 0)
183
+ return void 0;
184
+ const toPacket = (entry) => ({
185
+ entryId: entry.id,
186
+ timestamp: entry.timestamp,
187
+ text: textOf(entry),
188
+ origin: turnMessageOrigin(entry)
189
+ });
190
+ return {
191
+ personMessage: toPacket(opener),
192
+ personSteers: people.slice(1).map(toPacket),
193
+ assistantReplies: assistants.filter((e) => textOf(e).trim().length > 0).map(toPacket),
194
+ settleEntryId,
195
+ sessionTier: options.sessionTier ?? "unknown"
196
+ };
197
+ }
198
+ function precedingPersonMessages(entries, packet, count) {
199
+ if (count <= 0)
200
+ return [];
201
+ const branch = branchEntryIds(entries);
202
+ const live = entries.filter((e) => branch.has(e.id));
203
+ const openerIndex = live.findIndex((e) => e.id === packet.personMessage.entryId);
204
+ if (openerIndex === -1)
205
+ return [];
206
+ const found = [];
207
+ for (let i = openerIndex - 1; i >= 0 && found.length < count; i -= 1) {
208
+ const e = live[i];
209
+ if (e === void 0)
210
+ continue;
211
+ if (e.type !== "message" || e.message?.role !== "user")
212
+ continue;
213
+ if (turnMessageOrigin(e) !== "human-verified")
214
+ continue;
215
+ found.push({
216
+ entryId: e.id,
217
+ timestamp: e.timestamp,
218
+ text: textOf(e),
219
+ origin: "human-verified"
220
+ });
221
+ }
222
+ return found.reverse();
223
+ }
224
+
225
+ // packages/plugin-protocol/dist/skill-suggestion-evidence.js
226
+ var UUID = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
227
+ var UUID_ID = new RegExp(`^${UUID}$`, "i");
228
+ var ENTRY = "[a-z0-9_-]+";
229
+ var ENTRY_ID = new RegExp(`^${ENTRY}$`, "i");
230
+ var FRICTION_URI = /^friction:\/\/([a-z0-9]+(?:-[a-z0-9]+)*)$/;
231
+ var normalizeId = (value) => UUID_ID.test(value) ? value.toLowerCase() : value;
232
+ function sessionPattern(options) {
233
+ const known = (options.sessionIds ?? []).filter((id) => ENTRY_ID.test(id) && !UUID_ID.test(id)).map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
234
+ return `(?:${[UUID, ...new Set(known)].join("|")})`;
235
+ }
236
+ function sessionRef(sessionId, entryId, raw) {
237
+ return entryId === void 0 ? { kind: "session", sessionId: normalizeId(sessionId), raw } : {
238
+ kind: "message",
239
+ sessionId: normalizeId(sessionId),
240
+ entryId: normalizeId(entryId),
241
+ raw
242
+ };
243
+ }
244
+ function parseToken(raw, sessions) {
245
+ if (/^sessions?:\/\//i.test(raw)) {
246
+ const match = /^sessions?:\/\/([^/?#]+)([^?#]*)(?:\?([^#]*))?(?:#(.*))?$/i.exec(raw);
247
+ if (match === null)
248
+ return void 0;
249
+ const sessionId = match[1].replace(/\.jsonl$/i, "");
250
+ if (!new RegExp(`^${sessions}$`, "i").test(sessionId))
251
+ return void 0;
252
+ const path = match[2];
253
+ if (path !== "" && path !== "/" && !new RegExp(`^/${ENTRY}$`, "i").test(path))
254
+ return void 0;
255
+ const query = new URLSearchParams(match[3]);
256
+ const entryId = query.get("entry") ?? query.get("span") ?? query.get("from") ?? (path.length > 1 ? path.slice(1) : match[4]);
257
+ if (entryId !== void 0 && !ENTRY_ID.test(entryId))
258
+ return void 0;
259
+ return sessionRef(sessionId, entryId, raw);
260
+ }
261
+ if (/^friction:\/\//i.test(raw)) {
262
+ const reference = FRICTION_URI.exec(raw)?.[1];
263
+ return reference === void 0 || reference === "summary" ? void 0 : { kind: "friction", reference, raw };
264
+ }
265
+ if (/^[a-z][a-z0-9+.-]*:\/\//i.test(raw)) {
266
+ return { kind: "uri", uri: raw, raw };
267
+ }
268
+ const message = new RegExp(`^(${sessions})(?:\\.jsonl)?(?:[/#](${ENTRY})(?:#[0-9]+)?)?$`, "i").exec(raw);
269
+ return message === null ? void 0 : sessionRef(message[1], message[2], raw);
270
+ }
271
+ function findSkillSuggestionCitations(text, options = {}) {
272
+ const sessions = sessionPattern(options);
273
+ const tokens = new RegExp(`(?<![\\w/.:#-])(?:[a-z][a-z0-9+.-]*://[^\\s<>\`"'|\\[\\]()]+|${sessions}(?:\\.jsonl)?(?:[/#]${ENTRY}(?:#[0-9]+)?)?(?![\\w/#-]))`, "gi");
274
+ const citations = [];
275
+ for (const match of text.matchAll(tokens)) {
276
+ const raw = match[0].replace(/[.,;:!?]+$/u, "");
277
+ if (new RegExp(`^${UUID}(?:#[0-9]+)?$`, "i").test(raw) && /\b(?:call|result)(?:\s*:\s*|\s+)$/i.test(text.slice(0, match.index)))
278
+ continue;
279
+ const ref = parseToken(raw, sessions);
280
+ if (ref !== void 0)
281
+ citations.push({
282
+ start: match.index,
283
+ end: match.index + raw.length,
284
+ ref
285
+ });
286
+ }
287
+ const sessionIds = new Set(citations.flatMap(({ ref }) => ref.kind === "message" || ref.kind === "session" && ref.raw.indexOf("://") >= 0 ? [ref.sessionId] : []));
288
+ if (sessionIds.size === 1) {
289
+ const sessionId = [...sessionIds][0];
290
+ const relative = new RegExp(`\\b(?:call|result)(?:\\s*:\\s*|\\s+)((?:${UUID}|[0-9a-f]{8,32}|[0-9]+)|${ENTRY}(?=#[0-9]+))(?:#[0-9]+)?(?![\\w/#-])`, "gi");
291
+ for (const match of text.matchAll(relative)) {
292
+ const start = match.index;
293
+ const end = start + match[0].length;
294
+ if (citations.some((item) => start < item.end && end > item.start))
295
+ continue;
296
+ citations.push({
297
+ start,
298
+ end,
299
+ ref: sessionRef(sessionId, match[1], match[0])
300
+ });
301
+ }
302
+ }
303
+ return citations.sort((a, b) => a.start - b.start);
304
+ }
305
+ function skillSuggestionEvidenceKey(item) {
306
+ switch (item.kind) {
307
+ case "message":
308
+ return `message:${item.sessionId}/${item.entryId}`;
309
+ case "session":
310
+ return `session:${item.sessionId}`;
311
+ case "friction":
312
+ return `friction:${item.reference}`;
313
+ case "uri":
314
+ return `uri:${item.uri}`;
315
+ case "text":
316
+ return `text:${item.text.trim()}`;
317
+ }
318
+ }
319
+ function skillSuggestionEvidenceItems(evidence, options = {}) {
320
+ const items = [];
321
+ const keys = /* @__PURE__ */ new Set();
322
+ const visited = /* @__PURE__ */ new WeakSet();
323
+ const add = (item) => {
324
+ const key = skillSuggestionEvidenceKey(item);
325
+ if (keys.has(key))
326
+ return;
327
+ keys.add(key);
328
+ items.push(item);
329
+ };
330
+ const text = (value) => {
331
+ const citations = findSkillSuggestionCitations(value, options);
332
+ if (citations.length === 0) {
333
+ if (value.trim() !== "")
334
+ add({ kind: "text", text: value });
335
+ return;
336
+ }
337
+ let cursor = 0;
338
+ const rest = [];
339
+ for (const citation of citations) {
340
+ rest.push(value.slice(cursor, citation.start));
341
+ cursor = citation.end;
342
+ }
343
+ rest.push(value.slice(cursor));
344
+ const note = rest.join(" ").trim();
345
+ if (citations.every(({ ref }) => ref.kind === "uri") && /[\p{L}\p{N}]/u.test(note)) {
346
+ add({ kind: "text", text: value });
347
+ return;
348
+ }
349
+ for (const citation of citations)
350
+ add(citation.ref);
351
+ if (/[\p{L}\p{N}]/u.test(note.replace(/\b(?:call|result|view|pointer|and)\b/gi, "")))
352
+ add({ kind: "text", text: note.replace(/^[\s|,;`]+|[\s|,;`]+$/g, "") });
353
+ };
354
+ const visit = (value, depth) => {
355
+ if (value === null || value === void 0)
356
+ return;
357
+ if (typeof value === "string")
358
+ return text(value);
359
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint")
360
+ return text(String(value));
361
+ if (typeof value !== "object" || visited.has(value))
362
+ return;
363
+ visited.add(value);
364
+ if (depth >= 32) {
365
+ add({ kind: "text", text: "[evidence nested too deeply]" });
366
+ return;
367
+ }
368
+ if (Array.isArray(value)) {
369
+ for (const entry of value)
370
+ visit(entry, depth + 1);
371
+ return;
372
+ }
373
+ const object = value;
374
+ const sessionId = object.sessionId;
375
+ const entryId = object.entryId ?? object.messageId;
376
+ if (typeof sessionId === "string" && ENTRY_ID.test(sessionId) && (entryId === void 0 || typeof entryId === "string" && ENTRY_ID.test(entryId))) {
377
+ add(sessionRef(sessionId, entryId, `sessions://${sessionId}${entryId === void 0 ? "" : `/${entryId}`}`));
378
+ return;
379
+ }
380
+ if (object.kind === "text" && typeof object.text === "string") {
381
+ text(object.text);
382
+ return;
383
+ }
384
+ if (object.kind === "friction" && typeof object.reference === "string") {
385
+ text(`friction://${object.reference}`);
386
+ return;
387
+ }
388
+ if (object.kind === "uri" && typeof object.uri === "string") {
389
+ text(object.uri);
390
+ return;
391
+ }
392
+ for (const entry of Object.values(object))
393
+ visit(entry, depth + 1);
394
+ };
395
+ visit(evidence, 0);
396
+ return items;
397
+ }
136
398
  export {
137
399
  ATTACHMENTS_CUSTOM_TYPE,
138
400
  NON_ACTIVITY_TOOL_NAMES,
@@ -145,7 +407,11 @@ export {
145
407
  branchEntryIds,
146
408
  customEntriesFromEntries,
147
409
  matchesWorkBlock,
410
+ precedingPersonMessages,
148
411
  readProducedResourceDeclarations,
412
+ skillSuggestionEvidenceItems,
413
+ turnMessageOrigin,
414
+ turnPacket,
149
415
  turnSegments,
150
416
  workBlockCoverage,
151
417
  workBlockKey
@@ -263,6 +263,8 @@ function isLoneCapture(pattern) {
263
263
  return pattern.length === 1 && pattern[0].capture !== void 0 && pattern[0].rest !== true;
264
264
  }
265
265
  function matchParts(pattern, value, separator, captures, foldLiterals = false) {
266
+ if (pattern.length === 0)
267
+ return value === "";
266
268
  const parts = separator === void 0 ? [value] : value.split(separator);
267
269
  let partIndex = 0;
268
270
  for (let i = 0; i < pattern.length; i += 1) {
@@ -31,8 +31,8 @@ export declare const WhiteboardEntryInfo: z.ZodObject<{
31
31
  authorSessionId: z.ZodNullable<z.ZodString>;
32
32
  }, z.core.$strict>>;
33
33
  state: z.ZodEnum<{
34
- unavailable: "unavailable";
35
34
  available: "available";
35
+ unavailable: "unavailable";
36
36
  "unsupported-version": "unsupported-version";
37
37
  invalid: "invalid";
38
38
  }>;
@@ -53,8 +53,8 @@ export declare const WhiteboardEntryInspection: z.ZodObject<{
53
53
  authorSessionId: z.ZodNullable<z.ZodString>;
54
54
  }, z.core.$strict>>;
55
55
  state: z.ZodEnum<{
56
- unavailable: "unavailable";
57
56
  available: "available";
57
+ unavailable: "unavailable";
58
58
  "unsupported-version": "unsupported-version";
59
59
  invalid: "invalid";
60
60
  }>;
@@ -72,6 +72,9 @@ export declare const WhiteboardTypeInfo: z.ZodObject<{
72
72
  displayName: z.ZodString;
73
73
  schemaVersion: z.ZodNumber;
74
74
  available: z.ZodBoolean;
75
+ reference: z.ZodOptional<z.ZodObject<{
76
+ uriTemplate: z.ZodString;
77
+ }, z.core.$strict>>;
75
78
  }, z.core.$strict>;
76
79
 
77
80
  export declare type WhiteboardTypeInfo = Readonly<z.infer<typeof WhiteboardTypeInfo>>;
@@ -122,6 +122,9 @@ var { NonEmptyString, PluginId, PluginNamespace, LocalContributionId, GlobalCont
122
122
  var canonicalCommonSchemas = createCommonSchemas(true);
123
123
 
124
124
  // packages/plugin-protocol/dist/whiteboard.js
125
+ var WhiteboardEntryReference = z4.strictObject({
126
+ uriTemplate: z4.string().regex(/^[a-z][a-z0-9+.-]*:\/\/[^\s?#{}]+\/\{name\}$/u)
127
+ });
125
128
  var WhiteboardValue = JsonValue;
126
129
  var WhiteboardEntryEnvelope = z4.strictObject({
127
130
  id: NonEmptyString,
@@ -160,7 +163,8 @@ var WhiteboardTypeInfo = z4.strictObject({
160
163
  typeId: GlobalContributionId,
161
164
  displayName: NonEmptyString,
162
165
  schemaVersion: z4.number().int().positive(),
163
- available: z4.boolean()
166
+ available: z4.boolean(),
167
+ reference: WhiteboardEntryReference.optional()
164
168
  });
165
169
  export {
166
170
  JsonValue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yaklabs-ai/plugin-sdk",
3
- "version": "0.52.1",
3
+ "version": "0.54.0",
4
4
  "description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
5
5
  "author": "YakLabs",
6
6
  "type": "module",
@@ -33,6 +33,10 @@
33
33
  "types": "./dist/fs.d.ts",
34
34
  "default": "./dist/fs.js"
35
35
  },
36
+ "./text-diff": {
37
+ "types": "./dist/text-diff.d.ts",
38
+ "default": "./dist/text-diff.js"
39
+ },
36
40
  "./kay-agent/testing": {
37
41
  "types": "./dist/kay-agent-testing.d.ts",
38
42
  "default": "./dist/kay-agent-testing.js"