@yaklabs-ai/plugin-sdk 0.15.1 → 0.15.2

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 CHANGED
@@ -13,7 +13,7 @@ it under the name your plugin code actually imports:
13
13
  ```json
14
14
  {
15
15
  "dependencies": {
16
- "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.15.1"
16
+ "@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.15.2"
17
17
  }
18
18
  }
19
19
  ```
@@ -62,7 +62,7 @@ Every tool the entrypoint registers is declared in the manifest too:
62
62
  "description": "Greets people by name.",
63
63
  "version": "0.1.0",
64
64
  "namespace": "widgets",
65
- "compatibility": { "sdk": "^0.15.1" },
65
+ "compatibility": { "sdk": "^0.15.2" },
66
66
  "targets": {
67
67
  "kay": {
68
68
  "agent": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
3
  "package": "@yaklabs-ai/plugin-sdk",
4
- "version": "0.15.1",
4
+ "version": "0.15.2",
5
5
  "target": "npm",
6
6
  "firstPartyLicense": "MIT",
7
7
  "bundled": [
@@ -69,6 +69,41 @@ declare interface AgentConversationSourceNote {
69
69
  readonly rowKey: string;
70
70
  }
71
71
 
72
+ /**
73
+ * Build the conversation source stream in canonical block order. Callers classify attempts and
74
+ * custom messages with their presentation policy; only this traversal establishes boundaries.
75
+ * Structural inputs keep the protocol independent of the renderer and transcript implementation.
76
+ */
77
+ export declare function buildAgentConversationStream<TAttempt extends {
78
+ readonly id: string;
79
+ }, TMessage extends {
80
+ readonly id: string;
81
+ }, TRef>(blocks: readonly CanonicalBlock<TAttempt, TMessage>[], options: {
82
+ readonly rowKey: string;
83
+ readonly attempt: (attempt: TAttempt) => AgentConversationSourceItem<TRef> | undefined;
84
+ readonly message: (message: TMessage, blockId: string) => AgentConversationSourceItem<TRef> | undefined;
85
+ readonly text?: (block: TextBlock) => "note" | "neutral" | "boundary";
86
+ readonly owned?: ReadonlySet<string>;
87
+ readonly neutral?: (id: string, position: number) => void;
88
+ }): readonly AgentConversationSourceItem<TRef>[];
89
+
90
+ declare type CanonicalBlock<TAttempt, TMessage> = TextBlock | {
91
+ readonly kind: "work_episode";
92
+ readonly waves: readonly {
93
+ readonly attempts: readonly TAttempt[];
94
+ }[];
95
+ } | {
96
+ readonly kind: "tool_surface";
97
+ readonly attempt: TAttempt;
98
+ } | {
99
+ readonly kind: "custom_message";
100
+ readonly id: string;
101
+ readonly message: TMessage;
102
+ } | {
103
+ readonly kind: "steer_message" | "unknown_activity";
104
+ readonly id: string;
105
+ };
106
+
72
107
  export declare function groupAgentConversationStream<TRef>(stream: readonly AgentConversationSourceItem<TRef>[]): readonly AgentConversationRun<TRef>[];
73
108
 
74
109
  export declare function immediateFollowingAgentConversationWave<TAttempt extends {
@@ -90,4 +125,10 @@ export declare function receivedConversation(customType: string | undefined, det
90
125
  /** Terminal daemon-run outcomes shared by stored records and conversation results. */
91
126
  declare type RunSettlementOutcome = "completed" | "interrupted" | "cancelled" | "failed";
92
127
 
128
+ declare type TextBlock = {
129
+ readonly kind: "narration" | "provisional_response" | "final_answer";
130
+ readonly id: string;
131
+ readonly text: string;
132
+ };
133
+
93
134
  export { }
@@ -1,3 +1,71 @@
1
+ // packages/plugin-protocol/dist/agent-conversation-stream.js
2
+ function buildAgentConversationStream(blocks, options) {
3
+ const stream = [];
4
+ const barBoundaryId = `${options.rowKey}:bar`;
5
+ const ownedByBar = (id) => {
6
+ if (options.owned?.has(id) !== true)
7
+ return false;
8
+ const last = stream.at(-1);
9
+ if (last?.kind !== "boundary" || last.id !== barBoundaryId)
10
+ stream.push({ kind: "boundary", id: barBoundaryId, reason: "surface" });
11
+ return true;
12
+ };
13
+ const pushAttempt = (attempt) => {
14
+ if (ownedByBar(attempt.id))
15
+ return;
16
+ const item = options.attempt(attempt);
17
+ if (item !== void 0)
18
+ stream.push(item);
19
+ };
20
+ for (const block of blocks) {
21
+ switch (block.kind) {
22
+ case "narration":
23
+ case "provisional_response":
24
+ case "final_answer": {
25
+ if (ownedByBar(block.id))
26
+ break;
27
+ const kind = options.text?.(block) ?? (block.text.trim() === "" ? "neutral" : "boundary");
28
+ if (kind === "neutral")
29
+ options.neutral?.(block.id, stream.length - 0.5);
30
+ else if (kind === "note")
31
+ stream.push({ kind: "note", id: block.id, rowKey: options.rowKey });
32
+ else
33
+ stream.push({
34
+ kind: "boundary",
35
+ id: block.id,
36
+ reason: "assistant_text"
37
+ });
38
+ break;
39
+ }
40
+ case "work_episode":
41
+ for (const wave of block.waves)
42
+ for (const attempt of wave.attempts)
43
+ pushAttempt(attempt);
44
+ break;
45
+ case "tool_surface":
46
+ pushAttempt(block.attempt);
47
+ break;
48
+ case "custom_message": {
49
+ if (ownedByBar(block.message.id))
50
+ break;
51
+ const item = options.message(block.message, block.id);
52
+ if (item !== void 0)
53
+ stream.push(item);
54
+ else
55
+ options.neutral?.(block.message.id, stream.length - 0.5);
56
+ break;
57
+ }
58
+ case "steer_message":
59
+ stream.push({ kind: "boundary", id: block.id, reason: "user" });
60
+ break;
61
+ case "unknown_activity":
62
+ stream.push({ kind: "boundary", id: block.id, reason: "other" });
63
+ break;
64
+ }
65
+ }
66
+ return stream;
67
+ }
68
+
1
69
  // packages/plugin-protocol/dist/agent-conversation.js
2
70
  function workId(work) {
3
71
  return work.kind === "activity" ? work.attemptId : work.id;
@@ -167,6 +235,7 @@ function subagentProvenanceOf(record) {
167
235
  export {
168
236
  admittedSendSessionId,
169
237
  admittedSpawnSessionId,
238
+ buildAgentConversationStream,
170
239
  groupAgentConversationStream,
171
240
  immediateFollowingAgentConversationWave,
172
241
  isFoldedAgentConversationRun,