@right-link/paperclip-plugin-codex-remote 0.3.1 → 0.3.2

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 (60) hide show
  1. package/dist/chunk-FULSN5VN.js +5348 -0
  2. package/dist/chunk-YJYVA7CY.js +99 -0
  3. package/dist/chunk-ZLN6QQMX.js +3267 -0
  4. package/dist/cli/index.js +190 -2
  5. package/dist/index.js +28 -84
  6. package/dist/server/adapter.js +140 -135
  7. package/dist/server/index.js +41 -56
  8. package/dist/server-utils-C4H4WJOG.js +104 -0
  9. package/dist/ui/index.js +318 -3
  10. package/package.json +7 -5
  11. package/dist/cli/format-event.js +0 -213
  12. package/dist/cli/format-event.js.map +0 -1
  13. package/dist/cli/index.js.map +0 -1
  14. package/dist/cli/quota-probe.js +0 -97
  15. package/dist/cli/quota-probe.js.map +0 -1
  16. package/dist/index.js.map +0 -1
  17. package/dist/server/adapter.js.map +0 -1
  18. package/dist/server/adapter.test.js +0 -84
  19. package/dist/server/adapter.test.js.map +0 -1
  20. package/dist/server/codex-args.js +0 -60
  21. package/dist/server/codex-args.js.map +0 -1
  22. package/dist/server/codex-args.test.js +0 -94
  23. package/dist/server/codex-args.test.js.map +0 -1
  24. package/dist/server/codex-home.js +0 -378
  25. package/dist/server/codex-home.js.map +0 -1
  26. package/dist/server/codex-home.test.js +0 -244
  27. package/dist/server/codex-home.test.js.map +0 -1
  28. package/dist/server/execute.js +0 -906
  29. package/dist/server/execute.js.map +0 -1
  30. package/dist/server/execute.remote.test.js +0 -487
  31. package/dist/server/execute.remote.test.js.map +0 -1
  32. package/dist/server/index.js.map +0 -1
  33. package/dist/server/parse.js +0 -213
  34. package/dist/server/parse.js.map +0 -1
  35. package/dist/server/parse.test.js +0 -107
  36. package/dist/server/parse.test.js.map +0 -1
  37. package/dist/server/quota-spawn-error.test.js +0 -77
  38. package/dist/server/quota-spawn-error.test.js.map +0 -1
  39. package/dist/server/quota.js +0 -432
  40. package/dist/server/quota.js.map +0 -1
  41. package/dist/server/sandbox-env.js +0 -23
  42. package/dist/server/sandbox-env.js.map +0 -1
  43. package/dist/server/skills.js +0 -24
  44. package/dist/server/skills.js.map +0 -1
  45. package/dist/server/tailscale.js +0 -95
  46. package/dist/server/tailscale.js.map +0 -1
  47. package/dist/server/test.js +0 -811
  48. package/dist/server/test.js.map +0 -1
  49. package/dist/server/test.remote.test.js +0 -257
  50. package/dist/server/test.remote.test.js.map +0 -1
  51. package/dist/ui/build-config.js +0 -113
  52. package/dist/ui/build-config.js.map +0 -1
  53. package/dist/ui/build-config.test.js +0 -49
  54. package/dist/ui/build-config.test.js.map +0 -1
  55. package/dist/ui/index.js.map +0 -1
  56. package/dist/ui/parse-stdout.js +0 -261
  57. package/dist/ui/parse-stdout.js.map +0 -1
  58. package/dist/ui/parse-stdout.test.js +0 -77
  59. package/dist/ui/parse-stdout.test.js.map +0 -1
  60. package/dist/ui-parser.js.map +0 -1
package/dist/cli/index.js CHANGED
@@ -1,2 +1,190 @@
1
- export { printCodexStreamEvent } from "./format-event.js";
2
- //# sourceMappingURL=index.js.map
1
+ // src/cli/format-event.ts
2
+ import pc from "picocolors";
3
+ function asRecord(value) {
4
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
5
+ return value;
6
+ }
7
+ function asString(value, fallback = "") {
8
+ return typeof value === "string" ? value : fallback;
9
+ }
10
+ function asNumber(value, fallback = 0) {
11
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
12
+ }
13
+ function errorText(value) {
14
+ if (typeof value === "string") return value;
15
+ const rec = asRecord(value);
16
+ if (!rec) return "";
17
+ const msg = typeof rec.message === "string" && rec.message || typeof rec.error === "string" && rec.error || typeof rec.code === "string" && rec.code || "";
18
+ if (msg) return msg;
19
+ try {
20
+ return JSON.stringify(rec);
21
+ } catch {
22
+ return "";
23
+ }
24
+ }
25
+ function printItemStarted(item) {
26
+ const itemType = asString(item.type);
27
+ if (itemType === "command_execution") {
28
+ const command = asString(item.command);
29
+ console.log(pc.yellow("tool_call: command_execution"));
30
+ if (command) console.log(pc.gray(command));
31
+ return true;
32
+ }
33
+ if (itemType === "tool_use") {
34
+ const name = asString(item.name, "unknown");
35
+ console.log(pc.yellow(`tool_call: ${name}`));
36
+ if (item.input !== void 0) {
37
+ try {
38
+ console.log(pc.gray(JSON.stringify(item.input, null, 2)));
39
+ } catch {
40
+ console.log(pc.gray(String(item.input)));
41
+ }
42
+ }
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ function printItemCompleted(item) {
48
+ const itemType = asString(item.type);
49
+ if (itemType === "agent_message") {
50
+ const text = asString(item.text);
51
+ if (text) console.log(pc.green(`assistant: ${text}`));
52
+ return true;
53
+ }
54
+ if (itemType === "reasoning") {
55
+ const text = asString(item.text);
56
+ if (text) console.log(pc.gray(`thinking: ${text}`));
57
+ return true;
58
+ }
59
+ if (itemType === "tool_use") {
60
+ const name = asString(item.name, "unknown");
61
+ console.log(pc.yellow(`tool_call: ${name}`));
62
+ if (item.input !== void 0) {
63
+ try {
64
+ console.log(pc.gray(JSON.stringify(item.input, null, 2)));
65
+ } catch {
66
+ console.log(pc.gray(String(item.input)));
67
+ }
68
+ }
69
+ return true;
70
+ }
71
+ if (itemType === "command_execution") {
72
+ const command = asString(item.command);
73
+ const status = asString(item.status);
74
+ const exitCode = typeof item.exit_code === "number" && Number.isFinite(item.exit_code) ? item.exit_code : null;
75
+ const output = asString(item.aggregated_output).replace(/\s+$/, "");
76
+ const isError = exitCode !== null && exitCode !== 0 || status === "failed" || status === "errored" || status === "error" || status === "cancelled";
77
+ const summaryParts = [
78
+ "tool_result: command_execution",
79
+ command ? `command="${command}"` : "",
80
+ status ? `status=${status}` : "",
81
+ exitCode !== null ? `exit_code=${exitCode}` : ""
82
+ ].filter(Boolean);
83
+ console.log((isError ? pc.red : pc.cyan)(summaryParts.join(" ")));
84
+ if (output) console.log((isError ? pc.red : pc.gray)(output));
85
+ return true;
86
+ }
87
+ if (itemType === "file_change") {
88
+ const changes = Array.isArray(item.changes) ? item.changes : [];
89
+ const entries = changes.map((changeRaw) => asRecord(changeRaw)).filter((change) => Boolean(change)).map((change) => {
90
+ const kind = asString(change.kind, "update");
91
+ const path = asString(change.path, "unknown");
92
+ return `${kind} ${path}`;
93
+ });
94
+ const preview = entries.length > 0 ? entries.slice(0, 6).join(", ") : "none";
95
+ const more = entries.length > 6 ? ` (+${entries.length - 6} more)` : "";
96
+ console.log(pc.cyan(`file_change: ${preview}${more}`));
97
+ return true;
98
+ }
99
+ if (itemType === "error") {
100
+ const message = errorText(item.message ?? item.error ?? item);
101
+ if (message) console.log(pc.red(`error: ${message}`));
102
+ return true;
103
+ }
104
+ if (itemType === "tool_result") {
105
+ const isError = item.is_error === true || asString(item.status) === "error";
106
+ const text = asString(item.content) || asString(item.result) || asString(item.output);
107
+ console.log((isError ? pc.red : pc.cyan)(`tool_result${isError ? " (error)" : ""}`));
108
+ if (text) console.log((isError ? pc.red : pc.gray)(text));
109
+ return true;
110
+ }
111
+ return false;
112
+ }
113
+ function printCodexStreamEvent(raw, _debug) {
114
+ const line = raw.trim();
115
+ if (!line) return;
116
+ let parsed = null;
117
+ try {
118
+ parsed = JSON.parse(line);
119
+ } catch {
120
+ console.log(line);
121
+ return;
122
+ }
123
+ const type = asString(parsed.type);
124
+ if (type === "thread.started") {
125
+ const threadId = asString(parsed.thread_id);
126
+ const model = asString(parsed.model);
127
+ const details = [threadId ? `session: ${threadId}` : "", model ? `model: ${model}` : ""].filter(Boolean).join(", ");
128
+ console.log(pc.blue(`Codex thread started${details ? ` (${details})` : ""}`));
129
+ return;
130
+ }
131
+ if (type === "turn.started") {
132
+ console.log(pc.blue("turn started"));
133
+ return;
134
+ }
135
+ if (type === "item.started" || type === "item.completed") {
136
+ const item = asRecord(parsed.item);
137
+ if (item) {
138
+ const handled = type === "item.started" ? printItemStarted(item) : printItemCompleted(item);
139
+ if (!handled) {
140
+ const itemType = asString(item.type, "unknown");
141
+ const id = asString(item.id);
142
+ const status = asString(item.status);
143
+ const meta = [id ? `id=${id}` : "", status ? `status=${status}` : ""].filter(Boolean).join(" ");
144
+ console.log(pc.gray(`${type}: ${itemType}${meta ? ` (${meta})` : ""}`));
145
+ }
146
+ } else {
147
+ console.log(pc.gray(type));
148
+ }
149
+ return;
150
+ }
151
+ if (type === "turn.completed") {
152
+ const usage = asRecord(parsed.usage);
153
+ const input = asNumber(usage?.input_tokens);
154
+ const output = asNumber(usage?.output_tokens);
155
+ const cached = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens));
156
+ const cost = asNumber(parsed.total_cost_usd);
157
+ const isError = parsed.is_error === true;
158
+ const subtype = asString(parsed.subtype);
159
+ const errors = Array.isArray(parsed.errors) ? parsed.errors.map(errorText).filter(Boolean) : [];
160
+ console.log(
161
+ pc.blue(`tokens: in=${input} out=${output} cached=${cached} cost=$${cost.toFixed(6)}`)
162
+ );
163
+ if (subtype || isError || errors.length > 0) {
164
+ console.log(
165
+ pc.red(`result: subtype=${subtype || "unknown"} is_error=${isError ? "true" : "false"}`)
166
+ );
167
+ if (errors.length > 0) console.log(pc.red(`errors: ${errors.join(" | ")}`));
168
+ }
169
+ return;
170
+ }
171
+ if (type === "turn.failed") {
172
+ const usage = asRecord(parsed.usage);
173
+ const input = asNumber(usage?.input_tokens);
174
+ const output = asNumber(usage?.output_tokens);
175
+ const cached = asNumber(usage?.cached_input_tokens, asNumber(usage?.cache_read_input_tokens));
176
+ const message = errorText(parsed.error ?? parsed.message);
177
+ console.log(pc.red(`turn failed${message ? `: ${message}` : ""}`));
178
+ console.log(pc.blue(`tokens: in=${input} out=${output} cached=${cached}`));
179
+ return;
180
+ }
181
+ if (type === "error") {
182
+ const message = errorText(parsed.message ?? parsed.error ?? parsed);
183
+ if (message) console.log(pc.red(`error: ${message}`));
184
+ return;
185
+ }
186
+ console.log(line);
187
+ }
188
+ export {
189
+ printCodexStreamEvent
190
+ };
package/dist/index.js CHANGED
@@ -1,84 +1,28 @@
1
- export const type = "codex_remote";
2
- export const label = "Codex (remote)";
3
- export const SANDBOX_INSTALL_COMMAND = "npm install -g @openai/codex";
4
- export const DEFAULT_CODEX_REMOTE_MODEL = "gpt-5.3-codex";
5
- export const DEFAULT_CODEX_REMOTE_BYPASS_APPROVALS_AND_SANDBOX = true;
6
- export const CODEX_REMOTE_FAST_MODE_SUPPORTED_MODELS = ["gpt-5.4"];
7
- function normalizeModelId(model) {
8
- return typeof model === "string" ? model.trim() : "";
9
- }
10
- export function isCodexRemoteKnownModel(model) {
11
- const normalizedModel = normalizeModelId(model);
12
- if (!normalizedModel)
13
- return false;
14
- return models.some((entry) => entry.id === normalizedModel);
15
- }
16
- export function isCodexRemoteManualModel(model) {
17
- const normalizedModel = normalizeModelId(model);
18
- return Boolean(normalizedModel) && !isCodexRemoteKnownModel(normalizedModel);
19
- }
20
- export function isCodexRemoteFastModeSupported(model) {
21
- if (isCodexRemoteManualModel(model))
22
- return true;
23
- const normalizedModel = typeof model === "string" ? model.trim() : "";
24
- return CODEX_REMOTE_FAST_MODE_SUPPORTED_MODELS.includes(normalizedModel);
25
- }
26
- export const models = [
27
- { id: "gpt-5.4", label: "gpt-5.4" },
28
- { id: DEFAULT_CODEX_REMOTE_MODEL, label: DEFAULT_CODEX_REMOTE_MODEL },
29
- { id: "gpt-5.3-codex-spark", label: "gpt-5.3-codex-spark" },
30
- { id: "gpt-5", label: "gpt-5" },
31
- { id: "o3", label: "o3" },
32
- { id: "o4-mini", label: "o4-mini" },
33
- { id: "gpt-5-mini", label: "gpt-5-mini" },
34
- { id: "gpt-5-nano", label: "gpt-5-nano" },
35
- { id: "o3-mini", label: "o3-mini" },
36
- { id: "codex-mini-latest", label: "Codex Mini" },
37
- ];
38
- export const modelProfiles = [
39
- {
40
- key: "cheap",
41
- label: "Cheap",
42
- description: "Use the lowest-cost known Codex local model lane without changing the primary model.",
43
- adapterConfig: {
44
- model: "gpt-5.3-codex-spark",
45
- // Spark is the cheap lane by model price; high effort keeps Codex coding behavior usable for delegated work.
46
- modelReasoningEffort: "high",
47
- },
48
- source: "adapter_default",
49
- },
50
- ];
51
- export const agentConfigurationDoc = `# codex_remote agent configuration
52
-
53
- Adapter: codex_remote
54
-
55
- Core fields:
56
- - cwd (string, optional): default absolute working directory fallback for the agent process (created if missing when possible)
57
- - instructionsFilePath (string, optional): absolute path to a markdown instructions file prepended to stdin prompt at runtime
58
- - model (string, optional): Codex model id
59
- - modelReasoningEffort (string, optional): reasoning effort override (minimal|low|medium|high|xhigh) passed via -c model_reasoning_effort=...
60
- - promptTemplate (string, optional): run prompt template
61
- - search (boolean, optional): run codex with --search
62
- - fastMode (boolean, optional): enable Codex Fast mode; supported on GPT-5.4 and passed through for manual model IDs
63
- - dangerouslyBypassApprovalsAndSandbox (boolean, optional): run with bypass flag
64
- - command (string, optional): defaults to "codex"
65
- - extraArgs (string[], optional): additional CLI args
66
- - env (object, optional): KEY=VALUE environment variables
67
- - workspaceStrategy (object, optional): execution workspace strategy; currently supports { type: "git_worktree", baseRef?, branchTemplate?, worktreeParentDir? }
68
- - workspaceRuntime (object, optional): reserved for workspace runtime metadata; workspace runtime services are manually controlled from the workspace UI and are not auto-started by heartbeats
69
-
70
- Operational fields:
71
- - timeoutSec (number, optional): run timeout in seconds
72
- - graceSec (number, optional): SIGTERM grace period in seconds
73
-
74
- Notes:
75
- - Prompts are piped via stdin (Codex receives "-" prompt argument).
76
- - If instructionsFilePath is configured, Paperclip prepends that file's contents to the stdin prompt on every run.
77
- - Codex exec automatically applies repo-scoped AGENTS.md instructions from the active workspace. Paperclip cannot suppress that discovery in exec mode, so repo AGENTS.md files may still apply even when you only configured an explicit instructionsFilePath.
78
- - Paperclip injects desired local skills into the effective CODEX_HOME/skills/ directory at execution time so Codex can discover "$paperclip" and related skills without polluting the project working directory. In managed-home mode (the default) this is ~/.paperclip/instances/<id>/companies/<companyId>/codex-home/skills/; when CODEX_HOME is explicitly overridden in adapter config, that override is used instead.
79
- - Unless explicitly overridden in adapter config, Paperclip runs Codex with a per-company managed CODEX_HOME under the active Paperclip instance and seeds auth/config from the shared Codex home (the CODEX_HOME env var, when set, or ~/.codex).
80
- - Some model/tool combinations reject certain effort levels (for example minimal with web search enabled).
81
- - Fast mode is supported on GPT-5.4 and manual model IDs. When enabled for those models, Paperclip applies \`service_tier="fast"\` and \`features.fast_mode=true\`.
82
- - When Paperclip realizes a workspace/runtime for a run, it injects PAPERCLIP_WORKSPACE_* and PAPERCLIP_RUNTIME_* env vars for agent-side tooling.
83
- `;
84
- //# sourceMappingURL=index.js.map
1
+ import {
2
+ CODEX_REMOTE_FAST_MODE_SUPPORTED_MODELS,
3
+ DEFAULT_CODEX_REMOTE_BYPASS_APPROVALS_AND_SANDBOX,
4
+ DEFAULT_CODEX_REMOTE_MODEL,
5
+ SANDBOX_INSTALL_COMMAND,
6
+ agentConfigurationDoc,
7
+ isCodexRemoteFastModeSupported,
8
+ isCodexRemoteKnownModel,
9
+ isCodexRemoteManualModel,
10
+ label,
11
+ modelProfiles,
12
+ models,
13
+ type
14
+ } from "./chunk-YJYVA7CY.js";
15
+ export {
16
+ CODEX_REMOTE_FAST_MODE_SUPPORTED_MODELS,
17
+ DEFAULT_CODEX_REMOTE_BYPASS_APPROVALS_AND_SANDBOX,
18
+ DEFAULT_CODEX_REMOTE_MODEL,
19
+ SANDBOX_INSTALL_COMMAND,
20
+ agentConfigurationDoc,
21
+ isCodexRemoteFastModeSupported,
22
+ isCodexRemoteKnownModel,
23
+ isCodexRemoteManualModel,
24
+ label,
25
+ modelProfiles,
26
+ models,
27
+ type
28
+ };
@@ -1,157 +1,162 @@
1
- /**
2
- * External adapter entry point.
3
- *
4
- * Paperclip's adapter-plugin store loads an external adapter package by
5
- * importing its main entry and calling `createServerAdapter()`, which must
6
- * return a complete `ServerAdapterModule`. This module assembles the
7
- * standalone codex_remote adapter from the package's own building blocks plus
8
- * the sandbox preflight / remote-default behavior that previously lived in a
9
- * host-side registry wrapper — so nothing needs to change in upstream
10
- * Paperclip to register this adapter.
11
- */
12
- import { buildSandboxNpmInstallCommand, getAdapterSessionManagement, } from "@paperclipai/adapter-utils";
13
- import { execute as baseExecute } from "./execute.js";
14
- import { testEnvironment as baseTestEnvironment } from "./test.js";
15
- import { listCodexSkills, syncCodexSkills } from "./skills.js";
16
- import { sessionCodec, getQuotaWindows } from "./index.js";
17
- import { models, modelProfiles, agentConfigurationDoc, type } from "../index.js";
18
- export const CODEX_REMOTE_TYPE = type;
19
- const DEFAULT_REMOTE_TIMEOUT_SEC = 300;
20
- const CODEX_RUNTIME_PACKAGE = "@openai/codex";
21
- const CODEX_RUNTIME_FALLBACK_COMMAND = "codex";
1
+ import {
2
+ buildSandboxNpmInstallCommand,
3
+ execute,
4
+ getAdapterSessionManagement,
5
+ getQuotaWindows,
6
+ listCodexSkills,
7
+ sessionCodec,
8
+ syncCodexSkills,
9
+ testEnvironment
10
+ } from "../chunk-FULSN5VN.js";
11
+ import {
12
+ agentConfigurationDoc,
13
+ modelProfiles,
14
+ models,
15
+ type
16
+ } from "../chunk-YJYVA7CY.js";
17
+ import "../chunk-ZLN6QQMX.js";
18
+
19
+ // src/server/adapter.ts
20
+ var CODEX_REMOTE_TYPE = type;
21
+ var DEFAULT_REMOTE_TIMEOUT_SEC = 300;
22
+ var CODEX_RUNTIME_PACKAGE = "@openai/codex";
23
+ var CODEX_RUNTIME_FALLBACK_COMMAND = "codex";
22
24
  function requireRemoteTarget(ctx) {
23
- const target = ctx.executionTarget;
24
- if (!target || target.kind !== "remote") {
25
- throw new Error("codex_remote requires a remote execution target.");
26
- }
27
- if (target.transport === "sandbox" && !target.runner) {
28
- throw new Error("codex_remote requires a sandbox runner from the environment provider.");
29
- }
30
- return target;
25
+ const target = ctx.executionTarget;
26
+ if (!target || target.kind !== "remote") {
27
+ throw new Error("codex_remote requires a remote execution target.");
28
+ }
29
+ if (target.transport === "sandbox" && !target.runner) {
30
+ throw new Error("codex_remote requires a sandbox runner from the environment provider.");
31
+ }
32
+ return target;
31
33
  }
32
34
  function isSandboxTarget(target) {
33
- return target.transport === "sandbox";
35
+ return target.transport === "sandbox";
34
36
  }
35
37
  function failureResult(error, prefix) {
36
- const message = error instanceof Error ? error.message : String(error);
37
- return {
38
- exitCode: 1,
39
- signal: null,
40
- timedOut: false,
41
- errorMessage: `${prefix}: ${message}`,
42
- resultJson: {
43
- error: message,
44
- phase: prefix,
45
- },
46
- };
38
+ const message = error instanceof Error ? error.message : String(error);
39
+ return {
40
+ exitCode: 1,
41
+ signal: null,
42
+ timedOut: false,
43
+ errorMessage: `${prefix}: ${message}`,
44
+ resultJson: {
45
+ error: message,
46
+ phase: prefix
47
+ }
48
+ };
47
49
  }
48
- export function applyCodexRemoteDefaults(config) {
49
- const hasExplicitTimeout = typeof config.timeoutSec === "number" && Number.isFinite(config.timeoutSec) && config.timeoutSec > 0;
50
- return {
51
- ...config,
52
- timeoutSec: hasExplicitTimeout ? config.timeoutSec : DEFAULT_REMOTE_TIMEOUT_SEC,
53
- dangerouslyBypassApprovalsAndSandbox: true,
54
- // Codex Remote is sandbox-runtime only. The agent owns repository cloning
55
- // and Git finalization when the task requires them, so do not upload the
56
- // host workspace or request provider Git-clone realization.
57
- remoteWorkspaceSync: false,
58
- };
50
+ function applyCodexRemoteDefaults(config) {
51
+ const hasExplicitTimeout = typeof config.timeoutSec === "number" && Number.isFinite(config.timeoutSec) && config.timeoutSec > 0;
52
+ return {
53
+ ...config,
54
+ timeoutSec: hasExplicitTimeout ? config.timeoutSec : DEFAULT_REMOTE_TIMEOUT_SEC,
55
+ dangerouslyBypassApprovalsAndSandbox: true,
56
+ // Codex Remote is sandbox-runtime only. The agent owns repository cloning
57
+ // and Git finalization when the task requires them, so do not upload the
58
+ // host workspace or request provider Git-clone realization.
59
+ remoteWorkspaceSync: false
60
+ };
59
61
  }
60
62
  async function verifySandboxWorkspace(input) {
61
- const shell = input.target.shellCommand === "sh" ? "sh" : "bash";
62
- const marker = input.bridgeChannel ? "BRIDGE_SESSION_OK" : "WORKSPACE_OK";
63
- const label = input.bridgeChannel ? "bridge channel" : "main session";
64
- const result = await input.target.runner.execute({
65
- command: shell,
66
- args: [
67
- "-c",
68
- `mkdir -p ${JSON.stringify(input.target.remoteCwd)} && ls -la ${JSON.stringify(input.target.remoteCwd)} 2>&1 && echo ${marker}`,
69
- ],
70
- cwd: "/",
71
- env: input.bridgeChannel ? { PAPERCLIP_SANDBOX_EXEC_CHANNEL: "bridge" } : undefined,
72
- timeoutMs: input.bridgeChannel ? 90_000 : 30_000,
73
- });
74
- if (result.timedOut || (result.exitCode ?? 1) !== 0) {
75
- const detail = [result.stderr, result.stdout].filter(Boolean).join("\n").trim();
76
- throw new Error(`codex_remote sandbox workspace verify (${label}) failed with exit=${result.exitCode ?? "null"} timedOut=${result.timedOut}${detail ? `: ${detail}` : ""}`);
77
- }
78
- await input.ctx.onLog("stdout", `[paperclip] codex_remote workspace verify (${label}): exit=${result.exitCode} timedOut=${result.timedOut}\n${result.stdout || ""}\n${result.stderr || ""}`);
63
+ const shell = input.target.shellCommand === "sh" ? "sh" : "bash";
64
+ const marker = input.bridgeChannel ? "BRIDGE_SESSION_OK" : "WORKSPACE_OK";
65
+ const label = input.bridgeChannel ? "bridge channel" : "main session";
66
+ const result = await input.target.runner.execute({
67
+ command: shell,
68
+ args: [
69
+ "-c",
70
+ `mkdir -p ${JSON.stringify(input.target.remoteCwd)} && ls -la ${JSON.stringify(input.target.remoteCwd)} 2>&1 && echo ${marker}`
71
+ ],
72
+ cwd: "/",
73
+ env: input.bridgeChannel ? { PAPERCLIP_SANDBOX_EXEC_CHANNEL: "bridge" } : void 0,
74
+ timeoutMs: input.bridgeChannel ? 9e4 : 3e4
75
+ });
76
+ if (result.timedOut || (result.exitCode ?? 1) !== 0) {
77
+ const detail = [result.stderr, result.stdout].filter(Boolean).join("\n").trim();
78
+ throw new Error(
79
+ `codex_remote sandbox workspace verify (${label}) failed with exit=${result.exitCode ?? "null"} timedOut=${result.timedOut}${detail ? `: ${detail}` : ""}`
80
+ );
81
+ }
82
+ await input.ctx.onLog(
83
+ "stdout",
84
+ `[paperclip] codex_remote workspace verify (${label}): exit=${result.exitCode} timedOut=${result.timedOut}
85
+ ${result.stdout || ""}
86
+ ${result.stderr || ""}`
87
+ );
79
88
  }
80
89
  async function executeCodexRemote(ctx) {
81
- const target = requireRemoteTarget(ctx);
82
- const config = applyCodexRemoteDefaults(ctx.config);
83
- const codexRunTimeoutMs = typeof config.timeoutSec === "number" && config.timeoutSec > 0
84
- ? config.timeoutSec * 1_000
85
- : DEFAULT_REMOTE_TIMEOUT_SEC * 1_000;
86
- if (isSandboxTarget(target)) {
87
- try {
88
- await verifySandboxWorkspace({ ctx, target });
89
- await verifySandboxWorkspace({ ctx, target, bridgeChannel: true });
90
- }
91
- catch (error) {
92
- return failureResult(error, "codex_remote_prepare_failed");
93
- }
94
- }
90
+ const target = requireRemoteTarget(ctx);
91
+ const config = applyCodexRemoteDefaults(ctx.config);
92
+ const codexRunTimeoutMs = typeof config.timeoutSec === "number" && config.timeoutSec > 0 ? config.timeoutSec * 1e3 : DEFAULT_REMOTE_TIMEOUT_SEC * 1e3;
93
+ if (isSandboxTarget(target)) {
95
94
  try {
96
- return await baseExecute({
97
- ...ctx,
98
- executionTarget: isSandboxTarget(target)
99
- ? {
100
- ...target,
101
- timeoutMs: codexRunTimeoutMs,
102
- }
103
- : target,
104
- config,
105
- });
106
- }
107
- catch (error) {
108
- return failureResult(error, "codex_remote_execute_failed");
95
+ await verifySandboxWorkspace({ ctx, target });
96
+ await verifySandboxWorkspace({ ctx, target, bridgeChannel: true });
97
+ } catch (error) {
98
+ return failureResult(error, "codex_remote_prepare_failed");
109
99
  }
100
+ }
101
+ try {
102
+ return await execute({
103
+ ...ctx,
104
+ executionTarget: isSandboxTarget(target) ? {
105
+ ...target,
106
+ timeoutMs: codexRunTimeoutMs
107
+ } : target,
108
+ config
109
+ });
110
+ } catch (error) {
111
+ return failureResult(error, "codex_remote_execute_failed");
112
+ }
110
113
  }
111
114
  function hasPathSeparator(value) {
112
- return value.includes("/") || value.includes("\\");
115
+ return value.includes("/") || value.includes("\\");
113
116
  }
114
117
  function shellQuote(value) {
115
- return `'${value.replace(/'/g, `'\\''`)}'`;
118
+ return `'${value.replace(/'/g, `'\\''`)}'`;
116
119
  }
117
120
  function readConfiguredCommand(config) {
118
- const value = typeof config.command === "string" ? config.command.trim() : "";
119
- return value.length > 0 ? value : CODEX_RUNTIME_FALLBACK_COMMAND;
121
+ const value = typeof config.command === "string" ? config.command.trim() : "";
122
+ return value.length > 0 ? value : CODEX_RUNTIME_FALLBACK_COMMAND;
120
123
  }
121
124
  function buildRuntimeCommandSpec(config) {
122
- const command = readConfiguredCommand(config);
123
- const canSelfInstall = !hasPathSeparator(command) && command === CODEX_RUNTIME_FALLBACK_COMMAND;
124
- const installLine = buildSandboxNpmInstallCommand(CODEX_RUNTIME_PACKAGE);
125
- return {
126
- command,
127
- detectCommand: command,
128
- installCommand: canSelfInstall
129
- ? `if ! command -v ${shellQuote(command)} >/dev/null 2>&1; then ${installLine}; fi`
130
- : null,
131
- };
125
+ const command = readConfiguredCommand(config);
126
+ const canSelfInstall = !hasPathSeparator(command) && command === CODEX_RUNTIME_FALLBACK_COMMAND;
127
+ const installLine = buildSandboxNpmInstallCommand(CODEX_RUNTIME_PACKAGE);
128
+ return {
129
+ command,
130
+ detectCommand: command,
131
+ installCommand: canSelfInstall ? `if ! command -v ${shellQuote(command)} >/dev/null 2>&1; then ${installLine}; fi` : null
132
+ };
132
133
  }
133
- export function createServerAdapter() {
134
- return {
135
- type: CODEX_REMOTE_TYPE,
136
- execute: (ctx) => executeCodexRemote(ctx),
137
- testEnvironment: (ctx) => baseTestEnvironment({
138
- ...ctx,
139
- adapterType: CODEX_REMOTE_TYPE,
140
- config: applyCodexRemoteDefaults(ctx.config),
141
- }),
142
- listSkills: listCodexSkills,
143
- syncSkills: syncCodexSkills,
144
- sessionCodec,
145
- sessionManagement: getAdapterSessionManagement(CODEX_REMOTE_TYPE) ?? undefined,
146
- models,
147
- modelProfiles,
148
- supportsLocalAgentJwt: true,
149
- supportsInstructionsBundle: true,
150
- instructionsPathKey: "instructionsFilePath",
151
- requiresMaterializedRuntimeSkills: false,
152
- getRuntimeCommandSpec: (config) => buildRuntimeCommandSpec(config),
153
- getQuotaWindows,
154
- agentConfigurationDoc,
155
- };
134
+ function createServerAdapter() {
135
+ return {
136
+ type: CODEX_REMOTE_TYPE,
137
+ execute: (ctx) => executeCodexRemote(ctx),
138
+ testEnvironment: (ctx) => testEnvironment({
139
+ ...ctx,
140
+ adapterType: CODEX_REMOTE_TYPE,
141
+ config: applyCodexRemoteDefaults(ctx.config)
142
+ }),
143
+ listSkills: listCodexSkills,
144
+ syncSkills: syncCodexSkills,
145
+ sessionCodec,
146
+ sessionManagement: getAdapterSessionManagement(CODEX_REMOTE_TYPE) ?? void 0,
147
+ models,
148
+ modelProfiles,
149
+ supportsLocalAgentJwt: true,
150
+ supportsInstructionsBundle: true,
151
+ instructionsPathKey: "instructionsFilePath",
152
+ requiresMaterializedRuntimeSkills: false,
153
+ getRuntimeCommandSpec: (config) => buildRuntimeCommandSpec(config),
154
+ getQuotaWindows,
155
+ agentConfigurationDoc
156
+ };
156
157
  }
157
- //# sourceMappingURL=adapter.js.map
158
+ export {
159
+ CODEX_REMOTE_TYPE,
160
+ applyCodexRemoteDefaults,
161
+ createServerAdapter
162
+ };