mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-12 22:56:58 +01:00
fix(agents): retain Legacy ACP network restrictions during selection
Reject restrictive or unresolved ACP network settings with field-specific Legacy guidance instead of silently discarding them. Preserve unused CLI flags, recorded native profiles and trusted server policy. Synchronize the required feature and access maps without claiming live qualification. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
5675a6ff62
commit
fe1ecf1c34
8 files changed
+261
-2
No files matched your search
@@ -9,6 +9,12 @@ Each capability needs operation-level review before its entire scope can be
|
||||
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
|
||||
for format, permission checks, evidence and maintenance.
|
||||
|
||||
Scoped runner-default source review: 2026-10-12 at
|
||||
`eee0534154eaf5d0d3f2bbc97c1e24d86f34a5a5`, limited to creation/configuration,
|
||||
approval activation, built-in provisioning and import preservation described
|
||||
below. The original baseline commit above still governs unrelated entries; this
|
||||
update does not claim operation-complete review or live agent verification.
|
||||
|
||||
## `hire`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -24,17 +30,45 @@ native hires.
|
||||
Policy: Agent creation/configuration uses action grants, resource policies and change
|
||||
consent; some controls require a board actor.
|
||||
|
||||
The creation boundary resolves the request-level runner before adapter validation
|
||||
and credential normalization. Omitted/automatic new Codex selection uses the
|
||||
qualified target's default; explicit Legacy is retained. Disabled adapters and
|
||||
external overrides affect new selection, while missing credentials/runtime or
|
||||
incompatible settings remain errors. Existing agents and reviewed pending hires
|
||||
retain their recorded execution. Native `hire_agent` explicitly inherits its
|
||||
caller's runtime and remains subject to permission and credential restrictions;
|
||||
it is not an arbitrary host-configuration or login tool. REST/CLI creation and
|
||||
hire runner options use the [shared request contract](../../packages/shared/src/validators/agent.ts).
|
||||
|
||||
Evidence: `source-only` — [implementation](../../server/src/routes/agents.ts#L1395) at
|
||||
the reviewed commit above.
|
||||
|
||||
Scoped Evidence: `source-only` — [creation policy](../../server/src/services/agent-hiring.ts),
|
||||
[runner resolution](../../server/src/services/agent-runner-selection.ts),
|
||||
[native hire binding](../../server/src/services/native-runtime/paperclip-runner-tool-authority.ts),
|
||||
[frozen approval activation](../../server/src/modules/agent-lifecycle/adapters/approvals.ts)
|
||||
and [same-harness import preservation](../../server/src/services/company-portability.ts)
|
||||
at the scoped commit. No permitted-agent journey was executed for this map update.
|
||||
|
||||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||||
remaining operations before qualifying the whole capability.
|
||||
|
||||
For this scope, compare automatic and explicit Legacy creation, assert foreign
|
||||
company/environment and missing-grant denials, then compare pending approval
|
||||
configuration across restart and activation. An unrelated edit/import update must
|
||||
not change existing execution; a new package without a runner choice receives
|
||||
creation defaults. Do not count a board call or component test as agent evidence.
|
||||
|
||||
Gaps: Identity/persona hiring works. Operator account login and sensitive
|
||||
adapter/environment configuration are separate guarded actions.
|
||||
|
||||
The runner request does not grant new account, environment-probe or native API
|
||||
fallback authority; see [validation access](./runs-adapters.md#validation) and
|
||||
[environment administration](./execution-environments.md#probe). Full access
|
||||
qualification remains not run.
|
||||
|
||||
## `instructions`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -138,3 +172,10 @@ remaining operations before qualifying the whole capability.
|
||||
|
||||
Gaps: Provisioning checks agents:create. Enabling/running its built-in routine is not
|
||||
the same permission path.
|
||||
|
||||
Scoped source review: [built-in provisioning](../../server/src/services/built-in-agents.ts)
|
||||
recognizes the underlying Codex harness of a native company agent. New configured
|
||||
provisioning resolves the runner, while unrelated reconciliation and same-harness
|
||||
edits retain existing execution. Verify explicit runner changes preserve compatible
|
||||
saved settings; the general creation/access policy above still applies. This is
|
||||
source-only evidence at the scoped commit, not a live provisioning result.
|
||||
@@ -9,6 +9,11 @@ Each capability needs operation-level review before its entire scope can be
|
||||
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
|
||||
for format, permission checks, evidence and maintenance.
|
||||
|
||||
Scoped runner-default source review: 2026-10-12 at
|
||||
`eee0534154eaf5d0d3f2bbc97c1e24d86f34a5a5`, limited to first-agent selection,
|
||||
selected-runtime validation and draft restoration. Unrelated baseline entries
|
||||
retain the original source commit; no live agent verification is added.
|
||||
|
||||
## `instance`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -74,10 +79,25 @@ provider-account/environment setup.
|
||||
Policy: Instance setup is operator work; company creation is board; agent creation/task
|
||||
creation retain their individual permissions.
|
||||
|
||||
The wizard selects the Codex harness and lets the server resolve an automatic
|
||||
new-agent runner; explicit Legacy remains available. Supported-platform and
|
||||
immutable sandbox evidence follow [environment probe policy](./execution-environments.md#probe).
|
||||
Creation/discovery do not provision a target to determine this default. Adapter
|
||||
setup validation requires `agents:create`, plus saved-agent update access when
|
||||
testing an existing agent; interactive account login additionally requires a
|
||||
board user and owner-bound session. An agent's right to hire is not login or
|
||||
instance-environment administration authority.
|
||||
|
||||
Evidence: `source-only` —
|
||||
[implementation](../../ui/src/components/OnboardingWizard.tsx#L279) at the reviewed
|
||||
commit above.
|
||||
|
||||
Scoped Evidence: `source-only` — [wizard/default selection](../../ui/src/components/OnboardingWizard.tsx),
|
||||
[creation resolver](../../server/src/services/agent-runner-selection.ts) and
|
||||
[setup/login authorization](../../server/src/routes/agents.ts) at the scoped
|
||||
commit. Existing agent/approval execution preservation follows
|
||||
[hiring access](./agents.md#hire); no live onboarding proof is claimed here.
|
||||
|
||||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||||
@@ -86,6 +106,11 @@ remaining operations before qualifying the whole capability.
|
||||
Gaps: Account authorization, environment administration and model selection need
|
||||
separate checks.
|
||||
|
||||
Verify automatic onboarding without a post-hire runner change, explicit Legacy,
|
||||
saved configuration after reload and the actual selected runtime's useful task
|
||||
plus follow-up. Assert denied agent login/probe and foreign-company account or
|
||||
environment access separately. These agent-context checks remain `not-run`.
|
||||
|
||||
## `first-task`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -134,3 +159,8 @@ evidence.
|
||||
|
||||
Gaps: No server onboarding-draft API for this browser-local state; classify explicitly
|
||||
or intentionally make it a cross-client product feature.
|
||||
|
||||
Scoped source review of [draft restoration](../../ui/src/components/OnboardingWizard.tsx)
|
||||
preserves harness/runner intent and invalidates obsolete setup-test results after
|
||||
a selection change. Browser draft continuity is not API or live-agent evidence,
|
||||
and opening a saved Legacy agent does not apply new-agent defaults.
|
||||
@@ -9,6 +9,11 @@ Each capability needs operation-level review before its entire scope can be
|
||||
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
|
||||
for format, permission checks, evidence and maintenance.
|
||||
|
||||
Scoped runner-default source review: 2026-10-12 at
|
||||
`eee0534154eaf5d0d3f2bbc97c1e24d86f34a5a5`, limited to runner discovery,
|
||||
selected-runtime testing and saved execution/session preservation. The original
|
||||
baseline source and review depth remain unchanged for unrelated operations.
|
||||
|
||||
## `availability`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -35,6 +40,15 @@ remaining operations before qualifying the whole capability.
|
||||
Gaps: Raw instance adapter listing requires board, while company model discovery exists
|
||||
for eligible agents.
|
||||
|
||||
Scoped source-only evidence: [adapter discovery](../../server/src/routes/adapters.ts)
|
||||
reports supported runners/effective default for the selected company/environment;
|
||||
[selection policy](../../server/src/services/agent-runner-selection.ts) reads
|
||||
server-owned immutable sandbox facts without provisioning. New Codex defaults
|
||||
and explicit overrides follow the [shared runner contract](../../packages/shared/src/agent-runner.ts);
|
||||
other harness defaults remain unchanged. The board inventory does not grant a
|
||||
native agent an equivalent discovery binding. See
|
||||
[probe restrictions](./execution-environments.md#probe) for acquiring qualification.
|
||||
|
||||
## `validation`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -60,6 +74,22 @@ remaining operations before qualifying the whole capability.
|
||||
Gaps: Environment test path checks creation/configuration policy; missing provider auth
|
||||
must use its owner setup flow.
|
||||
|
||||
Scoped source review: [test authorization and resolution](../../server/src/routes/agents.ts)
|
||||
requires same-company `agents:create`, saved-agent update access when supplied,
|
||||
allowed environment selection, and normal secret/responsible-user checks. An
|
||||
unchanged saved runner avoids new-creation policy but still receives selected
|
||||
runtime validation. [Native readiness](../../server/src/services/native-runtime/setup-readiness.ts)
|
||||
tests native Codex startup/model/account and bounded teardown; an authentication
|
||||
or Legacy CLI check cannot replace that runtime evidence. Missing dependencies,
|
||||
credentials, invalid models and incompatible settings fail without silently
|
||||
changing runners. Account login remains board/owner-bound.
|
||||
|
||||
Verification for this scope remains `not-run`: use an admitted agent REST/CLI
|
||||
validation path, assert missing grants and cross-company targets/accounts are
|
||||
denied, then prove the useful task/follow-up separately. `hire_agent` inherits its
|
||||
caller's runtime; do not assume its binding accepts arbitrary runner or account
|
||||
settings. See [creation access](./agents.md#hire).
|
||||
|
||||
## `runs`
|
||||
|
||||
Review: `baseline`.
|
||||
@@ -109,3 +139,10 @@ own policy and access review.
|
||||
|
||||
Gaps: Execution context reset is not a permitted generic native API mutation or an
|
||||
ordinary agent management path.
|
||||
|
||||
Scoped source-only evidence: [configuration changes](../../server/src/services/agent-configuration.ts)
|
||||
and [native execution/recovery](../../server/src/services/native-runtime/native-session-executor.ts)
|
||||
retain existing execution on unrelated edits and use recorded run configuration
|
||||
for active/recovered runs. Explicit runner changes use revisions and session
|
||||
invalidation. Verify saved configuration, current versus historical run identity,
|
||||
restart and follow-up without granting session-reset authority to an agent.
|
||||
@@ -8,7 +8,7 @@ Agent access: [companion](../agent-access-map/agents.md).
|
||||
|
||||
## Sub-features
|
||||
|
||||
- `hire`: choose identity, adapter, model, and required account settings; edit
|
||||
- `hire`: choose identity, harness, model, and required account settings; edit
|
||||
reporting relationships through the agent configuration afterward.
|
||||
- `instructions`: edit agent configuration and instruction files with durable revisions.
|
||||
- `organization`: inspect and change reporting relationships through supported controls.
|
||||
@@ -39,6 +39,25 @@ Automated: [new agent page](../../ui/src/pages/NewAgent.test.tsx) and [configura
|
||||
|
||||
Manual: Hire an agent with a distinct name and role. Complete any required approval, reload the roster, and open its configuration. Confirm manager, adapter, and model persisted; run a small task to prove execution readiness.
|
||||
|
||||
For a new Codex hire, choose the Codex harness. Automatic selection uses Paperclip
|
||||
Runner on a qualified selected target; Advanced offers an explicit Legacy runner
|
||||
override. Other harness defaults are unchanged. Record the persisted runner and
|
||||
underlying harness, rather than treating the displayed Codex name as execution
|
||||
proof. See [runtime selection and validation](./runs-adapters.md#adapter-setup)
|
||||
and [target qualification](./execution-environments.md#environment-settings).
|
||||
|
||||
Repeat with an explicit Legacy Codex hire. If approval is required, compare its
|
||||
reviewed execution configuration before and after restart and activation; approval
|
||||
must retain the reviewed runner. Test an existing Legacy and native agent through
|
||||
an unrelated edit, reload and restart: neither is automatically upgraded.
|
||||
|
||||
Creation defaults also apply to API/CLI hires, built-ins, plugins and new team
|
||||
imports. Exports preserve resolved execution choices; a package without a runner
|
||||
choice uses the new-agent default, while updating an existing same-harness agent
|
||||
preserves its execution. For a native Codex import, edit a model or account binding
|
||||
and verify unchanged runtime settings survive; an explicit clear must stay cleared.
|
||||
Use the [portability recipe](./companies.md) for package preparation and boundaries.
|
||||
|
||||
The current hiring wizard assigns the first hire CEO and subsequent hires
|
||||
General reporting to the CEO. Change manager/role afterward through supported
|
||||
configuration. Process/HTTP agents can be created through API/CLI but are excluded
|
||||
@@ -50,6 +69,12 @@ Automated: [instruction service](../../server/src/__tests__/agent-instructions-s
|
||||
|
||||
Manual: Save a harmless instruction edit, reload, and verify its revision and effect in the next eligible run. Pause and resume the disposable agent; confirm pause prevents new work and does not erase previous runs.
|
||||
|
||||
An explicit runner change is a configuration change, with normal revisions and
|
||||
session invalidation. Incompatible settings must produce a field-specific error;
|
||||
selecting another runner must not silently discard them or change an active run's
|
||||
recorded execution. Keep runner choice in Advanced and verify the next eligible
|
||||
run separately from historical transcripts.
|
||||
|
||||
### `organization`
|
||||
|
||||
Automated: [org chart](../../ui/src/pages/OrgChart.test.tsx) is component evidence. Built-in setup also has [configuration modal tests](../../ui/src/components/ConfigureBuiltInAgentModal.test.tsx).
|
||||
|
||||
@@ -50,6 +50,22 @@ company's onboarding route, and finish; drafts save automatically. Follow the
|
||||
created first task, verify the selected agent and company, and inspect its output
|
||||
or explicit authentication gate. Reload both company and task.
|
||||
|
||||
For Codex, choose the harness and leave runner selection automatic to prove the
|
||||
first-agent default. On a qualified target it saves Paperclip Runner; Advanced
|
||||
also permits Legacy. Do not switch runners after onboarding when claiming proof
|
||||
of that default. Test the selected runtime and account, then complete a bounded
|
||||
useful task and follow-up with an independently checked file artifact. Saved
|
||||
execution configuration and recorded run identity must match after reload.
|
||||
Use [runner validation](./runs-adapters.md#adapter-setup) and
|
||||
[environment qualification](./execution-environments.md#environment-settings)
|
||||
for the prerequisites; a successful login alone is insufficient.
|
||||
|
||||
Leave and resume during harness/runner setup. Confirm the draft retains the
|
||||
explicit choice and compatible account bindings, old native Codex setup links
|
||||
recover the harness and runner, and a changed harness or runner invalidates stale
|
||||
test results. Existing Legacy agents remain Legacy when their onboarding/setup
|
||||
configuration is reopened; this journey does not migrate them.
|
||||
|
||||
### `cli-setup`
|
||||
|
||||
Automated: [CLI onboarding](../../cli/src/__tests__/onboard.test.ts) and [isolated test drive](../../cli/src/__tests__/test-drive.test.ts) cover their setup contracts; they do not establish that every model account is usable.
|
||||
|
||||
@@ -33,12 +33,44 @@ Automated: [adapter validation routes](../../server/src/__tests__/agent-adapter-
|
||||
|
||||
Manual: Select the intended adapter and account, refresh model choices, and run its environment test. Save, reload, then execute a small task. Repeat with a deliberately unavailable account and verify the failure remains visible.
|
||||
|
||||
Choose Codex as the harness; the UI displays its name/icon for both runners.
|
||||
Advanced identifies the automatic default and offers Paperclip Runner or Legacy.
|
||||
Only new Codex agents default to the native runner on supported macOS or GNU/Linux
|
||||
targets; the [shared selection contract](../../packages/shared/src/agent-runner.ts)
|
||||
and [runtime prerequisites](../../packages/paperclip-runner/README.md) define the
|
||||
platform/libc boundary. Windows and Alpine/musl remain Legacy; other harness
|
||||
defaults are unchanged. Disabled adapters, external overrides, and selected-target
|
||||
qualification also affect availability.
|
||||
|
||||
For sandbox defaults, follow the [environment probe](./execution-environments.md#environment-settings)
|
||||
recipe first. Discovery/creation read company-bound immutable-image evidence
|
||||
without allocating a target. A mutable image or snapshot name does not establish
|
||||
native compatibility. Then test the actual selected runtime with its selected
|
||||
account/model: a legacy CLI or authentication probe alone cannot establish native
|
||||
readiness. Missing dependencies, failed authentication, invalid models and
|
||||
incompatible custom settings must remain actionable errors without silent runner
|
||||
switching. Saved unchanged execution can still be tested without applying new
|
||||
selection policy, but runtime/account validation must still run.
|
||||
|
||||
Verify an automatic Codex hire and an explicit Legacy control through a useful
|
||||
file artifact, follow-up and reload. Preserve Codex reasoning effort and account
|
||||
isolation; retain explicit Legacy permission choices, including false. Reopen an
|
||||
existing agent, make an unrelated edit, and confirm both its persisted runner and
|
||||
next run stay unchanged. Use [hiring/import preservation](./agents.md#hire-agent)
|
||||
for approval and portability controls.
|
||||
|
||||
### `run-history`
|
||||
|
||||
Automated: [live run routes](../../server/src/__tests__/agent-live-run-routes.test.ts) and [run event sequencing](../../server/src/__tests__/heartbeat-run-event-sequencing.test.ts) cover run data contracts.
|
||||
|
||||
Manual: Start a disposable task, open its running transcript, and follow it to a terminal outcome. Reload and compare task/run IDs, status, output, and cost. Verify a failed run remains distinguishable from a completed run with useful output.
|
||||
|
||||
An explicit runner change starts a configuration revision and invalidates the
|
||||
eligible session. Active runs, restart recovery and historical transcript parsing
|
||||
retain their recorded execution configuration; do not infer their runner from a
|
||||
later edit to the agent. Account/harness branding and execution identity are
|
||||
different observations, both required in the evidence.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Model accounts are managed in Apps and inline agent account controls.
|
||||
|
||||
@@ -9,7 +9,8 @@ vi.mock("./environment-probe.js", () => ({ readSandboxPlatformQualification: sta
|
||||
vi.mock("./environment-config.js", () => ({ resolveEnvironmentDriverConfigForRuntime: state.resolveEnvironment }));
|
||||
vi.mock("@paperclipai/adapter-utils/ssh", () => ({ runSshCommand: state.ssh }));
|
||||
import { AGENT_RUNNER_SSH_PLATFORM_COMMAND, agentRunnerAvailability, resolveAgentRunnerTargetForCompany, resolveNewAgentRunner, resolveNewAgentRunnerForCompany } from "./agent-runner-selection.js";
|
||||
import { buildCodexAcpConfig } from "@paperclipai/adapter-codex-local/server";
|
||||
import { buildCodexAcpConfig, resolveCodexExecutionEngine } from "@paperclipai/adapter-codex-local/server";
|
||||
import { secretService } from "./secrets.js";
|
||||
import { localAgentRunnerTarget } from "../lib/agent-runner-platform.js";
|
||||
const target = { driver: "local", platform: "linux", architecture: "x64" };
|
||||
const qualifiedTargets = [target, { driver: "local", platform: "linux", architecture: "arm64" }, { driver: "local", platform: "darwin", architecture: "arm64" }, { driver: "local", platform: "darwin", architecture: "x64" }];
|
||||
@@ -183,6 +184,71 @@ describe("server-owned Codex runner selection", () => {
|
||||
.toThrow(expect.objectContaining({ status: 422, details: { code: "agent_runner_config_incompatible", fields: ["acpPermissionMode"] } }));
|
||||
});
|
||||
|
||||
it.each([undefined, "acp"])("rejects effective Legacy ACP network denial for engine=%s before native selection", async engine => {
|
||||
const adapterConfig = { ...(engine ? { engine } : {}), env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" } };
|
||||
expect(resolveCodexExecutionEngine(adapterConfig).engine).toBe("acp");
|
||||
expect(buildCodexAcpConfig(adapterConfig)).toMatchObject({ env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" } });
|
||||
// Native permissions use a separately trusted server variable. This would
|
||||
// enable networking despite the saved Legacy flag without admission rejection.
|
||||
const { codexNetworkAccess } = await import(new URL(
|
||||
"../../../packages/paperclip-runner/src/drivers/codex/codex-security-config.ts", import.meta.url,
|
||||
).href);
|
||||
expect(codexNetworkAccess({ PAPERCLIP_RUNNER_NETWORK_ACCESS: "enabled", PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" })).toBe(true);
|
||||
for (const runner of [undefined, "auto", "paperclip"] as const) {
|
||||
expect(() => resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target, runner }))
|
||||
.toThrow(expect.objectContaining({ status: 422, details: { code: "agent_runner_config_incompatible", fields: ["env.PAPERCLIP_CODEX_ACP_NETWORK_ACCESS"] } }));
|
||||
}
|
||||
expect(resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target, runner: "legacy" }))
|
||||
.toEqual({ adapterType: "codex_local", adapterConfig });
|
||||
expect(adapterConfig.env).toEqual({ PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" });
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ type: "plain", value: "false" },
|
||||
{ type: "secret_ref", secretId: "fixture-policy", version: "latest" },
|
||||
{ type: "user_secret_ref", key: "fixture-policy", version: "latest" },
|
||||
])("does not discard a bound ACP network restriction or guess its value (%j)", async binding => {
|
||||
const adapterConfig = { engine: "acp", env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: binding } };
|
||||
if (binding.type === "plain") {
|
||||
const resolved = await secretService({} as never).resolveEnvBindings("fixture-company", adapterConfig.env);
|
||||
expect(buildCodexAcpConfig({ ...adapterConfig, env: resolved.env }))
|
||||
.toMatchObject({ env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" } });
|
||||
}
|
||||
expect(() => resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target }))
|
||||
.toThrow(expect.objectContaining({ status: 422, details: { code: "agent_runner_config_incompatible", fields: ["env.PAPERCLIP_CODEX_ACP_NETWORK_ACCESS"] } }));
|
||||
expect(resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target, runner: "legacy" }))
|
||||
.toEqual({ adapterType: "codex_local", adapterConfig });
|
||||
});
|
||||
|
||||
it.each([
|
||||
{ extraArgs: ["-c", "sandbox_workspace_write.network_access=true"] },
|
||||
{ extraArgs: [], args: ["-c", "sandbox_workspace_write.network_access=true"] },
|
||||
])("retains actionable argument errors when Legacy arguments override a network flag (%j)", args => {
|
||||
const adapterConfig = { engine: "acp", ...args, env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" } };
|
||||
expect(buildCodexAcpConfig(adapterConfig)).toMatchObject({ env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "true" } });
|
||||
expect(() => resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target }))
|
||||
.toThrow(expect.objectContaining({ status: 422, details: { code: "agent_runner_config_incompatible", fields: [args.extraArgs.length ? "extraArgs" : "args"] } }));
|
||||
});
|
||||
|
||||
it.each(["true", "False", " false ", { type: "plain", value: "true" }])("keeps compatible ACP environment settings (%j) and native idempotence", value => {
|
||||
const adapterConfig = { engine: "acp", env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: value, OPENAI_API_KEY: { type: "secret_ref", secretId: "fixture-api-key" } } };
|
||||
const literal = typeof value === "string" ? value : value.value;
|
||||
expect(buildCodexAcpConfig({ ...adapterConfig, env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: literal } }))
|
||||
.toMatchObject({ env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "true" } });
|
||||
const resolved = resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target });
|
||||
expect(resolved.adapterType).toBe("paperclip_runner");
|
||||
expect(resolved.adapterConfig.env).toEqual(adapterConfig.env);
|
||||
expect(resolveNewAgentRunner(resolved)).toEqual(resolved);
|
||||
});
|
||||
|
||||
it("keeps a saved native profile and an explicitly selected Legacy CLI's unused ACP flag unchanged", () => {
|
||||
const adapterConfig = { engine: "cli", env: { PAPERCLIP_CODEX_ACP_NETWORK_ACCESS: "false" } };
|
||||
expect(resolveCodexExecutionEngine(adapterConfig).engine).toBe("cli");
|
||||
expect(resolveNewAgentRunner({ adapterType: "codex_local", adapterConfig, target }).adapterType).toBe("paperclip_runner");
|
||||
const saved = { adapterType: "paperclip_runner", adapterConfig: { provider: "codex", env: adapterConfig.env } };
|
||||
expect(resolveNewAgentRunner(saved)).toEqual(saved);
|
||||
});
|
||||
|
||||
it("preserves explicit historical native profiles, including managed configurations", () => {
|
||||
for (const config of [{ provider: "acpx", acpxAgent: "claude", model: "claude-sonnet-5" }, { provider: "claude_managed", managedProfileId: "profile", managedAgentsRetentionAcknowledged: true }, { provider: "aws_agentcore", agentCoreProfileId: "profile" }]) expect(resolveNewAgentRunner({ adapterType: "paperclip_runner", adapterConfig: config })).toEqual({ adapterType: "paperclip_runner", adapterConfig: config });
|
||||
});
|
||||
|
||||
@@ -96,6 +96,18 @@ export function resolveNewAgentRunner(input: AgentRunnerSelection): { adapterTyp
|
||||
if (config.dangerouslyBypassApprovalsAndSandbox === false) unsupported.push("dangerouslyBypassApprovalsAndSandbox");
|
||||
if (config.dangerouslyBypassSandbox === false) unsupported.push("dangerouslyBypassSandbox");
|
||||
if (unsupported.length) incompatible(unsupported.map(field => aliasSources.get(field) ?? field));
|
||||
const env = config.env && typeof config.env === "object" && !Array.isArray(config.env)
|
||||
? config.env as Record<string, unknown> : {};
|
||||
const network = env.PAPERCLIP_CODEX_ACP_NETWORK_ACCESS;
|
||||
const binding = network && typeof network === "object" && !Array.isArray(network)
|
||||
? network as Record<string, unknown> : null;
|
||||
// Native networking is server-owned. Never translate a Legacy restriction
|
||||
// into that trusted variable, or guess the value of a deferred policy binding.
|
||||
if (config.engine !== "cli" && (network === "false"
|
||||
|| (binding?.type === "plain" && binding.value === "false")
|
||||
|| binding?.type === "secret_ref" || binding?.type === "user_secret_ref")) {
|
||||
incompatible(["env.PAPERCLIP_CODEX_ACP_NETWORK_ACCESS"]);
|
||||
}
|
||||
const effort = config.modelReasoningEffort ?? config.reasoningEffort ?? config.effort;
|
||||
for (const key of ["engine", "command", "extraArgs", "args", "agentCommand", "mode", "nonInteractivePermissions", "stateDir", "warmHandleIdleMs", "dangerouslyBypassApprovalsAndSandbox", "dangerouslyBypassSandbox", "search", "fastMode", "reasoningEffort", "effort"]) delete config[key];
|
||||
if (config.model !== undefined && typeof config.model !== "string") incompatible(["model"]);
|
||||
|
||||
Reference in new issue
Block a user