@yaklabs-ai/plugin-sdk 0.15.1 → 0.15.3
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/README.md +2 -2
- package/THIRD-PARTY-INVENTORY.json +1 -1
- package/dist/agent-conversation.d.ts +41 -0
- package/dist/agent-conversation.js +69 -0
- package/dist/canonical-transcript.d.ts +8844 -0
- package/dist/canonical-transcript.js +3842 -0
- package/dist/kay-app-session-summary.d.ts +48 -14
- package/dist/kay-app.d.ts +213 -47
- package/dist/kay-app.js +153 -0
- package/dist/phase-shift.d.ts +3 -4
- package/dist/phase-shift.js +1 -1
- package/dist/transcript.d.ts +5 -6
- package/dist/transcript.js +1 -1
- package/package.json +5 -1
package/dist/kay-app.js
CHANGED
|
@@ -449,6 +449,154 @@ var KAY_APP_AUTOMATION_CONDITION_KINDS = [
|
|
|
449
449
|
"delayed-occurrence"
|
|
450
450
|
];
|
|
451
451
|
|
|
452
|
+
// packages/plugin-sdk/dist/kay-app/poller.js
|
|
453
|
+
function accountCursors(state) {
|
|
454
|
+
if (state === void 0)
|
|
455
|
+
return [];
|
|
456
|
+
if (state === null || typeof state !== "object" || Array.isArray(state) || !Array.isArray(state.accounts)) {
|
|
457
|
+
throw new Error("Invalid Poller state");
|
|
458
|
+
}
|
|
459
|
+
return state.accounts.map((entry) => {
|
|
460
|
+
if (entry === null || typeof entry !== "object" || Array.isArray(entry) || typeof entry.schemeId !== "string" || typeof entry.accountId !== "string" || !("cursor" in entry)) {
|
|
461
|
+
throw new Error("Invalid Poller account cursor");
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
schemeId: entry.schemeId,
|
|
465
|
+
accountId: entry.accountId,
|
|
466
|
+
cursor: entry.cursor
|
|
467
|
+
};
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
function ordinal(left, right) {
|
|
471
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
472
|
+
}
|
|
473
|
+
function plainText(value, max) {
|
|
474
|
+
let text = "";
|
|
475
|
+
for (const character of value) {
|
|
476
|
+
const code = character.charCodeAt(0);
|
|
477
|
+
const printable = code < 32 || code === 127 ? " " : character;
|
|
478
|
+
if (text.length + printable.length > max)
|
|
479
|
+
break;
|
|
480
|
+
text += printable;
|
|
481
|
+
}
|
|
482
|
+
return text;
|
|
483
|
+
}
|
|
484
|
+
function definePoller(app, localId, options) {
|
|
485
|
+
const { workflows, auth, events } = app;
|
|
486
|
+
if (!workflows)
|
|
487
|
+
throw new Error("Poller requires workflows");
|
|
488
|
+
if (!Number.isSafeInteger(options.every) || options.every <= 0) {
|
|
489
|
+
throw new TypeError("Poller interval must be a positive integer in milliseconds");
|
|
490
|
+
}
|
|
491
|
+
workflows.define(localId, {
|
|
492
|
+
name: options.name,
|
|
493
|
+
description: options.description,
|
|
494
|
+
trigger: {
|
|
495
|
+
kind: "time",
|
|
496
|
+
schedule: { kind: "every", intervalMs: options.every, anchorAtMs: 0 }
|
|
497
|
+
},
|
|
498
|
+
async run(ctx) {
|
|
499
|
+
if (!auth)
|
|
500
|
+
throw new Error("Poller requires account listing");
|
|
501
|
+
const previous = accountCursors(ctx.state);
|
|
502
|
+
const accounts = await ctx.runStep(async () => {
|
|
503
|
+
const listed = await auth.listAccounts({
|
|
504
|
+
serviceId: options.serviceId,
|
|
505
|
+
...options.schemeId === void 0 ? {} : { schemeId: options.schemeId }
|
|
506
|
+
});
|
|
507
|
+
return [...listed].sort((a, b) => ordinal(a.schemeId, b.schemeId) || ordinal(a.accountId, b.accountId));
|
|
508
|
+
}, { name: "list-poller-accounts" });
|
|
509
|
+
const next = [];
|
|
510
|
+
const details = [];
|
|
511
|
+
let published = 0;
|
|
512
|
+
let initialized = 0;
|
|
513
|
+
let skipped = 0;
|
|
514
|
+
let failed = 0;
|
|
515
|
+
for (const account of accounts) {
|
|
516
|
+
const saved = previous.find((entry) => entry.schemeId === account.schemeId && entry.accountId === account.accountId);
|
|
517
|
+
const outcome = await ctx.runStep(async () => {
|
|
518
|
+
if (account.status === "needs_reauth" || account.status === "refresh_failed" || account.status === "revoked") {
|
|
519
|
+
return {
|
|
520
|
+
status: "skipped",
|
|
521
|
+
summary: `Sign-in required (${account.status})`
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
let credential;
|
|
525
|
+
try {
|
|
526
|
+
credential = await options.resolveCredential(account, ctx.runId);
|
|
527
|
+
} catch {
|
|
528
|
+
throw new Error("Poller credential resolution failed");
|
|
529
|
+
}
|
|
530
|
+
if (credential.status !== "resolved") {
|
|
531
|
+
return {
|
|
532
|
+
status: "skipped",
|
|
533
|
+
summary: credential.status === "requires-auth" ? "Sign-in or required scope missing" : "Credential missing"
|
|
534
|
+
};
|
|
535
|
+
}
|
|
536
|
+
try {
|
|
537
|
+
const result = await options.poll({
|
|
538
|
+
account,
|
|
539
|
+
cursor: structuredClone(saved?.cursor),
|
|
540
|
+
credential,
|
|
541
|
+
runId: ctx.runId
|
|
542
|
+
});
|
|
543
|
+
return {
|
|
544
|
+
status: "polled",
|
|
545
|
+
result: {
|
|
546
|
+
cursor: result.cursor,
|
|
547
|
+
...saved === void 0 || result.events === void 0 ? {} : { events: result.events },
|
|
548
|
+
...result.summary === void 0 ? {} : { summary: plainText(result.summary, 600) }
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
} catch {
|
|
552
|
+
return {
|
|
553
|
+
status: "failed",
|
|
554
|
+
summary: "Provider poll failed; cursor retained"
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
}, { name: "poll-account" });
|
|
558
|
+
if (outcome.status !== "polled") {
|
|
559
|
+
if (saved !== void 0)
|
|
560
|
+
next.push(saved);
|
|
561
|
+
if (outcome.status === "skipped")
|
|
562
|
+
skipped++;
|
|
563
|
+
else
|
|
564
|
+
failed++;
|
|
565
|
+
details.push(`${account.schemeId}/${account.accountId}: ${outcome.summary}`);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
await ctx.runStep(async () => {
|
|
569
|
+
for (const event of outcome.result.events ?? []) {
|
|
570
|
+
events.publish(event.localId, {
|
|
571
|
+
...event.input,
|
|
572
|
+
source: { poller: localId, runId: ctx.runId }
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
return null;
|
|
576
|
+
}, { name: "publish-poller-events" });
|
|
577
|
+
published += outcome.result.events?.length ?? 0;
|
|
578
|
+
if (saved === void 0)
|
|
579
|
+
initialized++;
|
|
580
|
+
next.push({
|
|
581
|
+
schemeId: account.schemeId,
|
|
582
|
+
accountId: account.accountId,
|
|
583
|
+
cursor: outcome.result.cursor
|
|
584
|
+
});
|
|
585
|
+
if (outcome.result.summary)
|
|
586
|
+
details.push(`${account.schemeId}/${account.accountId}: ${outcome.result.summary}`);
|
|
587
|
+
}
|
|
588
|
+
return {
|
|
589
|
+
state: { accounts: next },
|
|
590
|
+
summary: {
|
|
591
|
+
headline: plainText(`${published} events; ${initialized} initialized; ${skipped} skipped; ${failed} failed`, 100),
|
|
592
|
+
...details.length === 0 ? {} : { details: plainText(details.join("; "), 600) },
|
|
593
|
+
author: "automation"
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
452
600
|
// packages/plugin-sdk/dist/kay-app/skills.js
|
|
453
601
|
function createUnavailableSkills(message) {
|
|
454
602
|
const unavailable = {
|
|
@@ -506,6 +654,9 @@ function createUnavailableUsage(message) {
|
|
|
506
654
|
}
|
|
507
655
|
|
|
508
656
|
// packages/plugin-sdk/dist/kay-app/workflows.js
|
|
657
|
+
function failedRunCause(outcome) {
|
|
658
|
+
return outcome.kind === "ran" && outcome.state === "failed" && outcome.failureRef !== void 0 ? { cause: { failureRef: outcome.failureRef } } : {};
|
|
659
|
+
}
|
|
509
660
|
var KayAppWorkflowFailure = class extends Error {
|
|
510
661
|
summary;
|
|
511
662
|
constructor(summary, options) {
|
|
@@ -538,6 +689,8 @@ export {
|
|
|
538
689
|
createUnavailableSkills,
|
|
539
690
|
createUnavailableTools,
|
|
540
691
|
createUnavailableUsage,
|
|
692
|
+
definePoller,
|
|
693
|
+
failedRunCause,
|
|
541
694
|
invalidObservation,
|
|
542
695
|
isRetryable,
|
|
543
696
|
parseLineSelector,
|
package/dist/phase-shift.d.ts
CHANGED
|
@@ -114,14 +114,13 @@ declare interface TranscriptSourceEntryLike extends TranscriptTreeEntryLike {
|
|
|
114
114
|
|
|
115
115
|
/**
|
|
116
116
|
* A session entry as {@link branchEntryIds} reads it: the fields above plus the
|
|
117
|
-
*
|
|
118
|
-
* never reads one, and
|
|
119
|
-
*
|
|
117
|
+
* parent link the walk follows to find the active branch. No timestamp: the walk
|
|
118
|
+
* never reads one, and callers hold entries whose timestamp is epoch
|
|
119
|
+
* milliseconds or an ISO string, so requiring either shape here would force one
|
|
120
120
|
* class of caller to convert entries it only wants walked.
|
|
121
121
|
*/
|
|
122
122
|
declare interface TranscriptTreeEntryLike extends TranscriptEntryLike {
|
|
123
123
|
readonly parentId?: string | null;
|
|
124
|
-
readonly targetId?: string | null;
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
export { }
|
package/dist/phase-shift.js
CHANGED
|
@@ -14,7 +14,7 @@ function branchEntryIds(entries) {
|
|
|
14
14
|
return EMPTY_BRANCH_IDS;
|
|
15
15
|
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
16
16
|
const onBranch = /* @__PURE__ */ new Set();
|
|
17
|
-
let cursor = last.
|
|
17
|
+
let cursor = last.id;
|
|
18
18
|
while (cursor !== null && !onBranch.has(cursor)) {
|
|
19
19
|
onBranch.add(cursor);
|
|
20
20
|
cursor = byId.get(cursor)?.parentId ?? null;
|
package/dist/transcript.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import { z } from 'zod';
|
|
|
3
3
|
export declare const ATTACHMENTS_CUSTOM_TYPE = "attachments";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* The ids on a session's active branch: the
|
|
7
|
-
* the
|
|
6
|
+
* The ids on a session's active branch: the parent chain walked from the tip,
|
|
7
|
+
* the last entry. Empty for an empty log.
|
|
8
8
|
*
|
|
9
9
|
* One walk shared by every reader of "is this entry still live", so a rewind
|
|
10
10
|
* means the same thing to every projection that calls it. Self-guarding
|
|
@@ -106,14 +106,13 @@ export declare interface TranscriptSourceEntryLike extends TranscriptTreeEntryLi
|
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* A session entry as {@link branchEntryIds} reads it: the fields above plus the
|
|
109
|
-
*
|
|
110
|
-
* never reads one, and
|
|
111
|
-
*
|
|
109
|
+
* parent link the walk follows to find the active branch. No timestamp: the walk
|
|
110
|
+
* never reads one, and callers hold entries whose timestamp is epoch
|
|
111
|
+
* milliseconds or an ISO string, so requiring either shape here would force one
|
|
112
112
|
* class of caller to convert entries it only wants walked.
|
|
113
113
|
*/
|
|
114
114
|
declare interface TranscriptTreeEntryLike extends TranscriptEntryLike {
|
|
115
115
|
readonly parentId?: string | null;
|
|
116
|
-
readonly targetId?: string | null;
|
|
117
116
|
}
|
|
118
117
|
|
|
119
118
|
/**
|
package/dist/transcript.js
CHANGED
|
@@ -27,7 +27,7 @@ function branchEntryIds(entries) {
|
|
|
27
27
|
return EMPTY_BRANCH_IDS;
|
|
28
28
|
const byId = new Map(entries.map((entry) => [entry.id, entry]));
|
|
29
29
|
const onBranch = /* @__PURE__ */ new Set();
|
|
30
|
-
let cursor = last.
|
|
30
|
+
let cursor = last.id;
|
|
31
31
|
while (cursor !== null && !onBranch.has(cursor)) {
|
|
32
32
|
onBranch.add(cursor);
|
|
33
33
|
cursor = byId.get(cursor)?.parentId ?? null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yaklabs-ai/plugin-sdk",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.3",
|
|
4
4
|
"description": "The Kay plugin SDK — types and helpers for authoring a Kay directory plugin.",
|
|
5
5
|
"author": "YakLabs",
|
|
6
6
|
"type": "module",
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
"types": "./dist/transcript.d.ts",
|
|
46
46
|
"default": "./dist/transcript.js"
|
|
47
47
|
},
|
|
48
|
+
"./canonical-transcript": {
|
|
49
|
+
"types": "./dist/canonical-transcript.d.ts",
|
|
50
|
+
"default": "./dist/canonical-transcript.js"
|
|
51
|
+
},
|
|
48
52
|
"./time": {
|
|
49
53
|
"types": "./dist/time.d.ts",
|
|
50
54
|
"default": "./dist/time.js"
|