@osolmaz/pi-workflows 0.5.2 → 0.6.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.
- package/README.md +13 -3
- package/dist/builtins/catalog.js +1 -1
- package/dist/builtins/monitor.workflow.d.ts +25 -69
- package/dist/builtins/monitor.workflow.js +194 -123
- package/dist/builtins/monitor.workflow.js.map +1 -1
- package/dist/extension/executor.d.ts +7 -2
- package/dist/extension/executor.js +20 -14
- package/dist/extension/executor.js.map +1 -1
- package/dist/extension/index.js +56 -15
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/step-message.d.ts +24 -0
- package/dist/extension/step-message.js +106 -0
- package/dist/extension/step-message.js.map +1 -0
- package/dist/extension/widget.d.ts +4 -2
- package/dist/extension/widget.js +111 -17
- package/dist/extension/widget.js.map +1 -1
- package/dist/extension/workflow-tool.d.ts +9 -0
- package/dist/extension/workflow-tool.js +10 -0
- package/dist/extension/workflow-tool.js.map +1 -1
- package/dist/host/rpc-bridge.js +25 -11
- package/dist/host/rpc-bridge.js.map +1 -1
- package/dist/host/rpc-executor.d.ts +2 -2
- package/dist/host/rpc-executor.js +23 -12
- package/dist/host/rpc-executor.js.map +1 -1
- package/dist/viewer/cli.js +1 -1
- package/dist/viewer/cli.js.map +1 -1
- package/dist/viewer/render.js +14 -0
- package/dist/viewer/render.js.map +1 -1
- package/dist/viewer/tui.js +1 -1
- package/dist/viewer/tui.js.map +1 -1
- package/dist/workflows/engine.d.ts +6 -1
- package/dist/workflows/engine.js +88 -6
- package/dist/workflows/engine.js.map +1 -1
- package/dist/workflows/index.d.ts +4 -2
- package/dist/workflows/index.js +2 -0
- package/dist/workflows/index.js.map +1 -1
- package/dist/workflows/progress.d.ts +34 -0
- package/dist/workflows/progress.js +268 -0
- package/dist/workflows/progress.js.map +1 -0
- package/dist/workflows/schema.js +21 -1
- package/dist/workflows/schema.js.map +1 -1
- package/dist/workflows/shell.d.ts +2 -2
- package/dist/workflows/shell.js +103 -25
- package/dist/workflows/shell.js.map +1 -1
- package/dist/workflows/store.d.ts +15 -2
- package/dist/workflows/store.js +44 -2
- package/dist/workflows/store.js.map +1 -1
- package/dist/workflows/types.d.ts +52 -1
- package/dist/workflows/updates.d.ts +15 -0
- package/dist/workflows/updates.js +188 -0
- package/dist/workflows/updates.js.map +1 -0
- package/docs/DESIGN_PHILOSOPHY.md +51 -0
- package/docs/MONITOR.md +282 -0
- package/docs/WORKFLOW_STEP_MESSAGES.md +141 -0
- package/docs/WORKFLOW_UPDATES.md +416 -0
- package/docs/development.md +7 -3
- package/docs/plans/2026-08-13-responsive-workflow-widget-plan.md +11 -3
- package/docs/plans/2026-08-16-workflow-updates-plan.md +494 -0
- package/docs/run-bundles.md +10 -2
- package/docs/workflows.md +57 -17
- package/package.json +1 -1
- package/src/builtins/catalog.ts +1 -1
- package/src/builtins/monitor.workflow.ts +217 -148
- package/src/extension/executor.ts +36 -14
- package/src/extension/index.ts +89 -23
- package/src/extension/step-message.ts +145 -0
- package/src/extension/widget.ts +158 -14
- package/src/extension/workflow-tool.ts +22 -0
- package/src/host/rpc-bridge.ts +37 -14
- package/src/host/rpc-executor.ts +35 -14
- package/src/viewer/cli.ts +1 -1
- package/src/viewer/render.ts +27 -0
- package/src/viewer/tui.ts +1 -1
- package/src/workflows/engine.ts +117 -4
- package/src/workflows/index.ts +32 -0
- package/src/workflows/progress.ts +326 -0
- package/src/workflows/schema.ts +23 -1
- package/src/workflows/shell.ts +109 -26
- package/src/workflows/store.ts +67 -2
- package/src/workflows/types.ts +78 -1
- package/src/workflows/updates.ts +208 -0
package/docs/MONITOR.md
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
# Built-in monitor
|
|
2
|
+
|
|
3
|
+
This specification defines the built-in `monitor` workflow and its use of [workflow updates](WORKFLOW_UPDATES.md).
|
|
4
|
+
|
|
5
|
+
The monitor checks a target, sends one status notification after every accepted check, publishes optional progress tracks, waits, and repeats until its stop rule or safety limit is reached.
|
|
6
|
+
|
|
7
|
+
## Minimal input
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"task": "Check pull request 123 in osolmaz/example. Read state and checks with gh. Observe only.",
|
|
12
|
+
"stopWhen": "Stop when the pull request is merged or closed."
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`everyMinutes` defaults to 30. The first check starts immediately.
|
|
17
|
+
|
|
18
|
+
## Input fields
|
|
19
|
+
|
|
20
|
+
| Field | Required | Type | Default | Meaning |
|
|
21
|
+
| --------------------- | -------- | ------- | ------------------ | -------------------------------- |
|
|
22
|
+
| `task` | Yes | string | None | Self-contained observation task. |
|
|
23
|
+
| `everyMinutes` | No | integer | `30` | Minutes between accepted checks. |
|
|
24
|
+
| `stopWhen` | No | string | Explicit user stop | Condition that ends monitoring. |
|
|
25
|
+
| `maxChecks` | No | integer | `1000` | Run safety limit. |
|
|
26
|
+
| `checkTimeoutMinutes` | No | integer | Derived | Timeout for one agent check. |
|
|
27
|
+
|
|
28
|
+
`task` is 1 to 8,000 characters after trimming. It should name the target, stable identifier, source of truth, durable outputs, and observation boundary. It must state any authorized mutations. Monitoring is read-only when the task does not authorize a mutation.
|
|
29
|
+
|
|
30
|
+
`everyMinutes` is from 1 through 1,440. The interval begins after a check report is durably queued. It does not delay the first check.
|
|
31
|
+
|
|
32
|
+
`stopWhen` is 1 to 4,000 characters when supplied. When the conversation gives no clear finish condition, the caller omits it and the workflow uses `Stop only when the user explicitly asks to stop.`
|
|
33
|
+
|
|
34
|
+
`maxChecks` is from 1 through 1,000. Agents must omit it unless the user explicitly asks for a fixed check count. The workflow's default of 1,000 is a disclosed runtime safety limit. The agent does not infer it as a finish condition.
|
|
35
|
+
|
|
36
|
+
`checkTimeoutMinutes` is from 5 through 1,440. When omitted, the workflow uses the larger of 60 minutes and `everyMinutes`. The node timeout includes the existing two-minute runtime margin.
|
|
37
|
+
|
|
38
|
+
`reportWhen` is removed. The monitor always reports after every accepted check.
|
|
39
|
+
|
|
40
|
+
## Check output
|
|
41
|
+
|
|
42
|
+
The check agent submits:
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"route": "continue",
|
|
47
|
+
"observation": "The pull request is open and 8 of 10 checks passed.",
|
|
48
|
+
"report": "PR 123 remains open. Eight of ten checks passed; two are running.",
|
|
49
|
+
"progress": {
|
|
50
|
+
"tracks": [
|
|
51
|
+
{
|
|
52
|
+
"key": "checks",
|
|
53
|
+
"data": {
|
|
54
|
+
"schema": "pi-workflows.progress.v1",
|
|
55
|
+
"label": "Checks",
|
|
56
|
+
"status": "running",
|
|
57
|
+
"completed": 8,
|
|
58
|
+
"total": 10,
|
|
59
|
+
"unit": "checks"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"reason": "The stop condition is not met."
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Fields:
|
|
69
|
+
|
|
70
|
+
| Field | Required | Type | Meaning |
|
|
71
|
+
| ------------- | -------- | ------ | ------------------------------ |
|
|
72
|
+
| `route` | Yes | string | `continue` or `stop`. |
|
|
73
|
+
| `observation` | Yes | string | Current factual state. |
|
|
74
|
+
| `report` | Yes | string | Concise user-facing update. |
|
|
75
|
+
| `progress` | No | object | Current progress tracks. |
|
|
76
|
+
| `reason` | Yes | string | Reason for the selected route. |
|
|
77
|
+
|
|
78
|
+
`observation` is at most 8,000 characters. `report` is at most 4,000 characters. `reason` is at most 2,000 characters. All three must be non-empty after trimming.
|
|
79
|
+
|
|
80
|
+
`progress.tracks` contains from 1 through 256 entries. Each entry has a unique `key` and one valid `pi-workflows.progress.v1` data object. The progress update rules, reserved `overall` key, and validation behavior come from [WORKFLOW_UPDATES.md](WORKFLOW_UPDATES.md).
|
|
81
|
+
|
|
82
|
+
Unknown check fields are validation errors. A missing report is a validation error for both routes.
|
|
83
|
+
|
|
84
|
+
## Graph
|
|
85
|
+
|
|
86
|
+
The built-in graph uses existing nodes:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
prepare
|
|
90
|
+
→ check
|
|
91
|
+
→ estimate
|
|
92
|
+
→ publish_progress
|
|
93
|
+
→ report
|
|
94
|
+
→ decide
|
|
95
|
+
├─ stop → finish
|
|
96
|
+
└─ continue → schedule → sleep → check
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `prepare` is a `compute` node that validates and applies input defaults.
|
|
100
|
+
- `check` is an `agent` node that inspects the target and submits the check output.
|
|
101
|
+
- `estimate` is a `compute` node that updates per-track rate and ETA state with the pure progress helpers.
|
|
102
|
+
- `publish_progress` is a function `action` that publishes each validated observed track.
|
|
103
|
+
- `report` is a `notify` node that queues exactly one report.
|
|
104
|
+
- `decide` is a `compute` node that applies the route and check safety limit.
|
|
105
|
+
- `schedule` is a function `action` that publishes the next-check time.
|
|
106
|
+
- `sleep` is the existing runtime-owned shell wait.
|
|
107
|
+
- `finish` is a `compute` node that returns the final observation and reason.
|
|
108
|
+
|
|
109
|
+
The workflow has no quiet route, report acknowledgement agent, or `presentationPrompt`.
|
|
110
|
+
|
|
111
|
+
## Check prompt
|
|
112
|
+
|
|
113
|
+
The check prompt includes:
|
|
114
|
+
|
|
115
|
+
- check number and safety limit
|
|
116
|
+
- task
|
|
117
|
+
- stop condition
|
|
118
|
+
- previous accepted observation
|
|
119
|
+
- previous progress and estimate summary when present
|
|
120
|
+
- read-only boundary unless the task authorizes a mutation
|
|
121
|
+
- required output shape
|
|
122
|
+
|
|
123
|
+
It tells the model that every accepted check must include a concise report. It tells the model to submit observed progress facts and target-provided ETA values only. The model does not calculate the official rate, confidence, or measured ETA.
|
|
124
|
+
|
|
125
|
+
A check may use available tools to read current state. It must use the target's authoritative source instead of treating a prior report or workflow update as current truth.
|
|
126
|
+
|
|
127
|
+
## Progress publication
|
|
128
|
+
|
|
129
|
+
`estimate` keeps the last eight usable intervals for each track in its normal node output. The output is durable and becomes the prior estimator state on the next loop visit.
|
|
130
|
+
|
|
131
|
+
`publish_progress` calls `context.publishUpdate()` once for each track with:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
{
|
|
135
|
+
type: "progress",
|
|
136
|
+
key: track.key,
|
|
137
|
+
data: track.data,
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The published data remains the observed progress snapshot. Derived estimates stay in the estimator output and presentation view. The widget and viewer combine the observed update history with the pure estimator so they do not misrepresent estimates as target facts.
|
|
142
|
+
|
|
143
|
+
When a check contains no progress object, `estimate` and `publish_progress` return an empty result. The report still runs.
|
|
144
|
+
|
|
145
|
+
## Schedule publication
|
|
146
|
+
|
|
147
|
+
Before sleeping, `schedule` publishes:
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"type": "monitor.schedule",
|
|
152
|
+
"key": "next-check",
|
|
153
|
+
"data": {
|
|
154
|
+
"schema": "pi-workflows.monitor-schedule.v1",
|
|
155
|
+
"lastCheckAt": "2026-08-16T10:15:30.000Z",
|
|
156
|
+
"nextCheckAt": "2026-08-16T10:45:30.000Z",
|
|
157
|
+
"everyMinutes": 30
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
All fields are required. Times use RFC 3339 UTC form. `everyMinutes` must match the prepared monitor configuration.
|
|
163
|
+
|
|
164
|
+
The schedule update lets the widget and viewer show time since the last check and time until the next check without calling a model or writing state on each clock tick.
|
|
165
|
+
|
|
166
|
+
## Report formatting
|
|
167
|
+
|
|
168
|
+
The notification begins with the submitted `report`. When progress is present, a model-free formatter appends a bounded structured summary.
|
|
169
|
+
|
|
170
|
+
Example:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
Import remains healthy.
|
|
174
|
+
Progress: 420/1,000 rows (42%, +60)
|
|
175
|
+
Rate: 29–33 rows/min
|
|
176
|
+
ETA: 18–20 min (medium confidence, 4 samples)
|
|
177
|
+
Next check: 30 min
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Rules:
|
|
181
|
+
|
|
182
|
+
- Show absolute values before deltas.
|
|
183
|
+
- Label source ETA as `source ETA`.
|
|
184
|
+
- Show `ETA unavailable` with a short reason when no valid estimate exists.
|
|
185
|
+
- Do not display a negative countdown after an ETA passes.
|
|
186
|
+
- Use `ETA passed; awaiting next check` until a new sample arrives.
|
|
187
|
+
- Keep failed, blocked, or stale state ahead of rate details.
|
|
188
|
+
- Show every track when the formatted report remains within 4,000 characters.
|
|
189
|
+
- When it does not fit, show `overall`, failed or blocked tracks, then as many active tracks as fit, followed by the omitted count.
|
|
190
|
+
|
|
191
|
+
Unrelated tracks are never combined. The monitor uses an explicit `overall` track when the target supplies meaningful aggregate progress.
|
|
192
|
+
|
|
193
|
+
## Notification delivery
|
|
194
|
+
|
|
195
|
+
Each accepted check reaches `report`, including a check that selects `stop`. The `notify` node writes one durable message through the existing session-addressed outbox.
|
|
196
|
+
|
|
197
|
+
The extension delivers the custom Pi message with `triggerTurn: false`. The notification stays in session history and later model context. Its arrival does not start an assistant response.
|
|
198
|
+
|
|
199
|
+
The monitor does not use `sendUserMessage`. It does not ask an agent to repeat or acknowledge the notification.
|
|
200
|
+
|
|
201
|
+
A check that times out or fails before producing accepted output is not an accepted check. The run enters its normal terminal error state and the extension shows the workflow lifecycle notification. It does not invent a successful check report.
|
|
202
|
+
|
|
203
|
+
## Routing and stopping
|
|
204
|
+
|
|
205
|
+
`route: "stop"` queues the report and then completes the workflow.
|
|
206
|
+
|
|
207
|
+
`route: "continue"` queues the report and then checks the safety limit. If the limit remains available, the workflow schedules and waits for the next check. If the accepted check reaches `maxChecks`, the workflow finishes after that check's report and records `Reached the <n>-check safety limit.`
|
|
208
|
+
|
|
209
|
+
A user cancellation stops the active check or wait immediately. It does not queue another report. The existing workflow lifecycle notification reports cancellation.
|
|
210
|
+
|
|
211
|
+
Failures, blocked states, and unavailable status follow the user's `stopWhen` rule. The check may continue after reporting an unavailable source when observation remains safe and the stop condition is not met. It must stop when the requested terminal state is verified.
|
|
212
|
+
|
|
213
|
+
## Widget
|
|
214
|
+
|
|
215
|
+
Progress display is optional. A monitor without progress uses the normal workflow graph widget.
|
|
216
|
+
|
|
217
|
+
With progress, the widget uses the existing 10-line budget. It keeps the active graph row and uses remaining lines for a compact progress panel. It shows `overall` first, then failed or blocked tracks, then active tracks. Existing widget scrolling exposes omitted tracks.
|
|
218
|
+
|
|
219
|
+
The widget may show:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
Overall 420/1,000 rows ETA 18–20m
|
|
223
|
+
Worker A running 7m elapsed
|
|
224
|
+
Worker B waiting
|
|
225
|
+
Last check 7m ago next check 23m
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Between checks, the existing one-second widget ticker may update:
|
|
229
|
+
|
|
230
|
+
- workflow and phase elapsed time
|
|
231
|
+
- time since the last progress sample
|
|
232
|
+
- ETA countdown derived from the last estimate
|
|
233
|
+
- time until the next check
|
|
234
|
+
|
|
235
|
+
It does not advance observed `completed`, publish updates, write bundle state, or call a model.
|
|
236
|
+
|
|
237
|
+
When an ETA expires, the widget shows that the estimate passed and waits for the next sample. `piw` shows the complete track list, update history, estimate basis, confidence, and source timestamps.
|
|
238
|
+
|
|
239
|
+
## Several monitored processes
|
|
240
|
+
|
|
241
|
+
One monitor can track several processes. Each uses a stable progress key. A missing key in a later check does not mean completion; the check should publish an explicit terminal or `unknown` state before it stops reporting that process.
|
|
242
|
+
|
|
243
|
+
The progress estimator treats each key independently. A phase, unit, total, or counter reset in one track does not reset another track.
|
|
244
|
+
|
|
245
|
+
## Interval and lifetime
|
|
246
|
+
|
|
247
|
+
The normal workflow engine remains finite. The built-in monitor therefore retains the 1,000-check safety ceiling and must not claim to be mathematically unbounded.
|
|
248
|
+
|
|
249
|
+
At the default 30-minute interval, the ceiling allows about 20 days and 20 hours after the immediate first check. A caller that needs longer unattended reconciliation should use the controller runtime. A controller-backed indefinite monitor is a separate resource lifecycle. The workflow engine keeps its finite-step guard.
|
|
250
|
+
|
|
251
|
+
The monitor skill must disclose a surfaced host limit and must never invent a smaller limit such as two checks. When no finish condition is clear, it sets the stop rule to explicit user stop and omits `maxChecks` so the workflow uses its documented safety ceiling.
|
|
252
|
+
|
|
253
|
+
## Safety boundaries
|
|
254
|
+
|
|
255
|
+
Monitoring authorizes observation and scheduled checks. It does not authorize retries, restarts, scaling, deployment, publication, cancellation of the target, or higher spending.
|
|
256
|
+
|
|
257
|
+
A progress object is data. It cannot contain a command or grant execution authority. Fixed probes belong in workflow-authored `action` or `shell` nodes.
|
|
258
|
+
|
|
259
|
+
Paid compute, inference runtime, and other domain policies continue to apply to every check.
|
|
260
|
+
|
|
261
|
+
## Validation and acceptance
|
|
262
|
+
|
|
263
|
+
The implementation must test:
|
|
264
|
+
|
|
265
|
+
- input defaults and bounds
|
|
266
|
+
- removal of `reportWhen`
|
|
267
|
+
- rejection of old quiet routes
|
|
268
|
+
- required reports on both routes
|
|
269
|
+
- exactly one notification per accepted check
|
|
270
|
+
- no assistant turn from a notification
|
|
271
|
+
- progress omission and multiple tracks
|
|
272
|
+
- invalid and duplicate track keys
|
|
273
|
+
- progress resets and stale samples
|
|
274
|
+
- measured, source, unavailable, paused, and expired ETA display
|
|
275
|
+
- schedule timestamps and countdown rendering
|
|
276
|
+
- final report before stop
|
|
277
|
+
- safety-limit report before completion
|
|
278
|
+
- immediate cancellation during a check or wait
|
|
279
|
+
- resume after host interruption
|
|
280
|
+
- widget behavior with zero, one, and many tracks
|
|
281
|
+
|
|
282
|
+
The real-Pi end-to-end test must start a short monitor, observe its custom notification without a new assistant turn, inspect the widget, and stop the run without mutating an external target.
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Workflow step messages
|
|
2
|
+
|
|
3
|
+
This specification defines how Pi Workflows shows agent-step instructions in an interactive Pi session. The model receives the complete step prompt, while the user sees a small workflow card that can be expanded.
|
|
4
|
+
|
|
5
|
+
This contract is implemented for the release after `0.5.3`.
|
|
6
|
+
|
|
7
|
+
## Goal
|
|
8
|
+
|
|
9
|
+
Agent-step prompts contain the task, workflow identity, attempt identity, output shape, and submission rules. This information is required by the model, but showing it as a large user message makes the conversation hard to read.
|
|
10
|
+
|
|
11
|
+
Pi Workflows will send the same prompt as a custom Pi message. A custom renderer will show a compact summary by default and the full content when expanded.
|
|
12
|
+
|
|
13
|
+
This is a presentation change. It does not add a workflow primitive, change graph execution, or change the step completion contract.
|
|
14
|
+
|
|
15
|
+
## Message contract
|
|
16
|
+
|
|
17
|
+
Interactive agent-step messages use the custom type `pi-workflows-agent-step`.
|
|
18
|
+
|
|
19
|
+
The message has this shape:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
export type WorkflowAgentStepMessageDetails = {
|
|
23
|
+
schema: "pi-workflows.agent-step-message.v1";
|
|
24
|
+
kind: "step" | "reminder" | "resume";
|
|
25
|
+
contract: AgentStepContract;
|
|
26
|
+
presentation?: {
|
|
27
|
+
runTitle?: string;
|
|
28
|
+
statusDetail?: string;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
pi.sendMessage(
|
|
33
|
+
{
|
|
34
|
+
customType: "pi-workflows-agent-step",
|
|
35
|
+
content: completeModelPrompt,
|
|
36
|
+
display: true,
|
|
37
|
+
details,
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
triggerTurn: true,
|
|
41
|
+
deliverAs: streaming ? "steer" : "followUp",
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`content` is the complete prompt that the existing executor would send as a user message. It remains available to the model and in session history.
|
|
47
|
+
|
|
48
|
+
`details` contains structured display data. The renderer reads this object directly and never parses the prompt text. `AgentStepContract` remains the source of every identity field and the expected-output field.
|
|
49
|
+
|
|
50
|
+
`kind` distinguishes the first delivery from a reminder or a resume that must repeat the instructions. An ordinary resume that can continue without another prompt does not create a message.
|
|
51
|
+
|
|
52
|
+
## Engine boundary
|
|
53
|
+
|
|
54
|
+
The workflow engine remains independent of Pi. It continues to produce an `AgentStepRequest` with a complete prompt and structured contract.
|
|
55
|
+
|
|
56
|
+
The request gains optional presentation data for the run title and node status detail. The conversation executor passes the prompt, contract, presentation data, delivery kind, and streaming state to the Pi extension. The RPC executor sends the same complete prompt to headless Pi without TUI metadata.
|
|
57
|
+
|
|
58
|
+
One pure formatter remains responsible for the model prompt used by both executors. Interactive delivery must not shorten, summarize, or rebuild the model prompt from display fields.
|
|
59
|
+
|
|
60
|
+
## Compact display
|
|
61
|
+
|
|
62
|
+
The collapsed card shows only useful workflow identity and current work. For example:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
▶ monitor › check
|
|
66
|
+
Checking the monitored target
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
A reminder or resumed delivery adds a short label:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
↻ monitor › check · reminder
|
|
73
|
+
Checking the monitored target
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The card uses the run title when it is more useful than the workflow name. It omits missing status detail instead of inventing one. Long fields are clipped or wrapped to the available terminal width.
|
|
77
|
+
|
|
78
|
+
The expanded card shows:
|
|
79
|
+
|
|
80
|
+
- workflow name and run title
|
|
81
|
+
- run id
|
|
82
|
+
- node id
|
|
83
|
+
- attempt id
|
|
84
|
+
- delivery kind
|
|
85
|
+
- expected output
|
|
86
|
+
- full model prompt
|
|
87
|
+
|
|
88
|
+
Expansion uses Pi's existing custom-message expansion state and keys. Pi Workflows does not add another toggle or store separate expansion state.
|
|
89
|
+
|
|
90
|
+
## Reminders and resumes
|
|
91
|
+
|
|
92
|
+
The existing bounded reminder behavior stays in place. A reminder uses the same custom message type and renderer. It keeps the contract and sets `kind: "reminder"`.
|
|
93
|
+
|
|
94
|
+
A resumed step uses `kind: "resume"` only when the executor must send the instructions again. The attempt id must still identify the active attempt. Stale attempts remain invalid.
|
|
95
|
+
|
|
96
|
+
## Notifications
|
|
97
|
+
|
|
98
|
+
Workflow notifications keep the separate custom type `pi-workflows-notification`.
|
|
99
|
+
|
|
100
|
+
Agent-step messages use `triggerTurn: true` because they ask the model to work. Notifications use `triggerTurn: false` because they report state to the user without asking for an assistant response.
|
|
101
|
+
|
|
102
|
+
The two message types must not share delivery code that can accidentally change this behavior.
|
|
103
|
+
|
|
104
|
+
## Session and persistence impact
|
|
105
|
+
|
|
106
|
+
New interactive step deliveries replace `sendUserMessage` with `sendMessage`. Existing session entries remain readable and are not rewritten.
|
|
107
|
+
|
|
108
|
+
The custom message is a normal documented Pi session message. Pi Workflows adds no Pi session schema, private entry type, or separate persistent store. Run bundles keep the existing full prompt and structured step contract, so this change does not alter the run-bundle schema.
|
|
109
|
+
|
|
110
|
+
If the renderer is unavailable, Pi still retains the custom message content. Pi Workflows does not add a fallback path that sends a duplicate user message.
|
|
111
|
+
|
|
112
|
+
## Public API boundary
|
|
113
|
+
|
|
114
|
+
This design uses the documented `pi.sendMessage()` and `pi.registerMessageRenderer()` APIs. The renderer uses Pi's standard `expanded` state.
|
|
115
|
+
|
|
116
|
+
It does not require a Pi core change or private Pi API.
|
|
117
|
+
|
|
118
|
+
The workflow package adds no node, graph action, tool action, or workflow-file field for this feature. Workflow authors do not configure message rendering.
|
|
119
|
+
|
|
120
|
+
## Validation and tests
|
|
121
|
+
|
|
122
|
+
The implementation must verify:
|
|
123
|
+
|
|
124
|
+
- interactive and RPC executors give the model the same complete prompt
|
|
125
|
+
- one step message starts one model turn
|
|
126
|
+
- collapsed rendering does not show the full prompt
|
|
127
|
+
- expanded rendering shows the full prompt and exact contract ids
|
|
128
|
+
- long and missing display fields render safely
|
|
129
|
+
- reminders and resumed deliveries keep the active attempt id
|
|
130
|
+
- stale attempts remain rejected after timeout or cancellation
|
|
131
|
+
- session replay restores the same custom message
|
|
132
|
+
- notifications still enter context without starting a model turn
|
|
133
|
+
- no duplicate user message is sent
|
|
134
|
+
|
|
135
|
+
The end-to-end test must inspect the provider-facing prompt as well as the TUI message record. A correct card with missing model instructions is a failure.
|
|
136
|
+
|
|
137
|
+
## Security
|
|
138
|
+
|
|
139
|
+
Workflow prompts and expected-output descriptions may contain untrusted text. The renderer treats them as text, applies terminal-safe wrapping, and does not interpret control sequences or markup from workflow data.
|
|
140
|
+
|
|
141
|
+
Collapsed cards avoid showing full prompts in the normal conversation view. Expanded content and session files still contain the complete prompt, so existing session privacy rules continue to apply.
|