@openharness/core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Maps a stream of SessionEvents into a ReadableStream of AI SDK 5
3
+ * UIMessageChunks. Handles text/reasoning part lifecycle (start/end),
4
+ * tool mapping, and OH-specific data parts for subagents, compaction,
5
+ * retry, and turn lifecycle.
6
+ */
7
+ export function sessionEventsToUIStream(events, options) {
8
+ return new ReadableStream({
9
+ async start(controller) {
10
+ let partCounter = 0;
11
+ const nextId = () => `oh-${++partCounter}`;
12
+ // Track active text/reasoning part IDs for start/end lifecycle
13
+ let textPartId = null;
14
+ let reasoningPartId = null;
15
+ // Track subagent start times for duration calculation
16
+ const subagentStartTimes = new Map();
17
+ const enqueue = (chunk) => controller.enqueue(chunk);
18
+ const endTextPart = () => {
19
+ if (textPartId) {
20
+ enqueue({ type: "text-end", id: textPartId });
21
+ textPartId = null;
22
+ }
23
+ };
24
+ const endReasoningPart = () => {
25
+ if (reasoningPartId) {
26
+ enqueue({ type: "reasoning-end", id: reasoningPartId });
27
+ reasoningPartId = null;
28
+ }
29
+ };
30
+ // Emit stream start
31
+ enqueue({ type: "start" });
32
+ try {
33
+ for await (const event of events) {
34
+ if (options?.signal?.aborted) {
35
+ enqueue({ type: "abort", reason: "aborted" });
36
+ break;
37
+ }
38
+ switch (event.type) {
39
+ // ── Text ──────────────────────────────────────────────
40
+ case "text.delta": {
41
+ if (!textPartId) {
42
+ endReasoningPart();
43
+ textPartId = nextId();
44
+ enqueue({ type: "text-start", id: textPartId });
45
+ }
46
+ enqueue({ type: "text-delta", id: textPartId, delta: event.text });
47
+ break;
48
+ }
49
+ case "text.done": {
50
+ endTextPart();
51
+ break;
52
+ }
53
+ // ── Reasoning ─────────────────────────────────────────
54
+ case "reasoning.delta": {
55
+ if (!reasoningPartId) {
56
+ endTextPart();
57
+ reasoningPartId = nextId();
58
+ enqueue({ type: "reasoning-start", id: reasoningPartId });
59
+ }
60
+ enqueue({
61
+ type: "reasoning-delta",
62
+ id: reasoningPartId,
63
+ delta: event.text,
64
+ });
65
+ break;
66
+ }
67
+ case "reasoning.done": {
68
+ endReasoningPart();
69
+ break;
70
+ }
71
+ // ── Tools ─────────────────────────────────────────────
72
+ case "tool.start": {
73
+ endTextPart();
74
+ endReasoningPart();
75
+ // Emit tool-input-start + tool-input-available (OH has full input at start)
76
+ enqueue({
77
+ type: "tool-input-start",
78
+ toolCallId: event.toolCallId,
79
+ toolName: event.toolName,
80
+ });
81
+ enqueue({
82
+ type: "tool-input-available",
83
+ toolCallId: event.toolCallId,
84
+ toolName: event.toolName,
85
+ input: event.input,
86
+ });
87
+ // If this is a task tool (subagent), emit subagent start data part
88
+ if (event.toolName === "task") {
89
+ const input = event.input;
90
+ if (input.agent) {
91
+ subagentStartTimes.set(event.toolCallId, Date.now());
92
+ enqueue({
93
+ type: "data-oh:subagent.start",
94
+ data: {
95
+ agentName: input.agent,
96
+ task: input.prompt ?? "",
97
+ },
98
+ });
99
+ }
100
+ }
101
+ break;
102
+ }
103
+ case "tool.done": {
104
+ enqueue({
105
+ type: "tool-output-available",
106
+ toolCallId: event.toolCallId,
107
+ output: event.output,
108
+ });
109
+ // If this is a task tool (subagent), emit subagent done data part
110
+ if (event.toolName === "task") {
111
+ const startTime = subagentStartTimes.get(event.toolCallId);
112
+ const durationMs = startTime ? Date.now() - startTime : 0;
113
+ subagentStartTimes.delete(event.toolCallId);
114
+ enqueue({
115
+ type: "data-oh:subagent.done",
116
+ data: {
117
+ agentName: event.toolName,
118
+ durationMs,
119
+ },
120
+ });
121
+ }
122
+ break;
123
+ }
124
+ case "tool.error": {
125
+ enqueue({
126
+ type: "tool-output-error",
127
+ toolCallId: event.toolCallId,
128
+ errorText: event.error,
129
+ });
130
+ // If this is a task tool (subagent), emit subagent error data part
131
+ if (event.toolName === "task") {
132
+ subagentStartTimes.delete(event.toolCallId);
133
+ enqueue({
134
+ type: "data-oh:subagent.error",
135
+ data: {
136
+ agentName: event.toolName,
137
+ error: event.error,
138
+ },
139
+ });
140
+ }
141
+ break;
142
+ }
143
+ // ── Steps ─────────────────────────────────────────────
144
+ case "step.start": {
145
+ endTextPart();
146
+ endReasoningPart();
147
+ enqueue({ type: "start-step" });
148
+ break;
149
+ }
150
+ case "step.done": {
151
+ endTextPart();
152
+ endReasoningPart();
153
+ enqueue({ type: "finish-step" });
154
+ break;
155
+ }
156
+ // ── Done ──────────────────────────────────────────────
157
+ case "done": {
158
+ endTextPart();
159
+ endReasoningPart();
160
+ const finishReason = event.result === "complete"
161
+ ? "stop"
162
+ : event.result === "max_steps"
163
+ ? "tool-calls"
164
+ : event.result === "error"
165
+ ? "error"
166
+ : "unknown";
167
+ enqueue({ type: "finish", finishReason });
168
+ break;
169
+ }
170
+ // ── Error ─────────────────────────────────────────────
171
+ case "error": {
172
+ enqueue({
173
+ type: "error",
174
+ errorText: event.error.message,
175
+ });
176
+ break;
177
+ }
178
+ // ── Session lifecycle → OH data parts ─────────────────
179
+ case "turn.start": {
180
+ enqueue({
181
+ type: "data-oh:turn.start",
182
+ data: { turnIndex: event.turnNumber },
183
+ });
184
+ break;
185
+ }
186
+ case "turn.done": {
187
+ enqueue({
188
+ type: "data-oh:turn.done",
189
+ data: {
190
+ turnIndex: event.turnNumber,
191
+ durationMs: 0, // not tracked by session currently
192
+ },
193
+ });
194
+ break;
195
+ }
196
+ case "compaction.start": {
197
+ enqueue({
198
+ type: "data-oh:session.compacting",
199
+ data: {},
200
+ });
201
+ enqueue({
202
+ type: "data-oh:compaction.start",
203
+ data: {},
204
+ });
205
+ break;
206
+ }
207
+ case "compaction.done": {
208
+ enqueue({
209
+ type: "data-oh:compaction.done",
210
+ data: { messagesRemoved: 0 },
211
+ });
212
+ break;
213
+ }
214
+ case "compaction.pruned": {
215
+ enqueue({
216
+ type: "data-oh:compaction.done",
217
+ data: { messagesRemoved: event.messagesRemoved },
218
+ });
219
+ break;
220
+ }
221
+ case "retry": {
222
+ enqueue({
223
+ type: "data-oh:retry",
224
+ data: {
225
+ attempt: event.attempt,
226
+ reason: event.error.message,
227
+ delayMs: event.delayMs,
228
+ },
229
+ });
230
+ break;
231
+ }
232
+ // compaction.summary — no UI-facing chunk needed
233
+ case "compaction.summary":
234
+ break;
235
+ }
236
+ }
237
+ }
238
+ catch (err) {
239
+ const message = err instanceof Error ? err.message : String(err);
240
+ controller.enqueue({ type: "error", errorText: message });
241
+ }
242
+ controller.close();
243
+ },
244
+ });
245
+ }
246
+ //# sourceMappingURL=ui-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui-stream.js","sourceRoot":"","sources":["../src/ui-stream.ts"],"names":[],"mappings":"AAMA;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAmC,EACnC,OAAkC;IAElC,OAAO,IAAI,cAAc,CAAU;QACjC,KAAK,CAAC,KAAK,CAAC,UAAU;YACpB,IAAI,WAAW,GAAG,CAAC,CAAC;YACpB,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;YAE3C,+DAA+D;YAC/D,IAAI,UAAU,GAAkB,IAAI,CAAC;YACrC,IAAI,eAAe,GAAkB,IAAI,CAAC;YAE1C,sDAAsD;YACtD,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAkB,CAAC;YAErD,MAAM,OAAO,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAE9D,MAAM,WAAW,GAAG,GAAG,EAAE;gBACvB,IAAI,UAAU,EAAE,CAAC;oBACf,OAAO,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;oBAC9C,UAAU,GAAG,IAAI,CAAC;gBACpB,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,gBAAgB,GAAG,GAAG,EAAE;gBAC5B,IAAI,eAAe,EAAE,CAAC;oBACpB,OAAO,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;oBACxD,eAAe,GAAG,IAAI,CAAC;gBACzB,CAAC;YACH,CAAC,CAAC;YAEF,oBAAoB;YACpB,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAa,CAAC,CAAC;YAEtC,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;oBACjC,IAAI,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;wBAC7B,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAa,CAAC,CAAC;wBACzD,MAAM;oBACR,CAAC;oBAED,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;wBACnB,yDAAyD;wBACzD,KAAK,YAAY,CAAC,CAAC,CAAC;4BAClB,IAAI,CAAC,UAAU,EAAE,CAAC;gCAChB,gBAAgB,EAAE,CAAC;gCACnB,UAAU,GAAG,MAAM,EAAE,CAAC;gCACtB,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;4BAClD,CAAC;4BACD,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;4BACnE,MAAM;wBACR,CAAC;wBAED,KAAK,WAAW,CAAC,CAAC,CAAC;4BACjB,WAAW,EAAE,CAAC;4BACd,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,iBAAiB,CAAC,CAAC,CAAC;4BACvB,IAAI,CAAC,eAAe,EAAE,CAAC;gCACrB,WAAW,EAAE,CAAC;gCACd,eAAe,GAAG,MAAM,EAAE,CAAC;gCAC3B,OAAO,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;4BAC5D,CAAC;4BACD,OAAO,CAAC;gCACN,IAAI,EAAE,iBAAiB;gCACvB,EAAE,EAAE,eAAe;gCACnB,KAAK,EAAE,KAAK,CAAC,IAAI;6BAClB,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,gBAAgB,CAAC,CAAC,CAAC;4BACtB,gBAAgB,EAAE,CAAC;4BACnB,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,YAAY,CAAC,CAAC,CAAC;4BAClB,WAAW,EAAE,CAAC;4BACd,gBAAgB,EAAE,CAAC;4BAEnB,4EAA4E;4BAC5E,OAAO,CAAC;gCACN,IAAI,EAAE,kBAAkB;gCACxB,UAAU,EAAE,KAAK,CAAC,UAAU;gCAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;6BACzB,CAAC,CAAC;4BACH,OAAO,CAAC;gCACN,IAAI,EAAE,sBAAsB;gCAC5B,UAAU,EAAE,KAAK,CAAC,UAAU;gCAC5B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gCACxB,KAAK,EAAE,KAAK,CAAC,KAAK;6BACnB,CAAC,CAAC;4BAEH,mEAAmE;4BACnE,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gCAC9B,MAAM,KAAK,GAAG,KAAK,CAAC,KAA4C,CAAC;gCACjE,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;oCAChB,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;oCACrD,OAAO,CAAC;wCACN,IAAI,EAAE,wBAAwB;wCAC9B,IAAI,EAAE;4CACJ,SAAS,EAAE,KAAK,CAAC,KAAK;4CACtB,IAAI,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;yCACzB;qCACF,CAAC,CAAC;gCACL,CAAC;4BACH,CAAC;4BACD,MAAM;wBACR,CAAC;wBAED,KAAK,WAAW,CAAC,CAAC,CAAC;4BACjB,OAAO,CAAC;gCACN,IAAI,EAAE,uBAAuB;gCAC7B,UAAU,EAAE,KAAK,CAAC,UAAU;gCAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;6BACrB,CAAC,CAAC;4BAEH,kEAAkE;4BAClE,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gCAC9B,MAAM,SAAS,GAAG,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gCAC3D,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;gCAC1D,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gCAC5C,OAAO,CAAC;oCACN,IAAI,EAAE,uBAAuB;oCAC7B,IAAI,EAAE;wCACJ,SAAS,EAAE,KAAK,CAAC,QAAQ;wCACzB,UAAU;qCACX;iCACF,CAAC,CAAC;4BACL,CAAC;4BACD,MAAM;wBACR,CAAC;wBAED,KAAK,YAAY,CAAC,CAAC,CAAC;4BAClB,OAAO,CAAC;gCACN,IAAI,EAAE,mBAAmB;gCACzB,UAAU,EAAE,KAAK,CAAC,UAAU;gCAC5B,SAAS,EAAE,KAAK,CAAC,KAAK;6BACvB,CAAC,CAAC;4BAEH,mEAAmE;4BACnE,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;gCAC9B,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gCAC5C,OAAO,CAAC;oCACN,IAAI,EAAE,wBAAwB;oCAC9B,IAAI,EAAE;wCACJ,SAAS,EAAE,KAAK,CAAC,QAAQ;wCACzB,KAAK,EAAE,KAAK,CAAC,KAAK;qCACnB;iCACF,CAAC,CAAC;4BACL,CAAC;4BACD,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,YAAY,CAAC,CAAC,CAAC;4BAClB,WAAW,EAAE,CAAC;4BACd,gBAAgB,EAAE,CAAC;4BACnB,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAa,CAAC,CAAC;4BAC3C,MAAM;wBACR,CAAC;wBAED,KAAK,WAAW,CAAC,CAAC,CAAC;4BACjB,WAAW,EAAE,CAAC;4BACd,gBAAgB,EAAE,CAAC;4BACnB,OAAO,CAAC,EAAE,IAAI,EAAE,aAAa,EAAa,CAAC,CAAC;4BAC5C,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,MAAM,CAAC,CAAC,CAAC;4BACZ,WAAW,EAAE,CAAC;4BACd,gBAAgB,EAAE,CAAC;4BACnB,MAAM,YAAY,GAChB,KAAK,CAAC,MAAM,KAAK,UAAU;gCACzB,CAAC,CAAC,MAAM;gCACR,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,WAAW;oCAC5B,CAAC,CAAC,YAAY;oCACd,CAAC,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO;wCACxB,CAAC,CAAC,OAAO;wCACT,CAAC,CAAC,SAAS,CAAC;4BACpB,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAa,CAAC,CAAC;4BACrD,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,OAAO,CAAC,CAAC,CAAC;4BACb,OAAO,CAAC;gCACN,IAAI,EAAE,OAAO;gCACb,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;6BACpB,CAAC,CAAC;4BACd,MAAM;wBACR,CAAC;wBAED,yDAAyD;wBACzD,KAAK,YAAY,CAAC,CAAC,CAAC;4BAClB,OAAO,CAAC;gCACN,IAAI,EAAE,oBAAoB;gCAC1B,IAAI,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE;6BACtC,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,WAAW,CAAC,CAAC,CAAC;4BACjB,OAAO,CAAC;gCACN,IAAI,EAAE,mBAAmB;gCACzB,IAAI,EAAE;oCACJ,SAAS,EAAE,KAAK,CAAC,UAAU;oCAC3B,UAAU,EAAE,CAAC,EAAE,mCAAmC;iCACnD;6BACF,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,kBAAkB,CAAC,CAAC,CAAC;4BACxB,OAAO,CAAC;gCACN,IAAI,EAAE,4BAA4B;gCAClC,IAAI,EAAE,EAAE;6BACT,CAAC,CAAC;4BACH,OAAO,CAAC;gCACN,IAAI,EAAE,0BAA0B;gCAChC,IAAI,EAAE,EAAE;6BACT,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,iBAAiB,CAAC,CAAC,CAAC;4BACvB,OAAO,CAAC;gCACN,IAAI,EAAE,yBAAyB;gCAC/B,IAAI,EAAE,EAAE,eAAe,EAAE,CAAC,EAAE;6BAC7B,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,mBAAmB,CAAC,CAAC,CAAC;4BACzB,OAAO,CAAC;gCACN,IAAI,EAAE,yBAAyB;gCAC/B,IAAI,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,eAAe,EAAE;6BACjD,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,KAAK,OAAO,CAAC,CAAC,CAAC;4BACb,OAAO,CAAC;gCACN,IAAI,EAAE,eAAe;gCACrB,IAAI,EAAE;oCACJ,OAAO,EAAE,KAAK,CAAC,OAAO;oCACtB,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO;oCAC3B,OAAO,EAAE,KAAK,CAAC,OAAO;iCACvB;6BACF,CAAC,CAAC;4BACH,MAAM;wBACR,CAAC;wBAED,iDAAiD;wBACjD,KAAK,oBAAoB;4BACvB,MAAM;oBACV,CAAC;gBACH,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,UAAU,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAa,CAAC,CAAC;YACvE,CAAC;YAED,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openharness/core",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Building blocks for capable, general-purpose agents",
6
6
  "exports": {
@@ -21,13 +21,6 @@
21
21
  "dist",
22
22
  "README.md"
23
23
  ],
24
- "scripts": {
25
- "build": "tsc",
26
- "cli": "tsx --env-file=.env example/cli.ts",
27
- "typecheck": "tsc --noEmit",
28
- "format": "oxfmt --write src example",
29
- "format:check": "oxfmt --check src example"
30
- },
31
24
  "keywords": [
32
25
  "agent",
33
26
  "ai",
@@ -45,13 +38,17 @@
45
38
  "@ai-sdk/anthropic": "^3.0.46",
46
39
  "@ai-sdk/openai": "^3.0.30",
47
40
  "@types/node": "^25.3.0",
48
- "chalk": "^5.6.2",
49
- "ora": "^9.3.0",
50
41
  "oxfmt": "^0.35.0",
51
42
  "tsx": "^4.21.0",
52
43
  "typescript": "^5.9.3"
53
44
  },
54
45
  "peerDependencies": {
55
46
  "zod": "^4.0.0"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc",
50
+ "typecheck": "tsc --noEmit",
51
+ "format": "oxfmt --write src",
52
+ "format:check": "oxfmt --check src"
56
53
  }
57
- }
54
+ }