mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
200 lines
8.8 KiB
Diff
200 lines
8.8 KiB
Diff
diff --git a/dist/live-checkpoint-BSIrfgVo.js b/dist/live-checkpoint-BSIrfgVo.js
|
|
index d454fd7c5bf742b469be75eb8c3988b694a0ffaa..5ddcd5cfcb80fd3417172a5e618f1e983e200644 100644
|
|
--- a/dist/live-checkpoint-BSIrfgVo.js
|
|
+++ b/dist/live-checkpoint-BSIrfgVo.js
|
|
@@ -1661,7 +1661,7 @@ const ZED_TAG_KEYS = /* @__PURE__ */ new Set([
|
|
"RedactedThinking",
|
|
"ToolUse"
|
|
]);
|
|
-const MAP_OBJECT_PATHS = /* @__PURE__ */ new Set(["request_token_usage", "messages.Agent.tool_results"]);
|
|
+const MAP_OBJECT_PATHS = /* @__PURE__ */ new Set(["request_token_usage", "messages.Agent.tool_results", "acpx.session_options.env"]);
|
|
const OPAQUE_VALUE_PATHS = /* @__PURE__ */ new Set([
|
|
"agent_capabilities",
|
|
"messages.Agent.content.ToolUse.input",
|
|
@@ -3135,8 +3135,8 @@ function promotePrefixedAuthEnvironment(env) {
|
|
}
|
|
return protectedKeys;
|
|
}
|
|
-function buildAgentEnvironment(authCredentials, sessionEnv) {
|
|
- const env = { ...process.env };
|
|
+function buildAgentEnvironment(authCredentials, sessionEnv, spawnEnvironment) {
|
|
+ const env = spawnEnvironment ? { ...spawnEnvironment } : { ...process.env };
|
|
const protectedAuthEnvKeys = promotePrefixedAuthEnvironment(env);
|
|
if (authCredentials) for (const [methodId, credential] of Object.entries(authCredentials)) {
|
|
addAuthCredentialEnvKeys(protectedAuthEnvKeys, methodId, credential);
|
|
@@ -3178,10 +3178,10 @@ function resolveConfiguredAuthCredential(methodId, authCredentials) {
|
|
const configCredentials = authCredentials ?? {};
|
|
return configCredentials[methodId] ?? configCredentials[toEnvToken(methodId)];
|
|
}
|
|
-function buildAgentSpawnOptions(cwd, authCredentials, sessionEnv) {
|
|
+function buildAgentSpawnOptions(cwd, authCredentials, sessionEnv, spawnEnvironment) {
|
|
return {
|
|
cwd,
|
|
- env: buildAgentEnvironment(authCredentials, sessionEnv),
|
|
+ env: buildAgentEnvironment(authCredentials, sessionEnv, spawnEnvironment),
|
|
stdio: [
|
|
"pipe",
|
|
"pipe",
|
|
@@ -4216,9 +4216,21 @@ var AcpClient = class {
|
|
this.lastAgentExit = void 0;
|
|
this.lastKnownPid = child.pid ?? void 0;
|
|
this.attachAgentLifecycleObservers(child);
|
|
+ if (this.options.onAgentSpawn) {
|
|
+ try {
|
|
+ if (!child.pid) throw new Error("ACPX agent spawn did not expose a valid process id.");
|
|
+ await this.options.onAgentSpawn({ pid: child.pid, startedAt: this.agentStartedAt });
|
|
+ } catch (error) {
|
|
+ try {
|
|
+ child.kill("SIGKILL");
|
|
+ } catch {}
|
|
+ throw error;
|
|
+ }
|
|
+ }
|
|
const startupStderr = [];
|
|
child.stderr.on("data", (chunk) => {
|
|
this.captureStartupStderr(startupStderr, chunk);
|
|
+ this.options.onAgentStderr?.(String(chunk));
|
|
if (!this.options.verbose) return;
|
|
process.stderr.write(chunk);
|
|
});
|
|
@@ -4253,7 +4265,12 @@ var AcpClient = class {
|
|
geminiAcp: isGeminiAcpCommand(spawnCommand, args),
|
|
copilotAcp: isCopilotAcpCommand(spawnCommand, args),
|
|
claudeAcp: isClaudeAcpCommand(spawnCommand, args),
|
|
- spawnOptions: buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials, this.options.sessionOptions?.env)
|
|
+ spawnOptions: buildAgentSpawnOptions(
|
|
+ this.options.spawnCwd ?? this.options.cwd,
|
|
+ this.options.authCredentials,
|
|
+ this.options.sessionOptions?.env,
|
|
+ this.options.spawnEnvironment?.()
|
|
+ )
|
|
};
|
|
}
|
|
logAgentLaunch(plan) {
|
|
@@ -5028,6 +5045,12 @@ var AcpClient = class {
|
|
attachAgentLifecycleObservers(child) {
|
|
child.once("exit", (exitCode, signal) => {
|
|
this.recordAgentExit("process_exit", exitCode, signal);
|
|
+ this.options.onAgentExit?.({
|
|
+ pid: child.pid ?? this.lastKnownPid,
|
|
+ exitCode,
|
|
+ signal,
|
|
+ exitedAt: isoNow$1()
|
|
+ });
|
|
});
|
|
child.once("close", (exitCode, signal) => {
|
|
this.recordAgentExit("process_close", exitCode, signal);
|
|
diff --git a/dist/runtime.d.ts b/dist/runtime.d.ts
|
|
index e8102acb03c4c38830ad5ec22f356125eb0423b7..efea5921f1c5dd5523325bc443469faef45e2233 100644
|
|
--- a/dist/runtime.d.ts
|
|
+++ b/dist/runtime.d.ts
|
|
@@ -1,7 +1,7 @@
|
|
import { _ as SessionRecord, a as AcpElicitationHandler, c as AcpElicitationResponse, f as McpServer$1, h as PermissionPolicy, i as AcpElicitationContext, l as AcpPermissionDecision, m as PermissionMode, n as SystemPromptOption, o as AcpElicitationMode, p as NonInteractivePermissionPolicy, s as AcpElicitationRequest, t as SessionAgentOptions, u as AcpPermissionRequest } from "./session-options-DwRDODlr.js";
|
|
import { a as RequestedModelUnsupportedErrorCode, i as RequestedModelUnsupportedError, n as REQUESTED_MODEL_UNSUPPORTED_ERROR_CODE, o as RequestedModelUnsupportedReason, r as REQUESTED_MODEL_UNSUPPORTED_REASONS, s as isRequestedModelUnsupportedError, t as AcpClient } from "./client-CxNllqui.js";
|
|
import fs from "node:fs";
|
|
-import { ToolCallContent, ToolCallLocation, ToolKind } from "@agentclientprotocol/sdk";
|
|
+import { SessionNotification, ToolCallContent, ToolCallLocation, ToolKind } from "@agentclientprotocol/sdk";
|
|
//#region src/agent-registry.d.ts
|
|
declare const DEFAULT_AGENT_NAME = "codex";
|
|
//#endregion
|
|
@@ -313,6 +313,29 @@ type AcpRuntimeOptions = {
|
|
onPermissionRequest?: (req: AcpPermissionRequest, ctx: {
|
|
signal: AbortSignal;
|
|
}) => Promise<AcpPermissionDecision | undefined>;
|
|
+ /** Ephemeral allowlisted environment evaluated immediately before child spawn. */
|
|
+ spawnEnvironment?: () => Record<string, string>;
|
|
+ /** Host-only spawn cwd; does not change the cwd advertised in session/new. */
|
|
+ spawnCwd?: string;
|
|
+ onAgentSpawn?: (meta: { pid: number; startedAt: string }) => Promise<void> | void;
|
|
+ onAgentStderr?: (chunk: string) => void;
|
|
+ onAcpMessage?: (direction: "inbound" | "outbound", message: unknown) => void;
|
|
+ onAgentExit?: (meta: {
|
|
+ pid?: number;
|
|
+ exitCode: number | null;
|
|
+ signal: NodeJS.Signals | null;
|
|
+ exitedAt: string;
|
|
+ }) => void;
|
|
+ /** Ephemeral full ACP notification callback; never written to session records. */
|
|
+ onSessionNotification?: (notification: SessionNotification) => void;
|
|
+ /** Ephemeral normalized ACP client filesystem/terminal operation callback. */
|
|
+ onClientOperation?: (operation: {
|
|
+ method: string;
|
|
+ status: string;
|
|
+ summary: string;
|
|
+ details?: string;
|
|
+ timestamp: string;
|
|
+ }) => void;
|
|
};
|
|
type AcpFileSessionStoreOptions = {
|
|
stateDir: string;
|
|
diff --git a/dist/runtime.js b/dist/runtime.js
|
|
index a1f4a70a003792c6eacf68b6b038f37bfec1db53..ee3e155db800222aaf2353906dbad93698d17b74 100644
|
|
--- a/dist/runtime.js
|
|
+++ b/dist/runtime.js
|
|
@@ -812,7 +812,16 @@ var AcpRuntimeManager = class {
|
|
this.deps = deps;
|
|
}
|
|
createClient(options) {
|
|
- return this.deps.clientFactory?.(options) ?? new AcpClient(options);
|
|
+ const patchedOptions = {
|
|
+ ...options,
|
|
+ spawnCwd: this.options.spawnCwd,
|
|
+ spawnEnvironment: this.options.spawnEnvironment,
|
|
+ onAgentSpawn: this.options.onAgentSpawn,
|
|
+ onAgentStderr: this.options.onAgentStderr,
|
|
+ onAgentExit: this.options.onAgentExit,
|
|
+ onAcpMessage: this.options.onAcpMessage
|
|
+ };
|
|
+ return this.deps.clientFactory?.(patchedOptions) ?? new AcpClient(patchedOptions);
|
|
}
|
|
createSessionOwner(input) {
|
|
const owner = {
|
|
@@ -823,10 +832,14 @@ var AcpRuntimeManager = class {
|
|
input.client.setEventHandlers({
|
|
+ onAcpMessage: this.options.onAcpMessage,
|
|
onSessionUpdate: (notification) => this.routeOwnedSessionUpdate(owner, notification),
|
|
onClientOperation: (operation) => this.routeOwnedClientOperation(owner, operation)
|
|
});
|
|
return owner;
|
|
}
|
|
routeOwnedSessionUpdate(owner, notification) {
|
|
+ try {
|
|
+ this.options.onSessionNotification?.(notification);
|
|
+ } catch {}
|
|
const active = owner.activeTurn;
|
|
if (active) {
|
|
const { task, turn } = active;
|
|
@@ -863,6 +874,9 @@ var AcpRuntimeManager = class {
|
|
projection.checkpoint.request();
|
|
}
|
|
routeOwnedClientOperation(owner, operation) {
|
|
+ try {
|
|
+ this.options.onClientOperation?.(operation);
|
|
+ } catch {}
|
|
const active = owner.activeTurn;
|
|
if (!active) return;
|
|
const { task, turn } = active;
|
|
diff --git a/dist/session-options-DwRDODlr.d.ts b/dist/session-options-DwRDODlr.d.ts
|
|
index c3da1645235bbea22de3f8484149051cd7dca56b..a69d7327b8eaade69ee90a6bc2493b682f724084 100644
|
|
--- a/dist/session-options-DwRDODlr.d.ts
|
|
+++ b/dist/session-options-DwRDODlr.d.ts
|
|
@@ -116,6 +116,18 @@ type AcpClientOptions = {
|
|
};
|
|
env?: Record<string, string>;
|
|
};
|
|
+ /** Ephemeral child environment factory; its return value is never persisted. */
|
|
+ spawnEnvironment?: () => Record<string, string>;
|
|
+ /** Host-only child cwd, separate from the cwd advertised to ACP. */
|
|
+ spawnCwd?: string;
|
|
+ onAgentSpawn?: (meta: { pid: number; startedAt: string }) => Promise<void> | void;
|
|
+ onAgentStderr?: (chunk: string) => void;
|
|
+ onAgentExit?: (meta: {
|
|
+ pid?: number;
|
|
+ exitCode: number | null;
|
|
+ signal: NodeJS.Signals | null;
|
|
+ exitedAt: string;
|
|
+ }) => void;
|
|
onAcpMessage?: (direction: AcpMessageDirection, message: AcpJsonRpcMessage) => void;
|
|
onAcpOutputMessage?: (direction: AcpMessageDirection, message: AcpJsonRpcMessage) => void;
|
|
onSessionUpdate?: (notification: SessionNotification) => void;
|