mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 10:48:12 +02:00
## Thinking Path - Paperclip Runner needs its runtime preinstalled for fast sandbox startup. - Native and local adapters should launch one current CLI installation per provider. - An older global copy can shadow that installation, and exact native compatibility pins must match it. - Update the qualified releases and binary digests, expose shared CLI entrypoints from the provider pack, and prefer the image-owned bin directory. - Keep dependency installation in the image build; task startup only discovers, links, and verifies artifacts. ## Linked Issues or Issue Description **What happened?** Remote native startup rejected a stale global Codex, while CLI-only images lacked runnerd entirely. **Expected behavior** An image-baked runtime starts without uploading binaries or installing packages. All adapters share the same current provider CLI. **Steps to reproduce** Start a native remote task with the old global Codex and the updated runtime available only under `/opt/paperclip-runner/bin`. **Paperclip version or commit** Discovery behavior at `54a99d884`. **Deployment mode** Docker with a remote sandbox. ## What Changed - Prefer `/opt/paperclip-runner/bin`, then the user's local bin directory, then PATH. Existing metadata and version validation remains in force. - Qualify Codex 0.153.4, OpenCode 1.18.29, and Claude SDK 0.3.263 / CLI 2.1.263. Update binary digests, TypeScript/Rust checks, registry defaults, and the displayed OpenCode version together. - Share Codex and Claude's native executable with the ACP bridges through exact dependency overrides. Preserve the separately qualified ACP bridge implementations and their security patches. - Expose shared provider-pack CLI launchers; fail the pack build if Codex ACP resolves a separate Codex installation. Update the eval image's other agent CLIs to current stable releases and remove duplicate global provider installs. - Document the single-current-CLI policy in source comments and development guidance. Latest stable releases are resolved at review/build preparation and pinned; task startup never auto-updates. ## Verification - Native-session and adapter-registry suites: 158 tests passed. - Provider suites: 88 tests passed, 7 Linux-only checks skipped on macOS. One existing macOS temporary-path alias assertion passed when rerun with canonical `TMPDIR=/private/tmp`. - Package-contract and OpenCode materialization tests: 11 passed. - Full typecheck, build, and token gates passed. Rust native-provider/recovery tests: 19 passed. - Broad local suite: 5,974 passed, 23 failed, 41 skipped. Failures are in unchanged macOS workspace/path/port and connection suites; focused runtime tests pass. All latest-head Linux PR checks passed, including the full test shards, typecheck, build, runner verification, browser suites, and canary dry run. - The standalone fleet image built with one current provider CLI each and passed native Codex/Claude binary-integrity checks. A disposable Daytona sandbox reported ready in 798 ms; its baked runner completed an API-key `gpt-5.6-luna` turn in 2,430 ms and returned the expected marker with a usage receipt. No runtime artifacts were uploaded or installed. - The normal shared `codex exec` entrypoint also completed an API-key `gpt-5.6-luna` turn in 2,321 ms. - Both image builds verify the complete generated lockfile against a reviewed SHA-256 before package installation or lifecycle execution. Root lockfile changes remain CI-owned. Merge and rollout remain on hold for operator review. ## Risks - Updating provider CLIs changes their behavior for all adapters; version probes and live native smoke testing are required before image promotion. - The image-owned directory takes precedence. Its entries must launch the same shared CLI as the global PATH, not a private older/newer copy. - Application qualification pins and the deployed image must move together. No startup fallback installation is added. - No schema or authentication-policy changes. ## Model Used OpenAI GPT-6 (Codex). The session does not expose a more specific model ID or context-window size. Used reasoning, repository inspection, code execution, and browser verification. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
112 lines
4.4 KiB
Diff
112 lines
4.4 KiB
Diff
diff --git a/package.json b/package.json
|
|
--- a/package.json
|
|
+++ b/package.json
|
|
@@ -65,7 +65,7 @@
|
|
},
|
|
"dependencies": {
|
|
"@agentclientprotocol/sdk": "^1.3.0",
|
|
- "@openai/codex": "^0.148.0",
|
|
+ "@openai/codex": "0.153.4",
|
|
"diff": "^9.0.0",
|
|
"open": "^11.0.0",
|
|
"vscode-jsonrpc": "^9.0.1",
|
|
diff --git a/dist/index.js b/dist/index.js
|
|
--- a/dist/index.js
|
|
+++ b/dist/index.js
|
|
@@ -25341,7 +25341,7 @@
|
|
async handleElicitation(params) {
|
|
try {
|
|
const context = this.createMcpElicitationContext(params);
|
|
- if (this.shouldUseAcpElicitation(params)) {
|
|
+ if (!context.isToolApproval && this.shouldUseAcpElicitation(params)) {
|
|
const response2 = await this.connection.request(
|
|
methods.client.elicitation.create,
|
|
this.buildElicitationRequest(params, context),
|
|
@@ -25563,7 +25563,7 @@
|
|
toolCall: {
|
|
toolCallId: context.correlatedCallId,
|
|
kind: "execute",
|
|
- status: "pending"
|
|
+ status: "pending",
|
|
+ rawInput: { serverName: params.serverName }
|
|
// content: [messageContent], — omitted: already rendered via item/started
|
|
- // rawInput: { ... } — omitted: same reason
|
|
},
|
|
@@ -26988,4 +26988,13 @@
|
|
};
|
|
+function paperclipBaseInstructions(request) {
|
|
+ if (process.env.PAPERCLIP_ACPX_ISOLATED_CONTEXT !== "1") return void 0;
|
|
+ const prompt = request?._meta?.systemPrompt;
|
|
+ if (typeof prompt === "string") return prompt;
|
|
+ if (prompt && typeof prompt === "object" && typeof prompt.append === "string") {
|
|
+ return prompt.append;
|
|
+ }
|
|
+ return void 0;
|
|
+}
|
|
var CodexAcpClient = class {
|
|
codexClient;
|
|
config;
|
|
@@ -27288,6 +27297,7 @@
|
|
const response = await this.codexClient.threadResume({
|
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
cwd: request.cwd,
|
|
+ baseInstructions: paperclipBaseInstructions(request),
|
|
modelProvider: await this.getResumeModelProvider(),
|
|
threadId: request.sessionId
|
|
});
|
|
@@ -27310,6 +27320,7 @@
|
|
const response = await this.codexClient.threadResume({
|
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
cwd: request.cwd,
|
|
+ baseInstructions: paperclipBaseInstructions(request),
|
|
modelProvider: await this.getResumeModelProvider(),
|
|
threadId: request.sessionId
|
|
});
|
|
@@ -27337,5 +27348,6 @@
|
|
const response = await this.codexClient.threadStart({
|
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers),
|
|
modelProvider: this.getModelProvider(),
|
|
+ baseInstructions: paperclipBaseInstructions(request),
|
|
cwd: request.cwd
|
|
});
|
|
@@ -27437,5 +27449,12 @@
|
|
const mergedConfig = {
|
|
...mergeGatewayConfig(this.config, this.gatewayConfig),
|
|
+ ...(process.env.PAPERCLIP_ACPX_ISOLATED_CONTEXT === "1" ? {
|
|
+ "include_apps_instructions": false,
|
|
+ "features.apps": false,
|
|
+ "features.memory_tool": false,
|
|
+ "skills.include_instructions": true,
|
|
+ "mcp_servers": {}
|
|
+ } : {}),
|
|
projects: Object.fromEntries(sessionRoots.map((root) => [root, {
|
|
trust_level: "trusted"
|
|
}]))
|
|
@@ -27449,7 +27468,7 @@
|
|
server: mcp
|
|
}));
|
|
let serversToConfigure = requestedServers;
|
|
- if (shouldDeduplicateMcpConflicts()) {
|
|
+ if (process.env.PAPERCLIP_ACPX_ISOLATED_CONTEXT !== "1" && shouldDeduplicateMcpConflicts()) {
|
|
const existingNames = await this.getConfigMcpServerNames(projectPath);
|
|
serversToConfigure = requestedServers.filter((mcp) => !existingNames.has(mcp.name));
|
|
}
|
|
@@ -27483,14 +27502,15 @@
|
|
async refreshSkills(cwd, additionalRoots) {
|
|
if (!cwd) {
|
|
return;
|
|
}
|
|
- const skillExtraRoots = additionalRoots.map((root) => path6.join(root, ".agents", "skills"));
|
|
+ const isolated = process.env.PAPERCLIP_ACPX_ISOLATED_CONTEXT === "1";
|
|
+ const skillExtraRoots = isolated ? [] : additionalRoots.map((root) => path6.join(root, ".agents", "skills"));
|
|
if (!arraysEqual(this.skillExtraRoots, skillExtraRoots)) {
|
|
await this.codexClient.skillsExtraRootsSet({ extraRoots: skillExtraRoots });
|
|
this.skillExtraRoots = skillExtraRoots;
|
|
}
|
|
await this.codexClient.listSkills({
|
|
- cwds: [cwd, ...additionalRoots],
|
|
+ cwds: isolated ? [process.env.CODEX_HOME] : [cwd, ...additionalRoots],
|
|
forceReload: true
|
|
});
|
|
}
|