Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/agent-task-contracts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ jobs:
- run: npm run build
- run: npm run test:agent-task-contracts
- run: npm run test:runtime-sources-playground-integration
env:
WP_CODEBOX_RUN_NETWORK_INTEGRATION: "1"
- run: npm run test:redaction
- run: npm run test:production-boundary-enforcement
- run: npm run test:runtime-tool-policy
Expand Down
32 changes: 27 additions & 5 deletions packages/cli/src/agent-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,8 @@ $sandbox_external_runtime_package_import = wp_codebox_import_external_runtime_ag
$sandbox_stack['external_runtime_package_import'] = $sandbox_external_runtime_package_import;
if (!empty($sandbox_external_runtime_package_import['success']) && empty($sandbox_external_runtime_package_import['skipped'])) {
$sandbox_imported_agent = (string) ($sandbox_external_runtime_package_import['identity']['slug'] ?? '');
if (is_array($sandbox_runtime_task) && '' !== $sandbox_imported_agent) {
$sandbox_runtime_task['input']['package']['slug'] = $sandbox_imported_agent;
$sandbox_runtime_task['input']['package']['bootstrap_imported'] = true;
$sandbox_runtime_task['input']['metadata']['imported_agent'] = array('slug' => $sandbox_imported_agent);
}
$sandbox_external_runtime_package_import = wp_codebox_bind_external_runtime_package_identity($sandbox_runtime_task, $sandbox_imported_agent, $sandbox_external_runtime_package_import);
$sandbox_stack['external_runtime_package_import'] = $sandbox_external_runtime_package_import;
}

add_filter('agents_chat_runtime_principal_permission', static function (bool $allowed, $principal, array $input): bool {
Expand Down Expand Up @@ -263,6 +260,31 @@ function wp_codebox_import_external_runtime_agent_package(array $runtime_task):
}
}

function wp_codebox_bind_external_runtime_package_identity(&$runtime_task, string $agent_slug, array $import): array {
if (!is_array($runtime_task) || '' === $agent_slug) {
return array('success' => false, 'error' => array('code' => 'wp_codebox_external_runtime_package_identity_missing', 'message' => 'Canonical runtime package import did not produce one agent identity.'));
}
$task_input = is_array($runtime_task['input'] ?? null) ? $runtime_task['input'] : null;
$package = is_array($task_input['package'] ?? null) ? $task_input['package'] : null;
$chat_input = is_array($task_input['input'] ?? null) ? $task_input['input'] : array();
$metadata = is_array($task_input['metadata'] ?? null) ? $task_input['metadata'] : array();
$requested_package_slug = is_array($package) ? (string) ($package['slug'] ?? '') : '';
$requested_agent_slug = is_array($chat_input) ? (string) ($chat_input['agent'] ?? '') : '';
$metadata_agent_slug = is_array($metadata['imported_agent'] ?? null) ? (string) ($metadata['imported_agent']['slug'] ?? '') : '';
if (!is_array($package) || ('' !== $requested_package_slug && !hash_equals($agent_slug, $requested_package_slug)) || ('' !== $requested_agent_slug && !hash_equals($agent_slug, $requested_agent_slug)) || ('' !== $metadata_agent_slug && !hash_equals($agent_slug, $metadata_agent_slug))) {
return array('success' => false, 'error' => array('code' => 'wp_codebox_external_runtime_package_identity_mismatch', 'message' => 'Runtime package execution must use the single agent identity verified during canonical import.'));
}
$package['slug'] = $agent_slug;
$package['bootstrap_imported'] = true;
$chat_input['agent'] = $agent_slug;
$metadata['imported_agent'] = array('slug' => $agent_slug);
$task_input['package'] = $package;
$task_input['input'] = $chat_input;
$task_input['metadata'] = $metadata;
$runtime_task['input'] = $task_input;
return $import;
}

function wp_codebox_json_encode_agent_runtime_payload($value): string {
$json = wp_json_encode($value, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_INVALID_UTF8_SUBSTITUTE);
if (false !== $json) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ public function run( array $task ): array|WP_Error {
return $imports;
}

$agent_slug = $this->imported_agent_slug( $task );
$agent_slug = $this->imported_agent_slug( $task, $imports );
if ( is_wp_error( $agent_slug ) ) {
return $agent_slug;
}
if ( '' !== $agent_slug ) {
$input = is_array( $task['input'] ?? null ) ? $task['input'] : array();
$input['agent'] = $agent_slug;
$task['input'] = $input;
$input = is_array( $task['input'] ?? null ) ? $task['input'] : array();
$requested_agent = $this->string_value( $input['agent'] ?? '' );
if ( '' !== $requested_agent && ! hash_equals( $agent_slug, $requested_agent ) ) {
return new WP_Error( 'wp_codebox_runtime_package_agent_identity_mismatch', 'Runtime package execution must use the agent identity verified during import.', array( 'status' => 400 ) );
}
$input['agent'] = $agent_slug;
$task['input'] = $input;

$result = $this->execute_workflow( $task );
if ( is_wp_error( $result ) ) {
Expand Down Expand Up @@ -118,9 +120,6 @@ private function execute_workflow( array $task ): array|WP_Error {
$ability = 'agents/chat';
$input = is_array( $task['input'] ?? null ) ? $task['input'] : array();
$package = is_array( $task['package'] ?? null ) ? $task['package'] : array();
if ( ! isset( $input['agent'] ) && '' !== $this->string_value( $package['slug'] ?? '' ) ) {
$input['agent'] = $this->string_value( $package['slug'] );
}
if ( ! isset( $input['message'] ) ) {
$input['message'] = $this->string_value( $input['prompt'] ?? '' );
}
Expand Down Expand Up @@ -149,16 +148,22 @@ private function execute_workflow( array $task ): array|WP_Error {
return $result;
}

/** @param array<string,mixed> $task Runtime package task. @return string|WP_Error */
private function imported_agent_slug( array $task ): string|WP_Error {
/** @param array<string,mixed> $task Runtime package task. @param array<int,array<string,mixed>> $imports Import results. @return string|WP_Error */
private function imported_agent_slug( array $task, array $imports ): string|WP_Error {
$package = is_array( $task['package'] ?? null ) ? $task['package'] : array();
$imported_slugs = array_values( array_unique( array_filter( array_map( static fn( mixed $import ): string => is_array( $import ) && ! empty( $import['success'] ) ? trim( (string) ( $import['agent_slug'] ?? '' ) ) : '', $imports ) ) ) );
if ( 1 !== count( $imports ) || 1 !== count( $imported_slugs ) ) {
return new WP_Error( 'wp_codebox_runtime_package_imported_agent_unresolved', 'Runtime package import must resolve exactly one agent identity.', array( 'status' => 400 ) );
}
$slug = $imported_slugs[0];
if ( ! hash_equals( $slug, $this->string_value( $package['slug'] ?? '' ) ) || ! function_exists( 'wp_get_agent' ) || ! wp_get_agent( $slug ) ) {
return new WP_Error( 'wp_codebox_runtime_package_imported_agent_unresolved', 'The imported runtime package agent identity did not resolve exactly.', array( 'status' => 400 ) );
}
if ( empty( $package['bootstrap_imported'] ) ) {
return '';
return $slug;
}
$metadata = is_array( $task['metadata'] ?? null ) ? $task['metadata'] : array();
$slug = $this->string_value( $metadata['imported_agent']['slug'] ?? '' );
$bootstrap = is_array( $GLOBALS['wp_codebox_private_runtime_package_import'] ?? null ) ? $GLOBALS['wp_codebox_private_runtime_package_import'] : array();
if ( '' === $slug || ! hash_equals( $slug, $this->string_value( $bootstrap['identity']['slug'] ?? '' ) ) || ! function_exists( 'wp_get_agent' ) || ! wp_get_agent( $slug ) ) {
if ( ! hash_equals( $slug, $this->string_value( $bootstrap['identity']['slug'] ?? '' ) ) ) {
return new WP_Error( 'wp_codebox_runtime_package_imported_agent_unresolved', 'The imported runtime package agent identity did not resolve exactly.', array( 'status' => 400 ) );
}

Expand Down
9 changes: 7 additions & 2 deletions scripts/php-runtime-package-public-contract-smoke.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,18 @@ function wp_get_ability( string $name ): ?WP_Codebox_Runtime_Package_Smoke_Abili
);
$GLOBALS['wp_codebox_runtime_package_registered_agents']['store-idea-agent'] = true;
$bootstrap_task = $wpsg_like_task;
$bootstrap_task['package']['slug'] = 'caller-controlled-agent';
$bootstrap_task['package']['bootstrap_imported'] = true;
$bootstrap_task['input']['agent'] = 'caller-controlled-agent';
$bootstrap_task['input']['agent'] = 'store-idea-agent';
$bootstrap = WP_Codebox_Abilities::run_runtime_package( $bootstrap_task + array( 'runtime_provider' => 'codebox-runtime-package' ) );
assert( ! is_wp_error( $bootstrap ) );
assert( 'store-idea-agent' === $GLOBALS['wp_codebox_runtime_package_smoke_input']['agent'] );

$spoofed_bootstrap_task = $bootstrap_task;
$spoofed_bootstrap_task['input']['agent'] = 'caller-controlled-agent';
$spoofed_bootstrap = WP_Codebox_Abilities::run_runtime_package( $spoofed_bootstrap_task + array( 'runtime_provider' => 'codebox-runtime-package' ) );
assert( is_wp_error( $spoofed_bootstrap ) );
assert( 'wp_codebox_runtime_package_agent_identity_mismatch' === $spoofed_bootstrap->get_error_code() );

file_put_contents( $staged_bundle_file, "tampered\n" );
$tampered = WP_Codebox_Abilities::run_runtime_package( $wpsg_like_task + array( 'runtime_provider' => 'codebox-runtime-package' ) );
assert( is_wp_error( $tampered ) );
Expand Down
31 changes: 29 additions & 2 deletions tests/agent-no-data-machine-loop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,19 @@ assert.match(sandboxAgentCode, /'model' => \$configured_model/)
const docsAgentDirectory = process.env.DOCS_AGENT_DIR
const publicPackageBytes = docsAgentDirectory
? await readFile(join(docsAgentDirectory, "bundles", "technical-docs-agent", "native", "technical-docs-maintenance-agent.agent.json"))
: await readFile(new URL("./fixtures/external-native-package/flat-agent.agent.json", import.meta.url))
: await readFile(new URL("./fixtures/external-native-package/technical-bootstrap-agent.agent.json", import.meta.url))
const publicAgentSlug = canonicalExternalNativeAgentIdentity(publicPackageBytes).slug
const skillsPackageBytes = await readFile(new URL("./fixtures/external-native-package/skills-agent.agent.json", import.meta.url))
assert.deepEqual(canonicalExternalNativeAgentIdentity(skillsPackageBytes), { slug: "skills-agent" })
assert.deepEqual(canonicalExternalNativeAgentIdentity(publicPackageBytes), { slug: docsAgentDirectory ? "technical-docs-maintenance-agent" : "technical-bootstrap-agent" })
const publicPackageDigest = `sha256-bytes-v1:${await import("node:crypto").then(({ createHash }) => createHash("sha256").update(publicPackageBytes).digest("hex"))}`
const bootstrapCode = await resolveSandboxTaskCode({
task: "Say hello",
agent: "wp-codebox-sandbox",
runtimeTask: {
ability: "wp-codebox/run-runtime-package",
input: {
package: { slug: "caller-controlled-agent", source: "public-external-package", bootstrap: { encoding: "base64", bytes: publicPackageBytes.toString("base64"), digest: publicPackageDigest } },
package: { slug: publicAgentSlug, source: "public-external-package", bootstrap: { encoding: "base64", bytes: publicPackageBytes.toString("base64"), digest: publicPackageDigest } },
},
},
sandboxToolPolicy: { schema: "wp-codebox/sandbox-tool-policy/v1", version: 1, tools: [] },
Expand All @@ -211,6 +214,30 @@ assert.match(bootstrapCode, /wp_codebox_import_external_runtime_agent_package/)
assert.ok(bootstrapCode.indexOf("wp_codebox_import_external_runtime_agent_package") < bootstrapCode.indexOf("wp_codebox_resolve_runtime_task_ability"))
assert.match(bootstrapCode, /base64_decode\(\$bootstrap\['bytes'\], true\)/)

const spoofedBootstrapCode = await resolveSandboxTaskCode({
task: "Say hello",
agent: "wp-codebox-sandbox",
runtimeTask: {
ability: "wp-codebox/run-runtime-package",
input: {
package: { slug: publicAgentSlug, source: "public-external-package", bootstrap: { encoding: "base64", bytes: publicPackageBytes.toString("base64"), digest: publicPackageDigest } },
input: { agent: "caller-controlled-agent" },
},
},
sandboxToolPolicy: { schema: "wp-codebox/sandbox-tool-policy/v1", version: 1, tools: [] },
})
const spoofedBootstrapOutput = execFileSync("php", ["-r", `${phpPreamble}
function wp_agent_import_runtime_bundles($bundles, $options) {
$package = json_decode((string) file_get_contents((string) ($bundles[0]['source'] ?? '')), true);
$slug = $package['agent']['agent_slug'] ?? '';
WP_Agents_Registry::get_instance()->register($slug, array('source' => 'canonical-importer'));
return array(array('success' => true, 'agent_slug' => $slug));
}
${spoofedBootstrapCode}`], { encoding: "utf8" })
const spoofedBootstrap = JSON.parse(spoofedBootstrapOutput) as { agent_runtime?: { success?: boolean, error?: { code?: string } } }
assert.equal(spoofedBootstrap.agent_runtime?.success, false)
assert.equal(spoofedBootstrap.agent_runtime?.error?.code, "wp_codebox_external_runtime_package_identity_mismatch")

const failedImportOutput = execFileSync("php", ["-r", `${phpPreamble}
function wp_agent_import_runtime_bundles($bundles, $options) { $GLOBALS['external_source'] = $bundles[0]['source']; return array(array('success' => false)); }
${bootstrapCode}`], {
Expand Down
15 changes: 15 additions & 0 deletions tests/fixtures/external-native-package/skills-agent.agent.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"schema_version": 1,
"bundle_slug": "skills-agent",
"bundle_version": "1.0.0",
"agent": {
"agent_slug": "skills-agent",
"agent_name": "Skills Agent",
"description": "Fixture for a package that supplies skills through enabled tools.",
"agent_config": {
"instructions": "SKILLS PACKAGE INSTRUCTION",
"enabled_tools": ["workspace_read", "workspace_write"],
"modes": ["chat", "task"]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"schema_version": 1,
"bundle_slug": "technical-bootstrap-agent",
"bundle_version": "1.0.0",
"agent": {
"agent_slug": "technical-bootstrap-agent",
"agent_name": "Technical Bootstrap Agent",
"description": "Fixture for a technical documentation bootstrap package.",
"agent_config": {
"instructions": "TECHNICAL BOOTSTRAP PACKAGE INSTRUCTION",
"enabled_tools": ["workspace_ls", "workspace_read", "workspace_write"],
"tool_call_rules": [{"id": "require-write", "require_tool_use": true, "require_one_of": ["workspace_write"]}],
"modes": ["chat"]
}
}
}
Loading
Loading