@fragno-dev/pi-harness 0.0.0-stage → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +16 -0
- package/README.md +181 -2
- package/dist/browser/agent-harness-event-protocol-CuKubox1.js +666 -0
- package/dist/browser/agent-harness-event-protocol-CuKubox1.js.map +1 -0
- package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts +261 -0
- package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts.map +1 -0
- package/dist/browser/client/clients.d.ts +2 -0
- package/dist/browser/client/clients.js +2 -0
- package/dist/browser/client/pi-workflow-emission-stream.d.ts +13 -0
- package/dist/browser/client/pi-workflow-emission-stream.d.ts.map +1 -0
- package/dist/browser/client/pi-workflow-emission-stream.js +29 -0
- package/dist/browser/client/pi-workflow-emission-stream.js.map +1 -0
- package/dist/browser/client/react.d.ts +147 -0
- package/dist/browser/client/react.d.ts.map +1 -0
- package/dist/browser/client/react.js +187 -0
- package/dist/browser/client/react.js.map +1 -0
- package/dist/browser/client/solid.d.ts +150 -0
- package/dist/browser/client/solid.d.ts.map +1 -0
- package/dist/browser/client/solid.js +130 -0
- package/dist/browser/client/solid.js.map +1 -0
- package/dist/browser/client/svelte.d.ts +150 -0
- package/dist/browser/client/svelte.d.ts.map +1 -0
- package/dist/browser/client/svelte.js +132 -0
- package/dist/browser/client/svelte.js.map +1 -0
- package/dist/browser/client/vanilla.d.ts +177 -0
- package/dist/browser/client/vanilla.d.ts.map +1 -0
- package/dist/browser/client/vanilla.js +159 -0
- package/dist/browser/client/vanilla.js.map +1 -0
- package/dist/browser/client/vue.d.ts +150 -0
- package/dist/browser/client/vue.d.ts.map +1 -0
- package/dist/browser/client/vue.js +128 -0
- package/dist/browser/client/vue.js.map +1 -0
- package/dist/browser/client/workflow-lofi-session-projection.d.ts +17 -0
- package/dist/browser/client/workflow-lofi-session-projection.d.ts.map +1 -0
- package/dist/browser/client/workflow-lofi-session-projection.js +107 -0
- package/dist/browser/client/workflow-lofi-session-projection.js.map +1 -0
- package/dist/browser/clients-DYXj19je.d.ts +247 -0
- package/dist/browser/clients-DYXj19je.d.ts.map +1 -0
- package/dist/browser/clients-pIAk6ClP.js +1853 -0
- package/dist/browser/clients-pIAk6ClP.js.map +1 -0
- package/dist/browser/pi/context-usage.d.ts +20 -0
- package/dist/browser/pi/context-usage.d.ts.map +1 -0
- package/dist/browser/pi/context-usage.js +84 -0
- package/dist/browser/pi/context-usage.js.map +1 -0
- package/dist/browser/pi/harness/agent-harness-event-protocol.d.ts +2 -0
- package/dist/browser/pi/harness/agent-harness-event-protocol.js +2 -0
- package/dist/browser/pi/route-schemas.d.ts +2 -0
- package/dist/browser/pi/route-schemas.js +130 -0
- package/dist/browser/pi/route-schemas.js.map +1 -0
- package/dist/browser/pi/workflow-session-projection.d.ts +2 -0
- package/dist/browser/pi/workflow-session-projection.js +2 -0
- package/dist/browser/route-schemas-DQB5ZR1E.d.ts +109 -0
- package/dist/browser/route-schemas-DQB5ZR1E.d.ts.map +1 -0
- package/dist/browser/types-8q4RWFXT.js +23 -0
- package/dist/browser/types-8q4RWFXT.js.map +1 -0
- package/dist/browser/types-Dk856kV1.d.ts +527 -0
- package/dist/browser/types-Dk856kV1.d.ts.map +1 -0
- package/dist/browser/workflow-session-projection-CJ4MUkpJ.js +443 -0
- package/dist/browser/workflow-session-projection-CJ4MUkpJ.js.map +1 -0
- package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts +93 -0
- package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts.map +1 -0
- package/dist/node/pi/compact-command-outcome-projection.js +41 -0
- package/dist/node/pi/compact-command-outcome-projection.js.map +1 -0
- package/dist/node/pi/context-usage.d.ts +20 -0
- package/dist/node/pi/context-usage.d.ts.map +1 -0
- package/dist/node/pi/context-usage.js +84 -0
- package/dist/node/pi/context-usage.js.map +1 -0
- package/dist/node/pi/definition.d.ts +535 -0
- package/dist/node/pi/definition.d.ts.map +1 -0
- package/dist/node/pi/definition.js +71 -0
- package/dist/node/pi/definition.js.map +1 -0
- package/dist/node/pi/factory.d.ts +142 -0
- package/dist/node/pi/factory.d.ts.map +1 -0
- package/dist/node/pi/factory.js +22 -0
- package/dist/node/pi/factory.js.map +1 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.d.ts +261 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.d.ts.map +1 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.js +588 -0
- package/dist/node/pi/harness/agent-harness-event-protocol.js.map +1 -0
- package/dist/node/pi/harness/json-value.js +82 -0
- package/dist/node/pi/harness/json-value.js.map +1 -0
- package/dist/node/pi/harness/pi-operation-completed.d.ts +16 -0
- package/dist/node/pi/harness/pi-operation-completed.d.ts.map +1 -0
- package/dist/node/pi/harness/pi-operation-completed.js +71 -0
- package/dist/node/pi/harness/pi-operation-completed.js.map +1 -0
- package/dist/node/pi/harness/session-storage.d.ts +62 -0
- package/dist/node/pi/harness/session-storage.d.ts.map +1 -0
- package/dist/node/pi/harness/session-storage.js +174 -0
- package/dist/node/pi/harness/session-storage.js.map +1 -0
- package/dist/node/pi/pi-jsonl-export.d.ts +11 -0
- package/dist/node/pi/pi-jsonl-export.d.ts.map +1 -0
- package/dist/node/pi/pi-jsonl-export.js +31 -0
- package/dist/node/pi/pi-jsonl-export.js.map +1 -0
- package/dist/node/pi/route-schemas.d.ts +109 -0
- package/dist/node/pi/route-schemas.d.ts.map +1 -0
- package/dist/node/pi/route-schemas.js +130 -0
- package/dist/node/pi/route-schemas.js.map +1 -0
- package/dist/node/pi/session-command-protocol.d.ts +14 -0
- package/dist/node/pi/session-command-protocol.d.ts.map +1 -0
- package/dist/node/pi/session-command-protocol.js +25 -0
- package/dist/node/pi/session-command-protocol.js.map +1 -0
- package/dist/node/pi/session-entry-projection.js +79 -0
- package/dist/node/pi/session-entry-projection.js.map +1 -0
- package/dist/node/pi/skills.d.ts +70 -0
- package/dist/node/pi/skills.d.ts.map +1 -0
- package/dist/node/pi/skills.js +150 -0
- package/dist/node/pi/skills.js.map +1 -0
- package/dist/node/pi/tools.d.ts +12 -0
- package/dist/node/pi/tools.d.ts.map +1 -0
- package/dist/node/pi/tools.js +8 -0
- package/dist/node/pi/tools.js.map +1 -0
- package/dist/node/pi/types.d.ts +165 -0
- package/dist/node/pi/types.d.ts.map +1 -0
- package/dist/node/pi/types.js +49 -0
- package/dist/node/pi/types.js.map +1 -0
- package/dist/node/pi/wait-for-command-step.js +46 -0
- package/dist/node/pi/wait-for-command-step.js.map +1 -0
- package/dist/node/pi/workflow-session-live-projection.js +220 -0
- package/dist/node/pi/workflow-session-live-projection.js.map +1 -0
- package/dist/node/pi/workflow-session-projection.d.ts +84 -0
- package/dist/node/pi/workflow-session-projection.d.ts.map +1 -0
- package/dist/node/pi/workflow-session-projection.js +100 -0
- package/dist/node/pi/workflow-session-projection.js.map +1 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.d.ts +37 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.d.ts.map +1 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.js +219 -0
- package/dist/node/pi/workflows/interactive-chat-workflow.js.map +1 -0
- package/dist/node/pi/workflows/workflow-agent-harness.d.ts +142 -0
- package/dist/node/pi/workflows/workflow-agent-harness.d.ts.map +1 -0
- package/dist/node/pi/workflows/workflow-agent-harness.js +450 -0
- package/dist/node/pi/workflows/workflow-agent-harness.js.map +1 -0
- package/dist/node/routes.d.ts +631 -0
- package/dist/node/routes.d.ts.map +1 -0
- package/dist/node/routes.js +355 -0
- package/dist/node/routes.js.map +1 -0
- package/dist/node/schema.d.ts +5 -0
- package/dist/node/schema.d.ts.map +1 -0
- package/dist/node/schema.js +7 -0
- package/dist/node/schema.js.map +1 -0
- package/package.json +175 -3
package/LICENSE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright 2025 - present "ReJot Nederland B.V.", and individual contributors.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4
|
+
associated documentation files (the “Software”), to deal in the Software without restriction,
|
|
5
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
6
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
7
|
+
furnished to do so, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
10
|
+
portions of the Software.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
13
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
14
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
|
15
|
+
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
16
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,182 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @fragno-dev/pi-harness
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Fragno fragment that provides Pi session/commands routes, workflow-backed AgentHarness helpers,
|
|
4
|
+
and client integrations.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
Import the logical surface you need directly:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { AgentHarness } from "@earendil-works/pi-agent-core";
|
|
12
|
+
import { defineWorkflow } from "@fragno-dev/workflows/workflow";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
import { piHarnessDefinition } from "@fragno-dev/pi-harness/definition";
|
|
16
|
+
import { createPiHarness } from "@fragno-dev/pi-harness/factory";
|
|
17
|
+
import { piSessionCommandPayloadSchema } from "@fragno-dev/pi-harness/route-schemas";
|
|
18
|
+
import { definePiTool } from "@fragno-dev/pi-harness/tools";
|
|
19
|
+
import type { PiFragmentConfig } from "@fragno-dev/pi-harness/types";
|
|
20
|
+
import { createInteractiveChatWorkflow } from "@fragno-dev/pi-harness/workflows/interactive-chat-workflow";
|
|
21
|
+
import {
|
|
22
|
+
applyWorkflowAgentHarnessStepResult,
|
|
23
|
+
createPiHarnessSessionState,
|
|
24
|
+
restoreWorkflowBackedSession,
|
|
25
|
+
withWorkflowAgentHarness,
|
|
26
|
+
} from "@fragno-dev/pi-harness/workflows/workflow-agent-harness";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
There is intentionally no package-root barrel export.
|
|
30
|
+
|
|
31
|
+
Interactive chat workflows reconstruct normal `AgentHarness` options for every workflow replay:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
createInteractiveChatWorkflow({
|
|
35
|
+
options: async (event) => ({
|
|
36
|
+
model,
|
|
37
|
+
models,
|
|
38
|
+
systemPrompt: await loadSystemPrompt(event.payload),
|
|
39
|
+
resources: await loadResources(event.payload),
|
|
40
|
+
tools: await loadSessionTools(event.instanceId),
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The `options` callback runs outside durable workflow steps, so it may return non-serializable
|
|
46
|
+
runtime resources such as session-scoped tool `execute` functions. Session creation may include an
|
|
47
|
+
arbitrary `metadata` object; Pi Harness stores it with the session, forwards it as
|
|
48
|
+
`event.payload.metadata`, and includes it in operation accounting.
|
|
49
|
+
|
|
50
|
+
Custom workflows own their durable steps and use real Pi `Session` and `AgentHarness` objects. Fold
|
|
51
|
+
each completed step result into workflow-local state before starting the next operation:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
const workflow = defineWorkflow(
|
|
55
|
+
{ name: "search-chat", schema: z.object({}) },
|
|
56
|
+
async (event, step) => {
|
|
57
|
+
let state = createPiHarnessSessionState({
|
|
58
|
+
metadata: { id: event.instanceId, createdAt: event.timestamp.toISOString() },
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
while (true) {
|
|
62
|
+
const commandEvent = await step.waitForEvent("wait-command", {
|
|
63
|
+
type: "command",
|
|
64
|
+
timeout: "7 days",
|
|
65
|
+
});
|
|
66
|
+
const command = piSessionCommandPayloadSchema.parse(commandEvent.payload);
|
|
67
|
+
if (command.kind !== "prompt") continue;
|
|
68
|
+
|
|
69
|
+
const result = await step.do(`command:${command.commandId}`, async (tx) => {
|
|
70
|
+
const restored = restoreWorkflowBackedSession({
|
|
71
|
+
operationId: `${workflow.name}:${event.instanceId}:command:${command.commandId}`,
|
|
72
|
+
state,
|
|
73
|
+
previousEmissions: await tx.previousEmissions(),
|
|
74
|
+
models,
|
|
75
|
+
});
|
|
76
|
+
const harness = new AgentHarness({
|
|
77
|
+
models,
|
|
78
|
+
model,
|
|
79
|
+
tools: [searchTool, writeTool],
|
|
80
|
+
activeToolNames: ["search"],
|
|
81
|
+
...restored.options,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
return await withWorkflowAgentHarness({
|
|
85
|
+
restored,
|
|
86
|
+
harness,
|
|
87
|
+
tx,
|
|
88
|
+
runDurableStep: () => harness.prompt(command.input.text),
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
state = applyWorkflowAgentHarnessStepResult(state, result);
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
`activeToolNames` is a per-harness-operation policy for exposing only a subset of registered tools.
|
|
99
|
+
|
|
100
|
+
## Harness event protocol
|
|
101
|
+
|
|
102
|
+
Pi Harness encodes every subscribed `AgentHarness` event with its compact, versioned event protocol.
|
|
103
|
+
Workflow projections, routes, and clients use the same protocol automatically. Protocol selection is
|
|
104
|
+
not configurable.
|
|
105
|
+
|
|
106
|
+
The frontend projection preserves event count, order, and event type while omitting provider-owned
|
|
107
|
+
assistant metadata and signatures. Import the projected event types separately when needed:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import type { PiHarnessFrontendEvent } from "@fragno-dev/pi-harness/harness/agent-harness-event-protocol";
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Measure event protocol allocation
|
|
114
|
+
|
|
115
|
+
Run the isolated allocation benchmark when changing the compact event protocol:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pnpm --filter @fragno-dev/pi-harness measure:event-encoder
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The benchmark runs text streams and large `write_file` tool-call argument streams in fresh Node
|
|
122
|
+
processes. It reports sampled encoder and decoder allocation together with the encoded JSON bytes
|
|
123
|
+
produced for increasing payload sizes. Decoder cases use smaller payloads because replaying a
|
|
124
|
+
quadratic stream is intentionally expensive. The command fails when allocation or encoded bytes grow
|
|
125
|
+
more than 1.25 times the corresponding input growth, distinguishing approximately linear growth from
|
|
126
|
+
quadratic cumulative-payload behavior.
|
|
127
|
+
|
|
128
|
+
Use shorter cases while iterating or write the complete profiles to JSON:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pnpm --filter @fragno-dev/pi-harness measure:event-encoder -- \
|
|
132
|
+
--sizes 16384,32768 \
|
|
133
|
+
--runs 1 \
|
|
134
|
+
--streams 1 \
|
|
135
|
+
--json benchmark-results/pi-event-encoder.json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Operation completion hook
|
|
139
|
+
|
|
140
|
+
Interactive workflow input may include an opaque, JSON-serializable `actor`. It remains part of the
|
|
141
|
+
durable workflow parameters and the interactive workflow forwards it to each agent-loop operation.
|
|
142
|
+
Pi Harness does not interpret its shape.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
const config = {
|
|
146
|
+
workflows: [interactiveChatWorkflow],
|
|
147
|
+
onOperationCompleted: async ({ actor, sessionId, operation, modelCalls, usage }, context) => {
|
|
148
|
+
await recordUsage({
|
|
149
|
+
idempotencyKey: context.idempotencyKey,
|
|
150
|
+
actor,
|
|
151
|
+
sessionId,
|
|
152
|
+
operation,
|
|
153
|
+
modelCalls,
|
|
154
|
+
usage,
|
|
155
|
+
});
|
|
156
|
+
},
|
|
157
|
+
} satisfies PiFragmentConfig;
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The callback runs through the Pi fragment's durable-hook namespace. Node integrations must include
|
|
161
|
+
both the workflows and Pi fragments in the same durable-hooks processor:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { createDurableHooksProcessor } from "@fragno-dev/db/dispatchers/node";
|
|
165
|
+
|
|
166
|
+
const dispatcher = createDurableHooksProcessor([workflowsFragment, piFragment]);
|
|
167
|
+
dispatcher.startPolling();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`onOperationCompleted` is a durable hook triggered when a harness operation reaches a committed
|
|
171
|
+
terminal outcome. One operation can span multiple Pi turns and model calls when the agent uses
|
|
172
|
+
tools, so the payload includes both the individual calls and their aggregate usage. Failed and
|
|
173
|
+
aborted provider responses are included because they can still report billable usage.
|
|
174
|
+
|
|
175
|
+
Usage reporting currently covers operations that expose assistant messages. Compact operations and
|
|
176
|
+
tree navigation with summarization are not reported because Pi does not expose their internal model
|
|
177
|
+
calls as first-class harness events yet.
|
|
178
|
+
|
|
179
|
+
Workflow steps use optimistic concurrency control. In the rare case that the same step executes more
|
|
180
|
+
than once, only the execution whose transaction commits triggers the hook. Provider usage from
|
|
181
|
+
losing executions is therefore not reported. This is an intentional limitation for consumers
|
|
182
|
+
implementing allowances or usage limits.
|