@pi-ohm/pip-flue 0.6.4-dev.1781976430566.1.1516b3b
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/ARCH.md +231 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +5 -0
- package/package.json +34 -0
package/ARCH.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# @pi-ohm/pip-flue Architecture
|
|
2
|
+
|
|
3
|
+
`@pi-ohm/pip-flue` adapts Flue into PiP. It lets Pi packages use Flue-backed child agents through the generic `PipRunner` contract from `@pi-ohm/core/pip`.
|
|
4
|
+
|
|
5
|
+
## Goal
|
|
6
|
+
|
|
7
|
+
Make Pi able to run a conductor loop that creates durable child loops:
|
|
8
|
+
|
|
9
|
+
```txt
|
|
10
|
+
parent Pi session
|
|
11
|
+
-> PipController
|
|
12
|
+
-> FluePipRunner
|
|
13
|
+
-> local Flue Node server
|
|
14
|
+
-> many Flue agent instances keyed by pipId
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
This is the primitive needed for looped orchestration: one parent loop creates implementation, review, fix, and merge loops dynamically.
|
|
18
|
+
|
|
19
|
+
## Package boundary
|
|
20
|
+
|
|
21
|
+
`@pi-ohm/core/pip` owns only generic PiP primitives:
|
|
22
|
+
|
|
23
|
+
- `PipRunner`
|
|
24
|
+
- `PipController`
|
|
25
|
+
- `pipId`
|
|
26
|
+
- parent and child lifecycle metadata
|
|
27
|
+
- graph storage
|
|
28
|
+
- status vocabulary
|
|
29
|
+
|
|
30
|
+
`@pi-ohm/pip-flue` owns Flue specifics:
|
|
31
|
+
|
|
32
|
+
- `@flue/sdk` usage
|
|
33
|
+
- Flue base URL and headers
|
|
34
|
+
- Flue agent name selection
|
|
35
|
+
- mapping Flue events to `PipStatus`
|
|
36
|
+
- tracking Flue submission ids per `pipId`
|
|
37
|
+
- optional local Flue process management
|
|
38
|
+
|
|
39
|
+
Do not add Flue dependencies to `@pi-ohm/core`.
|
|
40
|
+
|
|
41
|
+
## Runtime topology
|
|
42
|
+
|
|
43
|
+
Run one Flue Node server per Pi root session, not one server per child session.
|
|
44
|
+
|
|
45
|
+
Why:
|
|
46
|
+
|
|
47
|
+
- Flue already multiplexes instances through `/agents/:name/:id`.
|
|
48
|
+
- The generated Node server owns dispatch, queues, persistence, and event streams.
|
|
49
|
+
- One process can host many child agents.
|
|
50
|
+
- Per-child servers would duplicate builds, ports, DBs, queues, and shutdown handling.
|
|
51
|
+
|
|
52
|
+
The local server is addressed through public HTTP using `@flue/sdk`.
|
|
53
|
+
|
|
54
|
+
Avoid:
|
|
55
|
+
|
|
56
|
+
- importing `@flue/runtime/internal`
|
|
57
|
+
- embedding Flue in-process through private runtime helpers
|
|
58
|
+
- driving Pi integration through `flue connect`, which is private IPC and local CLI UX
|
|
59
|
+
|
|
60
|
+
## Managed Flue workspace
|
|
61
|
+
|
|
62
|
+
A Pi-managed Flue workspace can be a small generated source area:
|
|
63
|
+
|
|
64
|
+
```txt
|
|
65
|
+
.flue/
|
|
66
|
+
agents/pi-worker.ts
|
|
67
|
+
db.ts
|
|
68
|
+
flue.config.ts
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`db.ts` should use file-backed SQLite so agent sessions and accepted prompts survive process restart:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { sqlite } from "@flue/runtime/node";
|
|
75
|
+
|
|
76
|
+
export default sqlite("./data/flue.db");
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Production-ish local execution should use:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
flue build --target node
|
|
83
|
+
PORT=<port> node dist/server.mjs
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use `flue dev --target node` for human edit loops only.
|
|
87
|
+
|
|
88
|
+
## Public adapter shape
|
|
89
|
+
|
|
90
|
+
Target export:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
createFluePipRunner(input): PipRunner
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Initial input shape:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
interface FluePipRunnerInput {
|
|
100
|
+
readonly baseUrl: string;
|
|
101
|
+
readonly agentName: string;
|
|
102
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
103
|
+
readonly token?: string;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Later process management can be separate:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
ensureFlueServer(input): Result<FlueServerHandle, FlueServerError>
|
|
111
|
+
createManagedFluePipRunner(input): PipRunner
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Keep the SDK adapter and server manager separate so remote Flue deployments can reuse the same runner.
|
|
115
|
+
|
|
116
|
+
## Identity mapping
|
|
117
|
+
|
|
118
|
+
| PiP | Flue |
|
|
119
|
+
| ------------------ | ----------------------------------------------------- |
|
|
120
|
+
| `pipId` | agent instance id |
|
|
121
|
+
| `role` | Flue agent name or Pi domain role mapped to one agent |
|
|
122
|
+
| `parentSessionId` | Pi-owned graph metadata |
|
|
123
|
+
| `childSessionId` | synthetic `flue:<agentName>:<pipId>` |
|
|
124
|
+
| `childSessionPath` | `null` until core has a generic child ref |
|
|
125
|
+
|
|
126
|
+
First implementation should use one configured `agentName`, usually `pi-worker`. Package-level consumers can map roles to agent names later.
|
|
127
|
+
|
|
128
|
+
## Lifecycle mapping
|
|
129
|
+
|
|
130
|
+
### `spawn`
|
|
131
|
+
|
|
132
|
+
- Create a PiP record for `pipId`.
|
|
133
|
+
- If an initial prompt exists, call `client.agents.send(agentName, pipId, { message })`.
|
|
134
|
+
- Store the returned `submissionId` against the `pipId`.
|
|
135
|
+
- Return `running` when Flue accepts the prompt.
|
|
136
|
+
- If no prompt exists, return `running` with the synthetic child identity.
|
|
137
|
+
|
|
138
|
+
### `send`
|
|
139
|
+
|
|
140
|
+
- Call `client.agents.send(agentName, pipId, { message })`.
|
|
141
|
+
- Track the latest `submissionId` for that `pipId`.
|
|
142
|
+
- Return `running` after admission.
|
|
143
|
+
|
|
144
|
+
### `wait`
|
|
145
|
+
|
|
146
|
+
- Stream `client.agents.stream(agentName, pipId, { offset })`.
|
|
147
|
+
- Filter events by the tracked `submissionId` when known.
|
|
148
|
+
- Complete when the prompt operation reaches a terminal `operation` event.
|
|
149
|
+
- Return timeout without guessing completion.
|
|
150
|
+
|
|
151
|
+
### `get`
|
|
152
|
+
|
|
153
|
+
- Read cached runtime state for the `pipId`.
|
|
154
|
+
- Optionally catch up the Flue stream to refresh status.
|
|
155
|
+
- Return `not_found` only when the adapter has no local or persisted knowledge of the `pipId`.
|
|
156
|
+
|
|
157
|
+
### `abort`
|
|
158
|
+
|
|
159
|
+
Flue SDK currently provides no public direct-prompt abort endpoint. First implementation should either:
|
|
160
|
+
|
|
161
|
+
- return an explicit unsupported `PipError`, or
|
|
162
|
+
- abort only local stream consumption and mark the PiP status as `interrupted` if the Flue runtime exposes a safe public mechanism later.
|
|
163
|
+
|
|
164
|
+
Do not fabricate cancellation.
|
|
165
|
+
|
|
166
|
+
### `close`
|
|
167
|
+
|
|
168
|
+
First implementation should close adapter-local tracking and return the previous status. Deleting Flue conversation state needs a public server endpoint or a package-owned admin route in the generated app.
|
|
169
|
+
|
|
170
|
+
### `resume`
|
|
171
|
+
|
|
172
|
+
Resume by reattaching to the Flue agent stream using stored `pipId`, `agentName`, stream offset, and latest `submissionId`.
|
|
173
|
+
|
|
174
|
+
## Status mapping
|
|
175
|
+
|
|
176
|
+
| Flue event | PiP status |
|
|
177
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------- |
|
|
178
|
+
| accepted prompt | `running` |
|
|
179
|
+
| `operation` with `operationKind: "prompt"`, `isError: false` | `completed` with result text |
|
|
180
|
+
| `operation` with `operationKind: "prompt"`, `isError: true` | `errored` |
|
|
181
|
+
| `submission_settled` with `outcome: "failed"` | `errored` |
|
|
182
|
+
| stream/read failure | `errored` only when the failure is terminal and attributable to the child |
|
|
183
|
+
| timeout while waiting | keep prior status, return `timedOut: true` |
|
|
184
|
+
|
|
185
|
+
The adapter should keep enough local state to avoid turning a transient stream issue into a fake terminal status.
|
|
186
|
+
|
|
187
|
+
## Core gaps to consider later
|
|
188
|
+
|
|
189
|
+
No core changes are required for the first proof because `PipRunner` already exists.
|
|
190
|
+
|
|
191
|
+
Likely useful upgrades:
|
|
192
|
+
|
|
193
|
+
- `PipController.list(...)`
|
|
194
|
+
- persisted runner kind, for example `pi-sdk` or `flue`
|
|
195
|
+
- generic child reference instead of Pi-specific `childSessionPath`
|
|
196
|
+
- status writes after `send`, `wait`, `get`, and `resume`
|
|
197
|
+
- durable adapter state for `agentName`, stream offset, and latest `submissionId`
|
|
198
|
+
|
|
199
|
+
Potential generic child ref:
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
type PipChildRef =
|
|
203
|
+
| {
|
|
204
|
+
readonly kind: "pi-session";
|
|
205
|
+
readonly sessionId: string;
|
|
206
|
+
readonly sessionPath: string | null;
|
|
207
|
+
}
|
|
208
|
+
| {
|
|
209
|
+
readonly kind: "flue-agent";
|
|
210
|
+
readonly agentName: string;
|
|
211
|
+
readonly instanceId: string;
|
|
212
|
+
};
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Non-goals
|
|
216
|
+
|
|
217
|
+
- No Flue-specific imports in `@pi-ohm/core`.
|
|
218
|
+
- No in-process use of `@flue/runtime/internal`.
|
|
219
|
+
- No per-child Flue server.
|
|
220
|
+
- No backwards compatibility constraints for early experiments.
|
|
221
|
+
- No fake abort or delete semantics.
|
|
222
|
+
- Support anything other than local sandbox for Flue in this MVP.
|
|
223
|
+
|
|
224
|
+
## Implementation phases
|
|
225
|
+
|
|
226
|
+
1. SDK-only runner against an already-running Flue server.
|
|
227
|
+
2. File-backed adapter state for `submissionId`, stream offset, and last status.
|
|
228
|
+
3. Managed local Node server per workspace.
|
|
229
|
+
4. Generated `.flue` app with `pi-worker` and SQLite `db.ts`.
|
|
230
|
+
5. Optional package-owned admin route for deletion, health, and manifest checks.
|
|
231
|
+
6. Core child-ref upgrade if Flue proves useful beyond the first adapter.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PipRunner } from "@pi-ohm/core/pip";
|
|
2
|
+
|
|
3
|
+
//#region src/index.d.ts
|
|
4
|
+
declare const packageName = "@pi-ohm/pip-flue";
|
|
5
|
+
interface FluePipRunnerInput {
|
|
6
|
+
readonly baseUrl: string;
|
|
7
|
+
readonly agentName: string;
|
|
8
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
9
|
+
readonly token?: string;
|
|
10
|
+
}
|
|
11
|
+
type FluePipRunnerFactory = (input: FluePipRunnerInput) => PipRunner;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { FluePipRunnerFactory, FluePipRunnerInput, packageName };
|
package/dist/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pi-ohm/pip-flue",
|
|
3
|
+
"version": "0.6.4-dev.1781976430566.1.1516b3b",
|
|
4
|
+
"homepage": "https://github.com/pi-ohm/pi-ohm/tree/dev/packages/pip-flue#readme",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/pi-ohm/pi-ohm.git",
|
|
8
|
+
"directory": "packages/pip-flue"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"ARCH.md"
|
|
13
|
+
],
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "dist/index.js",
|
|
16
|
+
"types": "dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"access": "public",
|
|
25
|
+
"provenance": true
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "vp pack src/index.ts"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@flue/sdk": "^1.0.0-beta.1",
|
|
32
|
+
"@pi-ohm/core": "0.6.4-dev.1781976430566.1.1516b3b"
|
|
33
|
+
}
|
|
34
|
+
}
|