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
35 changes: 35 additions & 0 deletions actions/setup/sh/cloud_hypervisor_kvm_access.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set +o histexpand

# Grant only the current runner user access to KVM. This avoids weakening the
# device permissions for unrelated users on the host.

set -euo pipefail

echo "::group::Configure cloud-hypervisor KVM access"

if [[ "${RUNNER_ENVIRONMENT:-}" != "github-hosted" || "${RUNNER_OS:-}" != "Linux" || "${RUNNER_ARCH:-}" != "X64" || "${ImageOS:-}" != ubuntu* ]]; then
echo "::error::cloud-hypervisor KVM access is supported only on GitHub-hosted Ubuntu x86_64 runners."
exit 1
fi

if [[ ! -e /dev/kvm ]]; then
echo "::error::/dev/kvm is missing. cloud-hypervisor preview requires a KVM-capable runner."
exit 1
fi

if ! command -v setfacl >/dev/null 2>&1; then
echo "::error::setfacl is required to grant scoped access to /dev/kvm."
exit 1
fi

runner_uid="$(id -u)"
sudo setfacl -m "u:${runner_uid}:rw" /dev/kvm

if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then
echo "::error::failed to grant the runner user read/write access to /dev/kvm."
exit 1
fi

echo "runner user has scoped read/write access to /dev/kvm"
echo "::endgroup::"
45 changes: 40 additions & 5 deletions actions/setup/sh/cloud_hypervisor_setup_bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ set +o histexpand
# cloud-hypervisor guest bundle for the requested AWF version.
#
# Outputs (GITHUB_OUTPUT):
# binary_path, kernel_path, rootfs_path, supervisor_path
# binary_sha256, kernel_sha256, rootfs_sha256, supervisor_sha256
# binary_path, virtiofsd_path, kernel_path, rootfs_path, supervisor_path
# binary_sha256, virtiofsd_sha256, kernel_sha256, rootfs_sha256,
# supervisor_sha256

set -euo pipefail

Expand Down Expand Up @@ -74,7 +75,7 @@ lookup_sha256() {
local rel="$1"
local full="$2"
local candidate
for candidate in "${rel#./}" "$(basename "${rel#./}")" "${full#${bundle_root}/}" "${full#${extract_dir}/}"; do
for candidate in "${rel#./}" "$(basename "${rel#./}")" "${full#"${bundle_root}"/}" "${full#"${extract_dir}"/}"; do
local sum
sum="$(awk -v target="${candidate}" '{sub(/^\.\//, "", $2); if ($2==target) {print $1; exit}}' "${sha_file}")"
if [[ -n "${sum}" ]]; then
Expand All @@ -101,32 +102,62 @@ binary_rel="cloud-hypervisor"
kernel_rel="vmlinux.bin"
rootfs_rel="rootfs.ext4"
supervisor_rel="awf-supervisor"
virtiofsd_rel="virtiofsd"

binary_path="$(resolve_path "${binary_rel}" || true)"
kernel_path="$(resolve_path "${kernel_rel}" || true)"
rootfs_path="$(resolve_path "${rootfs_rel}" || true)"
supervisor_path="$(resolve_path "${supervisor_rel}" || true)"
virtiofsd_path="$(resolve_path "${virtiofsd_rel}" || true)"

if [[ -z "${binary_path}" || -z "${kernel_path}" || -z "${rootfs_path}" || -z "${supervisor_path}" ]]; then
if [[ -z "${binary_path}" || -z "${kernel_path}" || -z "${rootfs_path}" || -z "${supervisor_path}" || -z "${virtiofsd_path}" ]]; then
echo "::error::failed to resolve one or more cloud-hypervisor artifact files after extraction"
exit 1
fi

if [[ "$(dirname "${binary_path}")" != "$(dirname "${virtiofsd_path}")" ]]; then
echo "::error::virtiofsd must be colocated with the cloud-hypervisor binary"
exit 1
fi

binary_sha256="$(lookup_sha256 "${binary_rel}" "${binary_path}" || true)"
kernel_sha256="$(lookup_sha256 "${kernel_rel}" "${kernel_path}" || true)"
rootfs_sha256="$(lookup_sha256 "${rootfs_rel}" "${rootfs_path}" || true)"
supervisor_sha256="$(lookup_sha256 "${supervisor_rel}" "${supervisor_path}" || true)"
virtiofsd_sha256="$(lookup_sha256 "${virtiofsd_rel}" "${virtiofsd_path}" || true)"

if [[ -z "${binary_sha256}" || -z "${kernel_sha256}" || -z "${rootfs_sha256}" || -z "${supervisor_sha256}" ]]; then
if [[ -z "${binary_sha256}" || -z "${kernel_sha256}" || -z "${rootfs_sha256}" || -z "${supervisor_sha256}" || -z "${virtiofsd_sha256}" ]]; then
echo "::error::failed to resolve one or more cloud-hypervisor SHA256 digests from ${checksums_name}"
exit 1
fi

manifest_path="${bundle_root}/${manifest_name}"
if ! jq -e '
.schemaVersion == 1
and .architecture == "x86_64"
and (.cloudHypervisor.version | type == "string" and length > 0)
and (.cloudHypervisor.binarySha256 | type == "string" and test("^[0-9A-Fa-f]{64}$"))
and (.virtiofsd.version | type == "string" and length > 0)
and (.virtiofsd.binarySha256 | type == "string" and test("^[0-9A-Fa-f]{64}$"))
' "${manifest_path}" >/dev/null; then
echo "::error::${manifest_name} does not match the cloud-hypervisor release bundle contract"
exit 1
fi

manifest_binary_sha256="$(jq -r '.cloudHypervisor.binarySha256 | ascii_downcase' "${manifest_path}")"
manifest_virtiofsd_sha256="$(jq -r '.virtiofsd.binarySha256 | ascii_downcase' "${manifest_path}")"
if [[ "${manifest_binary_sha256}" != "${binary_sha256,,}" || "${manifest_virtiofsd_sha256}" != "${virtiofsd_sha256,,}" ]]; then
echo "::error::${manifest_name} digest fields do not match ${checksums_name}"
exit 1
fi

echo "::group::Verify cloud-hypervisor bundle checksums"
verify_sha256 "${binary_sha256}" "${binary_path}"
verify_sha256 "${kernel_sha256}" "${kernel_path}"
verify_sha256 "${rootfs_sha256}" "${rootfs_path}"
verify_sha256 "${supervisor_sha256}" "${supervisor_path}"
verify_sha256 "${virtiofsd_sha256}" "${virtiofsd_path}"
chmod 0755 "${binary_path}" "${supervisor_path}" "${virtiofsd_path}"
echo "bundle checksums verified"
echo "::endgroup::"

Expand All @@ -136,10 +167,12 @@ if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
echo "kernel_path=${kernel_path}"
echo "rootfs_path=${rootfs_path}"
echo "supervisor_path=${supervisor_path}"
echo "virtiofsd_path=${virtiofsd_path}"
echo "binary_sha256=${binary_sha256}"
echo "kernel_sha256=${kernel_sha256}"
echo "rootfs_sha256=${rootfs_sha256}"
echo "supervisor_sha256=${supervisor_sha256}"
echo "virtiofsd_sha256=${virtiofsd_sha256}"
} >> "${GITHUB_OUTPUT}"
fi
if [[ -n "${GITHUB_ENV:-}" ]]; then
Expand All @@ -148,10 +181,12 @@ if [[ -n "${GITHUB_ENV:-}" ]]; then
echo "GH_AW_CLOUD_HYPERVISOR_KERNEL=${kernel_path}"
echo "GH_AW_CLOUD_HYPERVISOR_ROOTFS=${rootfs_path}"
echo "GH_AW_CLOUD_HYPERVISOR_SUPERVISOR=${supervisor_path}"
echo "GH_AW_CLOUD_HYPERVISOR_VIRTIOFSD=${virtiofsd_path}"
echo "GH_AW_CLOUD_HYPERVISOR_BINARY_SHA256=${binary_sha256}"
echo "GH_AW_CLOUD_HYPERVISOR_KERNEL_SHA256=${kernel_sha256}"
echo "GH_AW_CLOUD_HYPERVISOR_ROOTFS_SHA256=${rootfs_sha256}"
echo "GH_AW_CLOUD_HYPERVISOR_SUPERVISOR_SHA256=${supervisor_sha256}"
echo "GH_AW_CLOUD_HYPERVISOR_VIRTIOFSD_SHA256=${virtiofsd_sha256}"
} >> "${GITHUB_ENV}"
fi

Expand Down
127 changes: 119 additions & 8 deletions docs/public/editor/autocomplete-data.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
"skills": {
"type": "array",
"desc": "Optional list of external skill references to install during activation.",
"desc": "Optional list of skill references to install during activation.",
"array": true
},
"metadata": {
Expand Down Expand Up @@ -67,6 +67,11 @@
"enum": [true, false],
"leaf": true
},
"ambient-folders": {
"type": "array",
"desc": "Workspace-relative folders to bundle in the activation artifact and restore before the agent runs.",
"array": true
},
"on": {
"type": "string|object",
"desc": "Workflow triggers that define when the agentic workflow should run.",
Expand Down Expand Up @@ -719,6 +724,11 @@
}
}
},
"enclaves": {
"type": "array",
"desc": "AWF-owned private-repository executors exposed only through the compiler-launched MCP gateway.",
"array": true
},
"sandbox": {
"type": "string|object",
"desc": "Sandbox configuration for AI engines.",
Expand Down Expand Up @@ -796,14 +806,21 @@
"token-steering": {
"type": "boolean",
"desc": "Enable or disable API proxy token steering.",
"enum": [true, false],
"leaf": true
},
"runtime": {
"type": "string",
"desc": "Container runtime for the agent container. cloud-hypervisor is preview-only and limited to GitHub-hosted Ubuntu x86_64 runners with /dev/kvm.",
"desc": "Container runtime for the agent container.",
"enum": ["gvisor", "docker-sbx", "cloud-hypervisor"],
"leaf": true
},
"runtime-install": {
"type": "boolean",
"desc": "Controls generation of sandbox runtime installation steps for gVisor and docker-sbx.",
"enum": [true, false],
"leaf": true
},
"config": {
"type": "object",
"desc": "Custom sandbox runtime configuration.",
Expand Down Expand Up @@ -835,6 +852,10 @@
"anthropic": {
"type": "object",
"desc": "AWF API proxy target configuration for a single LLM provider."
},
"copilot": {
"type": "object",
"desc": "AWF API proxy target configuration for the Copilot BYOK provider."
}
}
},
Expand All @@ -847,7 +868,7 @@
"allow-host-ports": {
"type": "array",
"desc": "Additional host TCP ports the agent may connect to when legacy-security is enabled.",
"leaf": true
"array": true
}
}
},
Expand Down Expand Up @@ -1080,6 +1101,11 @@
"type": "integer|string",
"desc": "Maximum delay cap in ms.",
"leaf": true
},
"watchdog-timeout": {
"type": "integer|string",
"desc": "Post-result idle watchdog timeout in seconds.",
"leaf": true
}
}
},
Expand Down Expand Up @@ -1146,6 +1172,26 @@
"type": "string",
"desc": "Anthropic WIF workspace ID (e.g., ws_...).",
"leaf": true
},
"workload-identity-provider": {
"type": "string",
"desc": "Google Cloud WIF workload identity provider resource name (e.g., projects/PROJECT_NUMBER/locations/global/workloadIde...",
"leaf": true
},
"service-account": {
"type": "string",
"desc": "Google Cloud service account email to impersonate via WIF (e.g., my-sa@my-project.iam.gserviceaccount.com).",
"leaf": true
},
"project": {
"type": "string",
"desc": "Google Cloud project ID used for Vertex AI / Gemini Enterprise inference.",
"leaf": true
},
"location": {
"type": "string",
"desc": "Google Cloud region for Vertex AI inference (e.g., us-central1).",
"leaf": true
}
}
},
Expand Down Expand Up @@ -1708,27 +1754,27 @@
},
"bounded-queries": {
"type": "object",
"desc": "AWF bounded-query configuration for finite private-repository questions. Every query runs in a fresh backend-specific sandbox independently from the primary agent sandbox.",
"desc": "AWF bounded-query configuration for cross-repository private data access (AWF v0.27.44+).",
"children": {
"private-repos": {
"type": "array",
"desc": "Private repositories approved for bounded-query access, each with repo and sensitivity fields.",
"desc": "List of private repositories the agent may query via bounded queries.",
"array": true
},
"runtime": {
"type": "string",
"desc": "Isolated query backend. sbx is experimental, capability-gated, fail-closed, and never falls back to docker or gvisor.",
"desc": "Isolated backend used to execute each bounded-query script.",
"enum": ["docker", "gvisor", "sbx"],
"leaf": true
},
"timeout": {
"type": "integer",
"desc": "Maximum execution time in seconds for one bounded-query invocation.",
"desc": "Maximum execution time in seconds for a single bounded-query invocation.",
"leaf": true
},
"memory-limit": {
"type": "string",
"desc": "Memory limit for bounded-query execution, such as 512m or 2g.",
"desc": "Memory limit for bounded-query container execution (e.g.",
"leaf": true
},
"interpreter": {
Expand Down Expand Up @@ -1836,6 +1882,22 @@
"type": "array",
"desc": "List of allowed file extensions (e.g., [\".json\", \".txt\"]).",
"array": true
},
"validation": {
"type": "object",
"desc": "Custom domain validation hook for this cache-memory entry",
"children": {
"script": {
"type": "string",
"desc": "JavaScript validator body that runs over the complete cache-memory directory before persistence.",
"leaf": true
},
"timeout-minutes": {
"type": "integer",
"desc": "Maximum validator runtime in minutes (default: 1, max: 5)",
"leaf": true
}
}
}
},
"array": true
Expand Down Expand Up @@ -1986,6 +2048,22 @@
"desc": "When true, all .json files are pretty-printed (2-space indent) before being committed, making them human-readable in ...",
"enum": [true, false],
"leaf": true
},
"validation": {
"type": "object",
"desc": "Custom domain validation hook for this repo-memory entry",
"children": {
"script": {
"type": "string",
"desc": "JavaScript validator body that runs over the complete repo-memory directory after optional JSON formatting and before...",
"leaf": true
},
"timeout-minutes": {
"type": "integer",
"desc": "Maximum validator runtime in minutes (default: 1, max: 5)",
"leaf": true
}
}
}
},
"array": true
Expand Down Expand Up @@ -2057,6 +2135,11 @@
"desc": "List of allowed domains for URL redaction in safe output handlers.",
"array": true
},
"data": {
"type": "boolean|object|string",
"desc": "Structured data configuration for body-based safe outputs.",
"leaf": true
},
"allowed-github-references": {
"type": "array",
"desc": "List of allowed repositories for GitHub references (e.g., #123 or owner/repo#456).",
Expand Down Expand Up @@ -2371,6 +2454,12 @@
"desc": "Repository to create failure tracking issues in, in the format 'owner/repo'.",
"leaf": true
},
"report-failed-jobs": {
"type": "boolean",
"desc": "Controls whether to report failed non-builtin jobs as issues (default: true).",
"enum": [true, false],
"leaf": true
},
"max-bot-mentions": {
"type": "integer|string",
"desc": "Maximum number of bot trigger references (e.g.",
Expand Down Expand Up @@ -2514,6 +2603,28 @@
"leaf": true
}
}
},
"workload-identity": {
"type": "object",
"desc": "Exchange a GitHub Actions OIDC token for a cloud access token before OTLP export.",
"children": {
"provider": {
"type": "string",
"desc": "Cloud workload identity provider.",
"enum": ["google"],
"leaf": true
},
"audience": {
"type": "string",
"desc": "Google Workload Identity Provider resource name (e.g.",
"leaf": true
},
"service-account": {
"type": "string",
"desc": "Optional Google service account email to impersonate after STS token exchange.",
"leaf": true
}
}
}
}
}
Expand Down
Loading
Loading