@perstack/react 0.0.44 → 0.0.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -77
- package/dist/src/index.d.ts +48 -70
- package/dist/src/index.js +46 -123
- package/dist/src/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,18 +12,18 @@ pnpm add @perstack/react
|
|
|
12
12
|
|
|
13
13
|
## Usage
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### useRun
|
|
16
16
|
|
|
17
|
-
The main hook for managing Perstack
|
|
18
|
-
|
|
19
|
-
- **
|
|
17
|
+
The main hook for managing Perstack run state. It processes events into:
|
|
18
|
+
|
|
19
|
+
- **activities** - Accumulated activities from RunEvent (append-only)
|
|
20
|
+
- **streaming** - Current streaming state for real-time display
|
|
20
21
|
|
|
21
22
|
```tsx
|
|
22
|
-
import {
|
|
23
|
+
import { useRun } from "@perstack/react"
|
|
23
24
|
|
|
24
|
-
function
|
|
25
|
-
const {
|
|
26
|
-
useLogStore()
|
|
25
|
+
function ExpertRunner() {
|
|
26
|
+
const { activities, streaming, isComplete, addEvent, appendHistoricalEvents } = useRun()
|
|
27
27
|
|
|
28
28
|
// Add events from your event source
|
|
29
29
|
useEffect(() => {
|
|
@@ -36,37 +36,54 @@ function MyComponent() {
|
|
|
36
36
|
|
|
37
37
|
return (
|
|
38
38
|
<div>
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
{run.isReasoningActive && (
|
|
45
|
-
<div>[{run.expertKey}] Reasoning: {run.reasoning}</div>
|
|
46
|
-
)}
|
|
47
|
-
{run.isRunResultActive && (
|
|
48
|
-
<div>[{run.expertKey}] Generating: {run.runResult}</div>
|
|
49
|
-
)}
|
|
50
|
-
</div>
|
|
39
|
+
{/* Show streaming content (grouped by run for parallel execution) */}
|
|
40
|
+
{Object.entries(streaming.runs).map(([runId, run]) => (
|
|
41
|
+
run.isReasoningActive && (
|
|
42
|
+
<div key={runId}>[{run.expertKey}] Reasoning: {run.reasoning}</div>
|
|
43
|
+
)
|
|
51
44
|
))}
|
|
45
|
+
|
|
46
|
+
{/* Show accumulated activities */}
|
|
47
|
+
<ActivityLog activities={activities} />
|
|
48
|
+
|
|
49
|
+
{isComplete && <div>Run complete!</div>}
|
|
52
50
|
</div>
|
|
53
51
|
)
|
|
54
52
|
}
|
|
55
53
|
```
|
|
56
54
|
|
|
57
|
-
###
|
|
55
|
+
### useEventStream
|
|
58
56
|
|
|
59
|
-
A
|
|
57
|
+
A hook for consuming PerstackEvent streams with automatic connection management. This hook is API-agnostic and accepts a factory function that creates the event source.
|
|
60
58
|
|
|
61
59
|
```tsx
|
|
62
|
-
import {
|
|
63
|
-
|
|
64
|
-
function
|
|
65
|
-
const {
|
|
60
|
+
import { useEventStream } from "@perstack/react"
|
|
61
|
+
|
|
62
|
+
function JobActivityView({ jobId, isRunning }: { jobId: string; isRunning: boolean }) {
|
|
63
|
+
const { activities, streaming, isConnected, isComplete, error } = useEventStream({
|
|
64
|
+
enabled: isRunning,
|
|
65
|
+
createEventSource: async ({ signal }) => {
|
|
66
|
+
const response = await fetch(`/api/jobs/${jobId}/stream`, { signal })
|
|
67
|
+
// Return an async generator of PerstackEvent
|
|
68
|
+
return parseSSEStream(response.body)
|
|
69
|
+
},
|
|
70
|
+
})
|
|
66
71
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
return (
|
|
73
|
+
<div>
|
|
74
|
+
{isConnected && <span>Live</span>}
|
|
75
|
+
{activities.map((activity) => (
|
|
76
|
+
<ActivityCard key={activity.id} activity={activity} />
|
|
77
|
+
))}
|
|
78
|
+
{Object.entries(streaming.runs).map(([runId, run]) => (
|
|
79
|
+
<div key={runId}>
|
|
80
|
+
{run.isReasoningActive && <div>Thinking: {run.reasoning}</div>}
|
|
81
|
+
{run.isRunResultActive && <div>Generating: {run.runResult}</div>}
|
|
82
|
+
</div>
|
|
83
|
+
))}
|
|
84
|
+
{error && <div>Error: {error.message}</div>}
|
|
85
|
+
</div>
|
|
86
|
+
)
|
|
70
87
|
}
|
|
71
88
|
```
|
|
72
89
|
|
|
@@ -76,77 +93,61 @@ For advanced use cases, you can use the utility functions directly:
|
|
|
76
93
|
|
|
77
94
|
```tsx
|
|
78
95
|
import {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
96
|
+
createInitialActivityProcessState,
|
|
97
|
+
processRunEventToActivity,
|
|
98
|
+
toolToActivity,
|
|
99
|
+
groupActivitiesByRun,
|
|
82
100
|
} from "@perstack/react"
|
|
83
101
|
|
|
84
102
|
// Create processing state
|
|
85
|
-
const state =
|
|
103
|
+
const state = createInitialActivityProcessState()
|
|
86
104
|
|
|
87
|
-
// Process RunEvent into
|
|
88
|
-
const
|
|
89
|
-
|
|
105
|
+
// Process RunEvent into Activity
|
|
106
|
+
const activities = []
|
|
107
|
+
processRunEventToActivity(state, event, (activity) => activities.push(activity))
|
|
90
108
|
|
|
91
|
-
//
|
|
92
|
-
const
|
|
109
|
+
// Group activities by run ID
|
|
110
|
+
const grouped = groupActivitiesByRun(activities)
|
|
93
111
|
```
|
|
94
112
|
|
|
95
113
|
## API
|
|
96
114
|
|
|
97
|
-
###
|
|
115
|
+
### useRun()
|
|
98
116
|
|
|
99
117
|
Returns an object with:
|
|
100
118
|
|
|
101
|
-
- `
|
|
102
|
-
- `
|
|
119
|
+
- `activities`: Array of `ActivityOrGroup` representing completed actions (append-only)
|
|
120
|
+
- `streaming`: Current `StreamingState` for real-time display
|
|
103
121
|
- `isComplete`: Whether the run is complete
|
|
104
122
|
- `eventCount`: Total number of processed events
|
|
105
123
|
- `addEvent(event)`: Add a new event to process
|
|
106
|
-
- `appendHistoricalEvents(events)`:
|
|
107
|
-
|
|
108
|
-
**Note:** Logs are append-only and never cleared. This is required for compatibility with Ink's `<Static>` component.
|
|
124
|
+
- `appendHistoricalEvents(events)`: Bulk load historical events
|
|
125
|
+
- `clearStreaming()`: Clear streaming state
|
|
109
126
|
|
|
110
|
-
|
|
127
|
+
**Note:** Activities are append-only and never cleared. This is required for compatibility with Ink's `<Static>` component.
|
|
111
128
|
|
|
112
|
-
|
|
129
|
+
### useEventStream(options)
|
|
113
130
|
|
|
114
|
-
|
|
115
|
-
- `handleRuntimeEvent(event)`: Process a RuntimeEvent, returns `true` if handled
|
|
116
|
-
- `clearStreaming()`: Reset streaming state
|
|
117
|
-
- `resetRuntimeState()`: Reset entire runtime state
|
|
131
|
+
Options:
|
|
118
132
|
|
|
119
|
-
|
|
133
|
+
- `enabled`: Whether the stream should be active
|
|
134
|
+
- `createEventSource`: Factory function that returns an async generator of `PerstackEvent`
|
|
120
135
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
Wraps `CheckpointAction` with an ID for React key purposes:
|
|
124
|
-
|
|
125
|
-
```typescript
|
|
126
|
-
type LogEntry = {
|
|
127
|
-
id: string
|
|
128
|
-
action: CheckpointAction
|
|
129
|
-
}
|
|
130
|
-
```
|
|
136
|
+
Returns an object with:
|
|
131
137
|
|
|
132
|
-
|
|
138
|
+
- `activities`: Array of `ActivityOrGroup` from processed events
|
|
139
|
+
- `streaming`: Current `StreamingState` for real-time display
|
|
140
|
+
- `isConnected`: Whether currently connected to the event source
|
|
141
|
+
- `isComplete`: Whether the run has completed
|
|
142
|
+
- `error`: Last error encountered, if any
|
|
133
143
|
|
|
134
|
-
|
|
144
|
+
The hook automatically:
|
|
145
|
+
- Connects when `enabled` is `true` and `createEventSource` is provided
|
|
146
|
+
- Disconnects and aborts when `enabled` becomes `false` or on unmount
|
|
147
|
+
- Processes events through `useRun` internally
|
|
148
|
+
- Clears error state on reconnection
|
|
135
149
|
|
|
136
|
-
|
|
137
|
-
type RuntimeState = {
|
|
138
|
-
query?: string
|
|
139
|
-
expertName?: string
|
|
140
|
-
model?: string
|
|
141
|
-
runtime?: string
|
|
142
|
-
runtimeVersion?: string
|
|
143
|
-
skills: Map<string, SkillState>
|
|
144
|
-
dockerBuild?: DockerBuildState
|
|
145
|
-
dockerContainers: Map<string, DockerContainerState>
|
|
146
|
-
proxyAccess?: ProxyAccessState
|
|
147
|
-
streaming: StreamingState
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
+
## Types
|
|
150
151
|
|
|
151
152
|
### StreamingState
|
|
152
153
|
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,40 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PerstackEvent, ActivityOrGroup, ToolCall, ToolResult, Activity } from '@perstack/core';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* RuntimeState represents the current state of the runtime environment.
|
|
5
|
-
* This is derived from RuntimeEvent and only the latest state matters.
|
|
6
|
-
*
|
|
7
|
-
* Unlike LogEntry (which accumulates), RuntimeState is replaced on each update.
|
|
8
|
-
*/
|
|
9
|
-
/** Skill connection state */
|
|
10
|
-
type SkillState = {
|
|
11
|
-
name: string;
|
|
12
|
-
status: "starting" | "connected" | "disconnected";
|
|
13
|
-
serverInfo?: {
|
|
14
|
-
name: string;
|
|
15
|
-
version: string;
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
/** Docker build progress state */
|
|
19
|
-
type DockerBuildState = {
|
|
20
|
-
stage: "pulling" | "building" | "complete" | "error";
|
|
21
|
-
service: string;
|
|
22
|
-
message: string;
|
|
23
|
-
progress?: number;
|
|
24
|
-
};
|
|
25
|
-
/** Docker container status state */
|
|
26
|
-
type DockerContainerState = {
|
|
27
|
-
status: "starting" | "running" | "healthy" | "unhealthy" | "stopped" | "error";
|
|
28
|
-
service: string;
|
|
29
|
-
message?: string;
|
|
30
|
-
};
|
|
31
|
-
/** Proxy access state (most recent) */
|
|
32
|
-
type ProxyAccessState = {
|
|
33
|
-
action: "allowed" | "blocked";
|
|
34
|
-
domain: string;
|
|
35
|
-
port: number;
|
|
36
|
-
reason?: string;
|
|
37
|
-
};
|
|
38
3
|
/** Per-run streaming state for real-time display */
|
|
39
4
|
type PerRunStreamingState = {
|
|
40
5
|
/** Expert key for this run */
|
|
@@ -53,31 +18,56 @@ type StreamingState = {
|
|
|
53
18
|
/** Per-run streaming state, keyed by runId */
|
|
54
19
|
runs: Record<string, PerRunStreamingState>;
|
|
55
20
|
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Options for creating an event stream connection.
|
|
24
|
+
*/
|
|
25
|
+
type EventStreamOptions = {
|
|
26
|
+
/** AbortSignal to cancel the stream */
|
|
27
|
+
signal: AbortSignal;
|
|
28
|
+
};
|
|
56
29
|
/**
|
|
57
|
-
*
|
|
58
|
-
*
|
|
30
|
+
* Factory function that creates an async generator of PerstackEvents.
|
|
31
|
+
* This abstraction allows the hook to work with any event source.
|
|
59
32
|
*/
|
|
60
|
-
type
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/** Model being used */
|
|
66
|
-
model?: string;
|
|
67
|
-
/** Runtime type (e.g., "docker", "local") */
|
|
68
|
-
runtime?: string;
|
|
69
|
-
/** Runtime version */
|
|
70
|
-
runtimeVersion?: string;
|
|
71
|
-
skills: Map<string, SkillState>;
|
|
72
|
-
/** Docker build progress (latest) */
|
|
73
|
-
dockerBuild?: DockerBuildState;
|
|
74
|
-
/** Docker container states (keyed by service name) */
|
|
75
|
-
dockerContainers: Map<string, DockerContainerState>;
|
|
76
|
-
proxyAccess?: ProxyAccessState;
|
|
33
|
+
type EventSourceFactory = (options: EventStreamOptions) => Promise<AsyncGenerator<PerstackEvent, void, unknown>>;
|
|
34
|
+
type EventStreamState = {
|
|
35
|
+
/** Accumulated activities from processed events */
|
|
36
|
+
activities: ActivityOrGroup[];
|
|
37
|
+
/** Current streaming state for real-time display */
|
|
77
38
|
streaming: StreamingState;
|
|
39
|
+
/** Whether currently connected to the event source */
|
|
40
|
+
isConnected: boolean;
|
|
41
|
+
/** Whether the run has completed */
|
|
42
|
+
isComplete: boolean;
|
|
43
|
+
/** Last error encountered, if any */
|
|
44
|
+
error: Error | null;
|
|
45
|
+
};
|
|
46
|
+
type UseEventStreamOptions = {
|
|
47
|
+
/** Whether the stream should be active */
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
/** Factory to create the event source when enabled */
|
|
50
|
+
createEventSource: EventSourceFactory | null;
|
|
78
51
|
};
|
|
79
|
-
/**
|
|
80
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Hook for consuming PerstackEvent streams with automatic connection management.
|
|
54
|
+
*
|
|
55
|
+
* This hook is API-agnostic - it accepts a factory function that creates
|
|
56
|
+
* the event source, allowing it to work with any backend.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```tsx
|
|
60
|
+
* const { activities, streaming, isConnected, error } = useEventStream({
|
|
61
|
+
* enabled: isRunning,
|
|
62
|
+
* createEventSource: async ({ signal }) => {
|
|
63
|
+
* const result = await apiClient.jobs.stream(jobId, { signal })
|
|
64
|
+
* if (!result.ok) throw new Error(result.error.message)
|
|
65
|
+
* return result.data.events
|
|
66
|
+
* },
|
|
67
|
+
* })
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function useEventStream(options: UseEventStreamOptions): EventStreamState;
|
|
81
71
|
|
|
82
72
|
/**
|
|
83
73
|
* Converts a tool call and result to an Activity.
|
|
@@ -172,18 +162,6 @@ type RunResult = {
|
|
|
172
162
|
*/
|
|
173
163
|
declare function useRun(): RunResult;
|
|
174
164
|
|
|
175
|
-
type RuntimeResult = {
|
|
176
|
-
runtimeState: RuntimeState;
|
|
177
|
-
handleRuntimeEvent: (event: PerstackEvent) => boolean;
|
|
178
|
-
resetRuntimeState: () => void;
|
|
179
|
-
};
|
|
180
|
-
/**
|
|
181
|
-
* Hook for managing RuntimeState from RuntimeEvent stream.
|
|
182
|
-
* Only handles infrastructure-level events (skills, docker, proxy).
|
|
183
|
-
* Streaming events are now handled by useRun.
|
|
184
|
-
*/
|
|
185
|
-
declare function useRuntime(): RuntimeResult;
|
|
186
|
-
|
|
187
165
|
/**
|
|
188
166
|
* Represents a group of activities belonging to the same run
|
|
189
167
|
*/
|
|
@@ -207,4 +185,4 @@ type RunGroup = {
|
|
|
207
185
|
*/
|
|
208
186
|
declare function groupActivitiesByRun(activities: ActivityOrGroup[]): RunGroup[];
|
|
209
187
|
|
|
210
|
-
export { type ActivityProcessState, type
|
|
188
|
+
export { type ActivityProcessState, type EventSourceFactory, type EventStreamOptions, type EventStreamState, type PerRunStreamingState, type RunGroup, type RunResult, type StreamingState, type UseEventStreamOptions, type ActivityProcessState as UtilActivityProcessState, createInitialActivityProcessState, groupActivitiesByRun, processRunEventToActivity, toolToActivity, useEventStream, useRun };
|
package/dist/src/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useState, useRef, useCallback } from 'react';
|
|
1
|
+
import { useState, useRef, useCallback, useEffect } from 'react';
|
|
2
2
|
import { BASE_SKILL_PREFIX, createBaseToolActivity, createGeneralToolActivity } from '@perstack/core';
|
|
3
3
|
|
|
4
|
-
// src/hooks/use-
|
|
4
|
+
// src/hooks/use-event-stream.ts
|
|
5
5
|
var TOOL_RESULT_EVENT_TYPES = /* @__PURE__ */ new Set(["resolveToolResults", "attemptCompletion"]);
|
|
6
6
|
function toolToActivity(toolCall, toolResult, reasoning, meta) {
|
|
7
7
|
const { skillName, toolName } = toolCall;
|
|
@@ -515,129 +515,52 @@ function useRun() {
|
|
|
515
515
|
};
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
-
// src/
|
|
519
|
-
function
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
"skillStarting",
|
|
531
|
-
"skillConnected",
|
|
532
|
-
"skillDisconnected",
|
|
533
|
-
"skillStderr",
|
|
534
|
-
"dockerBuildProgress",
|
|
535
|
-
"dockerContainerStatus",
|
|
536
|
-
"proxyAccess"
|
|
537
|
-
]);
|
|
538
|
-
var isRuntimeEvent = (event) => "type" in event && RUNTIME_EVENT_TYPES.has(event.type);
|
|
539
|
-
function useRuntime() {
|
|
540
|
-
const [runtimeState, setRuntimeState] = useState(createInitialRuntimeState);
|
|
541
|
-
const handleRuntimeEvent = useCallback((event) => {
|
|
542
|
-
if (!isRuntimeEvent(event)) {
|
|
543
|
-
return false;
|
|
518
|
+
// src/hooks/use-event-stream.ts
|
|
519
|
+
function useEventStream(options) {
|
|
520
|
+
const { enabled, createEventSource } = options;
|
|
521
|
+
const runState = useRun();
|
|
522
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
523
|
+
const [error, setError] = useState(null);
|
|
524
|
+
const abortControllerRef = useRef(null);
|
|
525
|
+
const addEventRef = useRef(runState.addEvent);
|
|
526
|
+
addEventRef.current = runState.addEvent;
|
|
527
|
+
useEffect(() => {
|
|
528
|
+
if (!enabled || !createEventSource) {
|
|
529
|
+
return;
|
|
544
530
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
});
|
|
565
|
-
return true;
|
|
566
|
-
}
|
|
567
|
-
case "skillConnected": {
|
|
568
|
-
if (event.type !== "skillConnected") return false;
|
|
569
|
-
setRuntimeState((prev) => {
|
|
570
|
-
const skills = new Map(prev.skills);
|
|
571
|
-
skills.set(event.skillName, {
|
|
572
|
-
name: event.skillName,
|
|
573
|
-
status: "connected",
|
|
574
|
-
serverInfo: event.serverInfo
|
|
575
|
-
});
|
|
576
|
-
return { ...prev, skills };
|
|
577
|
-
});
|
|
578
|
-
return true;
|
|
579
|
-
}
|
|
580
|
-
case "skillDisconnected": {
|
|
581
|
-
if (event.type !== "skillDisconnected") return false;
|
|
582
|
-
setRuntimeState((prev) => {
|
|
583
|
-
const skills = new Map(prev.skills);
|
|
584
|
-
skills.set(event.skillName, { name: event.skillName, status: "disconnected" });
|
|
585
|
-
return { ...prev, skills };
|
|
586
|
-
});
|
|
587
|
-
return true;
|
|
588
|
-
}
|
|
589
|
-
case "skillStderr":
|
|
590
|
-
return true;
|
|
591
|
-
case "dockerBuildProgress": {
|
|
592
|
-
if (event.type !== "dockerBuildProgress") return false;
|
|
593
|
-
setRuntimeState((prev) => ({
|
|
594
|
-
...prev,
|
|
595
|
-
dockerBuild: {
|
|
596
|
-
stage: event.stage,
|
|
597
|
-
service: event.service,
|
|
598
|
-
message: event.message,
|
|
599
|
-
progress: event.progress
|
|
600
|
-
}
|
|
601
|
-
}));
|
|
602
|
-
return true;
|
|
603
|
-
}
|
|
604
|
-
case "dockerContainerStatus": {
|
|
605
|
-
if (event.type !== "dockerContainerStatus") return false;
|
|
606
|
-
setRuntimeState((prev) => {
|
|
607
|
-
const dockerContainers = new Map(prev.dockerContainers);
|
|
608
|
-
dockerContainers.set(event.service, {
|
|
609
|
-
status: event.status,
|
|
610
|
-
service: event.service,
|
|
611
|
-
message: event.message
|
|
612
|
-
});
|
|
613
|
-
return { ...prev, dockerContainers };
|
|
614
|
-
});
|
|
615
|
-
return true;
|
|
616
|
-
}
|
|
617
|
-
case "proxyAccess": {
|
|
618
|
-
if (event.type !== "proxyAccess") return false;
|
|
619
|
-
setRuntimeState((prev) => ({
|
|
620
|
-
...prev,
|
|
621
|
-
proxyAccess: {
|
|
622
|
-
action: event.action,
|
|
623
|
-
domain: event.domain,
|
|
624
|
-
port: event.port,
|
|
625
|
-
reason: event.reason
|
|
626
|
-
}
|
|
627
|
-
}));
|
|
628
|
-
return true;
|
|
531
|
+
const abortController = new AbortController();
|
|
532
|
+
abortControllerRef.current = abortController;
|
|
533
|
+
const { signal } = abortController;
|
|
534
|
+
const connect = async () => {
|
|
535
|
+
setIsConnected(true);
|
|
536
|
+
setError(null);
|
|
537
|
+
try {
|
|
538
|
+
const events = await createEventSource({ signal });
|
|
539
|
+
for await (const event of events) {
|
|
540
|
+
if (signal.aborted) break;
|
|
541
|
+
addEventRef.current(event);
|
|
542
|
+
}
|
|
543
|
+
} catch (err) {
|
|
544
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
setError(err instanceof Error ? err : new Error("Stream connection failed"));
|
|
548
|
+
} finally {
|
|
549
|
+
setIsConnected(false);
|
|
629
550
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
}, []);
|
|
551
|
+
};
|
|
552
|
+
connect();
|
|
553
|
+
return () => {
|
|
554
|
+
abortController.abort();
|
|
555
|
+
abortControllerRef.current = null;
|
|
556
|
+
};
|
|
557
|
+
}, [enabled, createEventSource]);
|
|
637
558
|
return {
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
559
|
+
activities: runState.activities,
|
|
560
|
+
streaming: runState.streaming,
|
|
561
|
+
isConnected,
|
|
562
|
+
isComplete: runState.isComplete,
|
|
563
|
+
error
|
|
641
564
|
};
|
|
642
565
|
}
|
|
643
566
|
|
|
@@ -673,6 +596,6 @@ function groupActivitiesByRun(activities) {
|
|
|
673
596
|
return order.map((runId) => groupMap.get(runId));
|
|
674
597
|
}
|
|
675
598
|
|
|
676
|
-
export { createInitialActivityProcessState,
|
|
599
|
+
export { createInitialActivityProcessState, groupActivitiesByRun, processRunEventToActivity, toolToActivity, useEventStream, useRun };
|
|
677
600
|
//# sourceMappingURL=index.js.map
|
|
678
601
|
//# sourceMappingURL=index.js.map
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utils/event-to-activity.ts","../../src/hooks/use-run.ts","../../src/types/runtime-state.ts","../../src/hooks/use-runtime.ts","../../src/utils/group-by-run.ts"],"names":["runState","useState","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n Activity,\n ActivityOrGroup,\n ParallelActivitiesGroup,\n PerstackEvent,\n RunEvent,\n ToolCall,\n ToolResult,\n} from \"@perstack/core\"\nimport {\n BASE_SKILL_PREFIX,\n createBaseToolActivity,\n createGeneralToolActivity,\n} from \"@perstack/core\"\n\nconst TOOL_RESULT_EVENT_TYPES = new Set([\"resolveToolResults\", \"attemptCompletion\"])\n\n/**\n * Converts a tool call and result to an Activity.\n * Delegates to core's createBaseToolActivity/createGeneralToolActivity to avoid duplication.\n */\nexport function toolToActivity(\n toolCall: ToolCall,\n toolResult: ToolResult,\n reasoning: string | undefined,\n meta: {\n id: string\n expertKey: string\n runId: string\n previousActivityId?: string\n delegatedBy?: { expertKey: string; runId: string }\n },\n): Activity {\n const { skillName, toolName } = toolCall\n\n const baseActivity = skillName.startsWith(BASE_SKILL_PREFIX)\n ? createBaseToolActivity(toolName, toolCall, toolResult, reasoning)\n : createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning)\n\n // Override the base fields with the correct metadata\n return {\n ...baseActivity,\n id: meta.id,\n expertKey: meta.expertKey,\n runId: meta.runId,\n previousActivityId: meta.previousActivityId,\n delegatedBy: meta.delegatedBy,\n } as Activity\n}\n\ntype ToolState = {\n id: string\n toolCall: ToolCall\n logged: boolean\n}\n\n/**\n * Per-run state to support parallel execution.\n * Each run maintains its own independent state.\n */\ntype RunState = {\n expertKey: string\n queryLogged: boolean\n completionLogged: boolean\n isComplete: boolean\n completedReasoning?: string\n lastActivityId?: string\n delegatedBy?: {\n expertKey: string\n runId: string\n }\n /** Track if this run has pending delegate tool calls (for delegation complete detection) */\n pendingDelegateCount: number\n}\n\n/**\n * State for processing RunEvent stream into Activity[].\n * This state tracks tool calls and their results to create complete Activity items.\n *\n * Supports the daisy chain architecture:\n * - Within-Run ordering via lastActivityId (per-run state)\n * - Cross-Run ordering via delegatedBy (per-run state)\n *\n * Note: `tools` is NOT cleared on new run to support delegation results\n * that arrive after parent expert resumes with a new runId.\n */\nexport type ActivityProcessState = {\n /** Tool calls indexed by toolCallId - persisted across runs for delegation handling */\n tools: Map<string, ToolState>\n /** Per-run state to support parallel execution */\n runStates: Map<string, RunState>\n}\n\nexport function createInitialActivityProcessState(): ActivityProcessState {\n return {\n tools: new Map(),\n runStates: new Map(),\n }\n}\n\nfunction getOrCreateRunState(\n state: ActivityProcessState,\n runId: string,\n expertKey: string,\n): RunState {\n let runState = state.runStates.get(runId)\n if (!runState) {\n runState = {\n expertKey,\n queryLogged: false,\n completionLogged: false,\n isComplete: false,\n pendingDelegateCount: 0,\n }\n state.runStates.set(runId, runState)\n }\n return runState\n}\n\nconst isRunEvent = (event: PerstackEvent): event is RunEvent =>\n \"type\" in event && \"expertKey\" in event\n\nconst isCompleteStreamingReasoningEvent = (event: PerstackEvent): boolean =>\n \"type\" in event && event.type === \"completeStreamingReasoning\"\n\ntype DelegatedByInfo = {\n expert: { key: string }\n toolCallId: string\n toolName: string\n checkpointId: string\n runId: string\n}\n\nconst isToolCallsEvent = (event: RunEvent): event is RunEvent & { toolCalls: ToolCall[] } =>\n event.type === \"callTools\" && \"toolCalls\" in event\n\ntype DelegationTarget = {\n expert: { key: string; name: string; version: string }\n toolCallId: string\n toolName: string\n query: string\n}\n\nconst isStopRunByDelegateEvent = (\n event: RunEvent,\n): event is RunEvent & {\n checkpoint: { delegateTo?: DelegationTarget[] }\n} => event.type === \"stopRunByDelegate\" && \"checkpoint\" in event\n\nconst isStopRunByInteractiveToolEvent = (\n event: RunEvent,\n): event is RunEvent & {\n checkpoint: { pendingToolCalls?: ToolCall[] }\n} => event.type === \"stopRunByInteractiveTool\" && \"checkpoint\" in event\n\nconst isToolResultsEvent = (event: RunEvent): event is RunEvent & { toolResults: ToolResult[] } =>\n event.type === \"resolveToolResults\" && \"toolResults\" in event\n\nconst isToolResultEvent = (event: RunEvent): event is RunEvent & { toolResult: ToolResult } =>\n TOOL_RESULT_EVENT_TYPES.has(event.type) && \"toolResult\" in event\n\n/**\n * Wraps multiple activities in a ParallelActivitiesGroup with shared reasoning.\n * If only one activity, returns it directly.\n */\nfunction wrapInGroupIfParallel(\n activities: Activity[],\n reasoning: string | undefined,\n meta: { expertKey: string; runId: string; delegatedBy?: { expertKey: string; runId: string } },\n): ActivityOrGroup[] {\n if (activities.length <= 1) {\n return activities\n }\n\n // Remove reasoning from individual activities since it's on the group\n const activitiesWithoutReasoning = activities.map((a) => {\n const { reasoning: _, ...rest } = a\n return rest as Activity\n })\n\n const group: ParallelActivitiesGroup = {\n type: \"parallelGroup\",\n id: `parallel-${activities[0].id}`,\n expertKey: meta.expertKey,\n runId: meta.runId,\n reasoning,\n activities: activitiesWithoutReasoning,\n }\n\n return [group]\n}\n\n/**\n * Processes a RunEvent and produces Activity or ParallelActivitiesGroup items.\n * Only processes RunEvent (state machine transitions), not RuntimeEvent.\n *\n * @param state - Mutable processing state\n * @param event - The event to process\n * @param addActivity - Callback to add a new Activity or ParallelActivitiesGroup\n */\nexport function processRunEventToActivity(\n state: ActivityProcessState,\n event: PerstackEvent,\n addActivity: (activity: ActivityOrGroup) => void,\n): void {\n if (isCompleteStreamingReasoningEvent(event)) {\n const reasoningEvent = event as { text: string; runId: string; expertKey: string }\n const { runId, text, expertKey } = reasoningEvent\n const runState = state.runStates.get(runId)\n if (runState) {\n runState.completedReasoning = text\n } else {\n state.runStates.set(runId, {\n expertKey,\n queryLogged: false,\n completionLogged: false,\n isComplete: false,\n pendingDelegateCount: 0,\n completedReasoning: text,\n })\n }\n return\n }\n\n if (!isRunEvent(event)) {\n return\n }\n\n const runState = getOrCreateRunState(state, event.runId, event.expertKey)\n\n // Handle startRun - extract query from inputMessages and delegatedBy\n if (event.type === \"startRun\") {\n const startRunEvent = event as {\n inputMessages: Array<{ type: string; contents?: Array<{ type: string; text?: string }> }>\n initialCheckpoint?: {\n status?: string\n delegatedBy?: {\n expert: { key: string }\n toolCallId: string\n toolName: string\n checkpointId: string\n runId: string\n }\n }\n }\n const userMessage = startRunEvent.inputMessages.find((m) => m.type === \"userMessage\")\n const queryText = userMessage?.contents?.find((c) => c.type === \"textPart\")?.text\n\n // Extract delegatedBy from initialCheckpoint (only on first startRun for this runId)\n if (!runState.delegatedBy) {\n const delegatedByInfo = startRunEvent.initialCheckpoint?.delegatedBy\n if (delegatedByInfo) {\n runState.delegatedBy = {\n expertKey: delegatedByInfo.expert.key,\n runId: delegatedByInfo.runId,\n }\n }\n }\n\n // Check if this is a delegation return (parent expert resuming after delegation)\n // In this case, don't log the query again as it was already logged in the original run\n const isDelegationReturn =\n startRunEvent.initialCheckpoint?.status === \"stoppedByDelegate\" ||\n startRunEvent.initialCheckpoint?.status === \"stoppedByInteractiveTool\"\n\n if (queryText && !runState.queryLogged && !isDelegationReturn) {\n const activityId = `query-${event.runId}`\n addActivity({\n type: \"query\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n text: queryText,\n })\n runState.lastActivityId = activityId\n runState.queryLogged = true\n }\n return\n }\n\n // Handle resumeFromStop - extract delegatedBy from checkpoint for delegation return\n if (event.type === \"resumeFromStop\") {\n // Extract delegatedBy from checkpoint (only on first resumeFromStop for this runId)\n if (!runState.delegatedBy) {\n const resumeEvent = event as { checkpoint?: { delegatedBy?: DelegatedByInfo } }\n const delegatedByInfo = resumeEvent.checkpoint?.delegatedBy\n if (delegatedByInfo) {\n runState.delegatedBy = {\n expertKey: delegatedByInfo.expert.key,\n runId: delegatedByInfo.runId,\n }\n }\n }\n return\n }\n\n // Handle retry\n if (event.type === \"retry\") {\n const retryEvent = event as { reason: string }\n const activityId = `retry-${event.id}`\n addActivity({\n type: \"retry\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n reasoning: runState.completedReasoning,\n error: retryEvent.reason,\n message: \"\",\n })\n runState.lastActivityId = activityId\n runState.completedReasoning = undefined\n return\n }\n\n // Handle completion\n if (event.type === \"completeRun\") {\n if (!runState.completionLogged) {\n const text = (event as { text?: string }).text ?? \"\"\n const activityId = `completion-${event.runId}`\n addActivity({\n type: \"complete\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n reasoning: runState.completedReasoning,\n text,\n })\n runState.lastActivityId = activityId\n runState.completionLogged = true\n runState.isComplete = true\n runState.completedReasoning = undefined\n }\n return\n }\n\n // Handle error\n if (event.type === \"stopRunByError\") {\n const errorEvent = event as {\n error: { name: string; message: string; statusCode?: number; isRetryable?: boolean }\n }\n const activityId = `error-${event.id}`\n addActivity({\n type: \"error\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n errorName: errorEvent.error.name,\n error: errorEvent.error.message,\n isRetryable: errorEvent.error.isRetryable,\n })\n runState.lastActivityId = activityId\n runState.isComplete = true\n runState.completedReasoning = undefined\n return\n }\n\n // Track tool calls from callTools event\n if (isToolCallsEvent(event)) {\n for (const toolCall of event.toolCalls) {\n if (!state.tools.has(toolCall.id)) {\n state.tools.set(toolCall.id, { id: toolCall.id, toolCall, logged: false })\n }\n }\n }\n\n // Handle stopRunByDelegate - log delegation activities\n if (isStopRunByDelegateEvent(event)) {\n const reasoning = runState.completedReasoning\n const delegations = event.checkpoint.delegateTo ?? []\n runState.pendingDelegateCount += delegations.length\n\n const delegateActivities: Activity[] = []\n for (const delegation of delegations) {\n const existingTool = state.tools.get(delegation.toolCallId)\n if (!existingTool || !existingTool.logged) {\n // Mark as logged if exists\n if (existingTool) {\n existingTool.logged = true\n }\n const activityId = `delegate-${delegation.toolCallId}`\n delegateActivities.push({\n type: \"delegate\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n delegateExpertKey: delegation.expert.key,\n query: delegation.query,\n reasoning,\n })\n runState.lastActivityId = activityId\n }\n }\n\n // Wrap in group if multiple delegations\n const wrapped = wrapInGroupIfParallel(delegateActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n\n // Clear reasoning after delegation activities are logged\n runState.completedReasoning = undefined\n return\n }\n\n // Handle stopRunByInteractiveTool - log interactive tool activities\n if (isStopRunByInteractiveToolEvent(event)) {\n const reasoning = runState.completedReasoning\n const pendingToolCalls = event.checkpoint.pendingToolCalls ?? []\n\n const interactiveActivities: Activity[] = []\n for (const toolCall of pendingToolCalls) {\n const existingTool = state.tools.get(toolCall.id)\n if (!existingTool || !existingTool.logged) {\n // Mark as logged if exists\n if (existingTool) {\n existingTool.logged = true\n }\n const activityId = `interactive-${toolCall.id}`\n interactiveActivities.push({\n type: \"interactiveTool\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n skillName: toolCall.skillName,\n toolName: toolCall.toolName,\n args: toolCall.args as Record<string, unknown>,\n reasoning,\n })\n runState.lastActivityId = activityId\n }\n }\n\n // Wrap in group if multiple interactive tools\n const wrapped = wrapInGroupIfParallel(interactiveActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n\n // Clear reasoning after interactive tool activities are logged\n runState.completedReasoning = undefined\n return\n }\n\n // Process tool results\n if (isToolResultsEvent(event)) {\n const reasoning = runState.completedReasoning\n const toolActivities: Activity[] = []\n\n for (const toolResult of event.toolResults) {\n const tool = state.tools.get(toolResult.id)\n if (tool && !tool.logged) {\n const activityId = `action-${tool.id}`\n const activity = toolToActivity(tool.toolCall, toolResult, reasoning, {\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n })\n toolActivities.push(activity)\n runState.lastActivityId = activityId\n tool.logged = true\n }\n }\n\n if (toolActivities.length > 0) {\n // Wrap in group if multiple tool results\n const wrapped = wrapInGroupIfParallel(toolActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n runState.completedReasoning = undefined\n }\n } else if (isToolResultEvent(event)) {\n const { toolResult } = event\n const tool = state.tools.get(toolResult.id)\n if (tool && !tool.logged) {\n const activityId = `action-${tool.id}`\n const activity = toolToActivity(tool.toolCall, toolResult, runState.completedReasoning, {\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n })\n addActivity(activity)\n runState.lastActivityId = activityId\n tool.logged = true\n runState.completedReasoning = undefined\n }\n }\n}\n","import type { ActivityOrGroup, PerstackEvent, StreamingEvent } from \"@perstack/core\"\nimport { useCallback, useRef, useState } from \"react\"\nimport type { StreamingState } from \"../types/index.js\"\nimport {\n type ActivityProcessState,\n createInitialActivityProcessState,\n processRunEventToActivity,\n} from \"../utils/event-to-activity.js\"\n\nexport type { ActivityProcessState }\n\nconst STREAMING_EVENT_TYPES = new Set([\n \"startStreamingReasoning\",\n \"streamReasoning\",\n \"completeStreamingReasoning\",\n \"startStreamingRunResult\",\n \"streamRunResult\",\n \"completeStreamingRunResult\",\n])\n\nexport const isStreamingEvent = (event: PerstackEvent): event is StreamingEvent =>\n \"type\" in event && \"expertKey\" in event && STREAMING_EVENT_TYPES.has(event.type)\n\nexport type ProcessStreamingEventResult = {\n newState: StreamingState\n handled: boolean\n}\n\nexport function processStreamingEvent(\n event: StreamingEvent,\n prevState: StreamingState,\n): ProcessStreamingEventResult {\n const { runId, expertKey } = event\n\n switch (event.type) {\n case \"startStreamingReasoning\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n expertKey,\n reasoning: \"\",\n isReasoningActive: true,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"streamReasoning\": {\n if (event.type !== \"streamReasoning\") {\n return { newState: prevState, handled: false }\n }\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n reasoning: (prevState.runs[runId]?.reasoning ?? \"\") + event.delta,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"completeStreamingReasoning\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n isReasoningActive: false,\n },\n },\n },\n handled: false,\n }\n }\n\n case \"startStreamingRunResult\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n expertKey,\n reasoning: undefined,\n isReasoningActive: false,\n runResult: \"\",\n isRunResultActive: true,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"streamRunResult\": {\n if (event.type !== \"streamRunResult\") {\n return { newState: prevState, handled: false }\n }\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n runResult: (prevState.runs[runId]?.runResult ?? \"\") + event.delta,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"completeStreamingRunResult\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n isRunResultActive: false,\n },\n },\n },\n handled: true,\n }\n }\n\n default:\n return { newState: prevState, handled: false }\n }\n}\n\nexport type RunResult = {\n /** Accumulated activities from RunEvent (may include ParallelActivitiesGroup) */\n activities: ActivityOrGroup[]\n /** Current streaming state */\n streaming: StreamingState\n /** Whether the run is complete */\n isComplete: boolean\n /** Number of events processed */\n eventCount: number\n /** Add a new event to be processed */\n addEvent: (event: PerstackEvent) => void\n /** Append historical events (processes and appends to activities) */\n appendHistoricalEvents: (events: PerstackEvent[]) => void\n /** Clear streaming state */\n clearStreaming: () => void\n}\n\n/**\n * Hook for managing Run state from RunEvent stream.\n *\n * Architecture:\n * - ExpertStateEvent → ActivityOrGroup[] (accumulated, append-only)\n * - StreamingEvent → StreamingState (latest only, for display)\n *\n * IMPORTANT: activities are append-only and never cleared.\n * This is required for compatibility with Ink's <Static> component.\n */\nexport function useRun(): RunResult {\n const [activities, setActivities] = useState<ActivityOrGroup[]>([])\n const [streaming, setStreaming] = useState<StreamingState>({ runs: {} })\n const [eventCount, setEventCount] = useState(0)\n const [isComplete, setIsComplete] = useState(false)\n\n const stateRef = useRef<ActivityProcessState>(createInitialActivityProcessState())\n\n const clearStreaming = useCallback(() => {\n setStreaming({ runs: {} })\n }, [])\n\n const handleStreamingEvent = useCallback((event: StreamingEvent): boolean => {\n let handled = false\n setStreaming((prev) => {\n const result = processStreamingEvent(event, prev)\n handled = result.handled\n return result.newState\n })\n return handled\n }, [])\n\n const processEvent = useCallback((event: PerstackEvent) => {\n const newActivities: ActivityOrGroup[] = []\n const addActivity = (activity: ActivityOrGroup) => newActivities.push(activity)\n\n processRunEventToActivity(stateRef.current, event, addActivity)\n\n if (newActivities.length > 0) {\n setActivities((prev) => [...prev, ...newActivities])\n }\n\n const rootRunComplete = Array.from(stateRef.current.runStates.values()).some(\n (rs) => rs.isComplete && !rs.delegatedBy,\n )\n setIsComplete(rootRunComplete)\n }, [])\n\n const clearRunStreaming = useCallback((runId: string) => {\n setStreaming((prev) => {\n const { [runId]: _, ...rest } = prev.runs\n return { runs: rest }\n })\n }, [])\n\n const addEvent = useCallback(\n (event: PerstackEvent) => {\n if (isStreamingEvent(event)) {\n const handled = handleStreamingEvent(event)\n if (handled) {\n setEventCount((prev) => prev + 1)\n return\n }\n }\n\n if (\n \"type\" in event &&\n \"runId\" in event &&\n (event.type === \"completeRun\" || event.type === \"stopRunByError\")\n ) {\n clearRunStreaming(event.runId as string)\n }\n\n processEvent(event)\n setEventCount((prev) => prev + 1)\n },\n [handleStreamingEvent, clearRunStreaming, processEvent],\n )\n\n const appendHistoricalEvents = useCallback((historicalEvents: PerstackEvent[]) => {\n const newActivities: ActivityOrGroup[] = []\n const addActivity = (activity: ActivityOrGroup) => newActivities.push(activity)\n\n for (const event of historicalEvents) {\n processRunEventToActivity(stateRef.current, event, addActivity)\n }\n\n if (newActivities.length > 0) {\n setActivities((prev) => [...prev, ...newActivities])\n }\n\n setEventCount((prev) => prev + historicalEvents.length)\n const rootRunComplete = Array.from(stateRef.current.runStates.values()).some(\n (rs) => rs.isComplete && !rs.delegatedBy,\n )\n setIsComplete(rootRunComplete)\n }, [])\n\n return {\n activities,\n streaming,\n isComplete,\n eventCount,\n addEvent,\n appendHistoricalEvents,\n clearStreaming,\n }\n}\n","/**\n * RuntimeState represents the current state of the runtime environment.\n * This is derived from RuntimeEvent and only the latest state matters.\n *\n * Unlike LogEntry (which accumulates), RuntimeState is replaced on each update.\n */\n\n/** Skill connection state */\nexport type SkillState = {\n name: string\n status: \"starting\" | \"connected\" | \"disconnected\"\n serverInfo?: {\n name: string\n version: string\n }\n}\n\n/** Docker build progress state */\nexport type DockerBuildState = {\n stage: \"pulling\" | \"building\" | \"complete\" | \"error\"\n service: string\n message: string\n progress?: number\n}\n\n/** Docker container status state */\nexport type DockerContainerState = {\n status: \"starting\" | \"running\" | \"healthy\" | \"unhealthy\" | \"stopped\" | \"error\"\n service: string\n message?: string\n}\n\n/** Proxy access state (most recent) */\nexport type ProxyAccessState = {\n action: \"allowed\" | \"blocked\"\n domain: string\n port: number\n reason?: string\n}\n\n/** Per-run streaming state for real-time display */\nexport type PerRunStreamingState = {\n /** Expert key for this run */\n expertKey: string\n /** Accumulated reasoning text during extended thinking */\n reasoning?: string\n /** Accumulated run result text during generation */\n runResult?: string\n /** Whether reasoning is currently streaming */\n isReasoningActive?: boolean\n /** Whether run result is currently streaming */\n isRunResultActive?: boolean\n}\n\n/** Streaming state organized by run ID to support parallel execution */\nexport type StreamingState = {\n /** Per-run streaming state, keyed by runId */\n runs: Record<string, PerRunStreamingState>\n}\n\n/**\n * RuntimeState captures the current state of the runtime environment.\n * All fields represent the latest state from RuntimeEvent.\n */\nexport type RuntimeState = {\n // From initializeRuntime\n /** Current query being processed */\n query?: string\n /** Current expert name */\n expertName?: string\n /** Model being used */\n model?: string\n /** Runtime type (e.g., \"docker\", \"local\") */\n runtime?: string\n /** Runtime version */\n runtimeVersion?: string\n\n // Skill states (keyed by skill name)\n skills: Map<string, SkillState>\n\n // Docker states\n /** Docker build progress (latest) */\n dockerBuild?: DockerBuildState\n /** Docker container states (keyed by service name) */\n dockerContainers: Map<string, DockerContainerState>\n\n // Proxy access (latest)\n proxyAccess?: ProxyAccessState\n\n // Streaming state\n streaming: StreamingState\n}\n\n/** Creates an empty initial runtime state */\nexport function createInitialRuntimeState(): RuntimeState {\n return {\n skills: new Map(),\n dockerContainers: new Map(),\n streaming: { runs: {} },\n }\n}\n","import type { PerstackEvent, RuntimeEvent } from \"@perstack/core\"\nimport { useCallback, useState } from \"react\"\nimport type { RuntimeState } from \"../types/index.js\"\nimport { createInitialRuntimeState } from \"../types/index.js\"\n\nconst RUNTIME_EVENT_TYPES = new Set([\n \"initializeRuntime\",\n \"skillStarting\",\n \"skillConnected\",\n \"skillDisconnected\",\n \"skillStderr\",\n \"dockerBuildProgress\",\n \"dockerContainerStatus\",\n \"proxyAccess\",\n])\n\nconst isRuntimeEvent = (event: PerstackEvent): event is RuntimeEvent =>\n \"type\" in event && RUNTIME_EVENT_TYPES.has(event.type)\n\nexport type RuntimeResult = {\n runtimeState: RuntimeState\n handleRuntimeEvent: (event: PerstackEvent) => boolean\n resetRuntimeState: () => void\n}\n\n/**\n * Hook for managing RuntimeState from RuntimeEvent stream.\n * Only handles infrastructure-level events (skills, docker, proxy).\n * Streaming events are now handled by useRun.\n */\nexport function useRuntime(): RuntimeResult {\n const [runtimeState, setRuntimeState] = useState<RuntimeState>(createInitialRuntimeState)\n\n const handleRuntimeEvent = useCallback((event: PerstackEvent): boolean => {\n if (!isRuntimeEvent(event)) {\n return false\n }\n\n switch (event.type) {\n case \"initializeRuntime\": {\n if (event.type !== \"initializeRuntime\") return false\n setRuntimeState((prev) => ({\n ...prev,\n query: event.query,\n expertName: event.expertName,\n model: event.model,\n runtime: event.runtime,\n runtimeVersion: event.runtimeVersion,\n }))\n return true\n }\n\n case \"skillStarting\": {\n if (event.type !== \"skillStarting\") return false\n setRuntimeState((prev) => {\n const skills = new Map(prev.skills)\n skills.set(event.skillName, { name: event.skillName, status: \"starting\" })\n return { ...prev, skills }\n })\n return true\n }\n\n case \"skillConnected\": {\n if (event.type !== \"skillConnected\") return false\n setRuntimeState((prev) => {\n const skills = new Map(prev.skills)\n skills.set(event.skillName, {\n name: event.skillName,\n status: \"connected\",\n serverInfo: event.serverInfo,\n })\n return { ...prev, skills }\n })\n return true\n }\n\n case \"skillDisconnected\": {\n if (event.type !== \"skillDisconnected\") return false\n setRuntimeState((prev) => {\n const skills = new Map(prev.skills)\n skills.set(event.skillName, { name: event.skillName, status: \"disconnected\" })\n return { ...prev, skills }\n })\n return true\n }\n\n case \"skillStderr\":\n // skillStderr events are informational only (for logging)\n // No state update needed, but we still return true to indicate it's handled\n return true\n\n case \"dockerBuildProgress\": {\n if (event.type !== \"dockerBuildProgress\") return false\n setRuntimeState((prev) => ({\n ...prev,\n dockerBuild: {\n stage: event.stage,\n service: event.service,\n message: event.message,\n progress: event.progress,\n },\n }))\n return true\n }\n\n case \"dockerContainerStatus\": {\n if (event.type !== \"dockerContainerStatus\") return false\n setRuntimeState((prev) => {\n const dockerContainers = new Map(prev.dockerContainers)\n dockerContainers.set(event.service, {\n status: event.status,\n service: event.service,\n message: event.message,\n })\n return { ...prev, dockerContainers }\n })\n return true\n }\n\n case \"proxyAccess\": {\n if (event.type !== \"proxyAccess\") return false\n setRuntimeState((prev) => ({\n ...prev,\n proxyAccess: {\n action: event.action,\n domain: event.domain,\n port: event.port,\n reason: event.reason,\n },\n }))\n return true\n }\n\n default:\n return false\n }\n }, [])\n\n const resetRuntimeState = useCallback(() => {\n setRuntimeState(createInitialRuntimeState())\n }, [])\n\n return {\n runtimeState,\n handleRuntimeEvent,\n resetRuntimeState,\n }\n}\n","import type { ActivityOrGroup } from \"@perstack/core\"\n\n/**\n * Represents a group of activities belonging to the same run\n */\nexport type RunGroup = {\n runId: string\n expertKey: string\n activities: ActivityOrGroup[]\n delegatedBy?: {\n expertKey: string\n runId: string\n }\n}\n\n/**\n * Extract base properties from ActivityOrGroup for grouping.\n */\nfunction getActivityProps(activityOrGroup: ActivityOrGroup): {\n runId: string\n expertKey: string\n delegatedBy?: { expertKey: string; runId: string }\n} {\n if (activityOrGroup.type === \"parallelGroup\") {\n const firstActivity = activityOrGroup.activities[0]\n return {\n runId: activityOrGroup.runId,\n expertKey: activityOrGroup.expertKey,\n delegatedBy: firstActivity?.delegatedBy,\n }\n }\n return activityOrGroup\n}\n\n/**\n * Groups activities by their runId while preserving order.\n *\n * This function groups activities so that each run can be displayed in its own\n * visual section (e.g., separate <Static> components in Ink).\n *\n * @param activities - Array of activities or groups to group\n * @returns Array of RunGroup objects, ordered by first appearance\n */\nexport function groupActivitiesByRun(activities: ActivityOrGroup[]): RunGroup[] {\n const groupMap = new Map<string, RunGroup>()\n const order: string[] = []\n\n for (const activityOrGroup of activities) {\n const { runId, expertKey, delegatedBy } = getActivityProps(activityOrGroup)\n\n if (!groupMap.has(runId)) {\n groupMap.set(runId, {\n runId,\n expertKey,\n activities: [],\n delegatedBy,\n })\n order.push(runId)\n }\n\n const group = groupMap.get(runId)!\n group.activities.push(activityOrGroup)\n }\n\n return order.map((runId) => groupMap.get(runId)!)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/utils/event-to-activity.ts","../../src/hooks/use-run.ts","../../src/hooks/use-event-stream.ts","../../src/utils/group-by-run.ts"],"names":["runState","useState","useRef"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n Activity,\n ActivityOrGroup,\n ParallelActivitiesGroup,\n PerstackEvent,\n RunEvent,\n ToolCall,\n ToolResult,\n} from \"@perstack/core\"\nimport {\n BASE_SKILL_PREFIX,\n createBaseToolActivity,\n createGeneralToolActivity,\n} from \"@perstack/core\"\n\nconst TOOL_RESULT_EVENT_TYPES = new Set([\"resolveToolResults\", \"attemptCompletion\"])\n\n/**\n * Converts a tool call and result to an Activity.\n * Delegates to core's createBaseToolActivity/createGeneralToolActivity to avoid duplication.\n */\nexport function toolToActivity(\n toolCall: ToolCall,\n toolResult: ToolResult,\n reasoning: string | undefined,\n meta: {\n id: string\n expertKey: string\n runId: string\n previousActivityId?: string\n delegatedBy?: { expertKey: string; runId: string }\n },\n): Activity {\n const { skillName, toolName } = toolCall\n\n const baseActivity = skillName.startsWith(BASE_SKILL_PREFIX)\n ? createBaseToolActivity(toolName, toolCall, toolResult, reasoning)\n : createGeneralToolActivity(skillName, toolName, toolCall, toolResult, reasoning)\n\n // Override the base fields with the correct metadata\n return {\n ...baseActivity,\n id: meta.id,\n expertKey: meta.expertKey,\n runId: meta.runId,\n previousActivityId: meta.previousActivityId,\n delegatedBy: meta.delegatedBy,\n } as Activity\n}\n\ntype ToolState = {\n id: string\n toolCall: ToolCall\n logged: boolean\n}\n\n/**\n * Per-run state to support parallel execution.\n * Each run maintains its own independent state.\n */\ntype RunState = {\n expertKey: string\n queryLogged: boolean\n completionLogged: boolean\n isComplete: boolean\n completedReasoning?: string\n lastActivityId?: string\n delegatedBy?: {\n expertKey: string\n runId: string\n }\n /** Track if this run has pending delegate tool calls (for delegation complete detection) */\n pendingDelegateCount: number\n}\n\n/**\n * State for processing RunEvent stream into Activity[].\n * This state tracks tool calls and their results to create complete Activity items.\n *\n * Supports the daisy chain architecture:\n * - Within-Run ordering via lastActivityId (per-run state)\n * - Cross-Run ordering via delegatedBy (per-run state)\n *\n * Note: `tools` is NOT cleared on new run to support delegation results\n * that arrive after parent expert resumes with a new runId.\n */\nexport type ActivityProcessState = {\n /** Tool calls indexed by toolCallId - persisted across runs for delegation handling */\n tools: Map<string, ToolState>\n /** Per-run state to support parallel execution */\n runStates: Map<string, RunState>\n}\n\nexport function createInitialActivityProcessState(): ActivityProcessState {\n return {\n tools: new Map(),\n runStates: new Map(),\n }\n}\n\nfunction getOrCreateRunState(\n state: ActivityProcessState,\n runId: string,\n expertKey: string,\n): RunState {\n let runState = state.runStates.get(runId)\n if (!runState) {\n runState = {\n expertKey,\n queryLogged: false,\n completionLogged: false,\n isComplete: false,\n pendingDelegateCount: 0,\n }\n state.runStates.set(runId, runState)\n }\n return runState\n}\n\nconst isRunEvent = (event: PerstackEvent): event is RunEvent =>\n \"type\" in event && \"expertKey\" in event\n\nconst isCompleteStreamingReasoningEvent = (event: PerstackEvent): boolean =>\n \"type\" in event && event.type === \"completeStreamingReasoning\"\n\ntype DelegatedByInfo = {\n expert: { key: string }\n toolCallId: string\n toolName: string\n checkpointId: string\n runId: string\n}\n\nconst isToolCallsEvent = (event: RunEvent): event is RunEvent & { toolCalls: ToolCall[] } =>\n event.type === \"callTools\" && \"toolCalls\" in event\n\ntype DelegationTarget = {\n expert: { key: string; name: string; version: string }\n toolCallId: string\n toolName: string\n query: string\n}\n\nconst isStopRunByDelegateEvent = (\n event: RunEvent,\n): event is RunEvent & {\n checkpoint: { delegateTo?: DelegationTarget[] }\n} => event.type === \"stopRunByDelegate\" && \"checkpoint\" in event\n\nconst isStopRunByInteractiveToolEvent = (\n event: RunEvent,\n): event is RunEvent & {\n checkpoint: { pendingToolCalls?: ToolCall[] }\n} => event.type === \"stopRunByInteractiveTool\" && \"checkpoint\" in event\n\nconst isToolResultsEvent = (event: RunEvent): event is RunEvent & { toolResults: ToolResult[] } =>\n event.type === \"resolveToolResults\" && \"toolResults\" in event\n\nconst isToolResultEvent = (event: RunEvent): event is RunEvent & { toolResult: ToolResult } =>\n TOOL_RESULT_EVENT_TYPES.has(event.type) && \"toolResult\" in event\n\n/**\n * Wraps multiple activities in a ParallelActivitiesGroup with shared reasoning.\n * If only one activity, returns it directly.\n */\nfunction wrapInGroupIfParallel(\n activities: Activity[],\n reasoning: string | undefined,\n meta: { expertKey: string; runId: string; delegatedBy?: { expertKey: string; runId: string } },\n): ActivityOrGroup[] {\n if (activities.length <= 1) {\n return activities\n }\n\n // Remove reasoning from individual activities since it's on the group\n const activitiesWithoutReasoning = activities.map((a) => {\n const { reasoning: _, ...rest } = a\n return rest as Activity\n })\n\n const group: ParallelActivitiesGroup = {\n type: \"parallelGroup\",\n id: `parallel-${activities[0].id}`,\n expertKey: meta.expertKey,\n runId: meta.runId,\n reasoning,\n activities: activitiesWithoutReasoning,\n }\n\n return [group]\n}\n\n/**\n * Processes a RunEvent and produces Activity or ParallelActivitiesGroup items.\n * Only processes RunEvent (state machine transitions), not RuntimeEvent.\n *\n * @param state - Mutable processing state\n * @param event - The event to process\n * @param addActivity - Callback to add a new Activity or ParallelActivitiesGroup\n */\nexport function processRunEventToActivity(\n state: ActivityProcessState,\n event: PerstackEvent,\n addActivity: (activity: ActivityOrGroup) => void,\n): void {\n if (isCompleteStreamingReasoningEvent(event)) {\n const reasoningEvent = event as { text: string; runId: string; expertKey: string }\n const { runId, text, expertKey } = reasoningEvent\n const runState = state.runStates.get(runId)\n if (runState) {\n runState.completedReasoning = text\n } else {\n state.runStates.set(runId, {\n expertKey,\n queryLogged: false,\n completionLogged: false,\n isComplete: false,\n pendingDelegateCount: 0,\n completedReasoning: text,\n })\n }\n return\n }\n\n if (!isRunEvent(event)) {\n return\n }\n\n const runState = getOrCreateRunState(state, event.runId, event.expertKey)\n\n // Handle startRun - extract query from inputMessages and delegatedBy\n if (event.type === \"startRun\") {\n const startRunEvent = event as {\n inputMessages: Array<{ type: string; contents?: Array<{ type: string; text?: string }> }>\n initialCheckpoint?: {\n status?: string\n delegatedBy?: {\n expert: { key: string }\n toolCallId: string\n toolName: string\n checkpointId: string\n runId: string\n }\n }\n }\n const userMessage = startRunEvent.inputMessages.find((m) => m.type === \"userMessage\")\n const queryText = userMessage?.contents?.find((c) => c.type === \"textPart\")?.text\n\n // Extract delegatedBy from initialCheckpoint (only on first startRun for this runId)\n if (!runState.delegatedBy) {\n const delegatedByInfo = startRunEvent.initialCheckpoint?.delegatedBy\n if (delegatedByInfo) {\n runState.delegatedBy = {\n expertKey: delegatedByInfo.expert.key,\n runId: delegatedByInfo.runId,\n }\n }\n }\n\n // Check if this is a delegation return (parent expert resuming after delegation)\n // In this case, don't log the query again as it was already logged in the original run\n const isDelegationReturn =\n startRunEvent.initialCheckpoint?.status === \"stoppedByDelegate\" ||\n startRunEvent.initialCheckpoint?.status === \"stoppedByInteractiveTool\"\n\n if (queryText && !runState.queryLogged && !isDelegationReturn) {\n const activityId = `query-${event.runId}`\n addActivity({\n type: \"query\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n text: queryText,\n })\n runState.lastActivityId = activityId\n runState.queryLogged = true\n }\n return\n }\n\n // Handle resumeFromStop - extract delegatedBy from checkpoint for delegation return\n if (event.type === \"resumeFromStop\") {\n // Extract delegatedBy from checkpoint (only on first resumeFromStop for this runId)\n if (!runState.delegatedBy) {\n const resumeEvent = event as { checkpoint?: { delegatedBy?: DelegatedByInfo } }\n const delegatedByInfo = resumeEvent.checkpoint?.delegatedBy\n if (delegatedByInfo) {\n runState.delegatedBy = {\n expertKey: delegatedByInfo.expert.key,\n runId: delegatedByInfo.runId,\n }\n }\n }\n return\n }\n\n // Handle retry\n if (event.type === \"retry\") {\n const retryEvent = event as { reason: string }\n const activityId = `retry-${event.id}`\n addActivity({\n type: \"retry\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n reasoning: runState.completedReasoning,\n error: retryEvent.reason,\n message: \"\",\n })\n runState.lastActivityId = activityId\n runState.completedReasoning = undefined\n return\n }\n\n // Handle completion\n if (event.type === \"completeRun\") {\n if (!runState.completionLogged) {\n const text = (event as { text?: string }).text ?? \"\"\n const activityId = `completion-${event.runId}`\n addActivity({\n type: \"complete\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n reasoning: runState.completedReasoning,\n text,\n })\n runState.lastActivityId = activityId\n runState.completionLogged = true\n runState.isComplete = true\n runState.completedReasoning = undefined\n }\n return\n }\n\n // Handle error\n if (event.type === \"stopRunByError\") {\n const errorEvent = event as {\n error: { name: string; message: string; statusCode?: number; isRetryable?: boolean }\n }\n const activityId = `error-${event.id}`\n addActivity({\n type: \"error\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n errorName: errorEvent.error.name,\n error: errorEvent.error.message,\n isRetryable: errorEvent.error.isRetryable,\n })\n runState.lastActivityId = activityId\n runState.isComplete = true\n runState.completedReasoning = undefined\n return\n }\n\n // Track tool calls from callTools event\n if (isToolCallsEvent(event)) {\n for (const toolCall of event.toolCalls) {\n if (!state.tools.has(toolCall.id)) {\n state.tools.set(toolCall.id, { id: toolCall.id, toolCall, logged: false })\n }\n }\n }\n\n // Handle stopRunByDelegate - log delegation activities\n if (isStopRunByDelegateEvent(event)) {\n const reasoning = runState.completedReasoning\n const delegations = event.checkpoint.delegateTo ?? []\n runState.pendingDelegateCount += delegations.length\n\n const delegateActivities: Activity[] = []\n for (const delegation of delegations) {\n const existingTool = state.tools.get(delegation.toolCallId)\n if (!existingTool || !existingTool.logged) {\n // Mark as logged if exists\n if (existingTool) {\n existingTool.logged = true\n }\n const activityId = `delegate-${delegation.toolCallId}`\n delegateActivities.push({\n type: \"delegate\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n delegateExpertKey: delegation.expert.key,\n query: delegation.query,\n reasoning,\n })\n runState.lastActivityId = activityId\n }\n }\n\n // Wrap in group if multiple delegations\n const wrapped = wrapInGroupIfParallel(delegateActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n\n // Clear reasoning after delegation activities are logged\n runState.completedReasoning = undefined\n return\n }\n\n // Handle stopRunByInteractiveTool - log interactive tool activities\n if (isStopRunByInteractiveToolEvent(event)) {\n const reasoning = runState.completedReasoning\n const pendingToolCalls = event.checkpoint.pendingToolCalls ?? []\n\n const interactiveActivities: Activity[] = []\n for (const toolCall of pendingToolCalls) {\n const existingTool = state.tools.get(toolCall.id)\n if (!existingTool || !existingTool.logged) {\n // Mark as logged if exists\n if (existingTool) {\n existingTool.logged = true\n }\n const activityId = `interactive-${toolCall.id}`\n interactiveActivities.push({\n type: \"interactiveTool\",\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n skillName: toolCall.skillName,\n toolName: toolCall.toolName,\n args: toolCall.args as Record<string, unknown>,\n reasoning,\n })\n runState.lastActivityId = activityId\n }\n }\n\n // Wrap in group if multiple interactive tools\n const wrapped = wrapInGroupIfParallel(interactiveActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n\n // Clear reasoning after interactive tool activities are logged\n runState.completedReasoning = undefined\n return\n }\n\n // Process tool results\n if (isToolResultsEvent(event)) {\n const reasoning = runState.completedReasoning\n const toolActivities: Activity[] = []\n\n for (const toolResult of event.toolResults) {\n const tool = state.tools.get(toolResult.id)\n if (tool && !tool.logged) {\n const activityId = `action-${tool.id}`\n const activity = toolToActivity(tool.toolCall, toolResult, reasoning, {\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n })\n toolActivities.push(activity)\n runState.lastActivityId = activityId\n tool.logged = true\n }\n }\n\n if (toolActivities.length > 0) {\n // Wrap in group if multiple tool results\n const wrapped = wrapInGroupIfParallel(toolActivities, reasoning, {\n expertKey: event.expertKey,\n runId: event.runId,\n delegatedBy: runState.delegatedBy,\n })\n for (const item of wrapped) {\n addActivity(item)\n }\n runState.completedReasoning = undefined\n }\n } else if (isToolResultEvent(event)) {\n const { toolResult } = event\n const tool = state.tools.get(toolResult.id)\n if (tool && !tool.logged) {\n const activityId = `action-${tool.id}`\n const activity = toolToActivity(tool.toolCall, toolResult, runState.completedReasoning, {\n id: activityId,\n expertKey: event.expertKey,\n runId: event.runId,\n previousActivityId: runState.lastActivityId,\n delegatedBy: runState.delegatedBy,\n })\n addActivity(activity)\n runState.lastActivityId = activityId\n tool.logged = true\n runState.completedReasoning = undefined\n }\n }\n}\n","import type { ActivityOrGroup, PerstackEvent, StreamingEvent } from \"@perstack/core\"\nimport { useCallback, useRef, useState } from \"react\"\nimport type { StreamingState } from \"../types/index.js\"\nimport {\n type ActivityProcessState,\n createInitialActivityProcessState,\n processRunEventToActivity,\n} from \"../utils/event-to-activity.js\"\n\nexport type { ActivityProcessState }\n\nconst STREAMING_EVENT_TYPES = new Set([\n \"startStreamingReasoning\",\n \"streamReasoning\",\n \"completeStreamingReasoning\",\n \"startStreamingRunResult\",\n \"streamRunResult\",\n \"completeStreamingRunResult\",\n])\n\nexport const isStreamingEvent = (event: PerstackEvent): event is StreamingEvent =>\n \"type\" in event && \"expertKey\" in event && STREAMING_EVENT_TYPES.has(event.type)\n\nexport type ProcessStreamingEventResult = {\n newState: StreamingState\n handled: boolean\n}\n\nexport function processStreamingEvent(\n event: StreamingEvent,\n prevState: StreamingState,\n): ProcessStreamingEventResult {\n const { runId, expertKey } = event\n\n switch (event.type) {\n case \"startStreamingReasoning\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n expertKey,\n reasoning: \"\",\n isReasoningActive: true,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"streamReasoning\": {\n if (event.type !== \"streamReasoning\") {\n return { newState: prevState, handled: false }\n }\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n reasoning: (prevState.runs[runId]?.reasoning ?? \"\") + event.delta,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"completeStreamingReasoning\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n isReasoningActive: false,\n },\n },\n },\n handled: false,\n }\n }\n\n case \"startStreamingRunResult\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n expertKey,\n reasoning: undefined,\n isReasoningActive: false,\n runResult: \"\",\n isRunResultActive: true,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"streamRunResult\": {\n if (event.type !== \"streamRunResult\") {\n return { newState: prevState, handled: false }\n }\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n runResult: (prevState.runs[runId]?.runResult ?? \"\") + event.delta,\n },\n },\n },\n handled: true,\n }\n }\n\n case \"completeStreamingRunResult\": {\n return {\n newState: {\n ...prevState,\n runs: {\n ...prevState.runs,\n [runId]: {\n ...prevState.runs[runId],\n expertKey,\n isRunResultActive: false,\n },\n },\n },\n handled: true,\n }\n }\n\n default:\n return { newState: prevState, handled: false }\n }\n}\n\nexport type RunResult = {\n /** Accumulated activities from RunEvent (may include ParallelActivitiesGroup) */\n activities: ActivityOrGroup[]\n /** Current streaming state */\n streaming: StreamingState\n /** Whether the run is complete */\n isComplete: boolean\n /** Number of events processed */\n eventCount: number\n /** Add a new event to be processed */\n addEvent: (event: PerstackEvent) => void\n /** Append historical events (processes and appends to activities) */\n appendHistoricalEvents: (events: PerstackEvent[]) => void\n /** Clear streaming state */\n clearStreaming: () => void\n}\n\n/**\n * Hook for managing Run state from RunEvent stream.\n *\n * Architecture:\n * - ExpertStateEvent → ActivityOrGroup[] (accumulated, append-only)\n * - StreamingEvent → StreamingState (latest only, for display)\n *\n * IMPORTANT: activities are append-only and never cleared.\n * This is required for compatibility with Ink's <Static> component.\n */\nexport function useRun(): RunResult {\n const [activities, setActivities] = useState<ActivityOrGroup[]>([])\n const [streaming, setStreaming] = useState<StreamingState>({ runs: {} })\n const [eventCount, setEventCount] = useState(0)\n const [isComplete, setIsComplete] = useState(false)\n\n const stateRef = useRef<ActivityProcessState>(createInitialActivityProcessState())\n\n const clearStreaming = useCallback(() => {\n setStreaming({ runs: {} })\n }, [])\n\n const handleStreamingEvent = useCallback((event: StreamingEvent): boolean => {\n let handled = false\n setStreaming((prev) => {\n const result = processStreamingEvent(event, prev)\n handled = result.handled\n return result.newState\n })\n return handled\n }, [])\n\n const processEvent = useCallback((event: PerstackEvent) => {\n const newActivities: ActivityOrGroup[] = []\n const addActivity = (activity: ActivityOrGroup) => newActivities.push(activity)\n\n processRunEventToActivity(stateRef.current, event, addActivity)\n\n if (newActivities.length > 0) {\n setActivities((prev) => [...prev, ...newActivities])\n }\n\n const rootRunComplete = Array.from(stateRef.current.runStates.values()).some(\n (rs) => rs.isComplete && !rs.delegatedBy,\n )\n setIsComplete(rootRunComplete)\n }, [])\n\n const clearRunStreaming = useCallback((runId: string) => {\n setStreaming((prev) => {\n const { [runId]: _, ...rest } = prev.runs\n return { runs: rest }\n })\n }, [])\n\n const addEvent = useCallback(\n (event: PerstackEvent) => {\n if (isStreamingEvent(event)) {\n const handled = handleStreamingEvent(event)\n if (handled) {\n setEventCount((prev) => prev + 1)\n return\n }\n }\n\n if (\n \"type\" in event &&\n \"runId\" in event &&\n (event.type === \"completeRun\" || event.type === \"stopRunByError\")\n ) {\n clearRunStreaming(event.runId as string)\n }\n\n processEvent(event)\n setEventCount((prev) => prev + 1)\n },\n [handleStreamingEvent, clearRunStreaming, processEvent],\n )\n\n const appendHistoricalEvents = useCallback((historicalEvents: PerstackEvent[]) => {\n const newActivities: ActivityOrGroup[] = []\n const addActivity = (activity: ActivityOrGroup) => newActivities.push(activity)\n\n for (const event of historicalEvents) {\n processRunEventToActivity(stateRef.current, event, addActivity)\n }\n\n if (newActivities.length > 0) {\n setActivities((prev) => [...prev, ...newActivities])\n }\n\n setEventCount((prev) => prev + historicalEvents.length)\n const rootRunComplete = Array.from(stateRef.current.runStates.values()).some(\n (rs) => rs.isComplete && !rs.delegatedBy,\n )\n setIsComplete(rootRunComplete)\n }, [])\n\n return {\n activities,\n streaming,\n isComplete,\n eventCount,\n addEvent,\n appendHistoricalEvents,\n clearStreaming,\n }\n}\n","import type { ActivityOrGroup, PerstackEvent } from \"@perstack/core\"\nimport { useEffect, useRef, useState } from \"react\"\nimport type { StreamingState } from \"../types/index.js\"\nimport { useRun } from \"./use-run.js\"\n\n/**\n * Options for creating an event stream connection.\n */\nexport type EventStreamOptions = {\n /** AbortSignal to cancel the stream */\n signal: AbortSignal\n}\n\n/**\n * Factory function that creates an async generator of PerstackEvents.\n * This abstraction allows the hook to work with any event source.\n */\nexport type EventSourceFactory = (\n options: EventStreamOptions,\n) => Promise<AsyncGenerator<PerstackEvent, void, unknown>>\n\nexport type EventStreamState = {\n /** Accumulated activities from processed events */\n activities: ActivityOrGroup[]\n /** Current streaming state for real-time display */\n streaming: StreamingState\n /** Whether currently connected to the event source */\n isConnected: boolean\n /** Whether the run has completed */\n isComplete: boolean\n /** Last error encountered, if any */\n error: Error | null\n}\n\nexport type UseEventStreamOptions = {\n /** Whether the stream should be active */\n enabled: boolean\n /** Factory to create the event source when enabled */\n createEventSource: EventSourceFactory | null\n}\n\n/**\n * Hook for consuming PerstackEvent streams with automatic connection management.\n *\n * This hook is API-agnostic - it accepts a factory function that creates\n * the event source, allowing it to work with any backend.\n *\n * @example\n * ```tsx\n * const { activities, streaming, isConnected, error } = useEventStream({\n * enabled: isRunning,\n * createEventSource: async ({ signal }) => {\n * const result = await apiClient.jobs.stream(jobId, { signal })\n * if (!result.ok) throw new Error(result.error.message)\n * return result.data.events\n * },\n * })\n * ```\n */\nexport function useEventStream(options: UseEventStreamOptions): EventStreamState {\n const { enabled, createEventSource } = options\n\n const runState = useRun()\n const [isConnected, setIsConnected] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const abortControllerRef = useRef<AbortController | null>(null)\n // Store addEvent in a ref to avoid dependency changes triggering reconnection\n const addEventRef = useRef(runState.addEvent)\n addEventRef.current = runState.addEvent\n\n useEffect(() => {\n if (!enabled || !createEventSource) {\n return\n }\n\n const abortController = new AbortController()\n abortControllerRef.current = abortController\n const { signal } = abortController\n\n const connect = async () => {\n setIsConnected(true)\n setError(null)\n\n try {\n const events = await createEventSource({ signal })\n\n for await (const event of events) {\n if (signal.aborted) break\n addEventRef.current(event)\n }\n } catch (err) {\n if (err instanceof DOMException && err.name === \"AbortError\") {\n return // Intentional cancellation\n }\n setError(err instanceof Error ? err : new Error(\"Stream connection failed\"))\n } finally {\n setIsConnected(false)\n }\n }\n\n connect()\n\n return () => {\n abortController.abort()\n abortControllerRef.current = null\n }\n }, [enabled, createEventSource])\n\n return {\n activities: runState.activities,\n streaming: runState.streaming,\n isConnected,\n isComplete: runState.isComplete,\n error,\n }\n}\n","import type { ActivityOrGroup } from \"@perstack/core\"\n\n/**\n * Represents a group of activities belonging to the same run\n */\nexport type RunGroup = {\n runId: string\n expertKey: string\n activities: ActivityOrGroup[]\n delegatedBy?: {\n expertKey: string\n runId: string\n }\n}\n\n/**\n * Extract base properties from ActivityOrGroup for grouping.\n */\nfunction getActivityProps(activityOrGroup: ActivityOrGroup): {\n runId: string\n expertKey: string\n delegatedBy?: { expertKey: string; runId: string }\n} {\n if (activityOrGroup.type === \"parallelGroup\") {\n const firstActivity = activityOrGroup.activities[0]\n return {\n runId: activityOrGroup.runId,\n expertKey: activityOrGroup.expertKey,\n delegatedBy: firstActivity?.delegatedBy,\n }\n }\n return activityOrGroup\n}\n\n/**\n * Groups activities by their runId while preserving order.\n *\n * This function groups activities so that each run can be displayed in its own\n * visual section (e.g., separate <Static> components in Ink).\n *\n * @param activities - Array of activities or groups to group\n * @returns Array of RunGroup objects, ordered by first appearance\n */\nexport function groupActivitiesByRun(activities: ActivityOrGroup[]): RunGroup[] {\n const groupMap = new Map<string, RunGroup>()\n const order: string[] = []\n\n for (const activityOrGroup of activities) {\n const { runId, expertKey, delegatedBy } = getActivityProps(activityOrGroup)\n\n if (!groupMap.has(runId)) {\n groupMap.set(runId, {\n runId,\n expertKey,\n activities: [],\n delegatedBy,\n })\n order.push(runId)\n }\n\n const group = groupMap.get(runId)!\n group.activities.push(activityOrGroup)\n }\n\n return order.map((runId) => groupMap.get(runId)!)\n}\n"]}
|