chore: archive AgentDock v1 implementation

This commit is contained in:
leefer
2026-08-24 17:14:08 +08:00
commit f512bd58ec
66 changed files with 10663 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
script_path="$(readlink -f -- "${BASH_SOURCE[0]}")"
script_dir="$(cd -- "$(dirname -- "${script_path}")" && pwd)"
deploy_dir="$(cd -- "${script_dir}/.." && pwd)"
usage() {
cat <<'EOF'
Usage:
./scripts/ai <tool> [project] [tool arguments...]
Tools:
codex, claude, codebuddy, kimi, opencode, qwen, dsh
cc-switch, multica (management commands; no project argument)
Examples:
./scripts/ai codex my-project
./scripts/ai claude my-project
./scripts/ai kimi my-project -p "explain this project"
./scripts/ai dsh my-project --profile headless "run the tests"
./scripts/ai cc-switch
./scripts/ai multica daemon status
EOF
}
if [[ $# -lt 1 ]]; then
usage
exit 2
fi
tool="$1"
shift
case "${tool}" in
codex|claude|codebuddy|kimi|opencode|qwen|dsh|cc-switch|multica) ;;
*)
printf 'Unsupported tool: %s\n\n' "${tool}" >&2
usage >&2
exit 2
;;
esac
if [[ "${tool}" == "cc-switch" || "${tool}" == "multica" ]]; then
exec docker compose --project-directory "${deploy_dir}" exec ai-tools "${tool}" "$@"
fi
project="."
if [[ $# -gt 0 && "$1" != -* ]]; then
project="$1"
shift
fi
if [[ "${project}" == /* || "${project}" == *".."* ]]; then
printf 'Project must be a path below /workspace.\n' >&2
exit 2
fi
exec docker compose --project-directory "${deploy_dir}" exec \
--workdir "/workspace/${project}" ai-tools "${tool}" "$@"
+23
View File
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -uo pipefail
tools=(codex claude codebuddy kimi opencode qwen dsh cc-switch multica)
failed=0
printf '%-12s %s\n' "TOOL" "STATUS"
printf '%-12s %s\n' "------------" "------------------------------"
for tool in "${tools[@]}"; do
if command -v "${tool}" >/dev/null 2>&1; then
printf '%-12s %s\n' "${tool}" "OK: $(command -v "${tool}")"
else
printf '%-12s %s\n' "${tool}" "MISSING"
failed=1
fi
done
printf '\nNode.js: %s\n' "$(node --version 2>/dev/null || printf 'MISSING')"
printf 'npm: %s\n' "$(npm --version 2>/dev/null || printf 'MISSING')"
printf 'Git: %s\n' "$(git --version 2>/dev/null || printf 'MISSING')"
exit "${failed}"
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
deploy_dir="${1:-$(pwd)}"
certificate_dir="${deploy_dir}/proxy/certs"
certificate_file="${certificate_dir}/agentdock.crt"
key_file="${certificate_dir}/agentdock.key"
mkdir -p "${certificate_dir}"
chmod 755 "${certificate_dir}"
if [[ -f "${certificate_file}" && -f "${key_file}" ]]; then
printf 'Existing AgentDock certificate kept: %s\n' "${certificate_file}"
exit 0
fi
openssl req -x509 -nodes -newkey rsa:2048 -sha256 -days 3650 \
-keyout "${key_file}" \
-out "${certificate_file}" \
-subj "/CN=192.168.200.36/O=AgentDock LAN" \
-addext "subjectAltName=IP:192.168.200.36" \
-addext "keyUsage=digitalSignature,keyEncipherment" \
-addext "extendedKeyUsage=serverAuth"
chmod 644 "${key_file}"
chmod 644 "${certificate_file}"
printf 'AgentDock certificate created: %s\n' "${certificate_file}"
+18
View File
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ "${MULTICA_ENABLED:-true}" != "true" ]]; then
echo "multica runtime disabled by MULTICA_ENABLED"
exec sleep infinity
fi
config_file="${HOME}/.multica/config.json"
while ! jq -e '.server_url and .workspace_id' "${config_file}" >/dev/null 2>&1; do
sleep 10
done
exec multica daemon start \
--foreground \
--no-auto-update \
--max-concurrent-tasks "${MULTICA_DAEMON_MAX_CONCURRENT_TASKS:-2}" \
--runtime-name "${MULTICA_AGENT_RUNTIME_NAME:-AgentDock Ubuntu Runtime}"
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
multica setup self-host "$@"
# setup starts a detached daemon. Supervisor will immediately replace it with
# the foreground process used for container lifecycle and clean shutdown.
multica daemon stop >/dev/null 2>&1 || true
+50
View File
@@ -0,0 +1,50 @@
#!/usr/bin/env bash
set -euo pipefail
deploy_dir="${1:-$(pwd)}"
env_file="${deploy_dir}/.env"
password_file="${deploy_dir}/.agentdock-initial-password"
if [[ ! -f "${env_file}" ]]; then
cp "${deploy_dir}/.env.example" "${env_file}"
fi
chmod 600 "${env_file}"
has_key() {
grep -q "^${1}=" "${env_file}"
}
append_value() {
local key="$1"
local value="$2"
if ! has_key "${key}"; then
printf '\n%s=%s\n' "${key}" "${value}" >> "${env_file}"
fi
}
if ! has_key "ADMIN_PASSWORD"; then
admin_password="AgentDock-$(openssl rand -hex 12)"
append_value "ADMIN_PASSWORD" "${admin_password}"
printf '%s\n' "${admin_password}" > "${password_file}"
chmod 600 "${password_file}"
fi
append_value "RUNNER_TOKEN" "$(openssl rand -base64 48 | tr -d '\n')"
append_value "CONFIG_ENCRYPTION_KEY" "$(openssl rand -base64 48 | tr -d '\n')"
append_value "CONSOLE_HTTPS_PORT" "8443"
append_value "CONSOLE_DATA_PATH" "${deploy_dir}/console-data"
append_value "AI_TOOLS_IMAGE_TAG" "0.2.0"
append_value "CONSOLE_IMAGE_TAG" "0.1.0"
append_value "AI_TOOLS_MEMORY_LIMIT" "6g"
append_value "AI_TOOLS_CPU_LIMIT" "4.0"
append_value "CONSOLE_MEMORY_LIMIT" "512m"
append_value "CONSOLE_CPU_LIMIT" "1.0"
mkdir -p "${deploy_dir}/console-data"
chmod 700 "${deploy_dir}/console-data"
printf 'AgentDock console environment is ready.\n'
if [[ -f "${password_file}" ]]; then
printf 'Initial password file: %s\n' "${password_file}"
fi
+34
View File
@@ -0,0 +1,34 @@
param(
[Parameter(Mandatory = $true)]
[string]$Server,
[Parameter(Mandatory = $true)]
[ValidateSet("codex", "claude", "codebuddy", "kimi", "opencode", "qwen", "dsh")]
[string]$Tool,
[string]$Project = ".",
[string]$Container = "ai-tools",
[string[]]$ToolArguments
)
function ConvertTo-PosixArgument {
param([string]$Value)
return "'" + $Value.Replace("'", "'`"'`"'") + "'"
}
if ($Project.StartsWith("/") -or $Project -match "(^|[\\/])\.\.([\\/]|$)") {
throw "Project must be a path below /workspace."
}
$remoteArguments = @(
"docker", "exec", "-it",
"--workdir", "/workspace/$Project",
$Container,
$Tool
) + $ToolArguments
$remoteCommand = ($remoteArguments | ForEach-Object { ConvertTo-PosixArgument $_ }) -join " "
& ssh -tt $Server $remoteCommand
exit $LASTEXITCODE
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -euo pipefail
base_url="http://127.0.0.1:${RUNNER_PORT:-4174}"
authorization="Authorization: Bearer ${RUNNER_TOKEN:?RUNNER_TOKEN is required}"
response="$(curl -fsS \
-H "${authorization}" \
-H "Content-Type: application/json" \
-d '{"tool":"codex","project":".","cols":100,"rows":30}' \
"${base_url}/sessions")"
session_id="$(printf '%s' "${response}" | jq -r '.session.id')"
test -n "${session_id}"
cleanup() {
curl -fsS -X POST \
-H "${authorization}" \
-H "Content-Type: application/json" \
-d '{}' \
"${base_url}/sessions/${session_id}/stop" >/dev/null || true
}
trap cleanup EXIT
sleep 3
curl -fsS -H "${authorization}" "${base_url}/sessions/${session_id}/output" | tail -c 500
printf '\nSESSION=%s PTY_OK\n' "${session_id}"
+31
View File
@@ -0,0 +1,31 @@
[supervisord]
nodaemon=true
pidfile=/tmp/supervisord.pid
logfile=/dev/null
logfile_maxbytes=0
[program:runner]
command=node /opt/runner/index.js
priority=10
autostart=true
autorestart=true
startsecs=2
stopasgroup=true
killasgroup=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile_maxbytes=0
[program:multica]
command=/usr/local/bin/multica-runtime
priority=20
autostart=true
autorestart=true
startsecs=2
stopasgroup=true
killasgroup=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes=0
stderr_logfile=/dev/fd/2
stderr_logfile_maxbytes=0