refactor(artifacts): reconcile workspace artifacts at completion

This commit is contained in:
ZacharyZhang-NY committed 2026-04-24 00:58:07 -04:00
1 parent 2ddc67cc3d
commit fd86fc6668
17 files changed
+114 -436

No files matched your search

-1
View File
@@ -24,7 +24,6 @@ export const workerRpcMethodSchema = z.enum([
"persistMessage",
"prepareRun",
"beforeToolCall",
"afterToolCall",
"invokeInternalTool",
]);
@@ -8,13 +8,11 @@
* they need the SQLite connection, approval subsystem, and telemetry —
* none of which the worker should replicate.
*
* This is structurally the same pattern as `beforeToolCall`/
* `afterToolCall` in `hook-rpc.ts`; what's different
* is that those are side-effect hooks around pi's own tools, whereas
* this is a primary-effect tool whose business logic lives entirely in
* main. Keeping the payload shape minimal (name + JSON args) mirrors
* pi's `ToolCall` structure so adding a new internal tool requires no
* new RPC method — only a new handler entry.
* This mirrors the `beforeToolCall` RPC envelope in `hook-rpc.ts`:
* a minimal tool-call payload crosses the worker boundary and main owns
* the business effect. Keeping the payload shape minimal (name + JSON
* args) mirrors pi's `ToolCall` structure so adding a new internal tool
* requires no new RPC method — only a new handler entry.
*/
export interface InvokeInternalToolRpcPayload {
+5 -8
View File
@@ -1,15 +1,13 @@
/**
* Factory that assembles a `pi-agent-core` Agent from a prepared worker
* job. Encapsulates the full Pi contract (initial state, sessionId,
* thinkingLevel, beforeToolCall / afterToolCall / transformContext
* thinkingLevel, beforeToolCall / transformContext
* hooks, streamFn) so `worker-runner` stays focused on run lifecycle.
*
* The three tool-execution hooks proxy into main via the worker RPC
* client; main answers from `RuntimeBridge`. Pi's loop is tolerant of
* thrown hooks — a thrown `beforeToolCall` produces an error tool
* result, a thrown `afterToolCall` likewise — so RPC failures degrade
* to a deterministic tool-error instead of crashing the run. The
* `transformContext` runs the deterministic compactor in the worker
* `beforeToolCall` proxies into main via the worker RPC client; main
* answers from `RuntimeBridge`. Pi's loop is tolerant of thrown hooks,
* so approval RPC failures degrade to a deterministic tool-error. The
* `transformContext` hook runs the deterministic compactor in the worker
* process and lets compaction failures fail the run explicitly.
*/
@@ -84,7 +82,6 @@ export function createPiAgent(input: PiAgentFactoryInput): Agent {
headers: { ...(options?.headers ?? {}), ...(input.extraHeaders ?? {}) },
}),
beforeToolCall: hooks.beforeToolCall,
afterToolCall: hooks.afterToolCall,
transformContext: hooks.transformContext,
toolExecution: "sequential",
});
+1 -17
View File
@@ -3,7 +3,7 @@
* `pi-agent-core` callback signatures.
*
* Root `package.json` pins `@mariozechner/pi-agent-core` to 0.67.68
* while our worker wires local hooks — `beforeToolCall`, `afterToolCall`,
* while our worker wires local hooks — `beforeToolCall` and
* `transformContext` — into the pi Agent constructor. Those hooks carry
* deep structural coupling: pi decides the context shape passed in and
* the result shape we return. A silent signature drift on upgrade would
@@ -21,8 +21,6 @@
*/
import type {
AfterToolCallContext,
AfterToolCallResult,
AgentMessage,
AgentOptions,
BeforeToolCallContext,
@@ -37,7 +35,6 @@ import type {
* cascades into every `satisfies` check below.
*/
export type PiBeforeToolCall = NonNullable<AgentOptions["beforeToolCall"]>;
export type PiAfterToolCall = NonNullable<AgentOptions["afterToolCall"]>;
export type PiTransformContext = NonNullable<AgentOptions["transformContext"]>;
/**
@@ -47,8 +44,6 @@ export type PiTransformContext = NonNullable<AgentOptions["transformContext"]>;
*/
export type PiBeforeToolCallContext = BeforeToolCallContext;
export type PiBeforeToolCallResult = BeforeToolCallResult;
export type PiAfterToolCallContext = AfterToolCallContext;
export type PiAfterToolCallResult = AfterToolCallResult;
export type PiAgentMessage = AgentMessage;
/**
@@ -74,11 +69,6 @@ type LocalBeforeToolCallShape = (
signal?: AbortSignal,
) => Promise<BeforeToolCallResult | undefined>;
type LocalAfterToolCallShape = (
ctx: AfterToolCallContext,
signal?: AbortSignal,
) => Promise<AfterToolCallResult | undefined>;
type LocalTransformContextShape = (
messages: AgentMessage[],
signal?: AbortSignal,
@@ -92,7 +82,6 @@ type LocalTransformContextShape = (
* field on either side breaks the build.
*/
export type BeforeToolCallContract = ExpectHookType<PiBeforeToolCall, LocalBeforeToolCallShape>;
export type AfterToolCallContract = ExpectHookType<PiAfterToolCall, LocalAfterToolCallShape>;
export type TransformContextContract = ExpectHookType<PiTransformContext, LocalTransformContextShape>;
/**
@@ -108,11 +97,6 @@ export type BeforeToolCallHandlerResult = {
readonly reason: string | null;
};
export type AfterToolCallHandlerResult = {
readonly contentOverride: AfterToolCallResult["content"] | null;
readonly isErrorOverride: AfterToolCallResult["isError"] | null;
};
export type TransformContextHandlerResult = {
readonly changed: boolean;
readonly messages: AgentMessage[] | null;