@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.
Files changed (140) hide show
  1. package/LICENSE.md +16 -0
  2. package/README.md +181 -2
  3. package/dist/browser/agent-harness-event-protocol-CuKubox1.js +666 -0
  4. package/dist/browser/agent-harness-event-protocol-CuKubox1.js.map +1 -0
  5. package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts +261 -0
  6. package/dist/browser/agent-harness-event-protocol-d6mH_9n3.d.ts.map +1 -0
  7. package/dist/browser/client/clients.d.ts +2 -0
  8. package/dist/browser/client/clients.js +2 -0
  9. package/dist/browser/client/pi-workflow-emission-stream.d.ts +13 -0
  10. package/dist/browser/client/pi-workflow-emission-stream.d.ts.map +1 -0
  11. package/dist/browser/client/pi-workflow-emission-stream.js +29 -0
  12. package/dist/browser/client/pi-workflow-emission-stream.js.map +1 -0
  13. package/dist/browser/client/react.d.ts +147 -0
  14. package/dist/browser/client/react.d.ts.map +1 -0
  15. package/dist/browser/client/react.js +187 -0
  16. package/dist/browser/client/react.js.map +1 -0
  17. package/dist/browser/client/solid.d.ts +150 -0
  18. package/dist/browser/client/solid.d.ts.map +1 -0
  19. package/dist/browser/client/solid.js +130 -0
  20. package/dist/browser/client/solid.js.map +1 -0
  21. package/dist/browser/client/svelte.d.ts +150 -0
  22. package/dist/browser/client/svelte.d.ts.map +1 -0
  23. package/dist/browser/client/svelte.js +132 -0
  24. package/dist/browser/client/svelte.js.map +1 -0
  25. package/dist/browser/client/vanilla.d.ts +177 -0
  26. package/dist/browser/client/vanilla.d.ts.map +1 -0
  27. package/dist/browser/client/vanilla.js +159 -0
  28. package/dist/browser/client/vanilla.js.map +1 -0
  29. package/dist/browser/client/vue.d.ts +150 -0
  30. package/dist/browser/client/vue.d.ts.map +1 -0
  31. package/dist/browser/client/vue.js +128 -0
  32. package/dist/browser/client/vue.js.map +1 -0
  33. package/dist/browser/client/workflow-lofi-session-projection.d.ts +17 -0
  34. package/dist/browser/client/workflow-lofi-session-projection.d.ts.map +1 -0
  35. package/dist/browser/client/workflow-lofi-session-projection.js +107 -0
  36. package/dist/browser/client/workflow-lofi-session-projection.js.map +1 -0
  37. package/dist/browser/clients-DYXj19je.d.ts +247 -0
  38. package/dist/browser/clients-DYXj19je.d.ts.map +1 -0
  39. package/dist/browser/clients-pIAk6ClP.js +1853 -0
  40. package/dist/browser/clients-pIAk6ClP.js.map +1 -0
  41. package/dist/browser/pi/context-usage.d.ts +20 -0
  42. package/dist/browser/pi/context-usage.d.ts.map +1 -0
  43. package/dist/browser/pi/context-usage.js +84 -0
  44. package/dist/browser/pi/context-usage.js.map +1 -0
  45. package/dist/browser/pi/harness/agent-harness-event-protocol.d.ts +2 -0
  46. package/dist/browser/pi/harness/agent-harness-event-protocol.js +2 -0
  47. package/dist/browser/pi/route-schemas.d.ts +2 -0
  48. package/dist/browser/pi/route-schemas.js +130 -0
  49. package/dist/browser/pi/route-schemas.js.map +1 -0
  50. package/dist/browser/pi/workflow-session-projection.d.ts +2 -0
  51. package/dist/browser/pi/workflow-session-projection.js +2 -0
  52. package/dist/browser/route-schemas-DQB5ZR1E.d.ts +109 -0
  53. package/dist/browser/route-schemas-DQB5ZR1E.d.ts.map +1 -0
  54. package/dist/browser/types-8q4RWFXT.js +23 -0
  55. package/dist/browser/types-8q4RWFXT.js.map +1 -0
  56. package/dist/browser/types-Dk856kV1.d.ts +527 -0
  57. package/dist/browser/types-Dk856kV1.d.ts.map +1 -0
  58. package/dist/browser/workflow-session-projection-CJ4MUkpJ.js +443 -0
  59. package/dist/browser/workflow-session-projection-CJ4MUkpJ.js.map +1 -0
  60. package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts +93 -0
  61. package/dist/browser/workflow-session-projection-Dj_a79GF.d.ts.map +1 -0
  62. package/dist/node/pi/compact-command-outcome-projection.js +41 -0
  63. package/dist/node/pi/compact-command-outcome-projection.js.map +1 -0
  64. package/dist/node/pi/context-usage.d.ts +20 -0
  65. package/dist/node/pi/context-usage.d.ts.map +1 -0
  66. package/dist/node/pi/context-usage.js +84 -0
  67. package/dist/node/pi/context-usage.js.map +1 -0
  68. package/dist/node/pi/definition.d.ts +535 -0
  69. package/dist/node/pi/definition.d.ts.map +1 -0
  70. package/dist/node/pi/definition.js +71 -0
  71. package/dist/node/pi/definition.js.map +1 -0
  72. package/dist/node/pi/factory.d.ts +142 -0
  73. package/dist/node/pi/factory.d.ts.map +1 -0
  74. package/dist/node/pi/factory.js +22 -0
  75. package/dist/node/pi/factory.js.map +1 -0
  76. package/dist/node/pi/harness/agent-harness-event-protocol.d.ts +261 -0
  77. package/dist/node/pi/harness/agent-harness-event-protocol.d.ts.map +1 -0
  78. package/dist/node/pi/harness/agent-harness-event-protocol.js +588 -0
  79. package/dist/node/pi/harness/agent-harness-event-protocol.js.map +1 -0
  80. package/dist/node/pi/harness/json-value.js +82 -0
  81. package/dist/node/pi/harness/json-value.js.map +1 -0
  82. package/dist/node/pi/harness/pi-operation-completed.d.ts +16 -0
  83. package/dist/node/pi/harness/pi-operation-completed.d.ts.map +1 -0
  84. package/dist/node/pi/harness/pi-operation-completed.js +71 -0
  85. package/dist/node/pi/harness/pi-operation-completed.js.map +1 -0
  86. package/dist/node/pi/harness/session-storage.d.ts +62 -0
  87. package/dist/node/pi/harness/session-storage.d.ts.map +1 -0
  88. package/dist/node/pi/harness/session-storage.js +174 -0
  89. package/dist/node/pi/harness/session-storage.js.map +1 -0
  90. package/dist/node/pi/pi-jsonl-export.d.ts +11 -0
  91. package/dist/node/pi/pi-jsonl-export.d.ts.map +1 -0
  92. package/dist/node/pi/pi-jsonl-export.js +31 -0
  93. package/dist/node/pi/pi-jsonl-export.js.map +1 -0
  94. package/dist/node/pi/route-schemas.d.ts +109 -0
  95. package/dist/node/pi/route-schemas.d.ts.map +1 -0
  96. package/dist/node/pi/route-schemas.js +130 -0
  97. package/dist/node/pi/route-schemas.js.map +1 -0
  98. package/dist/node/pi/session-command-protocol.d.ts +14 -0
  99. package/dist/node/pi/session-command-protocol.d.ts.map +1 -0
  100. package/dist/node/pi/session-command-protocol.js +25 -0
  101. package/dist/node/pi/session-command-protocol.js.map +1 -0
  102. package/dist/node/pi/session-entry-projection.js +79 -0
  103. package/dist/node/pi/session-entry-projection.js.map +1 -0
  104. package/dist/node/pi/skills.d.ts +70 -0
  105. package/dist/node/pi/skills.d.ts.map +1 -0
  106. package/dist/node/pi/skills.js +150 -0
  107. package/dist/node/pi/skills.js.map +1 -0
  108. package/dist/node/pi/tools.d.ts +12 -0
  109. package/dist/node/pi/tools.d.ts.map +1 -0
  110. package/dist/node/pi/tools.js +8 -0
  111. package/dist/node/pi/tools.js.map +1 -0
  112. package/dist/node/pi/types.d.ts +165 -0
  113. package/dist/node/pi/types.d.ts.map +1 -0
  114. package/dist/node/pi/types.js +49 -0
  115. package/dist/node/pi/types.js.map +1 -0
  116. package/dist/node/pi/wait-for-command-step.js +46 -0
  117. package/dist/node/pi/wait-for-command-step.js.map +1 -0
  118. package/dist/node/pi/workflow-session-live-projection.js +220 -0
  119. package/dist/node/pi/workflow-session-live-projection.js.map +1 -0
  120. package/dist/node/pi/workflow-session-projection.d.ts +84 -0
  121. package/dist/node/pi/workflow-session-projection.d.ts.map +1 -0
  122. package/dist/node/pi/workflow-session-projection.js +100 -0
  123. package/dist/node/pi/workflow-session-projection.js.map +1 -0
  124. package/dist/node/pi/workflows/interactive-chat-workflow.d.ts +37 -0
  125. package/dist/node/pi/workflows/interactive-chat-workflow.d.ts.map +1 -0
  126. package/dist/node/pi/workflows/interactive-chat-workflow.js +219 -0
  127. package/dist/node/pi/workflows/interactive-chat-workflow.js.map +1 -0
  128. package/dist/node/pi/workflows/workflow-agent-harness.d.ts +142 -0
  129. package/dist/node/pi/workflows/workflow-agent-harness.d.ts.map +1 -0
  130. package/dist/node/pi/workflows/workflow-agent-harness.js +450 -0
  131. package/dist/node/pi/workflows/workflow-agent-harness.js.map +1 -0
  132. package/dist/node/routes.d.ts +631 -0
  133. package/dist/node/routes.d.ts.map +1 -0
  134. package/dist/node/routes.js +355 -0
  135. package/dist/node/routes.js.map +1 -0
  136. package/dist/node/schema.d.ts +5 -0
  137. package/dist/node/schema.d.ts.map +1 -0
  138. package/dist/node/schema.js +7 -0
  139. package/dist/node/schema.js.map +1 -0
  140. 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
- # Temporary Holding Version
1
+ # @fragno-dev/pi-harness
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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.