Sign inSign up

christianhkb/sbx-kit-pi-gcp-dev:0.3.0

Manifest digest

sha256:1eb4e2f64e6abdfe5631f43deaa2213fb01e7b1735771efd9b367c2ddb36e99b

Last pushed

13 days by christianhkb

Type

Sandbox Kit

Manifest digest

sha256:1eb4e2f64e6abdfe5631f43deaa2213fb01e7b1735771efd9b367c2ddb36e99b

yaml
schemaVersion: "3"
displayName: Pi GCP Development Environment
version: 0.3.0
kind: workload
provides:
    - [email protected]
    - [email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/base-files@14
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/ca-certificates-java@20260311
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/gcc-16-base@16
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/less@668
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/libgcc-s1@16
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/libjpeg8@8
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/libstdc++6@16
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/tzdata@2026
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
    - deb/[email protected]
capabilities:
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
                path: capabilities[0]
              type: com.docker.sandbox/lifecycle@1
              config:
                files:
                    - content: |
                        {
                          "providers": {
                            "gcp-oss-maas": {
                              "baseUrl": "https://aiplatform.googleapis.com/v1/projects/${{ kit.args.project }}/locations/${{ kit.args.location }}/endpoints/openapi",
                              "api": "openai-completions",
                              "apiKey": "$GCP_VERTEX_ACCESS_TOKEN",
                              "authHeader": true,
                              "models": [
                                {
                                  "id": "qwen/qwen3-next-80b-a3b-thinking-maas",
                                  "displayName": "Qwen 3 Next 80B Thinking (Agent Platform MaaS)",
                                  "reasoning": true,
                                  "input": ["text"],
                                  "contextWindow": 262144,
                                  "cost": {"input": 0.15, "output": 1.2, "cacheRead": 0, "cacheWrite": 0}
                                },
                                {
                                  "id": "qwen/qwen3-next-80b-a3b-instruct-maas",
                                  "displayName": "Qwen 3 Next 80B Instruct (Agent Platform MaaS)",
                                  "reasoning": false,
                                  "input": ["text"],
                                  "contextWindow": 262144,
                                  "cost": {"input": 0.15, "output": 1.2, "cacheRead": 0, "cacheWrite": 0}
                                },
                                {
                                  "id": "qwen/qwen3-coder-480b-a35b-instruct-maas",
                                  "displayName": "Qwen 3 Coder 480B Instruct (Agent Platform MaaS)",
                                  "reasoning": false,
                                  "input": ["text"],
                                  "contextWindow": 258000,
                                  "cost": {"input": 0.2, "output": 1.62, "cacheRead": 0.02, "cacheWrite": 0.2}
                                },
                                {
                                  "id": "zai-org/glm-5.2-maas",
                                  "displayName": "GLM 5.2 (Agent Platform MaaS)",
                                  "reasoning": true,
                                  "input": ["text"],
                                  "contextWindow": 1000000,
                                  "cost": {"input": 1.4, "output": 4.4, "cacheRead": 0.14, "cacheWrite": 1.4}
                                },
                                {
                                  "id": "zai-org/glm-5-maas",
                                  "displayName": "GLM 5 (Agent Platform MaaS)",
                                  "reasoning": true,
                                  "input": ["text"],
                                  "contextWindow": 200000,
                                  "cost": {"input": 1, "output": 3.2, "cacheRead": 0.1, "cacheWrite": 1}
                                },
                                {
                                  "id": "deepseek-ai/deepseek-v3.2-maas",
                                  "displayName": "Deepseek v3.2 (Agent Platform MaaS)",
                                  "reasoning": true,
                                  "input": ["text"],
                                  "contextWindow": 163840,
                                  "cost": {"input": 0.56, "output": 1.68, "cacheRead": 0.056, "cacheWrite": 0.56}
                                },
                                {
                                  "id": "moonshotai/kimi-k2-thinking-maas",
                                  "displayName": "Kimi K2 Thinking (Agent Platform MaaS)",
                                  "reasoning": true,
                                  "input": ["text"],
                                  "contextWindow": 262144,
                                  "cost": {"input": 0.6, "output": 2.5, "cacheRead": 0.06, "cacheWrite": 0.6}
                                }
                              ]
                            },
                            "gcp-anthropic": {
                              "baseUrl": "https://aiplatform.googleapis.com/v1/projects/${{ kit.args.project }}/locations/${{ kit.args.location }}/publishers/anthropic",
                              "api": "anthropic-messages",
                              "apiKey": "$GCP_VERTEX_ACCESS_TOKEN",
                              "authHeader": true,
                              "compat": {
                                "supportsStrictTools": false
                              },
                              "models": [
                                {
                                  "id": "claude-opus-5-5",
                                  "name": "Claude Opus 5.5 (Agent Platform)",
                                  "reasoning": true,
                                  "thinkingLevelMap": {
                                    "off": null,
                                    "minimal": null,
                                    "low": "low",
                                    "medium": "medium",
                                    "high": "high",
                                    "xhigh": "xhigh",
                                    "max": "max"
                                  },
                                  "input": ["text", "image"],
                                  "contextWindow": 1000000,
                                  "maxTokens": 128000,
                                  "compat": {
                                    "supportsMidConvoEffort": true,
                                    "supportsMidConvoSystemMessages": true,
                                    "supportsMidConvoToolChanges": true,
                                    "forceAdaptiveThinking": true,
                                    "supportsTemperature": false
                                  },
                                  "cost": {"input": 4, "output": 20, "cacheRead": 0.2, "cacheWrite": 5}
                                },
                                {
                                  "id": "claude-sonnet-5-5",
                                  "name": "Claude Sonnet 5.5 (Agent Platform)",
                                  "reasoning": true,
                                  "thinkingLevelMap": {
                                    "off": null,
                                    "minimal": null,
                                    "low": "low",
                                    "medium": "medium",
                                    "high": "high",
                                    "xhigh": "xhigh",
                                    "max": "max"
                                  },
                                  "input": ["text", "image"],
                                  "contextWindow": 1000000,
                                  "maxTokens": 128000,
                                  "compat": {
                                    "supportsMidConvoEffort": true,
                                    "supportsMidConvoSystemMessages": true,
                                    "supportsMidConvoToolChanges": true,
                                    "forceAdaptiveThinking": true,
                                    "supportsTemperature": false
                                  },
                                  "cost": {"input": 2, "output": 10, "cacheRead": 0.1, "cacheWrite": 2.5}
                                },
                                {
                                  "id": "claude-haiku-5-5",
                                  "name": "Claude Haiku 5.5 (Agent Platform)",
                                  "reasoning": true,
                                  "thinkingLevelMap": {
                                    "minimal": null,
                                    "low": "low",
                                    "medium": "medium",
                                    "high": "high",
                                    "xhigh": "xhigh",
                                    "max": "max"
                                  },
                                  "input": ["text", "image"],
                                  "contextWindow": 1000000,
                                  "maxTokens": 128000,
                                  "compat": {
                                    "supportsMidConvoEffort": true,
                                    "supportsMidConvoSystemMessages": true,
                                    "supportsMidConvoToolChanges": true,
                                    "forceAdaptiveThinking": true,
                                    "supportsTemperature": false
                                  },
                                  "cost": {
                                    "input": 0.1,
                                    "output": 0.5,
                                    "cacheRead": 0.01,
                                    "cacheWrite": 0.125,
                                    "tiers": [
                                      {"inputTokensAbove": 100000, "input": 0.5, "output": 2.5, "cacheRead": 0.05, "cacheWrite": 0.625}
                                    ]
                                  }
                                }
                              ]
                            }
                          }
                        }
                      mode: "0644"
                      overwrite: false
                      path: /home/agent/.pi/agent/models.json
                    - content: |
                        import { getApiProvider } from "@earendil-works/pi-ai/compat";
                        import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";

                        export default function (pi: ExtensionAPI) {
                          const anthropicApi = getApiProvider("anthropic-messages");
                          if (!anthropicApi) return;

                          pi.registerProvider("gcp-anthropic", {
                            api: "anthropic-messages",
                            streamSimple: (model, context, options) => {
                              const baseFetch = options?.fetch ?? globalThis.fetch;
                              const vertexFetch: typeof fetch = async (input, init) => {
                                const rawUrl =
                                  typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
                                const url = new URL(rawUrl);
                                const body = typeof init?.body === "string" ? JSON.parse(init.body) : undefined;
                                const modelId = body?.model ?? model.id;
                                if (body) {
                                  delete body.model;
                                  delete body.fallbacks;
                                  body.anthropic_version ??= "vertex-2023-10-16";
                                }
                                const specifier = body?.stream ? "streamRawPredict" : "rawPredict";
                                url.pathname = url.pathname.replace(/\/v1\/messages$/, `/models/${modelId}:${specifier}`);
                                url.searchParams.delete("beta");
                                return baseFetch(url.toString(), {
                                  ...init,
                                  body: body ? JSON.stringify(body) : init?.body,
                                });
                              };

                              return anthropicApi.streamSimple(model, context, {
                                ...options,
                                apiKey: undefined,
                                fetch: vertexFetch,
                              });
                            },
                          });
                        }
                      mode: "0644"
                      overwrite: false
                      path: /home/agent/.pi/agent/extensions/gcp-anthropic.ts
      declarationBlocks:
        - "0:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
        path: capabilities[0]
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
                path: capabilities[1]
              type: com.docker.sandbox/network-policy@1
              config:
                runtime:
                    allow:
                        - aiplatform.googleapis.com
      declarationBlocks:
        - "0:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
        path: capabilities[1]
    - group:
        description: Google Cloud Agent Platform AI
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
                path: capabilities[2]
              type: com.docker.sandbox/credential@1
              config:
                apiKey:
                    inject:
                        - domain: aiplatform.googleapis.com
                          format: Bearer %s
                          header: Authorization
                    name: GCP_VERTEX_ACCESS_TOKEN
                    proxyManaged: true
                phase: runtime
                service: gcp-vertex
              description: Google Cloud Agent Platform AI
      declarationBlocks:
        - "0:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
        path: capabilities[2]
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
                path: capabilities[3]
              type: com.docker.sandbox/git-identity@1
      declarationBlocks:
        - "0:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
        path: capabilities[3]
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
                path: capabilities[4]
              type: com.docker.sandbox/ssh-agent@1
              config:
                authenticate:
                    - github.com
                phase: runtime
                sign:
                    - git
                unrestricted: false
      declarationBlocks:
        - "0:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
        path: capabilities[4]
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
                path: capabilities[0]
              type: com.docker.sandbox/network-policy@1
              config:
                install:
                    allow:
                        - registry.npmjs.org
      declarationBlocks:
        - "1:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
        path: capabilities[0]
    - group:
        capabilities:
            - source:
                kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
                path: capabilities[1]
              type: com.docker.sandbox/lifecycle@1
              config:
                install:
                    - command: |
                        set -eu
                        want="${{ kit.args.version }}"
                        if [ "$want" != latest ] && pi --version 2>/dev/null | grep -qxF "$want"; then
                          echo "Pi $want already installed"
                          exit 0
                        fi
                        npm install -g "@earendil-works/pi-coding-agent@$want"
                        pi --version
                      description: Install the requested Pi release
                      env:
                        - NPM_CONFIG_PREFIX
                        - HTTP_PROXY
                        - HTTPS_PROXY
                        - NODE_EXTRA_CA_CERTS
                        - SSL_CERT_FILE
                      user: "1000"
      declarationBlocks:
        - "1:0"
      source:
        kit: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
        path: capabilities[1]
    - group:
        description: Push to GitHub over SSH and sign commits with the user's key
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
                path: capabilities[0]
              type: com.docker.sandbox/ssh-agent@1
              config:
                authenticate:
                    - [email protected]
                phase: runtime
                sign:
                    - git
                unrestricted: false
              description: Push to GitHub over SSH and sign commits with the user's key
      declarationBlocks:
        - "2:0"
      source:
        kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
        path: capabilities[0]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
                path: capabilities[1]
              type: com.docker.sandbox/network-policy@1
              config:
                runtime:
                    allow:
                        - github.com:22
      declarationBlocks:
        - "2:0"
      source:
        kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
        path: capabilities[1]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
                path: capabilities[2]
              type: com.docker.sandbox/lifecycle@1
              config:
                files:
                    - content: |
                        github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
                        github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
                        github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=
                      description: GitHub's published SSH host keys
                      mode: "0644"
                      path: /home/agent/.ssh/github-ssh-known-hosts
                startup:
                    - command: |
                        set -eu
                        config="${XDG_CONFIG_HOME:-$HOME/.config}/git/config"
                        mkdir -p "$(dirname "$config")"
                        set_default() {
                          if git config --file "$config" --get "$1" >/dev/null; then
                            return
                          else
                            status=$?
                            [ "$status" -eq 1 ] || return "$status"
                          fi
                          git config --file "$config" "$1" "$2"
                        }
                        set_default gpg.format ssh
                        set_default gpg.ssh.defaultKeyCommand 'ssh-add -L'
                        set_default commit.gpgsign true
                        set_default tag.gpgsign true
                      description: Merge missing signing defaults without replacing user settings
                      env:
                        - XDG_CONFIG_HOME
                    - command: |
                        set -eu
                        mkdir -p "$HOME/.ssh"
                        touch "$HOME/.ssh/known_hosts"
                        while IFS= read -r key; do
                          if grep -qxF "$key" "$HOME/.ssh/known_hosts"; then
                            continue
                          else
                            status=$?
                            [ "$status" -eq 1 ] || exit "$status"
                          fi
                          printf '\n%s\n' "$key" >> "$HOME/.ssh/known_hosts"
                        done < /home/agent/.ssh/github-ssh-known-hosts
                      description: Merge GitHub host keys while preserving existing entries
      declarationBlocks:
        - "2:0"
      source:
        kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
        path: capabilities[2]
    - group:
        optional: true
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
                path: capabilities[3]
              type: com.docker.sandbox/agent-context@1
              config:
                contentFile: /usr/share/sandbox/kit/pi-gcp-dev/context.md.parts/0.md
      declarationBlocks:
        - "2:0"
      source:
        kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
        path: capabilities[3]
    - group:
        optional: true
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
                path: capabilities[4]
              type: com.docker.sandbox/agent-context@2
              config:
                content: |
                    # GitHub over SSH

                    git can fetch from and push to GitHub over SSH (`[email protected]:owner/repo`)
                    with the user's key, through the agent at `$SSH_AUTH_SOCK`. Commits and
                    tags you make are signed through the same agent; Git may select a
                    different key from the one GitHub accepts for authentication.

                    - The agent logs in to github.com as `git` and makes git signatures. It
                      refuses every other server, account, and kind of signature, so `ssh` to
                      another host fails by design: do not work around it.
                    - GitHub's host keys are in `~/.ssh/known_hosts`. If ssh reports a changed
                      host key, stop and tell the user; never remove the entry or disable
                      host key checking.
                    - The key belongs to the user. Push only what the user asked for, and say
                      which commits you made.
      declarationBlocks:
        - "2:0"
      source:
        kit: docker.io/docker/sbx-kit-github-ssh:1.0.0
        path: capabilities[4]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[0]
              type: com.docker.sandbox/sbx@1
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[0]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[1]
              type: com.docker.sandbox/network-policy@1
              config:
                runtime:
                    allow:
                        - api.anthropic.com
                        - registry.npmjs.org
                        - platform.claude.com
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[1]
    - group:
        description: Anthropic API access (API key or claude.ai OAuth)
        optional: true
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[2]
              type: com.docker.sandbox/credential@1
              config:
                apiKey:
                    inject:
                        - domain: api.anthropic.com
                          format: '%s'
                          header: x-api-key
                    name: ANTHROPIC_API_KEY
                    proxyManaged: true
                oauth:
                    credentialFile:
                        path: ~/.pi/agent/auth.json
                        structure:
                            anthropic:
                                access: '{{.AccessToken}}'
                                expires: '{{.ExpiresAt}}'
                                refresh: '{{.RefreshToken}}'
                                type: oauth
                    resourceHosts:
                        - api.anthropic.com
                    sentinels:
                        accessToken: sk-ant-oat01-proxy-managed
                        refreshToken: sk-ant-ort01-proxy-managed
                    tokenEndpoint:
                        host: platform.claude.com
                        path: /v1/oauth/token
                phase: runtime
                service: anthropic
              description: Anthropic API access (API key or claude.ai OAuth)
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[2]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[3]
              type: com.docker.sandbox/lifecycle@1
              config:
                install:
                    - command: if [ -n "${HTTP_PROXY:-}" ]; then npm config set proxy="$HTTP_PROXY" https-proxy="${HTTPS_PROXY:-$HTTP_PROXY}"; fi
                      description: Point npm at the sandbox proxy in ~/.npmrc so pi's runtime npm use (`pi install npm:...`, `pi update`, startup package fetches) works in exec contexts that do not inherit the proxy environment variables
                      env:
                        - HTTP_PROXY
                        - HTTPS_PROXY
                      user: "1000"
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[3]
    - group:
        description: Drive pi non-interactively
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[4]
              type: com.docker.sandbox/agent-sessions@1
              config:
                prompt:
                    - -p
                    - '{{.Prompt}}'
              description: Drive pi non-interactively
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[4]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-pi:latest
                path: capabilities[5]
              type: com.docker.sandbox/agent-context@1
              config:
                filename: AGENTS.md
      declarationBlocks:
        - "3:0"
      source:
        kit: docker.io/docker/sbx-kit-pi:latest
        path: capabilities[5]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
                path: capabilities[0]
              type: com.docker.sandbox/network-policy@1
              config:
                runtime:
                    allow:
                        - api.github.com
      declarationBlocks:
        - "4:0"
      source:
        kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
        path: capabilities[0]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
                path: capabilities[1]
              type: com.docker.sandbox/lifecycle@1
              config:
                install:
                    - command: |
                        set -e

                        # Signing *machinery* stays machine-wide: it is inert unless something
                        # asks for a signature, and keeping it here means `git commit -S` works
                        # in any repository in the sandbox.
                        git config --system gpg.format ssh
                        # The key command is invoked through /bin/sh rather than executed
                        # directly. Files shipped under a kit's files/home/ tree land mode
                        # 0644 when the kit is installed from its OCI artifact -- per-file
                        # executable bits are not representable in a v2 layer (spec/OCI-v2.md)
                        # -- and git execs this value itself, so a bare path would die with
                        # "cannot exec: Permission denied" before a single one of the script's
                        # own diagnostics could run.
                        git config --system gpg.ssh.defaultKeyCommand '/bin/sh /home/agent/.config/git/ssh-signing-key-command'
                        git config --system gpg.ssh.allowedSignersFile /home/agent/.config/git/allowed_signers

                        # user.signingKey MUST stay unset: git only runs
                        # gpg.ssh.defaultKeyCommand when it is empty. Setting it to any value
                        # (even a placeholder) disables dynamic key resolution entirely.
                        git config --system --unset-all user.signingKey || true

                        # Signing *policy* is scoped, not machine-wide. Setting
                        # commit.gpgSign=true in /etc/gitconfig makes every `git commit` in the
                        # sandbox depend on a live SSH agent — including throwaway repositories
                        # created by test suites that have nothing to do with the user's work.
                        # When the forwarded agent goes away, those all fail too.
                        mkdir -p /etc/git
                        cat > /etc/git/signing-enabled.inc <<'INC'
                        # Included by /etc/gitconfig for repositories with a remote.
                        # See the git-ssh-sign kit.
                        [commit]
                        	gpgSign = true
                        [tag]
                        	gpgSign = true
                        INC
                        chmod 0644 /etc/git/signing-enabled.inc

                        # Clear anything an older version of this kit left machine-wide, so a
                        # re-install converges rather than layering.
                        git config --system --unset-all commit.gpgSign || true
                        git config --system --unset-all tag.gpgSign || true
                        git config --system --unset-all 'includeIf.hasconfig:remote.*.url:**.path' || true

                        # `includeIf "hasconfig:remote.*.url:**"` needs git >= 2.36. Probe for
                        # it rather than parsing a version string: build a throwaway repo with
                        # a remote and see whether the include actually fires. Note that `**`
                        # is only a cross-slash wildcard when it is a whole path component --
                        # `[email protected]:**` does NOT match `[email protected]:org/repo.git`, so
                        # a bare `**` ("has any remote at all") is the pattern to use here.
                        probe=$(mktemp -d)
                        git init -q "$probe"
                        git -C "$probe" remote add origin https://example.invalid/probe.git
                        printf '[commit]\n\tgpgSign = true\n' > "$probe/inc"
                        printf '[includeIf "hasconfig:remote.*.url:**"]\n\tpath = %s/inc\n' "$probe" > "$probe/sys"
                        supported=$(GIT_CONFIG_SYSTEM="$probe/sys" GIT_CONFIG_GLOBAL=/dev/null \
                            git -C "$probe" config --get commit.gpgSign 2>/dev/null || true)
                        rm -rf "$probe"

                        if [ "$supported" = "true" ]; then
                            git config --system 'includeIf.hasconfig:remote.*.url:**.path' /etc/git/signing-enabled.inc
                        else
                            # Old git: an unrecognised includeIf keyword evaluates false, which
                            # would silently disable signing. Fail closed (sign everywhere)
                            # rather than fail open (sign nothing).
                            echo "[git-ssh-sign] git $(git --version | awk '{print $3}') lacks includeIf hasconfig; enabling signing machine-wide" >&2
                            git config --system commit.gpgSign true
                            git config --system tag.gpgSign true
                        fi

                        if [ "$(git config --system --get core.hooksPath || true)" = "/home/agent/.config/git/hooks" ]; then
                            git config --system --unset-all core.hooksPath
                        fi
                      description: Configure SSH commit signing, scoped to repositories with a remote
                      user: "0"
      declarationBlocks:
        - "4:0"
      source:
        kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
        path: capabilities[1]
    - group:
        capabilities:
            - source:
                kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
                path: capabilities[2]
              type: com.docker.sandbox/agent-context@1
              config:
                contentFile: /usr/share/sandbox/kit/pi-gcp-dev/context.md.parts/1.md
      declarationBlocks:
        - "4:0"
      source:
        kit: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
        path: capabilities[2]
args:
    location:
        default: global
        description: Vertex AI endpoint location
    project:
        required: true
        description: GCP project used for Vertex AI
    version:
        default: 1.1.0
        description: Pi release to install (e.g. 1.1.0, or latest)
        pattern: ^([0-9]+\.[0-9]+\.[0-9]+|latest)$
kits:
    - ref: docker.io/docker/sbx-kit-pi:latest
      digest: sha256:7514ea9f2ce3613ea7e07cddf2aee3d8b598ef052ad68623603b20a332326a09
    - ref: docker.io/christianhkb/sbx-kit-pi-version:0.3.0
      digest: sha256:f8688c83a762ace234fdf6ab6b33c555ffc93b2847101d993a1012f4ccbd08e8
      args:
        version: ${{ kit.args.version }}
    - ref: docker.io/christianhkb/sbx-kit-pi-gcp:0.3.0
      digest: sha256:6167e4536509741b7e626a834249a66a2bd374c56f210684fef25155f6a67ec1
      args:
        location: ${{ kit.args.location }}
        project: ${{ kit.args.project }}
    - ref: docker.io/docker/sbx-kit-github-ssh:1.0.0
      digest: sha256:ff389a4245fe59e4d6812e9f3ca1219e56cad8019b370aead737f0795fb5db45
    - ref: docker.io/docker/sbx-kit-git-ssh-sign:1.0.0
      digest: sha256:79c6aaca0f08003913a68539c2105a0c4d7109b740aa2cbcadfa103b80336445