@yaklabs-ai/plugin-sdk 0.13.5 → 0.13.7
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 +19 -8
- package/THIRD-PARTY-INVENTORY.json +8 -1
- package/dist/agent-conversation.d.ts +93 -0
- package/dist/agent-conversation.js +174 -0
- package/dist/app-data.d.ts +7 -0
- package/dist/app-data.js +9 -0
- package/dist/disclosure.d.ts +5 -7
- package/dist/kay-agent-testing.d.ts +30 -7
- package/dist/kay-agent-testing.js +37 -0
- package/dist/kay-agent.d.ts +43 -8
- package/dist/kay-agent.js +197 -2
- package/dist/kay-app.d.ts +60 -55
- package/dist/kay-app.js +66 -50
- package/dist/time.d.ts +157 -0
- package/dist/time.js +37 -0
- package/dist/transcript-review.d.ts +310 -0
- package/dist/transcript-review.js +680 -0
- package/dist/transcript.d.ts +109 -0
- package/dist/transcript.js +83 -1
- package/dist/vendored-mcp.d.ts +1217 -0
- package/dist/vendored-mcp.js +471 -0
- package/package.json +23 -2
- package/skills/directory-plugin-authoring/SKILL.md +9 -8
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.13.
|
|
16
|
+
"@bonsai/plugin-sdk": "npm:@yaklabs-ai/plugin-sdk@^0.13.7"
|
|
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.13.
|
|
65
|
+
"compatibility": { "sdk": "^0.13.7" },
|
|
66
66
|
"targets": {
|
|
67
67
|
"kay": {
|
|
68
68
|
"agent": {
|
|
@@ -116,12 +116,23 @@ naming both versions, instead of loading it and finding no `activate`.
|
|
|
116
116
|
|
|
117
117
|
## Entrypoints
|
|
118
118
|
|
|
119
|
-
| Import
|
|
120
|
-
|
|
|
121
|
-
| `@bonsai/plugin-sdk/kay-agent`
|
|
122
|
-
| `@bonsai/plugin-sdk/kay-app`
|
|
123
|
-
| `@bonsai/plugin-sdk/kay-agent/testing`
|
|
124
|
-
| `@bonsai/plugin-sdk/disclosure`
|
|
119
|
+
| Import | What it gives you |
|
|
120
|
+
| --------------------------------------- | ------------------------------------------------------------------------------- |
|
|
121
|
+
| `@bonsai/plugin-sdk/kay-agent` | Tools, URI modules, search providers, auth — the per-session agent surface |
|
|
122
|
+
| `@bonsai/plugin-sdk/kay-app` | App-lifetime surface: storage, endpoints, app-scoped URI modules |
|
|
123
|
+
| `@bonsai/plugin-sdk/kay-agent/testing` | `invokeToolForTest`, `fauxAuthContext` — for your own `node --test` runs |
|
|
124
|
+
| `@bonsai/plugin-sdk/disclosure` | The conformance audit Bonsai gates your plugin with — run it before you ship |
|
|
125
|
+
| `@bonsai/plugin-sdk/time` | `Temporal` (Bonsai's own instance) and the time-zone helpers, from 0.13.6 |
|
|
126
|
+
| `@bonsai/plugin-sdk/transcript` | The active-branch walk; the turn walk and run records from 0.13.6 |
|
|
127
|
+
| `@bonsai/plugin-sdk/transcript-review` | The review fold: a session's spans, tool-call attempts and records, from 0.13.7 |
|
|
128
|
+
| `@bonsai/plugin-sdk/agent-conversation` | How a session's agent-to-agent traffic groups into conversations, from 0.13.7 |
|
|
129
|
+
| `@bonsai/plugin-sdk/app-data` | The app-data size caps, on an entry with no other import, from 0.13.7 |
|
|
130
|
+
| `@bonsai/plugin-sdk/vendored-mcp` | The kit for a plugin built on a vendor's hosted MCP server, from 0.13.7 |
|
|
131
|
+
|
|
132
|
+
A plugin that imports a subpath declares at least the version its row names (`^0.13.7` for the
|
|
133
|
+
last four). `vendored-mcp` builds the plugin's URI module (its link cards and help); hosting the
|
|
134
|
+
vendor's MCP server itself is a separate host decision, and Bonsai currently makes it only for
|
|
135
|
+
its own bundled plugins.
|
|
125
136
|
|
|
126
137
|
`kay-agent/host` is intentionally not published; it is Bonsai's own loading
|
|
127
138
|
machinery, not an authoring API.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"package": "@yaklabs-ai/plugin-sdk",
|
|
4
|
-
"version": "0.13.
|
|
4
|
+
"version": "0.13.7",
|
|
5
5
|
"target": "npm",
|
|
6
6
|
"firstPartyLicense": "MIT",
|
|
7
7
|
"bundled": [
|
|
@@ -50,6 +50,13 @@
|
|
|
50
50
|
"source": "https://github.com/eemeli/yaml",
|
|
51
51
|
"note": "Installed as a consumer dependency; it is not bundled into the staged artifacts.",
|
|
52
52
|
"versionRange": "^2.9.0"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "@js-temporal/polyfill",
|
|
56
|
+
"license": "ISC",
|
|
57
|
+
"source": "https://github.com/js-temporal/temporal-polyfill",
|
|
58
|
+
"note": "Installed as a consumer dependency; it is not bundled into the staged artifacts.",
|
|
59
|
+
"versionRange": "0.5.1"
|
|
53
60
|
}
|
|
54
61
|
]
|
|
55
62
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** The admitted inbox receipt, not a target guessed from tool arguments or prose. */
|
|
2
|
+
export declare function admittedSendSessionId(details: unknown): string | undefined;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The admitted-spawn stamp, or `undefined` when nothing was started.
|
|
6
|
+
*
|
|
7
|
+
* Two generations of stamp exist in durable transcripts and both must parse
|
|
8
|
+
* forever: version 2 (the messaging contract) writes
|
|
9
|
+
* `{ version: 2, sessionId, displayName, backgroundTaskId }` and exists only
|
|
10
|
+
* for admitted spawns (rejections are tool errors and stamp nothing);
|
|
11
|
+
* version 1 wrote `{ version: 1, accepted, childSessionId, label, … }`, where
|
|
12
|
+
* `accepted: false` carries no child session.
|
|
13
|
+
*/
|
|
14
|
+
export declare function admittedSpawnSessionId(details: unknown): string | undefined;
|
|
15
|
+
|
|
16
|
+
export declare type AgentConversationBoundaryReason = "assistant_text" | "user" | "spawn" | "custom" | "surface" | "other";
|
|
17
|
+
|
|
18
|
+
export declare interface AgentConversationPeerGroup<TRef = unknown> {
|
|
19
|
+
readonly peerId: string;
|
|
20
|
+
readonly firstItemId: string;
|
|
21
|
+
readonly items: readonly AgentConversationSourceConversation<TRef>[];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export declare type AgentConversationResultStatus = RunSettlementOutcome;
|
|
25
|
+
|
|
26
|
+
export declare interface AgentConversationRun<TRef = unknown> {
|
|
27
|
+
/** The first conversation item's id: stable while the run grows. */
|
|
28
|
+
readonly id: string;
|
|
29
|
+
/** Every conversation item, in canonical source order. */
|
|
30
|
+
readonly items: readonly AgentConversationSourceConversation<TRef>[];
|
|
31
|
+
/** Peers in first-appearance order. */
|
|
32
|
+
readonly peers: readonly AgentConversationPeerGroup<TRef>[];
|
|
33
|
+
/** Work strictly between two of this run's conversation items. */
|
|
34
|
+
readonly work: readonly AgentConversationRunWork[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Work a run can own: a tool attempt or a folded narration, in source order. */
|
|
38
|
+
declare type AgentConversationRunWork = AgentConversationSourceActivity | AgentConversationSourceNote;
|
|
39
|
+
|
|
40
|
+
declare interface AgentConversationSourceActivity {
|
|
41
|
+
readonly kind: "activity";
|
|
42
|
+
readonly attemptId: string;
|
|
43
|
+
readonly rowKey: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
declare interface AgentConversationSourceBoundary {
|
|
47
|
+
readonly kind: "boundary";
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly reason: AgentConversationBoundaryReason;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare interface AgentConversationSourceConversation<TRef = unknown> {
|
|
53
|
+
readonly kind: "conversation";
|
|
54
|
+
/** Source identity: a tool attempt id (outbound) or message item id. */
|
|
55
|
+
readonly id: string;
|
|
56
|
+
readonly peerId: string;
|
|
57
|
+
readonly direction: "inbound" | "outbound" | "result";
|
|
58
|
+
readonly status?: AgentConversationResultStatus;
|
|
59
|
+
readonly rowKey: string;
|
|
60
|
+
readonly ref: TRef;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export declare type AgentConversationSourceItem<TRef = unknown> = AgentConversationSourceConversation<TRef> | AgentConversationRunWork | AgentConversationSourceBoundary;
|
|
64
|
+
|
|
65
|
+
/** Narration that paints only inside a folded "Did work" rail. */
|
|
66
|
+
declare interface AgentConversationSourceNote {
|
|
67
|
+
readonly kind: "note";
|
|
68
|
+
readonly id: string;
|
|
69
|
+
readonly rowKey: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export declare function groupAgentConversationStream<TRef>(stream: readonly AgentConversationSourceItem<TRef>[]): readonly AgentConversationRun<TRef>[];
|
|
73
|
+
|
|
74
|
+
export declare function immediateFollowingAgentConversationWave<TAttempt extends {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
}>(run: AgentConversationRun<unknown>, waves: readonly (readonly TAttempt[])[], stream: readonly AgentConversationSourceItem[], order: ReadonlyMap<string, number>, sources: ReadonlyMap<string, {
|
|
77
|
+
readonly rowKey: string;
|
|
78
|
+
}>, claimedWaveAttemptIds: ReadonlySet<string>): readonly TAttempt[] | undefined;
|
|
79
|
+
|
|
80
|
+
/** Whether a run changes today's rendering: a pair (2+ items with one peer) or 2+ peers. */
|
|
81
|
+
export declare function isFoldedAgentConversationRun(run: AgentConversationRun<unknown>): boolean;
|
|
82
|
+
|
|
83
|
+
/** The received metadata that both work ownership and the conversation renderer recognize. */
|
|
84
|
+
export declare function receivedConversation(customType: string | undefined, details: unknown): {
|
|
85
|
+
readonly peerId: string;
|
|
86
|
+
readonly direction: "inbound" | "result";
|
|
87
|
+
readonly status?: AgentConversationResultStatus;
|
|
88
|
+
} | undefined;
|
|
89
|
+
|
|
90
|
+
/** Terminal daemon-run outcomes shared by stored records and conversation results. */
|
|
91
|
+
declare type RunSettlementOutcome = "completed" | "interrupted" | "cancelled" | "failed";
|
|
92
|
+
|
|
93
|
+
export { }
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// packages/plugin-protocol/dist/agent-conversation.js
|
|
2
|
+
function workId(work) {
|
|
3
|
+
return work.kind === "activity" ? work.attemptId : work.id;
|
|
4
|
+
}
|
|
5
|
+
function freezeRun(run) {
|
|
6
|
+
const peers = /* @__PURE__ */ new Map();
|
|
7
|
+
for (const item of run.items) {
|
|
8
|
+
const items = peers.get(item.peerId);
|
|
9
|
+
if (items === void 0)
|
|
10
|
+
peers.set(item.peerId, [item]);
|
|
11
|
+
else
|
|
12
|
+
items.push(item);
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
id: run.items[0].id,
|
|
16
|
+
items: run.items,
|
|
17
|
+
peers: [...peers].map(([peerId, items]) => ({
|
|
18
|
+
peerId,
|
|
19
|
+
firstItemId: items[0].id,
|
|
20
|
+
items
|
|
21
|
+
})),
|
|
22
|
+
work: run.work
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function groupAgentConversationStream(stream) {
|
|
26
|
+
const runs = [];
|
|
27
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
28
|
+
let active;
|
|
29
|
+
let queued = [];
|
|
30
|
+
const close = () => {
|
|
31
|
+
if (active !== void 0)
|
|
32
|
+
runs.push(freezeRun(active));
|
|
33
|
+
active = void 0;
|
|
34
|
+
queued = [];
|
|
35
|
+
};
|
|
36
|
+
for (const item of stream) {
|
|
37
|
+
if (item.kind === "boundary") {
|
|
38
|
+
close();
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (item.kind === "activity" || item.kind === "note") {
|
|
42
|
+
if (active !== void 0)
|
|
43
|
+
queued.push(item);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (active === void 0) {
|
|
47
|
+
active = { items: [item], work: [] };
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
for (const work of queued) {
|
|
51
|
+
if (claimed.has(workId(work)))
|
|
52
|
+
continue;
|
|
53
|
+
claimed.add(workId(work));
|
|
54
|
+
active.work.push(work);
|
|
55
|
+
}
|
|
56
|
+
queued = [];
|
|
57
|
+
active.items.push(item);
|
|
58
|
+
}
|
|
59
|
+
close();
|
|
60
|
+
return runs;
|
|
61
|
+
}
|
|
62
|
+
function immediateFollowingAgentConversationWave(run, waves, stream, order, sources, claimedWaveAttemptIds) {
|
|
63
|
+
if (run.work.length === 0)
|
|
64
|
+
return void 0;
|
|
65
|
+
const runIds = new Set(run.items.map((item) => item.id));
|
|
66
|
+
const end = Math.max(...run.items.map((item) => order.get(item.id) ?? -Infinity));
|
|
67
|
+
if (!Number.isFinite(end))
|
|
68
|
+
return void 0;
|
|
69
|
+
let candidate;
|
|
70
|
+
let candidateStart = Infinity;
|
|
71
|
+
for (const wave of waves) {
|
|
72
|
+
const followingAttempts = wave.filter((attempt) => {
|
|
73
|
+
const position = order.get(attempt.id);
|
|
74
|
+
return position !== void 0 && position > end && !claimedWaveAttemptIds.has(attempt.id);
|
|
75
|
+
});
|
|
76
|
+
if (followingAttempts.length === 0)
|
|
77
|
+
continue;
|
|
78
|
+
if (followingAttempts.some((attempt) => sources.get(attempt.id)?.rowKey !== run.items.at(-1)?.rowKey))
|
|
79
|
+
continue;
|
|
80
|
+
const start = Math.min(...followingAttempts.map((attempt) => order.get(attempt.id) ?? Infinity));
|
|
81
|
+
if (start < candidateStart) {
|
|
82
|
+
candidate = followingAttempts;
|
|
83
|
+
candidateStart = start;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (candidate === void 0)
|
|
87
|
+
return void 0;
|
|
88
|
+
const waveIds = new Set(candidate.map((attempt) => attempt.id));
|
|
89
|
+
for (const item of stream) {
|
|
90
|
+
const position = order.get(item.kind === "activity" ? item.attemptId : item.id);
|
|
91
|
+
if (position === void 0 || position <= end || position >= candidateStart)
|
|
92
|
+
continue;
|
|
93
|
+
if (item.kind === "conversation" && !runIds.has(item.id))
|
|
94
|
+
return void 0;
|
|
95
|
+
if (item.kind !== "activity" && item.kind !== "conversation")
|
|
96
|
+
return void 0;
|
|
97
|
+
if (item.kind === "activity" && !waveIds.has(item.attemptId))
|
|
98
|
+
return void 0;
|
|
99
|
+
}
|
|
100
|
+
return candidate;
|
|
101
|
+
}
|
|
102
|
+
function isFoldedAgentConversationRun(run) {
|
|
103
|
+
return run.peers.length >= 2 || run.peers.some((peer) => peer.items.length >= 2);
|
|
104
|
+
}
|
|
105
|
+
function admittedSpawnSessionId(details) {
|
|
106
|
+
if (typeof details !== "object" || details === null)
|
|
107
|
+
return void 0;
|
|
108
|
+
const record = details;
|
|
109
|
+
const sessionId = typeof record["sessionId"] === "string" ? record["sessionId"] : record["accepted"] === true && typeof record["childSessionId"] === "string" ? record["childSessionId"] : void 0;
|
|
110
|
+
return sessionId === void 0 || sessionId.trim() === "" ? void 0 : sessionId.trim();
|
|
111
|
+
}
|
|
112
|
+
function admittedSendSessionId(details) {
|
|
113
|
+
if (typeof details !== "object" || details === null)
|
|
114
|
+
return void 0;
|
|
115
|
+
const record = details;
|
|
116
|
+
const sessionId = typeof record["sessionId"] === "string" ? record["sessionId"].trim() : "";
|
|
117
|
+
return sessionId && typeof record["rowId"] === "string" && record["rowId"] !== "" && typeof record["backgroundTaskId"] === "string" ? sessionId : void 0;
|
|
118
|
+
}
|
|
119
|
+
function receivedConversation(customType, details) {
|
|
120
|
+
if (typeof details !== "object" || details === null)
|
|
121
|
+
return void 0;
|
|
122
|
+
const record = details;
|
|
123
|
+
if (customType === "collaboration_message") {
|
|
124
|
+
const provenance2 = record["provenance"];
|
|
125
|
+
if (typeof record["senderSessionId"] !== "string" || record["kind"] !== "message" && record["kind"] !== "progress" || typeof provenance2 !== "object" || provenance2 === null)
|
|
126
|
+
return void 0;
|
|
127
|
+
const source = provenance2;
|
|
128
|
+
if (source["source"] !== "subagent" || typeof source["sourceId"] !== "string")
|
|
129
|
+
return void 0;
|
|
130
|
+
return { peerId: record["senderSessionId"], direction: "inbound" };
|
|
131
|
+
}
|
|
132
|
+
if (customType !== "subagent_result")
|
|
133
|
+
return void 0;
|
|
134
|
+
const provenance = subagentProvenanceOf(record);
|
|
135
|
+
const status = record["status"];
|
|
136
|
+
if (provenance === void 0 || provenance.sourceId === "" || status !== "completed" && status !== "failed" && status !== "cancelled" && status !== "interrupted")
|
|
137
|
+
return void 0;
|
|
138
|
+
return { peerId: provenance.sourceId, direction: "result", status };
|
|
139
|
+
}
|
|
140
|
+
function subagentProvenanceOf(record) {
|
|
141
|
+
const provenance = record["provenance"];
|
|
142
|
+
if (typeof provenance === "object" && provenance !== null) {
|
|
143
|
+
const p = provenance;
|
|
144
|
+
if (p["source"] === "subagent" && typeof p["sourceId"] === "string") {
|
|
145
|
+
const label = p["label"];
|
|
146
|
+
return {
|
|
147
|
+
source: "subagent",
|
|
148
|
+
sourceId: p["sourceId"],
|
|
149
|
+
...typeof label === "string" ? { label } : {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const attribution = record["attribution"];
|
|
154
|
+
if (typeof attribution === "object" && attribution !== null) {
|
|
155
|
+
const a = attribution;
|
|
156
|
+
if (a["kind"] === "subagent" && typeof a["childSessionId"] === "string") {
|
|
157
|
+
const label = a["label"];
|
|
158
|
+
return {
|
|
159
|
+
source: "subagent",
|
|
160
|
+
sourceId: a["childSessionId"],
|
|
161
|
+
...typeof label === "string" ? { label } : {}
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return void 0;
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
admittedSendSessionId,
|
|
169
|
+
admittedSpawnSessionId,
|
|
170
|
+
groupAgentConversationStream,
|
|
171
|
+
immediateFollowingAgentConversationWave,
|
|
172
|
+
isFoldedAgentConversationRun,
|
|
173
|
+
receivedConversation
|
|
174
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Maximum UTF-8 JSON size of one plugin app-data live change. */
|
|
2
|
+
export declare const KAY_APP_DATA_CHANGE_MAX_BYTES: number;
|
|
3
|
+
|
|
4
|
+
/** Maximum UTF-8 JSON size of one plugin app-data snapshot. */
|
|
5
|
+
export declare const KAY_APP_DATA_SNAPSHOT_MAX_BYTES: number;
|
|
6
|
+
|
|
7
|
+
export { }
|
package/dist/app-data.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// packages/plugin-protocol/dist/app-data.js
|
|
2
|
+
var KAY_APP_DATA_SNAPSHOT_MAX_BYTES = 16 * 1024 * 1024;
|
|
3
|
+
var KAY_APP_DATA_CHANGE_MAX_BYTES = 256 * 1024;
|
|
4
|
+
var KAY_APP_DATA_READ_REQUEST_MAX_BYTES = 64 * 1024;
|
|
5
|
+
var KAY_APP_DATA_READ_RESULT_MAX_BYTES = 16 * 1024 * 1024;
|
|
6
|
+
export {
|
|
7
|
+
KAY_APP_DATA_CHANGE_MAX_BYTES,
|
|
8
|
+
KAY_APP_DATA_SNAPSHOT_MAX_BYTES
|
|
9
|
+
};
|
package/dist/disclosure.d.ts
CHANGED
|
@@ -2109,11 +2109,9 @@ declare interface KayAppTimeSnapshot {
|
|
|
2109
2109
|
/**
|
|
2110
2110
|
* The time zone the user is in, as an IANA id in the spelling ICU resolves (`America/New_York`).
|
|
2111
2111
|
* One zone can have two ids, and ICU picks one: `Asia/Kolkata` comes back as `Asia/Calcutta`. So
|
|
2112
|
-
* never compare zone ids with
|
|
2113
|
-
*
|
|
2114
|
-
*
|
|
2115
|
-
* results. Pass `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a
|
|
2116
|
-
* time for the user.
|
|
2112
|
+
* never compare zone ids with `===`: compare with `sameZone` from `@bonsai/plugin-sdk/time`. Pass
|
|
2113
|
+
* `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a time for the
|
|
2114
|
+
* user.
|
|
2117
2115
|
*
|
|
2118
2116
|
* When `zoneSource` is `utc-fallback` the zone is unknown, and this value is `UTC` only because a
|
|
2119
2117
|
* value is required.
|
|
@@ -3696,8 +3694,8 @@ declare function ReturnTypeDeferred<Type extends TSchema>(type: Type, options?:
|
|
|
3696
3694
|
* owns:
|
|
3697
3695
|
* - {@link RunFailureReason}.
|
|
3698
3696
|
* does_not_own:
|
|
3699
|
-
* - Classifying a failure into a reason (
|
|
3700
|
-
*
|
|
3697
|
+
* - Classifying a failure into a reason (`./run-failure-classifier.ts`), or the engine's
|
|
3698
|
+
* run-error mapping and recovery policy (`@herd/herd-agent`).
|
|
3701
3699
|
* ---
|
|
3702
3700
|
*/
|
|
3703
3701
|
/** Provider-neutral factual category for a failed model run. */
|
|
@@ -481,6 +481,19 @@ declare interface ConvertedArtifact {
|
|
|
481
481
|
*/
|
|
482
482
|
declare function Create(hidden: ObjectLike_2, enumerable: ObjectLike_2, options?: ObjectLike_2): ObjectLike_2;
|
|
483
483
|
|
|
484
|
+
/**
|
|
485
|
+
* A {@link TestClock} starting at `startMs`. Without a `zone` it answers the zone as unknown, like
|
|
486
|
+
* {@link fauxKayAgentCapabilities}; with one it answers that zone as the user's. Use it as
|
|
487
|
+
* `{ ...fauxKayAgentCapabilities(), time: createTestClock(0) }`.
|
|
488
|
+
*
|
|
489
|
+
* Throws `RangeError` for a non-finite time, and for a `zone` the host could never answer: the
|
|
490
|
+
* host answers an IANA id in the spelling ICU resolves (`Asia/Calcutta`, not `Asia/Kolkata`), so
|
|
491
|
+
* an alias, an abbreviation such as `EST` or a typo would make a test pass that production fails.
|
|
492
|
+
*/
|
|
493
|
+
export declare function createTestClock(startMs: number, options?: {
|
|
494
|
+
readonly zone?: string;
|
|
495
|
+
}): TestClock;
|
|
496
|
+
|
|
484
497
|
/** Creates a Cyclic type. */
|
|
485
498
|
declare function Cyclic<Defs extends TProperties, Ref extends string>($defs: Defs, $ref: Ref, options?: TSchemaOptions): TCyclic<Defs, Ref>;
|
|
486
499
|
|
|
@@ -2010,11 +2023,9 @@ declare interface KayAppTimeSnapshot {
|
|
|
2010
2023
|
/**
|
|
2011
2024
|
* The time zone the user is in, as an IANA id in the spelling ICU resolves (`America/New_York`).
|
|
2012
2025
|
* One zone can have two ids, and ICU picks one: `Asia/Kolkata` comes back as `Asia/Calcutta`. So
|
|
2013
|
-
* never compare zone ids with
|
|
2014
|
-
*
|
|
2015
|
-
*
|
|
2016
|
-
* results. Pass `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a
|
|
2017
|
-
* time for the user.
|
|
2026
|
+
* never compare zone ids with `===`: compare with `sameZone` from `@bonsai/plugin-sdk/time`. Pass
|
|
2027
|
+
* `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a time for the
|
|
2028
|
+
* user.
|
|
2018
2029
|
*
|
|
2019
2030
|
* When `zoneSource` is `utc-fallback` the zone is unknown, and this value is `UTC` only because a
|
|
2020
2031
|
* value is required.
|
|
@@ -3594,8 +3605,8 @@ declare function ReturnTypeDeferred<Type extends TSchema>(type: Type, options?:
|
|
|
3594
3605
|
* owns:
|
|
3595
3606
|
* - {@link RunFailureReason}.
|
|
3596
3607
|
* does_not_own:
|
|
3597
|
-
* - Classifying a failure into a reason (
|
|
3598
|
-
*
|
|
3608
|
+
* - Classifying a failure into a reason (`./run-failure-classifier.ts`), or the engine's
|
|
3609
|
+
* run-error mapping and recovery policy (`@herd/herd-agent`).
|
|
3599
3610
|
* ---
|
|
3600
3611
|
*/
|
|
3601
3612
|
/** Provider-neutral factual category for a failed model run. */
|
|
@@ -5077,6 +5088,18 @@ declare type TEscape0<Index extends string> = Index extends `${infer Left}~0${in
|
|
|
5077
5088
|
|
|
5078
5089
|
declare type TEscape1<Index extends string> = Index extends `${infer Left}~1${infer Right}` ? `${Left}/${TEscape<Right>}` : Index;
|
|
5079
5090
|
|
|
5091
|
+
/**
|
|
5092
|
+
* A time door (`api.time` / `app.time`) whose clock moves only when the test moves it. It also
|
|
5093
|
+
* answers `nowMs()`, so it replaces `createTestClock` from `@bonsai/time/testing` unchanged.
|
|
5094
|
+
*/
|
|
5095
|
+
export declare interface TestClock extends KayAppTime {
|
|
5096
|
+
nowMs(): number;
|
|
5097
|
+
/** Moves the clock forward (or backward, for a negative value) by `ms`. */
|
|
5098
|
+
advance(ms: number): void;
|
|
5099
|
+
/** Jumps the clock to an absolute epoch-millisecond value. */
|
|
5100
|
+
set(ms: number): void;
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5080
5103
|
/** Applies an Evaluate action to a type. */
|
|
5081
5104
|
declare type TEvaluate<Type extends TSchema> = (TEvaluateAction<Type>);
|
|
5082
5105
|
|
|
@@ -193,6 +193,42 @@ function fauxKayAgentCapabilities() {
|
|
|
193
193
|
familyFolder: { path: async () => void 0 }
|
|
194
194
|
};
|
|
195
195
|
}
|
|
196
|
+
function createTestClock(startMs, options = {}) {
|
|
197
|
+
let nowMs = finiteMs(startMs, "startMs");
|
|
198
|
+
const { zone } = options;
|
|
199
|
+
if (zone !== void 0)
|
|
200
|
+
requireResolvedZone(zone);
|
|
201
|
+
return {
|
|
202
|
+
nowMs: () => nowMs,
|
|
203
|
+
snapshot: () => zone === void 0 ? { nowMs, zone: "UTC", zoneSource: "utc-fallback" } : { nowMs, zone, zoneSource: "host" },
|
|
204
|
+
advance(ms) {
|
|
205
|
+
nowMs += finiteMs(ms, "ms");
|
|
206
|
+
},
|
|
207
|
+
set(ms) {
|
|
208
|
+
nowMs = finiteMs(ms, "ms");
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
function requireResolvedZone(zone) {
|
|
213
|
+
let resolved;
|
|
214
|
+
try {
|
|
215
|
+
resolved = new Intl.DateTimeFormat("en-US", {
|
|
216
|
+
timeZone: zone
|
|
217
|
+
}).resolvedOptions().timeZone;
|
|
218
|
+
} catch {
|
|
219
|
+
resolved = void 0;
|
|
220
|
+
}
|
|
221
|
+
const ianaShaped = zone.includes("/") || zone === "UTC";
|
|
222
|
+
if (!ianaShaped || resolved !== zone) {
|
|
223
|
+
throw new RangeError(`createTestClock: zone ${JSON.stringify(zone)} is not a zone the host answers` + (resolved !== void 0 && ianaShaped ? `; the host spells it ${JSON.stringify(resolved)}` : ""));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
function finiteMs(value, name) {
|
|
227
|
+
if (!Number.isFinite(value)) {
|
|
228
|
+
throw new RangeError(`createTestClock: ${name} must be a finite number, got ${String(value)}`);
|
|
229
|
+
}
|
|
230
|
+
return value;
|
|
231
|
+
}
|
|
196
232
|
function defaultTestToolContext() {
|
|
197
233
|
return { cwd: "/tmp", model: void 0 };
|
|
198
234
|
}
|
|
@@ -209,6 +245,7 @@ function producedResourcesForTest(result) {
|
|
|
209
245
|
return read;
|
|
210
246
|
}
|
|
211
247
|
export {
|
|
248
|
+
createTestClock,
|
|
212
249
|
fauxAuthContext,
|
|
213
250
|
fauxKayAgentCapabilities,
|
|
214
251
|
invokeToolForTest,
|
package/dist/kay-agent.d.ts
CHANGED
|
@@ -551,6 +551,8 @@ declare const CompareResultLeftInside = 2;
|
|
|
551
551
|
|
|
552
552
|
declare const CompareResultRightInside = 3;
|
|
553
553
|
|
|
554
|
+
export declare function compileUriClaim(claim: UriClaim): UriCompiledClaim;
|
|
555
|
+
|
|
554
556
|
/** Applies a Conditional action to the given types. */
|
|
555
557
|
declare function Conditional<Left extends TSchema, Right extends TSchema, True extends TSchema, False extends TSchema>(left: Left, right: Right, true_: True, false_: False, options?: TSchemaOptions): TConditional<Left, Right, True, False>;
|
|
556
558
|
|
|
@@ -2478,11 +2480,9 @@ declare interface KayAppTimeSnapshot {
|
|
|
2478
2480
|
/**
|
|
2479
2481
|
* The time zone the user is in, as an IANA id in the spelling ICU resolves (`America/New_York`).
|
|
2480
2482
|
* One zone can have two ids, and ICU picks one: `Asia/Kolkata` comes back as `Asia/Calcutta`. So
|
|
2481
|
-
* never compare zone ids with
|
|
2482
|
-
*
|
|
2483
|
-
*
|
|
2484
|
-
* results. Pass `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a
|
|
2485
|
-
* time for the user.
|
|
2483
|
+
* never compare zone ids with `===`: compare with `sameZone` from `@bonsai/plugin-sdk/time`. Pass
|
|
2484
|
+
* `zone` as the `timeZone` of `Intl.DateTimeFormat` or `toLocaleString` to format a time for the
|
|
2485
|
+
* user.
|
|
2486
2486
|
*
|
|
2487
2487
|
* When `zoneSource` is `utc-fallback` the zone is unknown, and this value is `UTC` only because a
|
|
2488
2488
|
* value is required.
|
|
@@ -4919,6 +4919,30 @@ declare const PluginCapabilityRefusalV1: z.ZodObject<{
|
|
|
4919
4919
|
envelope: z.ZodObject<{
|
|
4920
4920
|
binary: z.ZodString;
|
|
4921
4921
|
}, z.core.$strict>;
|
|
4922
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4923
|
+
target: z.ZodLiteral<"plugin">;
|
|
4924
|
+
slug: z.ZodLiteral<"mcp.host-server">;
|
|
4925
|
+
envelope: z.ZodObject<{
|
|
4926
|
+
name: z.ZodString;
|
|
4927
|
+
url: z.ZodString;
|
|
4928
|
+
}, z.core.$strict>;
|
|
4929
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4930
|
+
target: z.ZodLiteral<"plugin">;
|
|
4931
|
+
slug: z.ZodLiteral<"prompt.resident">;
|
|
4932
|
+
envelope: z.ZodObject<{}, z.core.$strict>;
|
|
4933
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4934
|
+
target: z.ZodLiteral<"plugin">;
|
|
4935
|
+
slug: z.ZodLiteral<"skills.declared-source">;
|
|
4936
|
+
envelope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
4937
|
+
channel: z.ZodLiteral<"git-clone">;
|
|
4938
|
+
locator: z.ZodString;
|
|
4939
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
4940
|
+
subdir: z.ZodOptional<z.ZodString>;
|
|
4941
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
4942
|
+
channel: z.ZodLiteral<"installer">;
|
|
4943
|
+
command: z.ZodString;
|
|
4944
|
+
args: z.ZodArray<z.ZodString>;
|
|
4945
|
+
}, z.core.$strict>], "channel">;
|
|
4922
4946
|
}, z.core.$strict>, z.ZodObject<{
|
|
4923
4947
|
target: z.ZodEnum<{
|
|
4924
4948
|
"kay.agent": "kay.agent";
|
|
@@ -5518,8 +5542,8 @@ declare function ReturnTypeDeferred<Type extends TSchema>(type: Type, options?:
|
|
|
5518
5542
|
* owns:
|
|
5519
5543
|
* - {@link RunFailureReason}.
|
|
5520
5544
|
* does_not_own:
|
|
5521
|
-
* - Classifying a failure into a reason (
|
|
5522
|
-
*
|
|
5545
|
+
* - Classifying a failure into a reason (`./run-failure-classifier.ts`), or the engine's
|
|
5546
|
+
* run-error mapping and recovery policy (`@herd/herd-agent`).
|
|
5523
5547
|
* ---
|
|
5524
5548
|
*/
|
|
5525
5549
|
/** Provider-neutral factual category for a failed model run. */
|
|
@@ -10114,7 +10138,7 @@ export declare interface UriCapabilitySpec {
|
|
|
10114
10138
|
readonly returns?: UriPayloadContract;
|
|
10115
10139
|
}
|
|
10116
10140
|
|
|
10117
|
-
declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
|
|
10141
|
+
export declare type UriClaim = UriSchemeClaim | UriPatternClaim | UrlPatternClaim;
|
|
10118
10142
|
|
|
10119
10143
|
declare interface UriCommonFlow {
|
|
10120
10144
|
readonly label: string;
|
|
@@ -10122,6 +10146,17 @@ declare interface UriCommonFlow {
|
|
|
10122
10146
|
readonly example: string;
|
|
10123
10147
|
}
|
|
10124
10148
|
|
|
10149
|
+
export declare interface UriCompiledClaim {
|
|
10150
|
+
readonly claim: UriClaim;
|
|
10151
|
+
match(input: string): UriCompiledClaimMatch | undefined;
|
|
10152
|
+
}
|
|
10153
|
+
|
|
10154
|
+
export declare interface UriCompiledClaimMatch {
|
|
10155
|
+
readonly claimKind: UriClaim["kind"];
|
|
10156
|
+
readonly captures?: Record<string, string>;
|
|
10157
|
+
readonly normalizedUri?: string;
|
|
10158
|
+
}
|
|
10159
|
+
|
|
10125
10160
|
/**
|
|
10126
10161
|
* A source changed (or was never witnessed) before a mediated mutation. Thrown by a
|
|
10127
10162
|
* module or by the host tool; the host renders it as a normal "not applied" tool
|