Sign inSign up

simonferquel/pi-hsp-kit:latest

Manifest digest

sha256:abad8082b0acf8992f910daed43e7862bfef142904e59179bcb2ad0e80238537

Last pushed

20 days by simonferquel

Type

Sandbox Kit

Manifest digest

sha256:abad8082b0acf8992f910daed43e7862bfef142904e59179bcb2ad0e80238537

yaml
schemaVersion: "2"
kind: sandbox
name: pi-hsp-kit
displayName: Pi (HSP Steering)
description: HSP-capable variant of simonferquel-clanker/pi-agent-mcp-kit -- the same `pi` terminal coding agent (with pi-mcp-adapter's hosted MCP gateway self-registration) plus this repo's pi-hsp extension baked into the image, wired up so the session declares Harness Steering Protocol (hsp/1) support. Built to test/demo the Agentic Platform's custom-kit-only HSP capability (APT-1382).
sandbox:
    image: docker.io/simonferquel/pi-hsp-base:latest
    entrypoint:
        - pi
    command:
        default:
            - -e
            - /opt/pi-hsp/src/index.ts
        interactive:
            - -e
            - /opt/pi-hsp/src/index.ts
agentInstructions:
    filename: AGENTS.md
permissions:
    network:
        allow:
            - api.anthropic.com
            - registry.npmjs.org
            - platform.claude.com:443
credentials:
    - service: anthropic
      apiKey:
        name: ANTHROPIC_API_KEY
        proxyManaged: true
        inject:
            - domain: api.anthropic.com
              header: x-api-key
              format: '%s'
      oauth:
        tokenEndpoint:
            host: platform.claude.com
            path: /v1/oauth/token
        resourceHosts:
            - api.anthropic.com
        sentinels:
            accessToken: sk-ant-oat01-proxy-managed
            refreshToken: sk-ant-ort01-proxy-managed
        credentialFile:
            path: ~/.pi/agent/auth.json
            structure:
                anthropic:
                    access: '{{.AccessToken}}'
                    expires: '{{.ExpiresAt}}'
                    refresh: '{{.RefreshToken}}'
                    type: oauth
setup:
    install:
        - command: if [ -n "${HTTP_PROXY:-}" ]; then npm config set proxy="$HTTP_PROXY" https-proxy="${HTTPS_PROXY:-$HTTP_PROXY}"; fi
          user: "1000"
          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
    startup:
        - command:
            - sh
            - -c
            - |
              set -e
              [ -n "${MCP_GATEWAY_URL:-}" ] || exit 0
              MCP_GATEWAY_URL="$MCP_GATEWAY_URL" MCP_SENTINEL_TOKEN_NAME="${MCP_SENTINEL_TOKEN_NAME:-mcp-gateway}" node <<'NODEEOF'
              'use strict';
              const fs = require('fs');
              const os = require('os');
              const path = require('path');

              const gatewayUrl = process.env.MCP_GATEWAY_URL;
              const tokenName = process.env.MCP_SENTINEL_TOKEN_NAME;
              const configPath = path.join(os.homedir(), '.pi', 'agent', 'mcp.json');

              let config = {};
              try {
                if (fs.existsSync(configPath)) {
                  const raw = fs.readFileSync(configPath, 'utf8');
                  const parsed = raw.trim() ? JSON.parse(raw) : {};
                  if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
                    config = parsed;
                  }
                }
              } catch (err) {
                process.stderr.write('pi-hsp-kit: mcp.json unreadable, skipping gateway registration: ' + err.message + '\n');
                process.exit(0);
              }

              if (typeof config.mcpServers !== 'object' || config.mcpServers === null || Array.isArray(config.mcpServers)) {
                config.mcpServers = {};
              }

              config.mcpServers['mcp-gateway'] = {
                url: gatewayUrl,
                headers: { Authorization: 'Bearer ' + tokenName },
                lifecycle: 'eager',
              };

              fs.mkdirSync(path.dirname(configPath), { recursive: true });
              const tmpPath = configPath + '.tmp';
              fs.writeFileSync(tmpPath, JSON.stringify(config, null, 2) + '\n');
              fs.renameSync(tmpPath, configPath);
              NODEEOF
          user: "1000"
          description: Register the sandbox's hosted MCP gateway (when reserved) as a remote MCP server in pi-mcp-adapter's ~/.pi/agent/mcp.json; no-op when no gateway is reserved