@byok-sdk/ui-runtime 0.4.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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/approval-timeline.d.ts +8 -0
- package/dist/approval-types.d.ts +46 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +616 -0
- package/dist/index.js.map +1 -0
- package/dist/timeline.d.ts +7 -0
- package/dist/types.d.ts +91 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ancienttwo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @byok-sdk/ui-runtime
|
|
2
|
+
|
|
3
|
+
React-free deterministic projection from BYOK typed activity tails to a
|
|
4
|
+
host-facing Live Activity Timeline view model. It owns no network,
|
|
5
|
+
authentication, persistence, redaction, or presentation behavior.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { replayTimeline } from '@byok-sdk/ui-runtime';
|
|
9
|
+
|
|
10
|
+
const snapshot = replayTimeline(activityTail);
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
MIT licensed. Node.js 22.22.0 or newer.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ApprovalObservation, type ApprovalTimelineTail } from '@byok-sdk/cloud';
|
|
2
|
+
import { type ApprovalProjectionMetadata, type ApprovalProjectionState, type TaskApprovalSnapshot } from './approval-types';
|
|
3
|
+
export declare function createApprovalProjectionState(taskId: string, metadata?: ApprovalProjectionMetadata): ApprovalProjectionState;
|
|
4
|
+
export declare function withApprovalProjectionMetadata(state: ApprovalProjectionState, metadata: ApprovalProjectionMetadata): ApprovalProjectionState;
|
|
5
|
+
export declare function foldApprovalObservation(state: ApprovalProjectionState, input: ApprovalObservation): ApprovalProjectionState;
|
|
6
|
+
export declare function foldApprovalTail(state: ApprovalProjectionState, tail: ApprovalTimelineTail): ApprovalProjectionState;
|
|
7
|
+
export declare function projectApprovalTimeline(state: ApprovalProjectionState): TaskApprovalSnapshot;
|
|
8
|
+
export declare function replayApprovalTimeline(tail: ApprovalTimelineTail): TaskApprovalSnapshot;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ApprovalObservation } from '@byok-sdk/cloud';
|
|
2
|
+
export declare const APPROVAL_LIFECYCLE_STATES: readonly ['approval-requested', 'approval-responded'];
|
|
3
|
+
export type ApprovalLifecycleState = (typeof APPROVAL_LIFECYCLE_STATES)[number];
|
|
4
|
+
export declare const APPROVAL_DECISION_STATES: readonly ['pending', 'approved', 'rejected'];
|
|
5
|
+
export type ApprovalDecisionState = (typeof APPROVAL_DECISION_STATES)[number];
|
|
6
|
+
export declare const APPROVAL_CORRELATION_STATES: readonly ['paired', 'unpaired-request', 'unpaired-resolution'];
|
|
7
|
+
export type ApprovalCorrelationState = (typeof APPROVAL_CORRELATION_STATES)[number];
|
|
8
|
+
export interface ApprovalProjectionMetadata {
|
|
9
|
+
readonly dropped: number;
|
|
10
|
+
readonly capacity?: number;
|
|
11
|
+
readonly expiresAt?: string;
|
|
12
|
+
readonly cursor?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ApprovalProjectionState {
|
|
15
|
+
readonly taskId: string;
|
|
16
|
+
readonly observations: readonly ApprovalObservation[];
|
|
17
|
+
readonly metadata: ApprovalProjectionMetadata;
|
|
18
|
+
}
|
|
19
|
+
export interface ApprovalProjectionItem {
|
|
20
|
+
readonly kind: 'approval';
|
|
21
|
+
readonly approvalId?: string;
|
|
22
|
+
readonly lifecycle: ApprovalLifecycleState;
|
|
23
|
+
readonly status: ApprovalDecisionState;
|
|
24
|
+
readonly correlation: ApprovalCorrelationState;
|
|
25
|
+
readonly firstRevision: number;
|
|
26
|
+
readonly sourceRevisions: readonly number[];
|
|
27
|
+
readonly sourceEnvelopeIds: readonly string[];
|
|
28
|
+
readonly summary?: string;
|
|
29
|
+
readonly decision?: 'approve' | 'reject';
|
|
30
|
+
readonly resolvedBy?: 'local';
|
|
31
|
+
readonly resolvedAt?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface TaskApprovalSnapshot {
|
|
34
|
+
readonly taskId: string;
|
|
35
|
+
readonly items: readonly ApprovalProjectionItem[];
|
|
36
|
+
readonly dropped: number;
|
|
37
|
+
readonly capacity?: number;
|
|
38
|
+
readonly expiresAt?: string;
|
|
39
|
+
readonly cursor?: number;
|
|
40
|
+
}
|
|
41
|
+
export declare const APPROVAL_PROJECTION_ERROR_CODES: readonly ['approval_input_invalid', 'approval_task_mismatch', 'approval_identity_collision', 'approval_revision_collision', 'approval_authority_collision'];
|
|
42
|
+
export type ApprovalProjectionErrorCode = (typeof APPROVAL_PROJECTION_ERROR_CODES)[number];
|
|
43
|
+
export declare class ApprovalProjectionError extends Error {
|
|
44
|
+
readonly code: ApprovalProjectionErrorCode;
|
|
45
|
+
constructor(code: ApprovalProjectionErrorCode, message: string, options?: ErrorOptions);
|
|
46
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,616 @@
|
|
|
1
|
+
import { ApprovalObservationSchema, TimelineEventSchema } from '@byok-sdk/cloud';
|
|
2
|
+
import { isKnownAgentEvent } from '@byok-sdk/protocol';
|
|
3
|
+
|
|
4
|
+
// src/approval-timeline.ts
|
|
5
|
+
|
|
6
|
+
// src/approval-types.ts
|
|
7
|
+
var APPROVAL_LIFECYCLE_STATES = [
|
|
8
|
+
"approval-requested",
|
|
9
|
+
"approval-responded"
|
|
10
|
+
];
|
|
11
|
+
var APPROVAL_DECISION_STATES = ["pending", "approved", "rejected"];
|
|
12
|
+
var APPROVAL_CORRELATION_STATES = [
|
|
13
|
+
"paired",
|
|
14
|
+
"unpaired-request",
|
|
15
|
+
"unpaired-resolution"
|
|
16
|
+
];
|
|
17
|
+
var APPROVAL_PROJECTION_ERROR_CODES = [
|
|
18
|
+
"approval_input_invalid",
|
|
19
|
+
"approval_task_mismatch",
|
|
20
|
+
"approval_identity_collision",
|
|
21
|
+
"approval_revision_collision",
|
|
22
|
+
"approval_authority_collision"
|
|
23
|
+
];
|
|
24
|
+
var ApprovalProjectionError = class extends Error {
|
|
25
|
+
code;
|
|
26
|
+
constructor(code, message, options) {
|
|
27
|
+
super(message, options);
|
|
28
|
+
this.name = "ApprovalProjectionError";
|
|
29
|
+
this.code = code;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/approval-timeline.ts
|
|
34
|
+
var DEFAULT_METADATA = Object.freeze({ dropped: 0 });
|
|
35
|
+
function fail(code, message, cause) {
|
|
36
|
+
throw new ApprovalProjectionError(code, message, cause === void 0 ? void 0 : { cause });
|
|
37
|
+
}
|
|
38
|
+
function validTaskId(taskId) {
|
|
39
|
+
return typeof taskId === "string" && taskId.length > 0 && taskId.length <= 200;
|
|
40
|
+
}
|
|
41
|
+
function canonicalTimestamp(value) {
|
|
42
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value;
|
|
43
|
+
}
|
|
44
|
+
function validateMetadata(metadata) {
|
|
45
|
+
if (!Number.isSafeInteger(metadata.dropped) || metadata.dropped < 0) {
|
|
46
|
+
fail("approval_input_invalid", "Approval metadata dropped must be a non-negative integer.");
|
|
47
|
+
}
|
|
48
|
+
if (metadata.capacity !== void 0 && (!Number.isSafeInteger(metadata.capacity) || metadata.capacity <= 0)) {
|
|
49
|
+
fail("approval_input_invalid", "Approval metadata capacity must be a positive integer when present.");
|
|
50
|
+
}
|
|
51
|
+
if (metadata.expiresAt !== void 0 && !canonicalTimestamp(metadata.expiresAt)) {
|
|
52
|
+
fail("approval_input_invalid", "Approval metadata expiresAt must be a canonical ISO timestamp when present.");
|
|
53
|
+
}
|
|
54
|
+
if (metadata.cursor !== void 0 && (!Number.isSafeInteger(metadata.cursor) || metadata.cursor <= 0)) {
|
|
55
|
+
fail("approval_input_invalid", "Approval metadata cursor must be a positive integer when present.");
|
|
56
|
+
}
|
|
57
|
+
return Object.freeze({ ...metadata });
|
|
58
|
+
}
|
|
59
|
+
function parseObservation(value) {
|
|
60
|
+
try {
|
|
61
|
+
return Object.freeze(structuredClone(ApprovalObservationSchema.parse(value)));
|
|
62
|
+
} catch (error) {
|
|
63
|
+
fail("approval_input_invalid", "Approval observation must satisfy the typed cloud authority.", error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function structurallyEqual(left, right, seen = /* @__PURE__ */ new WeakMap()) {
|
|
67
|
+
if (Object.is(left, right)) return true;
|
|
68
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
69
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
70
|
+
const prior = seen.get(left);
|
|
71
|
+
if (prior !== void 0) return prior === right;
|
|
72
|
+
seen.set(left, right);
|
|
73
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
74
|
+
return left.length === right.length && left.every((entry, index) => structurallyEqual(entry, right[index], seen));
|
|
75
|
+
}
|
|
76
|
+
const leftRecord = left;
|
|
77
|
+
const rightRecord = right;
|
|
78
|
+
const leftKeys = Object.keys(leftRecord).sort();
|
|
79
|
+
const rightKeys = Object.keys(rightRecord).sort();
|
|
80
|
+
return leftKeys.length === rightKeys.length && leftKeys.every(
|
|
81
|
+
(key, index) => key === rightKeys[index] && structurallyEqual(leftRecord[key], rightRecord[key], seen)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
function freezeItem(item) {
|
|
85
|
+
return Object.freeze({
|
|
86
|
+
...item,
|
|
87
|
+
sourceRevisions: Object.freeze([...item.sourceRevisions]),
|
|
88
|
+
sourceEnvelopeIds: Object.freeze([...item.sourceEnvelopeIds])
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function accumulatedItem(accumulator) {
|
|
92
|
+
const observations = [...accumulator.observations].sort((left, right) => left.revision - right.revision);
|
|
93
|
+
const resolution = accumulator.resolution;
|
|
94
|
+
return freezeItem({
|
|
95
|
+
kind: "approval",
|
|
96
|
+
approvalId: accumulator.approvalId,
|
|
97
|
+
lifecycle: resolution === void 0 ? "approval-requested" : "approval-responded",
|
|
98
|
+
status: resolution === void 0 ? "pending" : resolution.decision === "approve" ? "approved" : "rejected",
|
|
99
|
+
correlation: accumulator.request === void 0 ? "unpaired-resolution" : resolution === void 0 ? "unpaired-request" : "paired",
|
|
100
|
+
firstRevision: observations[0].revision,
|
|
101
|
+
sourceRevisions: observations.map(({ revision }) => revision),
|
|
102
|
+
sourceEnvelopeIds: observations.map(({ sourceEnvelopeId }) => sourceEnvelopeId),
|
|
103
|
+
...accumulator.request !== void 0 ? { summary: accumulator.request.summary } : {},
|
|
104
|
+
...resolution !== void 0 ? {
|
|
105
|
+
decision: resolution.decision,
|
|
106
|
+
resolvedBy: resolution.resolvedBy,
|
|
107
|
+
resolvedAt: resolution.at
|
|
108
|
+
} : {}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
function unpairedRequest(observation) {
|
|
112
|
+
const event = observation.event;
|
|
113
|
+
if (event.type !== "approval_requested") {
|
|
114
|
+
fail("approval_input_invalid", "Only approval requests may omit native approval identity.");
|
|
115
|
+
}
|
|
116
|
+
return freezeItem({
|
|
117
|
+
kind: "approval",
|
|
118
|
+
lifecycle: "approval-requested",
|
|
119
|
+
status: "pending",
|
|
120
|
+
correlation: "unpaired-request",
|
|
121
|
+
firstRevision: observation.revision,
|
|
122
|
+
sourceRevisions: [observation.revision],
|
|
123
|
+
sourceEnvelopeIds: [observation.sourceEnvelopeId],
|
|
124
|
+
summary: event.summary
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function projectItems(observations) {
|
|
128
|
+
const items = [];
|
|
129
|
+
const identified = /* @__PURE__ */ new Map();
|
|
130
|
+
for (const observation of observations) {
|
|
131
|
+
const event = observation.event;
|
|
132
|
+
if (event.type === "approval_requested" && event.approvalId === void 0) {
|
|
133
|
+
items.push(unpairedRequest(observation));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const approvalId = event.approvalId;
|
|
137
|
+
if (approvalId === void 0) {
|
|
138
|
+
fail("approval_input_invalid", "Approval resolution requires native approval identity.");
|
|
139
|
+
}
|
|
140
|
+
const accumulator = identified.get(approvalId) ?? { approvalId, observations: [] };
|
|
141
|
+
identified.set(approvalId, accumulator);
|
|
142
|
+
accumulator.observations.push(observation);
|
|
143
|
+
if (event.type === "approval_requested") {
|
|
144
|
+
if (accumulator.request !== void 0 && !structurallyEqual(accumulator.request, event)) {
|
|
145
|
+
fail("approval_authority_collision", `Approval ${approvalId} has conflicting request authority.`);
|
|
146
|
+
}
|
|
147
|
+
accumulator.request = event;
|
|
148
|
+
} else {
|
|
149
|
+
if (accumulator.resolution !== void 0 && !structurallyEqual(accumulator.resolution, event)) {
|
|
150
|
+
fail("approval_authority_collision", `Approval ${approvalId} has conflicting resolution authority.`);
|
|
151
|
+
}
|
|
152
|
+
accumulator.resolution = event;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
for (const accumulator of identified.values()) items.push(accumulatedItem(accumulator));
|
|
156
|
+
return Object.freeze(items.sort((left, right) => left.firstRevision - right.firstRevision));
|
|
157
|
+
}
|
|
158
|
+
function createApprovalProjectionState(taskId, metadata = DEFAULT_METADATA) {
|
|
159
|
+
if (!validTaskId(taskId)) {
|
|
160
|
+
fail("approval_input_invalid", "Approval taskId must contain 1 to 200 characters.");
|
|
161
|
+
}
|
|
162
|
+
return Object.freeze({
|
|
163
|
+
taskId,
|
|
164
|
+
observations: Object.freeze([]),
|
|
165
|
+
metadata: validateMetadata(metadata)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
function withApprovalProjectionMetadata(state, metadata) {
|
|
169
|
+
if (!validTaskId(state.taskId)) fail("approval_input_invalid", "Approval state taskId is invalid.");
|
|
170
|
+
return Object.freeze({
|
|
171
|
+
taskId: state.taskId,
|
|
172
|
+
observations: state.observations,
|
|
173
|
+
metadata: validateMetadata(metadata)
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function foldApprovalObservation(state, input) {
|
|
177
|
+
if (!validTaskId(state.taskId)) fail("approval_input_invalid", "Approval state taskId is invalid.");
|
|
178
|
+
const observation = parseObservation(input);
|
|
179
|
+
if (observation.taskId !== state.taskId) {
|
|
180
|
+
fail(
|
|
181
|
+
"approval_task_mismatch",
|
|
182
|
+
`Approval observation task ${observation.taskId} does not match state task ${state.taskId}.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
const identical = state.observations.find(
|
|
186
|
+
({ sourceEnvelopeId }) => sourceEnvelopeId === observation.sourceEnvelopeId
|
|
187
|
+
);
|
|
188
|
+
if (identical !== void 0) {
|
|
189
|
+
if (structurallyEqual(identical, observation)) return state;
|
|
190
|
+
fail("approval_identity_collision", "Approval source identity was reused for different content.");
|
|
191
|
+
}
|
|
192
|
+
if (state.observations.some(({ revision }) => revision === observation.revision)) {
|
|
193
|
+
fail("approval_revision_collision", "Approval revision was claimed by different source identity.");
|
|
194
|
+
}
|
|
195
|
+
const observations = [...state.observations, observation].sort((left, right) => left.revision - right.revision);
|
|
196
|
+
return Object.freeze({
|
|
197
|
+
taskId: state.taskId,
|
|
198
|
+
observations: Object.freeze(observations),
|
|
199
|
+
metadata: state.metadata
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function foldApprovalTail(state, tail) {
|
|
203
|
+
if (tail === null || typeof tail !== "object" || !validTaskId(tail.taskId) || !Array.isArray(tail.entries)) {
|
|
204
|
+
fail("approval_input_invalid", "Approval tail must contain a valid taskId and entries array.");
|
|
205
|
+
}
|
|
206
|
+
if (tail.taskId !== state.taskId) {
|
|
207
|
+
fail("approval_task_mismatch", `Approval tail task ${tail.taskId} does not match state task ${state.taskId}.`);
|
|
208
|
+
}
|
|
209
|
+
const revisions = tail.entries.map(({ revision }) => revision);
|
|
210
|
+
if (revisions.some((revision) => !Number.isSafeInteger(revision) || revision <= 0)) {
|
|
211
|
+
fail("approval_input_invalid", "Approval tail revisions must be positive integers.");
|
|
212
|
+
}
|
|
213
|
+
if (revisions.some((revision, index) => index > 0 && revision <= revisions[index - 1])) {
|
|
214
|
+
fail("approval_input_invalid", "Approval tail entries must be strictly ordered by native revision.");
|
|
215
|
+
}
|
|
216
|
+
if (tail.cursor !== revisions.at(-1)) {
|
|
217
|
+
fail("approval_input_invalid", "Approval tail cursor must equal its last retained revision.");
|
|
218
|
+
}
|
|
219
|
+
const stateCursor = state.observations.at(-1)?.revision;
|
|
220
|
+
if (stateCursor !== void 0 && (tail.cursor === void 0 || tail.cursor < stateCursor)) {
|
|
221
|
+
fail("approval_input_invalid", "Approval tail cursor must not move behind incremental state.");
|
|
222
|
+
}
|
|
223
|
+
for (const observation of tail.entries) {
|
|
224
|
+
const sameIdentity2 = state.observations.find(
|
|
225
|
+
({ sourceEnvelopeId }) => sourceEnvelopeId === observation.sourceEnvelopeId
|
|
226
|
+
);
|
|
227
|
+
if (sameIdentity2 !== void 0 && !structurallyEqual(sameIdentity2, observation)) {
|
|
228
|
+
fail("approval_identity_collision", "Approval source identity changed across tail snapshots.");
|
|
229
|
+
}
|
|
230
|
+
const sameRevision = state.observations.find(({ revision }) => revision === observation.revision);
|
|
231
|
+
if (sameRevision !== void 0 && sameRevision.sourceEnvelopeId !== observation.sourceEnvelopeId) {
|
|
232
|
+
fail("approval_revision_collision", "Approval revision changed source identity across tail snapshots.");
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
let next = createApprovalProjectionState(state.taskId, {
|
|
236
|
+
dropped: tail.dropped,
|
|
237
|
+
capacity: tail.capacity,
|
|
238
|
+
expiresAt: tail.expiresAt,
|
|
239
|
+
...tail.cursor !== void 0 ? { cursor: tail.cursor } : {}
|
|
240
|
+
});
|
|
241
|
+
for (const observation of tail.entries) next = foldApprovalObservation(next, observation);
|
|
242
|
+
return next;
|
|
243
|
+
}
|
|
244
|
+
function projectApprovalTimeline(state) {
|
|
245
|
+
if (!validTaskId(state.taskId)) fail("approval_input_invalid", "Approval state taskId is invalid.");
|
|
246
|
+
return Object.freeze({
|
|
247
|
+
taskId: state.taskId,
|
|
248
|
+
items: projectItems(state.observations),
|
|
249
|
+
dropped: state.metadata.dropped,
|
|
250
|
+
...state.metadata.capacity !== void 0 ? { capacity: state.metadata.capacity } : {},
|
|
251
|
+
...state.metadata.expiresAt !== void 0 ? { expiresAt: state.metadata.expiresAt } : {},
|
|
252
|
+
...state.metadata.cursor !== void 0 ? { cursor: state.metadata.cursor } : {}
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function replayApprovalTimeline(tail) {
|
|
256
|
+
if (tail === null || typeof tail !== "object" || !validTaskId(tail.taskId) || !Array.isArray(tail.entries)) {
|
|
257
|
+
fail("approval_input_invalid", "Approval tail must contain a valid taskId and entries array.");
|
|
258
|
+
}
|
|
259
|
+
return projectApprovalTimeline(foldApprovalTail(createApprovalProjectionState(tail.taskId), tail));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// src/types.ts
|
|
263
|
+
var TOOL_TIMELINE_STATES = [
|
|
264
|
+
"input-available",
|
|
265
|
+
"output-available",
|
|
266
|
+
"output-error",
|
|
267
|
+
"output-unknown",
|
|
268
|
+
"unpaired-use",
|
|
269
|
+
"unpaired-result"
|
|
270
|
+
];
|
|
271
|
+
var TIMELINE_FOLD_ERROR_CODES = [
|
|
272
|
+
"timeline_input_invalid",
|
|
273
|
+
"task_mismatch",
|
|
274
|
+
"identity_collision",
|
|
275
|
+
"order_collision",
|
|
276
|
+
"tool_collision"
|
|
277
|
+
];
|
|
278
|
+
var TimelineFoldError = class extends Error {
|
|
279
|
+
code;
|
|
280
|
+
constructor(code, message, options) {
|
|
281
|
+
super(message, options);
|
|
282
|
+
this.name = "TimelineFoldError";
|
|
283
|
+
this.code = code;
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
// src/timeline.ts
|
|
288
|
+
var DEFAULT_METADATA2 = Object.freeze({ dropped: 0 });
|
|
289
|
+
function compareEvents(left, right) {
|
|
290
|
+
return left.batchSeq - right.batchSeq || left.eventIndex - right.eventIndex;
|
|
291
|
+
}
|
|
292
|
+
function fail2(code, message, cause) {
|
|
293
|
+
throw new TimelineFoldError(code, message, cause === void 0 ? void 0 : { cause });
|
|
294
|
+
}
|
|
295
|
+
function validTaskId2(taskId) {
|
|
296
|
+
return typeof taskId === "string" && taskId.length > 0 && taskId.length <= 200;
|
|
297
|
+
}
|
|
298
|
+
function validateMetadata2(metadata) {
|
|
299
|
+
if (!Number.isSafeInteger(metadata.dropped) || metadata.dropped < 0) {
|
|
300
|
+
fail2("timeline_input_invalid", "Timeline metadata dropped must be a non-negative integer.");
|
|
301
|
+
}
|
|
302
|
+
if (metadata.capacity !== void 0 && (!Number.isSafeInteger(metadata.capacity) || metadata.capacity <= 0)) {
|
|
303
|
+
fail2("timeline_input_invalid", "Timeline metadata capacity must be a positive integer when present.");
|
|
304
|
+
}
|
|
305
|
+
if (metadata.expiresAt !== void 0 && (typeof metadata.expiresAt !== "string" || !Number.isFinite(Date.parse(metadata.expiresAt)) || new Date(metadata.expiresAt).toISOString() !== metadata.expiresAt)) {
|
|
306
|
+
fail2("timeline_input_invalid", "Timeline metadata expiresAt must be a canonical ISO timestamp when present.");
|
|
307
|
+
}
|
|
308
|
+
if (metadata.cursor !== void 0 && (!Number.isSafeInteger(metadata.cursor.batchSeq) || metadata.cursor.batchSeq < 0 || !Number.isSafeInteger(metadata.cursor.eventIndex) || metadata.cursor.eventIndex < 0)) {
|
|
309
|
+
fail2("timeline_input_invalid", "Timeline metadata cursor must contain non-negative integer coordinates.");
|
|
310
|
+
}
|
|
311
|
+
return Object.freeze({ ...metadata, cursor: metadata.cursor && Object.freeze({ ...metadata.cursor }) });
|
|
312
|
+
}
|
|
313
|
+
function deepFreeze(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
314
|
+
if (value === null || typeof value !== "object") return value;
|
|
315
|
+
if (seen.has(value)) return value;
|
|
316
|
+
seen.add(value);
|
|
317
|
+
for (const nested of Object.values(value)) deepFreeze(nested, seen);
|
|
318
|
+
return Object.freeze(value);
|
|
319
|
+
}
|
|
320
|
+
function assertWireValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
321
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return;
|
|
322
|
+
if (typeof value === "number") {
|
|
323
|
+
if (Number.isFinite(value)) return;
|
|
324
|
+
fail2("timeline_input_invalid", "Timeline event payload numbers must be finite JSON values.");
|
|
325
|
+
}
|
|
326
|
+
if (typeof value !== "object") {
|
|
327
|
+
fail2("timeline_input_invalid", "Timeline event payloads must contain JSON-compatible values.");
|
|
328
|
+
}
|
|
329
|
+
if (seen.has(value)) fail2("timeline_input_invalid", "Timeline event payloads must not contain cycles.");
|
|
330
|
+
seen.add(value);
|
|
331
|
+
if (Array.isArray(value)) {
|
|
332
|
+
for (const entry of value) assertWireValue(entry, seen);
|
|
333
|
+
} else {
|
|
334
|
+
const prototype = Object.getPrototypeOf(value);
|
|
335
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
336
|
+
fail2("timeline_input_invalid", "Timeline event payload objects must be plain JSON records.");
|
|
337
|
+
}
|
|
338
|
+
for (const entry of Object.values(value)) assertWireValue(entry, seen);
|
|
339
|
+
}
|
|
340
|
+
seen.delete(value);
|
|
341
|
+
}
|
|
342
|
+
function parseEvent(value) {
|
|
343
|
+
try {
|
|
344
|
+
const parsed = TimelineEventSchema.parse(value);
|
|
345
|
+
assertWireValue(parsed);
|
|
346
|
+
return deepFreeze(structuredClone(parsed));
|
|
347
|
+
} catch (error) {
|
|
348
|
+
fail2("timeline_input_invalid", "Timeline events must satisfy the typed cloud activity authority.", error);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function structurallyEqual2(left, right, seen = /* @__PURE__ */ new WeakMap()) {
|
|
352
|
+
if (Object.is(left, right)) return true;
|
|
353
|
+
if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
|
|
354
|
+
if (Array.isArray(left) !== Array.isArray(right)) return false;
|
|
355
|
+
const prior = seen.get(left);
|
|
356
|
+
if (prior !== void 0) return prior === right;
|
|
357
|
+
seen.set(left, right);
|
|
358
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
359
|
+
return left.length === right.length && left.every((entry, index) => structurallyEqual2(entry, right[index], seen));
|
|
360
|
+
}
|
|
361
|
+
const leftRecord = left;
|
|
362
|
+
const rightRecord = right;
|
|
363
|
+
const leftKeys = Object.keys(leftRecord).sort();
|
|
364
|
+
const rightKeys = Object.keys(rightRecord).sort();
|
|
365
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && structurallyEqual2(leftRecord[key], rightRecord[key], seen));
|
|
366
|
+
}
|
|
367
|
+
function eventKey(event) {
|
|
368
|
+
return Object.freeze({ sourceEnvelopeId: event.sourceEnvelopeId, eventIndex: event.eventIndex });
|
|
369
|
+
}
|
|
370
|
+
function orderKey(event) {
|
|
371
|
+
return Object.freeze({ taskId: event.taskId, batchSeq: event.batchSeq, eventIndex: event.eventIndex });
|
|
372
|
+
}
|
|
373
|
+
function sameIdentity(left, right) {
|
|
374
|
+
return left.sourceEnvelopeId === right.sourceEnvelopeId && left.eventIndex === right.eventIndex;
|
|
375
|
+
}
|
|
376
|
+
function sameOrder(left, right) {
|
|
377
|
+
return left.batchSeq === right.batchSeq && left.eventIndex === right.eventIndex;
|
|
378
|
+
}
|
|
379
|
+
function contiguous(left, right) {
|
|
380
|
+
return left.batchSeq === right.batchSeq && right.eventIndex === left.eventIndex + 1 || right.batchSeq === left.batchSeq + 1 && right.eventIndex === 0;
|
|
381
|
+
}
|
|
382
|
+
function gapsFor(events) {
|
|
383
|
+
const gaps = [];
|
|
384
|
+
for (let index = 1; index < events.length; index += 1) {
|
|
385
|
+
const previous = events[index - 1];
|
|
386
|
+
const current = events[index];
|
|
387
|
+
if (current.batchSeq === previous.batchSeq && current.eventIndex > previous.eventIndex + 1) {
|
|
388
|
+
gaps.push(Object.freeze({
|
|
389
|
+
kind: "event",
|
|
390
|
+
after: orderKey(previous),
|
|
391
|
+
before: orderKey(current),
|
|
392
|
+
missing: current.eventIndex - previous.eventIndex - 1
|
|
393
|
+
}));
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (current.batchSeq > previous.batchSeq) {
|
|
397
|
+
if (current.batchSeq > previous.batchSeq + 1) {
|
|
398
|
+
gaps.push(Object.freeze({
|
|
399
|
+
kind: "batch",
|
|
400
|
+
after: orderKey(previous),
|
|
401
|
+
before: orderKey(current),
|
|
402
|
+
missing: current.batchSeq - previous.batchSeq - 1
|
|
403
|
+
}));
|
|
404
|
+
}
|
|
405
|
+
if (current.eventIndex > 0) {
|
|
406
|
+
gaps.push(Object.freeze({
|
|
407
|
+
kind: "event",
|
|
408
|
+
after: orderKey(previous),
|
|
409
|
+
before: orderKey(current),
|
|
410
|
+
missing: current.eventIndex
|
|
411
|
+
}));
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return Object.freeze(gaps);
|
|
416
|
+
}
|
|
417
|
+
function toolItem(accumulator, toolCallId) {
|
|
418
|
+
const observations = [accumulator.use?.timelineEvent, accumulator.result?.timelineEvent].filter((event) => event !== void 0).sort(compareEvents);
|
|
419
|
+
const use = accumulator.use?.event;
|
|
420
|
+
const result = accumulator.result?.event;
|
|
421
|
+
const state = use === void 0 ? "unpaired-result" : result === void 0 ? "input-available" : result.isError === true ? "output-error" : result.isError === false ? "output-available" : "output-unknown";
|
|
422
|
+
return Object.freeze({
|
|
423
|
+
kind: "tool",
|
|
424
|
+
eventKeys: Object.freeze(observations.map(eventKey)),
|
|
425
|
+
orderKey: orderKey(observations[0]),
|
|
426
|
+
tool: accumulator.tool,
|
|
427
|
+
toolCallId,
|
|
428
|
+
state,
|
|
429
|
+
...use && Object.hasOwn(use, "input") ? { input: use.input } : {},
|
|
430
|
+
...result && Object.hasOwn(result, "output") ? { output: result.output } : {}
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
function unpairedTool(event, observation) {
|
|
434
|
+
return Object.freeze({
|
|
435
|
+
kind: "tool",
|
|
436
|
+
eventKeys: Object.freeze([eventKey(event)]),
|
|
437
|
+
orderKey: orderKey(event),
|
|
438
|
+
tool: observation.tool,
|
|
439
|
+
state: observation.type === "tool_use" ? "unpaired-use" : "unpaired-result",
|
|
440
|
+
...observation.type === "tool_use" && Object.hasOwn(observation, "input") ? { input: observation.input } : {},
|
|
441
|
+
...observation.type === "tool_result" && Object.hasOwn(observation, "output") ? { output: observation.output } : {}
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
function projectItems2(events) {
|
|
445
|
+
const items = [];
|
|
446
|
+
const tools = /* @__PURE__ */ new Map();
|
|
447
|
+
let previous;
|
|
448
|
+
for (const timelineEvent of events) {
|
|
449
|
+
const key = eventKey(timelineEvent);
|
|
450
|
+
const order = orderKey(timelineEvent);
|
|
451
|
+
const event = timelineEvent.event;
|
|
452
|
+
if (!isKnownAgentEvent(event)) {
|
|
453
|
+
items.push(Object.freeze({
|
|
454
|
+
kind: "unknown",
|
|
455
|
+
eventKeys: Object.freeze([key]),
|
|
456
|
+
orderKey: order,
|
|
457
|
+
eventType: event.type,
|
|
458
|
+
classification: "unknown-event"
|
|
459
|
+
}));
|
|
460
|
+
previous = timelineEvent;
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
switch (event.type) {
|
|
464
|
+
case "progress": {
|
|
465
|
+
const last = items.at(-1);
|
|
466
|
+
if (last?.kind === "text-activity" && previous !== void 0 && contiguous(previous, timelineEvent)) {
|
|
467
|
+
items[items.length - 1] = Object.freeze({
|
|
468
|
+
...last,
|
|
469
|
+
eventKeys: Object.freeze([...last.eventKeys, key]),
|
|
470
|
+
fragments: Object.freeze([...last.fragments, Object.freeze({ eventKey: key, text: event.text })])
|
|
471
|
+
});
|
|
472
|
+
} else {
|
|
473
|
+
items.push(Object.freeze({
|
|
474
|
+
kind: "text-activity",
|
|
475
|
+
eventKeys: Object.freeze([key]),
|
|
476
|
+
orderKey: order,
|
|
477
|
+
fragments: Object.freeze([Object.freeze({ eventKey: key, text: event.text })])
|
|
478
|
+
}));
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
case "tool_use":
|
|
483
|
+
case "tool_result": {
|
|
484
|
+
const callId = event.toolCallId;
|
|
485
|
+
if (callId === void 0) {
|
|
486
|
+
items.push(unpairedTool(timelineEvent, event));
|
|
487
|
+
break;
|
|
488
|
+
}
|
|
489
|
+
let accumulator = tools.get(callId);
|
|
490
|
+
if (accumulator === void 0) {
|
|
491
|
+
accumulator = { itemIndex: items.length, tool: event.tool };
|
|
492
|
+
tools.set(callId, accumulator);
|
|
493
|
+
items.push(unpairedTool(timelineEvent, event));
|
|
494
|
+
} else if (accumulator.tool !== event.tool) {
|
|
495
|
+
fail2("tool_collision", `Tool call ${callId} changed tool name from ${accumulator.tool} to ${event.tool}.`);
|
|
496
|
+
}
|
|
497
|
+
if (event.type === "tool_use") {
|
|
498
|
+
if (accumulator.use !== void 0) fail2("tool_collision", `Tool call ${callId} has multiple tool_use observations.`);
|
|
499
|
+
accumulator.use = { timelineEvent, event };
|
|
500
|
+
} else {
|
|
501
|
+
if (accumulator.result !== void 0) fail2("tool_collision", `Tool call ${callId} has multiple tool_result observations.`);
|
|
502
|
+
accumulator.result = { timelineEvent, event };
|
|
503
|
+
}
|
|
504
|
+
items[accumulator.itemIndex] = toolItem(accumulator, callId);
|
|
505
|
+
break;
|
|
506
|
+
}
|
|
507
|
+
case "artifact":
|
|
508
|
+
items.push(Object.freeze({
|
|
509
|
+
kind: "artifact",
|
|
510
|
+
eventKeys: Object.freeze([key]),
|
|
511
|
+
orderKey: order,
|
|
512
|
+
name: event.name,
|
|
513
|
+
contentType: event.contentType
|
|
514
|
+
}));
|
|
515
|
+
break;
|
|
516
|
+
case "usage":
|
|
517
|
+
items.push(Object.freeze({
|
|
518
|
+
kind: "usage",
|
|
519
|
+
eventKeys: Object.freeze([key]),
|
|
520
|
+
orderKey: order,
|
|
521
|
+
...event.inputTokens !== void 0 ? { inputTokens: event.inputTokens } : {},
|
|
522
|
+
...event.cachedInputTokens !== void 0 ? { cachedInputTokens: event.cachedInputTokens } : {},
|
|
523
|
+
...event.outputTokens !== void 0 ? { outputTokens: event.outputTokens } : {},
|
|
524
|
+
...event.reasoningTokens !== void 0 ? { reasoningTokens: event.reasoningTokens } : {},
|
|
525
|
+
...event.totalTokens !== void 0 ? { totalTokens: event.totalTokens } : {}
|
|
526
|
+
}));
|
|
527
|
+
break;
|
|
528
|
+
case "error":
|
|
529
|
+
items.push(Object.freeze({
|
|
530
|
+
kind: "error",
|
|
531
|
+
eventKeys: Object.freeze([key]),
|
|
532
|
+
orderKey: order,
|
|
533
|
+
message: event.message
|
|
534
|
+
}));
|
|
535
|
+
break;
|
|
536
|
+
case "turn_end":
|
|
537
|
+
items.push(Object.freeze({ kind: "boundary", eventKeys: Object.freeze([key]), orderKey: order }));
|
|
538
|
+
break;
|
|
539
|
+
case "needs_approval":
|
|
540
|
+
items.push(Object.freeze({
|
|
541
|
+
kind: "unknown",
|
|
542
|
+
eventKeys: Object.freeze([key]),
|
|
543
|
+
orderKey: order,
|
|
544
|
+
eventType: event.type,
|
|
545
|
+
classification: "unsupported-known-event"
|
|
546
|
+
}));
|
|
547
|
+
break;
|
|
548
|
+
default: {
|
|
549
|
+
const unsupported = event;
|
|
550
|
+
items.push(Object.freeze({
|
|
551
|
+
kind: "unknown",
|
|
552
|
+
eventKeys: Object.freeze([key]),
|
|
553
|
+
orderKey: order,
|
|
554
|
+
eventType: unsupported.type,
|
|
555
|
+
classification: "unsupported-known-event"
|
|
556
|
+
}));
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
previous = timelineEvent;
|
|
560
|
+
}
|
|
561
|
+
return Object.freeze(items);
|
|
562
|
+
}
|
|
563
|
+
function createTimelineState(taskId, metadata = DEFAULT_METADATA2) {
|
|
564
|
+
if (!validTaskId2(taskId)) fail2("timeline_input_invalid", "Timeline taskId must contain 1 to 200 characters.");
|
|
565
|
+
return Object.freeze({ taskId, events: Object.freeze([]), metadata: validateMetadata2(metadata) });
|
|
566
|
+
}
|
|
567
|
+
function withTimelineMetadata(state, metadata) {
|
|
568
|
+
if (!validTaskId2(state.taskId)) fail2("timeline_input_invalid", "Timeline state taskId is invalid.");
|
|
569
|
+
return Object.freeze({ taskId: state.taskId, events: state.events, metadata: validateMetadata2(metadata) });
|
|
570
|
+
}
|
|
571
|
+
function foldTimelineEvent(state, input) {
|
|
572
|
+
if (!validTaskId2(state.taskId)) fail2("timeline_input_invalid", "Timeline state taskId is invalid.");
|
|
573
|
+
const event = parseEvent(input);
|
|
574
|
+
if (event.taskId !== state.taskId) {
|
|
575
|
+
fail2("task_mismatch", `Timeline event task ${event.taskId} does not match state task ${state.taskId}.`);
|
|
576
|
+
}
|
|
577
|
+
const identical = state.events.find((existing) => sameIdentity(existing, event));
|
|
578
|
+
if (identical !== void 0) {
|
|
579
|
+
if (structurallyEqual2(identical, event)) return state;
|
|
580
|
+
fail2("identity_collision", "Timeline identity was reused for different event content.");
|
|
581
|
+
}
|
|
582
|
+
if (state.events.some((existing) => sameOrder(existing, event))) {
|
|
583
|
+
fail2("order_collision", "Timeline order coordinates were claimed by different source identities.");
|
|
584
|
+
}
|
|
585
|
+
const events = [...state.events, event].sort(compareEvents);
|
|
586
|
+
return Object.freeze({ taskId: state.taskId, events: Object.freeze(events), metadata: state.metadata });
|
|
587
|
+
}
|
|
588
|
+
function projectTimeline(state) {
|
|
589
|
+
if (!validTaskId2(state.taskId)) fail2("timeline_input_invalid", "Timeline state taskId is invalid.");
|
|
590
|
+
return Object.freeze({
|
|
591
|
+
taskId: state.taskId,
|
|
592
|
+
items: projectItems2(state.events),
|
|
593
|
+
gaps: gapsFor(state.events),
|
|
594
|
+
dropped: state.metadata.dropped,
|
|
595
|
+
...state.metadata.capacity !== void 0 ? { capacity: state.metadata.capacity } : {},
|
|
596
|
+
...state.metadata.expiresAt !== void 0 ? { expiresAt: state.metadata.expiresAt } : {},
|
|
597
|
+
...state.metadata.cursor !== void 0 ? { cursor: state.metadata.cursor } : {}
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
function replayTimeline(tail) {
|
|
601
|
+
if (tail === null || typeof tail !== "object" || !validTaskId2(tail.taskId) || !Array.isArray(tail.entries)) {
|
|
602
|
+
fail2("timeline_input_invalid", "Activity tail must contain a valid taskId and entries array.");
|
|
603
|
+
}
|
|
604
|
+
let state = createTimelineState(tail.taskId, {
|
|
605
|
+
dropped: tail.dropped,
|
|
606
|
+
capacity: tail.capacity,
|
|
607
|
+
expiresAt: tail.expiresAt,
|
|
608
|
+
...tail.cursor !== void 0 ? { cursor: tail.cursor } : {}
|
|
609
|
+
});
|
|
610
|
+
for (const event of tail.entries) state = foldTimelineEvent(state, event);
|
|
611
|
+
return projectTimeline(state);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export { APPROVAL_CORRELATION_STATES, APPROVAL_DECISION_STATES, APPROVAL_LIFECYCLE_STATES, APPROVAL_PROJECTION_ERROR_CODES, ApprovalProjectionError, TIMELINE_FOLD_ERROR_CODES, TOOL_TIMELINE_STATES, TimelineFoldError, createApprovalProjectionState, createTimelineState, foldApprovalObservation, foldApprovalTail, foldTimelineEvent, projectApprovalTimeline, projectTimeline, replayApprovalTimeline, replayTimeline, withApprovalProjectionMetadata, withTimelineMetadata };
|
|
615
|
+
//# sourceMappingURL=index.js.map
|
|
616
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/approval-types.ts","../src/approval-timeline.ts","../src/types.ts","../src/timeline.ts"],"names":["sameIdentity","DEFAULT_METADATA","fail","validTaskId","validateMetadata","structurallyEqual","projectItems"],"mappings":"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","file":"index.js","sourcesContent":["import type { ApprovalObservation } from '@byok-sdk/cloud';\n\nexport const APPROVAL_LIFECYCLE_STATES = [\n 'approval-requested',\n 'approval-responded',\n] as const;\n\nexport type ApprovalLifecycleState = (typeof APPROVAL_LIFECYCLE_STATES)[number];\n\nexport const APPROVAL_DECISION_STATES = ['pending', 'approved', 'rejected'] as const;\n\nexport type ApprovalDecisionState = (typeof APPROVAL_DECISION_STATES)[number];\n\nexport const APPROVAL_CORRELATION_STATES = [\n 'paired',\n 'unpaired-request',\n 'unpaired-resolution',\n] as const;\n\nexport type ApprovalCorrelationState = (typeof APPROVAL_CORRELATION_STATES)[number];\n\nexport interface ApprovalProjectionMetadata {\n readonly dropped: number;\n readonly capacity?: number;\n readonly expiresAt?: string;\n readonly cursor?: number;\n}\n\nexport interface ApprovalProjectionState {\n readonly taskId: string;\n readonly observations: readonly ApprovalObservation[];\n readonly metadata: ApprovalProjectionMetadata;\n}\n\nexport interface ApprovalProjectionItem {\n readonly kind: 'approval';\n readonly approvalId?: string;\n readonly lifecycle: ApprovalLifecycleState;\n readonly status: ApprovalDecisionState;\n readonly correlation: ApprovalCorrelationState;\n readonly firstRevision: number;\n readonly sourceRevisions: readonly number[];\n readonly sourceEnvelopeIds: readonly string[];\n readonly summary?: string;\n readonly decision?: 'approve' | 'reject';\n readonly resolvedBy?: 'local';\n readonly resolvedAt?: string;\n}\n\nexport interface TaskApprovalSnapshot {\n readonly taskId: string;\n readonly items: readonly ApprovalProjectionItem[];\n readonly dropped: number;\n readonly capacity?: number;\n readonly expiresAt?: string;\n readonly cursor?: number;\n}\n\nexport const APPROVAL_PROJECTION_ERROR_CODES = [\n 'approval_input_invalid',\n 'approval_task_mismatch',\n 'approval_identity_collision',\n 'approval_revision_collision',\n 'approval_authority_collision',\n] as const;\n\nexport type ApprovalProjectionErrorCode = (typeof APPROVAL_PROJECTION_ERROR_CODES)[number];\n\nexport class ApprovalProjectionError extends Error {\n readonly code: ApprovalProjectionErrorCode;\n\n constructor(code: ApprovalProjectionErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'ApprovalProjectionError';\n this.code = code;\n }\n}\n","import {\n ApprovalObservationSchema,\n type ApprovalObservation,\n type ApprovalTimelineTail,\n} from '@byok-sdk/cloud';\nimport {\n ApprovalProjectionError,\n type ApprovalProjectionItem,\n type ApprovalProjectionMetadata,\n type ApprovalProjectionState,\n type TaskApprovalSnapshot,\n} from './approval-types';\n\nconst DEFAULT_METADATA: ApprovalProjectionMetadata = Object.freeze({ dropped: 0 });\n\nfunction fail(\n code: ConstructorParameters<typeof ApprovalProjectionError>[0],\n message: string,\n cause?: unknown,\n): never {\n throw new ApprovalProjectionError(code, message, cause === undefined ? undefined : { cause });\n}\n\nfunction validTaskId(taskId: unknown): taskId is string {\n return typeof taskId === 'string' && taskId.length > 0 && taskId.length <= 200;\n}\n\nfunction canonicalTimestamp(value: unknown): value is string {\n return typeof value === 'string'\n && Number.isFinite(Date.parse(value))\n && new Date(value).toISOString() === value;\n}\n\nfunction validateMetadata(metadata: ApprovalProjectionMetadata): ApprovalProjectionMetadata {\n if (!Number.isSafeInteger(metadata.dropped) || metadata.dropped < 0) {\n fail('approval_input_invalid', 'Approval metadata dropped must be a non-negative integer.');\n }\n if (metadata.capacity !== undefined && (!Number.isSafeInteger(metadata.capacity) || metadata.capacity <= 0)) {\n fail('approval_input_invalid', 'Approval metadata capacity must be a positive integer when present.');\n }\n if (metadata.expiresAt !== undefined && !canonicalTimestamp(metadata.expiresAt)) {\n fail('approval_input_invalid', 'Approval metadata expiresAt must be a canonical ISO timestamp when present.');\n }\n if (metadata.cursor !== undefined && (!Number.isSafeInteger(metadata.cursor) || metadata.cursor <= 0)) {\n fail('approval_input_invalid', 'Approval metadata cursor must be a positive integer when present.');\n }\n return Object.freeze({ ...metadata });\n}\n\nfunction parseObservation(value: ApprovalObservation): ApprovalObservation {\n try {\n return Object.freeze(structuredClone(ApprovalObservationSchema.parse(value))) as ApprovalObservation;\n } catch (error) {\n fail('approval_input_invalid', 'Approval observation must satisfy the typed cloud authority.', error);\n }\n}\n\nfunction structurallyEqual(left: unknown, right: unknown, seen = new WeakMap<object, object>()): boolean {\n if (Object.is(left, right)) return true;\n if (left === null || right === null || typeof left !== 'object' || typeof right !== 'object') return false;\n if (Array.isArray(left) !== Array.isArray(right)) return false;\n const prior = seen.get(left);\n if (prior !== undefined) return prior === right;\n seen.set(left, right);\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length\n && left.every((entry, index) => structurallyEqual(entry, right[index], seen));\n }\n const leftRecord = left as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n const leftKeys = Object.keys(leftRecord).sort();\n const rightKeys = Object.keys(rightRecord).sort();\n return leftKeys.length === rightKeys.length\n && leftKeys.every(\n (key, index) => key === rightKeys[index]\n && structurallyEqual(leftRecord[key], rightRecord[key], seen),\n );\n}\n\nfunction freezeItem(item: ApprovalProjectionItem): ApprovalProjectionItem {\n return Object.freeze({\n ...item,\n sourceRevisions: Object.freeze([...item.sourceRevisions]),\n sourceEnvelopeIds: Object.freeze([...item.sourceEnvelopeIds]),\n });\n}\n\ninterface ApprovalAccumulator {\n readonly approvalId: string;\n readonly observations: ApprovalObservation[];\n request?: Extract<ApprovalObservation['event'], { type: 'approval_requested' }>;\n resolution?: Extract<ApprovalObservation['event'], { type: 'approval_resolved' }>;\n}\n\nfunction accumulatedItem(accumulator: ApprovalAccumulator): ApprovalProjectionItem {\n const observations = [...accumulator.observations].sort((left, right) => left.revision - right.revision);\n const resolution = accumulator.resolution;\n return freezeItem({\n kind: 'approval',\n approvalId: accumulator.approvalId,\n lifecycle: resolution === undefined ? 'approval-requested' : 'approval-responded',\n status: resolution === undefined ? 'pending' : resolution.decision === 'approve' ? 'approved' : 'rejected',\n correlation: accumulator.request === undefined\n ? 'unpaired-resolution'\n : resolution === undefined\n ? 'unpaired-request'\n : 'paired',\n firstRevision: observations[0]!.revision,\n sourceRevisions: observations.map(({ revision }) => revision),\n sourceEnvelopeIds: observations.map(({ sourceEnvelopeId }) => sourceEnvelopeId),\n ...(accumulator.request !== undefined ? { summary: accumulator.request.summary } : {}),\n ...(resolution !== undefined ? {\n decision: resolution.decision,\n resolvedBy: resolution.resolvedBy,\n resolvedAt: resolution.at,\n } : {}),\n });\n}\n\nfunction unpairedRequest(observation: ApprovalObservation): ApprovalProjectionItem {\n const event = observation.event;\n if (event.type !== 'approval_requested') {\n fail('approval_input_invalid', 'Only approval requests may omit native approval identity.');\n }\n return freezeItem({\n kind: 'approval',\n lifecycle: 'approval-requested',\n status: 'pending',\n correlation: 'unpaired-request',\n firstRevision: observation.revision,\n sourceRevisions: [observation.revision],\n sourceEnvelopeIds: [observation.sourceEnvelopeId],\n summary: event.summary,\n });\n}\n\nfunction projectItems(observations: readonly ApprovalObservation[]): readonly ApprovalProjectionItem[] {\n const items: ApprovalProjectionItem[] = [];\n const identified = new Map<string, ApprovalAccumulator>();\n\n for (const observation of observations) {\n const event = observation.event;\n if (event.type === 'approval_requested' && event.approvalId === undefined) {\n items.push(unpairedRequest(observation));\n continue;\n }\n\n const approvalId = event.approvalId;\n if (approvalId === undefined) {\n fail('approval_input_invalid', 'Approval resolution requires native approval identity.');\n }\n const accumulator = identified.get(approvalId) ?? { approvalId, observations: [] };\n identified.set(approvalId, accumulator);\n accumulator.observations.push(observation);\n\n if (event.type === 'approval_requested') {\n if (accumulator.request !== undefined && !structurallyEqual(accumulator.request, event)) {\n fail('approval_authority_collision', `Approval ${approvalId} has conflicting request authority.`);\n }\n accumulator.request = event;\n } else {\n if (accumulator.resolution !== undefined && !structurallyEqual(accumulator.resolution, event)) {\n fail('approval_authority_collision', `Approval ${approvalId} has conflicting resolution authority.`);\n }\n accumulator.resolution = event;\n }\n }\n\n for (const accumulator of identified.values()) items.push(accumulatedItem(accumulator));\n return Object.freeze(items.sort((left, right) => left.firstRevision - right.firstRevision));\n}\n\nexport function createApprovalProjectionState(\n taskId: string,\n metadata: ApprovalProjectionMetadata = DEFAULT_METADATA,\n): ApprovalProjectionState {\n if (!validTaskId(taskId)) {\n fail('approval_input_invalid', 'Approval taskId must contain 1 to 200 characters.');\n }\n return Object.freeze({\n taskId,\n observations: Object.freeze([]),\n metadata: validateMetadata(metadata),\n });\n}\n\nexport function withApprovalProjectionMetadata(\n state: ApprovalProjectionState,\n metadata: ApprovalProjectionMetadata,\n): ApprovalProjectionState {\n if (!validTaskId(state.taskId)) fail('approval_input_invalid', 'Approval state taskId is invalid.');\n return Object.freeze({\n taskId: state.taskId,\n observations: state.observations,\n metadata: validateMetadata(metadata),\n });\n}\n\nexport function foldApprovalObservation(\n state: ApprovalProjectionState,\n input: ApprovalObservation,\n): ApprovalProjectionState {\n if (!validTaskId(state.taskId)) fail('approval_input_invalid', 'Approval state taskId is invalid.');\n const observation = parseObservation(input);\n if (observation.taskId !== state.taskId) {\n fail(\n 'approval_task_mismatch',\n `Approval observation task ${observation.taskId} does not match state task ${state.taskId}.`,\n );\n }\n const identical = state.observations.find(\n ({ sourceEnvelopeId }) => sourceEnvelopeId === observation.sourceEnvelopeId,\n );\n if (identical !== undefined) {\n if (structurallyEqual(identical, observation)) return state;\n fail('approval_identity_collision', 'Approval source identity was reused for different content.');\n }\n if (state.observations.some(({ revision }) => revision === observation.revision)) {\n fail('approval_revision_collision', 'Approval revision was claimed by different source identity.');\n }\n const observations = [...state.observations, observation]\n .sort((left, right) => left.revision - right.revision);\n return Object.freeze({\n taskId: state.taskId,\n observations: Object.freeze(observations),\n metadata: state.metadata,\n });\n}\n\nexport function foldApprovalTail(\n state: ApprovalProjectionState,\n tail: ApprovalTimelineTail,\n): ApprovalProjectionState {\n if (tail === null || typeof tail !== 'object' || !validTaskId(tail.taskId) || !Array.isArray(tail.entries)) {\n fail('approval_input_invalid', 'Approval tail must contain a valid taskId and entries array.');\n }\n if (tail.taskId !== state.taskId) {\n fail('approval_task_mismatch', `Approval tail task ${tail.taskId} does not match state task ${state.taskId}.`);\n }\n const revisions = tail.entries.map(({ revision }) => revision);\n if (revisions.some((revision) => !Number.isSafeInteger(revision) || revision <= 0)) {\n fail('approval_input_invalid', 'Approval tail revisions must be positive integers.');\n }\n if (revisions.some((revision, index) => index > 0 && revision <= revisions[index - 1]!)) {\n fail('approval_input_invalid', 'Approval tail entries must be strictly ordered by native revision.');\n }\n if (tail.cursor !== revisions.at(-1)) {\n fail('approval_input_invalid', 'Approval tail cursor must equal its last retained revision.');\n }\n const stateCursor = state.observations.at(-1)?.revision;\n if (stateCursor !== undefined && (tail.cursor === undefined || tail.cursor < stateCursor)) {\n fail('approval_input_invalid', 'Approval tail cursor must not move behind incremental state.');\n }\n for (const observation of tail.entries) {\n const sameIdentity = state.observations.find(\n ({ sourceEnvelopeId }) => sourceEnvelopeId === observation.sourceEnvelopeId,\n );\n if (sameIdentity !== undefined && !structurallyEqual(sameIdentity, observation)) {\n fail('approval_identity_collision', 'Approval source identity changed across tail snapshots.');\n }\n const sameRevision = state.observations.find(({ revision }) => revision === observation.revision);\n if (sameRevision !== undefined && sameRevision.sourceEnvelopeId !== observation.sourceEnvelopeId) {\n fail('approval_revision_collision', 'Approval revision changed source identity across tail snapshots.');\n }\n }\n let next = createApprovalProjectionState(state.taskId, {\n dropped: tail.dropped,\n capacity: tail.capacity,\n expiresAt: tail.expiresAt,\n ...(tail.cursor !== undefined ? { cursor: tail.cursor } : {}),\n });\n for (const observation of tail.entries) next = foldApprovalObservation(next, observation);\n return next;\n}\n\nexport function projectApprovalTimeline(state: ApprovalProjectionState): TaskApprovalSnapshot {\n if (!validTaskId(state.taskId)) fail('approval_input_invalid', 'Approval state taskId is invalid.');\n return Object.freeze({\n taskId: state.taskId,\n items: projectItems(state.observations),\n dropped: state.metadata.dropped,\n ...(state.metadata.capacity !== undefined ? { capacity: state.metadata.capacity } : {}),\n ...(state.metadata.expiresAt !== undefined ? { expiresAt: state.metadata.expiresAt } : {}),\n ...(state.metadata.cursor !== undefined ? { cursor: state.metadata.cursor } : {}),\n });\n}\n\nexport function replayApprovalTimeline(tail: ApprovalTimelineTail): TaskApprovalSnapshot {\n if (tail === null || typeof tail !== 'object' || !validTaskId(tail.taskId) || !Array.isArray(tail.entries)) {\n fail('approval_input_invalid', 'Approval tail must contain a valid taskId and entries array.');\n }\n return projectApprovalTimeline(foldApprovalTail(createApprovalProjectionState(tail.taskId), tail));\n}\n","import type { ActivityCursor, TimelineEvent } from '@byok-sdk/cloud';\n\nexport interface TimelineEventKey {\n readonly sourceEnvelopeId: string;\n readonly eventIndex: number;\n}\n\nexport interface TimelineOrderKey {\n readonly taskId: string;\n readonly batchSeq: number;\n readonly eventIndex: number;\n}\n\nexport interface TimelineMetadata {\n readonly dropped: number;\n readonly capacity?: number;\n readonly expiresAt?: string;\n readonly cursor?: ActivityCursor;\n}\n\nexport interface TimelineState {\n readonly taskId: string;\n readonly events: readonly TimelineEvent[];\n readonly metadata: TimelineMetadata;\n}\n\nexport interface TimelineGap {\n readonly kind: 'batch' | 'event';\n readonly after: TimelineOrderKey;\n readonly before: TimelineOrderKey;\n readonly missing: number;\n}\n\ninterface TimelineItemBase {\n readonly eventKeys: readonly TimelineEventKey[];\n readonly orderKey: TimelineOrderKey;\n}\n\nexport interface TimelineTextFragment {\n readonly eventKey: TimelineEventKey;\n readonly text: string;\n}\n\nexport interface TextActivityTimelineItem extends TimelineItemBase {\n readonly kind: 'text-activity';\n readonly fragments: readonly TimelineTextFragment[];\n}\n\nexport const TOOL_TIMELINE_STATES = [\n 'input-available',\n 'output-available',\n 'output-error',\n 'output-unknown',\n 'unpaired-use',\n 'unpaired-result',\n] as const;\n\nexport type ToolTimelineState = (typeof TOOL_TIMELINE_STATES)[number];\n\nexport interface ToolTimelineItem extends TimelineItemBase {\n readonly kind: 'tool';\n readonly tool: string;\n readonly toolCallId?: string;\n readonly state: ToolTimelineState;\n readonly input?: unknown;\n readonly output?: unknown;\n}\n\nexport interface ArtifactTimelineItem extends TimelineItemBase {\n readonly kind: 'artifact';\n readonly name: string;\n readonly contentType: string;\n}\n\nexport interface UsageTimelineItem extends TimelineItemBase {\n readonly kind: 'usage';\n readonly inputTokens?: number;\n readonly cachedInputTokens?: number;\n readonly outputTokens?: number;\n readonly reasoningTokens?: number;\n readonly totalTokens?: number;\n}\n\nexport interface ErrorTimelineItem extends TimelineItemBase {\n readonly kind: 'error';\n readonly message: string;\n}\n\nexport interface BoundaryTimelineItem extends TimelineItemBase {\n readonly kind: 'boundary';\n}\n\nexport interface UnknownTimelineItem extends TimelineItemBase {\n readonly kind: 'unknown';\n readonly eventType: string;\n readonly classification: 'unknown-event' | 'unsupported-known-event';\n}\n\nexport type TimelineItem =\n | TextActivityTimelineItem\n | ToolTimelineItem\n | ArtifactTimelineItem\n | UsageTimelineItem\n | ErrorTimelineItem\n | BoundaryTimelineItem\n | UnknownTimelineItem;\n\nexport interface TaskTimelineSnapshot {\n readonly taskId: string;\n readonly items: readonly TimelineItem[];\n readonly gaps: readonly TimelineGap[];\n readonly dropped: number;\n readonly capacity?: number;\n readonly expiresAt?: string;\n readonly cursor?: ActivityCursor;\n}\n\nexport const TIMELINE_FOLD_ERROR_CODES = [\n 'timeline_input_invalid',\n 'task_mismatch',\n 'identity_collision',\n 'order_collision',\n 'tool_collision',\n] as const;\n\nexport type TimelineFoldErrorCode = (typeof TIMELINE_FOLD_ERROR_CODES)[number];\n\nexport class TimelineFoldError extends Error {\n readonly code: TimelineFoldErrorCode;\n\n constructor(code: TimelineFoldErrorCode, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = 'TimelineFoldError';\n this.code = code;\n }\n}\n","import {\n TimelineEventSchema,\n type ActivityTail,\n type TimelineEvent,\n} from '@byok-sdk/cloud';\nimport { isKnownAgentEvent, type AgentEvent } from '@byok-sdk/protocol';\nimport {\n TimelineFoldError,\n type TaskTimelineSnapshot,\n type TimelineEventKey,\n type TimelineGap,\n type TimelineItem,\n type TimelineMetadata,\n type TimelineOrderKey,\n type TimelineState,\n type ToolTimelineItem,\n} from './types';\n\ntype ToolUseEvent = Extract<AgentEvent, { type: 'tool_use' }>;\ntype ToolResultEvent = Extract<AgentEvent, { type: 'tool_result' }>;\n\ninterface ToolObservation {\n readonly timelineEvent: TimelineEvent;\n readonly event: ToolUseEvent | ToolResultEvent;\n}\n\ninterface ToolAccumulator {\n readonly itemIndex: number;\n readonly tool: string;\n use?: ToolObservation;\n result?: ToolObservation;\n}\n\nconst DEFAULT_METADATA: TimelineMetadata = Object.freeze({ dropped: 0 });\n\nfunction compareEvents(left: TimelineEvent, right: TimelineEvent): number {\n return left.batchSeq - right.batchSeq || left.eventIndex - right.eventIndex;\n}\n\nfunction fail(code: ConstructorParameters<typeof TimelineFoldError>[0], message: string, cause?: unknown): never {\n throw new TimelineFoldError(code, message, cause === undefined ? undefined : { cause });\n}\n\nfunction validTaskId(taskId: unknown): taskId is string {\n return typeof taskId === 'string' && taskId.length > 0 && taskId.length <= 200;\n}\n\nfunction validateMetadata(metadata: TimelineMetadata): TimelineMetadata {\n if (!Number.isSafeInteger(metadata.dropped) || metadata.dropped < 0) {\n fail('timeline_input_invalid', 'Timeline metadata dropped must be a non-negative integer.');\n }\n if (metadata.capacity !== undefined && (!Number.isSafeInteger(metadata.capacity) || metadata.capacity <= 0)) {\n fail('timeline_input_invalid', 'Timeline metadata capacity must be a positive integer when present.');\n }\n if (metadata.expiresAt !== undefined && (\n typeof metadata.expiresAt !== 'string'\n || !Number.isFinite(Date.parse(metadata.expiresAt))\n || new Date(metadata.expiresAt).toISOString() !== metadata.expiresAt\n )) {\n fail('timeline_input_invalid', 'Timeline metadata expiresAt must be a canonical ISO timestamp when present.');\n }\n if (metadata.cursor !== undefined && (\n !Number.isSafeInteger(metadata.cursor.batchSeq) || metadata.cursor.batchSeq < 0\n || !Number.isSafeInteger(metadata.cursor.eventIndex) || metadata.cursor.eventIndex < 0\n )) {\n fail('timeline_input_invalid', 'Timeline metadata cursor must contain non-negative integer coordinates.');\n }\n return Object.freeze({ ...metadata, cursor: metadata.cursor && Object.freeze({ ...metadata.cursor }) });\n}\n\nfunction deepFreeze<T>(value: T, seen = new WeakSet<object>()): T {\n if (value === null || typeof value !== 'object') return value;\n if (seen.has(value)) return value;\n seen.add(value);\n for (const nested of Object.values(value as Record<string, unknown>)) deepFreeze(nested, seen);\n return Object.freeze(value);\n}\n\nfunction assertWireValue(value: unknown, seen = new WeakSet<object>()): void {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return;\n if (typeof value === 'number') {\n if (Number.isFinite(value)) return;\n fail('timeline_input_invalid', 'Timeline event payload numbers must be finite JSON values.');\n }\n if (typeof value !== 'object') {\n fail('timeline_input_invalid', 'Timeline event payloads must contain JSON-compatible values.');\n }\n if (seen.has(value)) fail('timeline_input_invalid', 'Timeline event payloads must not contain cycles.');\n seen.add(value);\n if (Array.isArray(value)) {\n for (const entry of value) assertWireValue(entry, seen);\n } else {\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n fail('timeline_input_invalid', 'Timeline event payload objects must be plain JSON records.');\n }\n for (const entry of Object.values(value as Record<string, unknown>)) assertWireValue(entry, seen);\n }\n seen.delete(value);\n}\n\nfunction parseEvent(value: TimelineEvent): TimelineEvent {\n try {\n const parsed = TimelineEventSchema.parse(value);\n assertWireValue(parsed);\n return deepFreeze(structuredClone(parsed)) as TimelineEvent;\n } catch (error) {\n fail('timeline_input_invalid', 'Timeline events must satisfy the typed cloud activity authority.', error);\n }\n}\n\nfunction structurallyEqual(left: unknown, right: unknown, seen = new WeakMap<object, object>()): boolean {\n if (Object.is(left, right)) return true;\n if (left === null || right === null || typeof left !== 'object' || typeof right !== 'object') return false;\n if (Array.isArray(left) !== Array.isArray(right)) return false;\n const prior = seen.get(left);\n if (prior !== undefined) return prior === right;\n seen.set(left, right);\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((entry, index) => structurallyEqual(entry, right[index], seen));\n }\n const leftRecord = left as Record<string, unknown>;\n const rightRecord = right as Record<string, unknown>;\n const leftKeys = Object.keys(leftRecord).sort();\n const rightKeys = Object.keys(rightRecord).sort();\n return leftKeys.length === rightKeys.length\n && leftKeys.every((key, index) => key === rightKeys[index] && structurallyEqual(leftRecord[key], rightRecord[key], seen));\n}\n\nfunction eventKey(event: TimelineEvent): TimelineEventKey {\n return Object.freeze({ sourceEnvelopeId: event.sourceEnvelopeId, eventIndex: event.eventIndex });\n}\n\nfunction orderKey(event: TimelineEvent): TimelineOrderKey {\n return Object.freeze({ taskId: event.taskId, batchSeq: event.batchSeq, eventIndex: event.eventIndex });\n}\n\nfunction sameIdentity(left: TimelineEvent, right: TimelineEvent): boolean {\n return left.sourceEnvelopeId === right.sourceEnvelopeId && left.eventIndex === right.eventIndex;\n}\n\nfunction sameOrder(left: TimelineEvent, right: TimelineEvent): boolean {\n return left.batchSeq === right.batchSeq && left.eventIndex === right.eventIndex;\n}\n\nfunction contiguous(left: TimelineEvent, right: TimelineEvent): boolean {\n return (left.batchSeq === right.batchSeq && right.eventIndex === left.eventIndex + 1)\n || (right.batchSeq === left.batchSeq + 1 && right.eventIndex === 0);\n}\n\nfunction gapsFor(events: readonly TimelineEvent[]): readonly TimelineGap[] {\n const gaps: TimelineGap[] = [];\n for (let index = 1; index < events.length; index += 1) {\n const previous = events[index - 1]!;\n const current = events[index]!;\n if (current.batchSeq === previous.batchSeq && current.eventIndex > previous.eventIndex + 1) {\n gaps.push(Object.freeze({\n kind: 'event',\n after: orderKey(previous),\n before: orderKey(current),\n missing: current.eventIndex - previous.eventIndex - 1,\n }));\n continue;\n }\n if (current.batchSeq > previous.batchSeq) {\n if (current.batchSeq > previous.batchSeq + 1) {\n gaps.push(Object.freeze({\n kind: 'batch',\n after: orderKey(previous),\n before: orderKey(current),\n missing: current.batchSeq - previous.batchSeq - 1,\n }));\n }\n if (current.eventIndex > 0) {\n gaps.push(Object.freeze({\n kind: 'event',\n after: orderKey(previous),\n before: orderKey(current),\n missing: current.eventIndex,\n }));\n }\n }\n }\n return Object.freeze(gaps);\n}\n\nfunction toolItem(accumulator: ToolAccumulator, toolCallId: string): ToolTimelineItem {\n const observations = [accumulator.use?.timelineEvent, accumulator.result?.timelineEvent]\n .filter((event): event is TimelineEvent => event !== undefined)\n .sort(compareEvents);\n const use = accumulator.use?.event as ToolUseEvent | undefined;\n const result = accumulator.result?.event as ToolResultEvent | undefined;\n const state = use === undefined\n ? 'unpaired-result'\n : result === undefined\n ? 'input-available'\n : result.isError === true\n ? 'output-error'\n : result.isError === false\n ? 'output-available'\n : 'output-unknown';\n return Object.freeze({\n kind: 'tool',\n eventKeys: Object.freeze(observations.map(eventKey)),\n orderKey: orderKey(observations[0]!),\n tool: accumulator.tool,\n toolCallId,\n state,\n ...(use && Object.hasOwn(use, 'input') ? { input: use.input } : {}),\n ...(result && Object.hasOwn(result, 'output') ? { output: result.output } : {}),\n });\n}\n\nfunction unpairedTool(event: TimelineEvent, observation: ToolUseEvent | ToolResultEvent): ToolTimelineItem {\n return Object.freeze({\n kind: 'tool',\n eventKeys: Object.freeze([eventKey(event)]),\n orderKey: orderKey(event),\n tool: observation.tool,\n state: observation.type === 'tool_use' ? 'unpaired-use' : 'unpaired-result',\n ...(observation.type === 'tool_use' && Object.hasOwn(observation, 'input') ? { input: observation.input } : {}),\n ...(observation.type === 'tool_result' && Object.hasOwn(observation, 'output') ? { output: observation.output } : {}),\n });\n}\n\nfunction projectItems(events: readonly TimelineEvent[]): readonly TimelineItem[] {\n const items: TimelineItem[] = [];\n const tools = new Map<string, ToolAccumulator>();\n let previous: TimelineEvent | undefined;\n\n for (const timelineEvent of events) {\n const key = eventKey(timelineEvent);\n const order = orderKey(timelineEvent);\n const event = timelineEvent.event;\n if (!isKnownAgentEvent(event)) {\n items.push(Object.freeze({\n kind: 'unknown', eventKeys: Object.freeze([key]), orderKey: order,\n eventType: event.type, classification: 'unknown-event',\n }));\n previous = timelineEvent;\n continue;\n }\n\n switch (event.type) {\n case 'progress': {\n const last = items.at(-1);\n if (last?.kind === 'text-activity' && previous !== undefined && contiguous(previous, timelineEvent)) {\n items[items.length - 1] = Object.freeze({\n ...last,\n eventKeys: Object.freeze([...last.eventKeys, key]),\n fragments: Object.freeze([...last.fragments, Object.freeze({ eventKey: key, text: event.text })]),\n });\n } else {\n items.push(Object.freeze({\n kind: 'text-activity', eventKeys: Object.freeze([key]), orderKey: order,\n fragments: Object.freeze([Object.freeze({ eventKey: key, text: event.text })]),\n }));\n }\n break;\n }\n case 'tool_use':\n case 'tool_result': {\n const callId = event.toolCallId;\n if (callId === undefined) {\n items.push(unpairedTool(timelineEvent, event));\n break;\n }\n let accumulator = tools.get(callId);\n if (accumulator === undefined) {\n accumulator = { itemIndex: items.length, tool: event.tool };\n tools.set(callId, accumulator);\n items.push(unpairedTool(timelineEvent, event));\n } else if (accumulator.tool !== event.tool) {\n fail('tool_collision', `Tool call ${callId} changed tool name from ${accumulator.tool} to ${event.tool}.`);\n }\n if (event.type === 'tool_use') {\n if (accumulator.use !== undefined) fail('tool_collision', `Tool call ${callId} has multiple tool_use observations.`);\n accumulator.use = { timelineEvent, event };\n } else {\n if (accumulator.result !== undefined) fail('tool_collision', `Tool call ${callId} has multiple tool_result observations.`);\n accumulator.result = { timelineEvent, event };\n }\n items[accumulator.itemIndex] = toolItem(accumulator, callId);\n break;\n }\n case 'artifact':\n items.push(Object.freeze({\n kind: 'artifact', eventKeys: Object.freeze([key]), orderKey: order,\n name: event.name, contentType: event.contentType,\n }));\n break;\n case 'usage':\n items.push(Object.freeze({\n kind: 'usage', eventKeys: Object.freeze([key]), orderKey: order,\n ...(event.inputTokens !== undefined ? { inputTokens: event.inputTokens } : {}),\n ...(event.cachedInputTokens !== undefined ? { cachedInputTokens: event.cachedInputTokens } : {}),\n ...(event.outputTokens !== undefined ? { outputTokens: event.outputTokens } : {}),\n ...(event.reasoningTokens !== undefined ? { reasoningTokens: event.reasoningTokens } : {}),\n ...(event.totalTokens !== undefined ? { totalTokens: event.totalTokens } : {}),\n }));\n break;\n case 'error':\n items.push(Object.freeze({\n kind: 'error', eventKeys: Object.freeze([key]), orderKey: order, message: event.message,\n }));\n break;\n case 'turn_end':\n items.push(Object.freeze({ kind: 'boundary', eventKeys: Object.freeze([key]), orderKey: order }));\n break;\n case 'needs_approval':\n items.push(Object.freeze({\n kind: 'unknown', eventKeys: Object.freeze([key]), orderKey: order,\n eventType: event.type, classification: 'unsupported-known-event',\n }));\n break;\n default: {\n // A newer protocol package can classify a variant as known even when\n // this older UI runtime has no semantic projection for it. Preserve\n // its position without interpreting or exposing its opaque payload.\n const unsupported = event as { readonly type: string };\n items.push(Object.freeze({\n kind: 'unknown', eventKeys: Object.freeze([key]), orderKey: order,\n eventType: unsupported.type, classification: 'unsupported-known-event',\n }));\n }\n }\n previous = timelineEvent;\n }\n return Object.freeze(items);\n}\n\nexport function createTimelineState(taskId: string, metadata: TimelineMetadata = DEFAULT_METADATA): TimelineState {\n if (!validTaskId(taskId)) fail('timeline_input_invalid', 'Timeline taskId must contain 1 to 200 characters.');\n return Object.freeze({ taskId, events: Object.freeze([]), metadata: validateMetadata(metadata) });\n}\n\nexport function withTimelineMetadata(state: TimelineState, metadata: TimelineMetadata): TimelineState {\n if (!validTaskId(state.taskId)) fail('timeline_input_invalid', 'Timeline state taskId is invalid.');\n return Object.freeze({ taskId: state.taskId, events: state.events, metadata: validateMetadata(metadata) });\n}\n\nexport function foldTimelineEvent(state: TimelineState, input: TimelineEvent): TimelineState {\n if (!validTaskId(state.taskId)) fail('timeline_input_invalid', 'Timeline state taskId is invalid.');\n const event = parseEvent(input);\n if (event.taskId !== state.taskId) {\n fail('task_mismatch', `Timeline event task ${event.taskId} does not match state task ${state.taskId}.`);\n }\n const identical = state.events.find((existing) => sameIdentity(existing, event));\n if (identical !== undefined) {\n if (structurallyEqual(identical, event)) return state;\n fail('identity_collision', 'Timeline identity was reused for different event content.');\n }\n if (state.events.some((existing) => sameOrder(existing, event))) {\n fail('order_collision', 'Timeline order coordinates were claimed by different source identities.');\n }\n const events = [...state.events, event].sort(compareEvents);\n return Object.freeze({ taskId: state.taskId, events: Object.freeze(events), metadata: state.metadata });\n}\n\nexport function projectTimeline(state: TimelineState): TaskTimelineSnapshot {\n if (!validTaskId(state.taskId)) fail('timeline_input_invalid', 'Timeline state taskId is invalid.');\n return Object.freeze({\n taskId: state.taskId,\n items: projectItems(state.events),\n gaps: gapsFor(state.events),\n dropped: state.metadata.dropped,\n ...(state.metadata.capacity !== undefined ? { capacity: state.metadata.capacity } : {}),\n ...(state.metadata.expiresAt !== undefined ? { expiresAt: state.metadata.expiresAt } : {}),\n ...(state.metadata.cursor !== undefined ? { cursor: state.metadata.cursor } : {}),\n });\n}\n\nexport function replayTimeline(tail: ActivityTail): TaskTimelineSnapshot {\n if (tail === null || typeof tail !== 'object' || !validTaskId(tail.taskId) || !Array.isArray(tail.entries)) {\n fail('timeline_input_invalid', 'Activity tail must contain a valid taskId and entries array.');\n }\n let state = createTimelineState(tail.taskId, {\n dropped: tail.dropped,\n capacity: tail.capacity,\n expiresAt: tail.expiresAt,\n ...(tail.cursor !== undefined ? { cursor: tail.cursor } : {}),\n });\n for (const event of tail.entries) state = foldTimelineEvent(state, event);\n return projectTimeline(state);\n}\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ActivityTail, type TimelineEvent } from '@byok-sdk/cloud';
|
|
2
|
+
import { type TaskTimelineSnapshot, type TimelineMetadata, type TimelineState } from './types';
|
|
3
|
+
export declare function createTimelineState(taskId: string, metadata?: TimelineMetadata): TimelineState;
|
|
4
|
+
export declare function withTimelineMetadata(state: TimelineState, metadata: TimelineMetadata): TimelineState;
|
|
5
|
+
export declare function foldTimelineEvent(state: TimelineState, input: TimelineEvent): TimelineState;
|
|
6
|
+
export declare function projectTimeline(state: TimelineState): TaskTimelineSnapshot;
|
|
7
|
+
export declare function replayTimeline(tail: ActivityTail): TaskTimelineSnapshot;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { ActivityCursor, TimelineEvent } from '@byok-sdk/cloud';
|
|
2
|
+
export interface TimelineEventKey {
|
|
3
|
+
readonly sourceEnvelopeId: string;
|
|
4
|
+
readonly eventIndex: number;
|
|
5
|
+
}
|
|
6
|
+
export interface TimelineOrderKey {
|
|
7
|
+
readonly taskId: string;
|
|
8
|
+
readonly batchSeq: number;
|
|
9
|
+
readonly eventIndex: number;
|
|
10
|
+
}
|
|
11
|
+
export interface TimelineMetadata {
|
|
12
|
+
readonly dropped: number;
|
|
13
|
+
readonly capacity?: number;
|
|
14
|
+
readonly expiresAt?: string;
|
|
15
|
+
readonly cursor?: ActivityCursor;
|
|
16
|
+
}
|
|
17
|
+
export interface TimelineState {
|
|
18
|
+
readonly taskId: string;
|
|
19
|
+
readonly events: readonly TimelineEvent[];
|
|
20
|
+
readonly metadata: TimelineMetadata;
|
|
21
|
+
}
|
|
22
|
+
export interface TimelineGap {
|
|
23
|
+
readonly kind: 'batch' | 'event';
|
|
24
|
+
readonly after: TimelineOrderKey;
|
|
25
|
+
readonly before: TimelineOrderKey;
|
|
26
|
+
readonly missing: number;
|
|
27
|
+
}
|
|
28
|
+
interface TimelineItemBase {
|
|
29
|
+
readonly eventKeys: readonly TimelineEventKey[];
|
|
30
|
+
readonly orderKey: TimelineOrderKey;
|
|
31
|
+
}
|
|
32
|
+
export interface TimelineTextFragment {
|
|
33
|
+
readonly eventKey: TimelineEventKey;
|
|
34
|
+
readonly text: string;
|
|
35
|
+
}
|
|
36
|
+
export interface TextActivityTimelineItem extends TimelineItemBase {
|
|
37
|
+
readonly kind: 'text-activity';
|
|
38
|
+
readonly fragments: readonly TimelineTextFragment[];
|
|
39
|
+
}
|
|
40
|
+
export declare const TOOL_TIMELINE_STATES: readonly ['input-available', 'output-available', 'output-error', 'output-unknown', 'unpaired-use', 'unpaired-result'];
|
|
41
|
+
export type ToolTimelineState = (typeof TOOL_TIMELINE_STATES)[number];
|
|
42
|
+
export interface ToolTimelineItem extends TimelineItemBase {
|
|
43
|
+
readonly kind: 'tool';
|
|
44
|
+
readonly tool: string;
|
|
45
|
+
readonly toolCallId?: string;
|
|
46
|
+
readonly state: ToolTimelineState;
|
|
47
|
+
readonly input?: unknown;
|
|
48
|
+
readonly output?: unknown;
|
|
49
|
+
}
|
|
50
|
+
export interface ArtifactTimelineItem extends TimelineItemBase {
|
|
51
|
+
readonly kind: 'artifact';
|
|
52
|
+
readonly name: string;
|
|
53
|
+
readonly contentType: string;
|
|
54
|
+
}
|
|
55
|
+
export interface UsageTimelineItem extends TimelineItemBase {
|
|
56
|
+
readonly kind: 'usage';
|
|
57
|
+
readonly inputTokens?: number;
|
|
58
|
+
readonly cachedInputTokens?: number;
|
|
59
|
+
readonly outputTokens?: number;
|
|
60
|
+
readonly reasoningTokens?: number;
|
|
61
|
+
readonly totalTokens?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface ErrorTimelineItem extends TimelineItemBase {
|
|
64
|
+
readonly kind: 'error';
|
|
65
|
+
readonly message: string;
|
|
66
|
+
}
|
|
67
|
+
export interface BoundaryTimelineItem extends TimelineItemBase {
|
|
68
|
+
readonly kind: 'boundary';
|
|
69
|
+
}
|
|
70
|
+
export interface UnknownTimelineItem extends TimelineItemBase {
|
|
71
|
+
readonly kind: 'unknown';
|
|
72
|
+
readonly eventType: string;
|
|
73
|
+
readonly classification: 'unknown-event' | 'unsupported-known-event';
|
|
74
|
+
}
|
|
75
|
+
export type TimelineItem = TextActivityTimelineItem | ToolTimelineItem | ArtifactTimelineItem | UsageTimelineItem | ErrorTimelineItem | BoundaryTimelineItem | UnknownTimelineItem;
|
|
76
|
+
export interface TaskTimelineSnapshot {
|
|
77
|
+
readonly taskId: string;
|
|
78
|
+
readonly items: readonly TimelineItem[];
|
|
79
|
+
readonly gaps: readonly TimelineGap[];
|
|
80
|
+
readonly dropped: number;
|
|
81
|
+
readonly capacity?: number;
|
|
82
|
+
readonly expiresAt?: string;
|
|
83
|
+
readonly cursor?: ActivityCursor;
|
|
84
|
+
}
|
|
85
|
+
export declare const TIMELINE_FOLD_ERROR_CODES: readonly ['timeline_input_invalid', 'task_mismatch', 'identity_collision', 'order_collision', 'tool_collision'];
|
|
86
|
+
export type TimelineFoldErrorCode = (typeof TIMELINE_FOLD_ERROR_CODES)[number];
|
|
87
|
+
export declare class TimelineFoldError extends Error {
|
|
88
|
+
readonly code: TimelineFoldErrorCode;
|
|
89
|
+
constructor(code: TimelineFoldErrorCode, message: string, options?: ErrorOptions);
|
|
90
|
+
}
|
|
91
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@byok-sdk/ui-runtime",
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "React-free deterministic Live Activity Timeline projection for BYOK task activity",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Ancienttwo/byok-sdk.git",
|
|
10
|
+
"directory": "packages/ui-runtime"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Ancienttwo/byok-sdk/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/Ancienttwo/byok-sdk#readme",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22.22.0"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"main": "./dist/index.js",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"import": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup && tsc -p tsconfig.build.json",
|
|
40
|
+
"dev": "tsup --watch",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"clean": "rm -rf dist"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@byok-sdk/cloud": "0.4.2",
|
|
48
|
+
"@byok-sdk/protocol": "0.4.2"
|
|
49
|
+
}
|
|
50
|
+
}
|