mirror of
https://github.com/MoonshotAI/kimi-code.git
synced 2026-08-03 21:45:27 +00:00
* feat(klient): contract-driven facade with http/ipc/memory transports - add zod-validated contract sections (global/session/agent) under src/contract and a facade exposing global.*, session(id).*, agent(id).* - select transport once at creation via subpath entries (@moonshot-ai/klient/http|ipc|memory); drop legacy channel/client/ httpChannel/wsChannel/wsKlient/proxy implementations - absorb packages/server-e2e into packages/klient test/e2e suites (dual-backend, legacy v1, v2 wire) and remove the server-e2e workspace - expose model registry and catalog services on kap-server v2 RPC surface * fix(klient): derive session status from agentActivityView The engine retired its sessionActivity service in #1751 (session busy is now derived from agent activity views), but the facade still called the deleted wire channel and imported the deleted engine module, breaking typecheck and every klient suite at import time. - drop the sessionActivity contract/registry entries and mirror the agentActivityView service instead (agent scope) - compose session status() client-side from the pending interaction lists and each agent's agentActivityView, keeping the retired service's precedence and typing SessionStatus locally in the facade - replace the deleted-channel call in the v2 smoke suite with a sessionInteractionService probe - fix the legacy image-file suite to wait with the harness's waitForSessionBusy
187 lines
6.8 KiB
Bash
Executable file
187 lines
6.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
PACKAGE_DIR="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
|
REPO_ROOT="$(cd -- "${PACKAGE_DIR}/../.." && pwd)"
|
|
|
|
workspace_slug="$(
|
|
basename -- "${REPO_ROOT}" \
|
|
| tr '[:upper:]' '[:lower:]' \
|
|
| tr -cs 'a-z0-9_.-' '-' \
|
|
| sed -e 's/^[^a-z0-9]*//' -e 's/[^a-z0-9]*$//' \
|
|
| cut -c1-48
|
|
)"
|
|
if [[ -z "${workspace_slug}" ]]; then
|
|
workspace_slug="workspace"
|
|
fi
|
|
workspace_hash="$(printf '%s' "${REPO_ROOT}" | cksum | awk '{print $1}')"
|
|
RUN_ID="${KIMI_SERVER_E2E_RUN_ID:-${workspace_slug}-${workspace_hash}}"
|
|
|
|
BASE_IMAGE="${KIMI_SERVER_E2E_BASE_IMAGE:-kimi-server-e2e-base:${RUN_ID}}"
|
|
IMAGE="${KIMI_SERVER_E2E_IMAGE:-kimi-server-e2e:${RUN_ID}}"
|
|
CONTAINER="${KIMI_SERVER_E2E_CONTAINER:-kimi-server-e2e-${RUN_ID}}"
|
|
STATE_ROOT="${KIMI_SERVER_E2E_STATE_ROOT:-${HOME}/.kimi-code-server-dev}"
|
|
PORT="${KIMI_SERVER_E2E_PORT:-58627}"
|
|
|
|
KIMI_HOME_HOST="${KIMI_SERVER_E2E_KIMI_HOME_HOST:-${STATE_ROOT}/docker-e2e/${RUN_ID}/kimi-code-home}"
|
|
KIMI_HOME_CONTAINER="/data/docker-e2e/kimi-code-home"
|
|
SEED_HOME_HOST="${KIMI_SERVER_E2E_SEED_KIMI_HOME_HOST:-${STATE_ROOT}/kimi-home/kimi-code-home}"
|
|
|
|
if [[ -n "${KIMI_SERVER_E2E_REPORT_DIR_HOST:-}" ]]; then
|
|
REPORT_DIR_HOST="${KIMI_SERVER_E2E_REPORT_DIR_HOST}"
|
|
REPORT_ROOT_HOST="$(dirname -- "${REPORT_DIR_HOST}")"
|
|
REPORT_DIR_NAME="$(basename -- "${REPORT_DIR_HOST}")"
|
|
else
|
|
REPORT_ROOT_HOST="${KIMI_SERVER_E2E_REPORT_ROOT_HOST:-${STATE_ROOT}/server-e2e-reports/docker/${RUN_ID}}"
|
|
REPORT_DIR_NAME="latest"
|
|
REPORT_DIR_HOST="${REPORT_ROOT_HOST}/${REPORT_DIR_NAME}"
|
|
fi
|
|
REPORT_ROOT_CONTAINER="/data/server-e2e-reports/docker"
|
|
REPORT_DIR_CONTAINER="${REPORT_ROOT_CONTAINER}/${REPORT_DIR_NAME}"
|
|
TMPDIR_CONTAINER="/data/docker-e2e/tmp"
|
|
|
|
NM_ROOT="${STATE_ROOT}/docker-e2e/${RUN_ID}/nm"
|
|
|
|
workspace_node_modules=(
|
|
"root:/workspace/kimi-code/node_modules"
|
|
"apps_kimi-code:/workspace/kimi-code/apps/kimi-code/node_modules"
|
|
"apps_kimi-web:/workspace/kimi-code/apps/kimi-web/node_modules"
|
|
"apps_vis:/workspace/kimi-code/apps/vis/node_modules"
|
|
"apps_vis_server:/workspace/kimi-code/apps/vis/server/node_modules"
|
|
"apps_vis_web:/workspace/kimi-code/apps/vis/web/node_modules"
|
|
"docs:/workspace/kimi-code/docs/node_modules"
|
|
"pkg_acp-adapter:/workspace/kimi-code/packages/acp-adapter/node_modules"
|
|
"pkg_agent-core:/workspace/kimi-code/packages/agent-core/node_modules"
|
|
"pkg_kap-server:/workspace/kimi-code/packages/kap-server/node_modules"
|
|
"pkg_server-e2e:/workspace/kimi-code/packages/klient/node_modules"
|
|
"pkg_kaos:/workspace/kimi-code/packages/kaos/node_modules"
|
|
"pkg_kosong:/workspace/kimi-code/packages/kosong/node_modules"
|
|
"pkg_migration-legacy:/workspace/kimi-code/packages/migration-legacy/node_modules"
|
|
"pkg_node-sdk:/workspace/kimi-code/packages/node-sdk/node_modules"
|
|
"pkg_oauth:/workspace/kimi-code/packages/oauth/node_modules"
|
|
"pkg_protocol:/workspace/kimi-code/packages/protocol/node_modules"
|
|
"pkg_services:/workspace/kimi-code/packages/services/node_modules"
|
|
"pkg_telemetry:/workspace/kimi-code/packages/telemetry/node_modules"
|
|
)
|
|
|
|
mkdir -p "${STATE_ROOT}" "${KIMI_HOME_HOST}" "${REPORT_DIR_HOST}" "${NM_ROOT}"
|
|
for mount in "${workspace_node_modules[@]}"; do
|
|
mkdir -p "${NM_ROOT}/${mount%%:*}"
|
|
done
|
|
|
|
# Seed only auth/config into the isolated docker-e2e home. Never copy server
|
|
# locks, sessions, uploaded files, or reports from the compose server home.
|
|
if [[ -f "${SEED_HOME_HOST}/config.toml" && ! -f "${KIMI_HOME_HOST}/config.toml" ]]; then
|
|
cp "${SEED_HOME_HOST}/config.toml" "${KIMI_HOME_HOST}/config.toml"
|
|
fi
|
|
if [[ -d "${SEED_HOME_HOST}/credentials" && ! -d "${KIMI_HOME_HOST}/credentials" ]]; then
|
|
cp -R "${SEED_HOME_HOST}/credentials" "${KIMI_HOME_HOST}/credentials"
|
|
fi
|
|
|
|
if [[ "${KIMI_SERVER_E2E_SKIP_BUILD:-0}" != "1" ]]; then
|
|
docker build -t "${BASE_IMAGE}" -f "${REPO_ROOT}/Dockerfile" "${REPO_ROOT}"
|
|
docker build \
|
|
-t "${IMAGE}" \
|
|
-f "${PACKAGE_DIR}/Dockerfile" \
|
|
--build-arg "BASE_IMAGE=${BASE_IMAGE}" \
|
|
"${REPO_ROOT}"
|
|
fi
|
|
|
|
docker rm -f "${CONTAINER}" >/dev/null 2>&1 || true
|
|
|
|
read -r -d '' container_script <<'EOS' || true
|
|
set -euo pipefail
|
|
|
|
cd /workspace/kimi-code
|
|
mkdir -p "${KIMI_CODE_HOME}/server" "${KIMI_SERVER_E2E_REPORT_DIR}" "${TMPDIR}" /data/server-e2e-reports/docker
|
|
rm -f "${KIMI_CODE_HOME}/server/lock"
|
|
|
|
if [[ ! -e /workspace/kimi-code/node_modules/.modules.yaml || ! -e /workspace/kimi-code/packages/klient/node_modules/ws ]]; then
|
|
echo "[server-e2e:docker] installing pnpm deps"
|
|
pnpm install --frozen-lockfile
|
|
else
|
|
echo "[server-e2e:docker] pnpm deps already present"
|
|
fi
|
|
|
|
server_log="/data/server-e2e-reports/docker/server.log"
|
|
: > "${server_log}"
|
|
|
|
echo "[server-e2e:docker] starting server on container-local ${KIMI_SERVER_URL}"
|
|
pnpm dev:server -- \
|
|
--host 127.0.0.1 \
|
|
--port "${KIMI_SERVER_E2E_PORT}" \
|
|
--log-level debug \
|
|
--debug-endpoints \
|
|
>"${server_log}" 2>&1 &
|
|
server_pid=$!
|
|
|
|
cleanup() {
|
|
status=$?
|
|
if kill -0 "${server_pid}" >/dev/null 2>&1; then
|
|
kill "${server_pid}" >/dev/null 2>&1 || true
|
|
wait "${server_pid}" >/dev/null 2>&1 || true
|
|
fi
|
|
exit "${status}"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
ready=0
|
|
for attempt in $(seq 1 90); do
|
|
if curl -fsS "${KIMI_SERVER_URL}/api/v1/meta" >/tmp/server-meta.json 2>/tmp/server-curl.err; then
|
|
ready=1
|
|
echo "[server-e2e:docker] server ready: $(cat /tmp/server-meta.json)"
|
|
break
|
|
fi
|
|
if ! kill -0 "${server_pid}" >/dev/null 2>&1; then
|
|
echo "[server-e2e:docker] server exited before readiness" >&2
|
|
tail -n 200 "${server_log}" >&2 || true
|
|
exit 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
|
|
if [[ "${ready}" != "1" ]]; then
|
|
echo "[server-e2e:docker] server did not become ready within 90s" >&2
|
|
cat /tmp/server-curl.err >&2 || true
|
|
tail -n 200 "${server_log}" >&2 || true
|
|
exit 1
|
|
fi
|
|
|
|
cd /workspace/kimi-code/packages/klient
|
|
pnpm test
|
|
EOS
|
|
|
|
docker_args=(
|
|
run
|
|
--rm
|
|
--init
|
|
--name "${CONTAINER}"
|
|
--workdir /workspace/kimi-code/packages/klient
|
|
--env "KIMI_CODE_HOME=${KIMI_HOME_CONTAINER}"
|
|
--env "KIMI_SERVER_E2E_PORT=${PORT}"
|
|
--env "KIMI_SERVER_URL=http://127.0.0.1:${PORT}"
|
|
--env "KIMI_SERVER_E2E_REPORT_DIR=${REPORT_DIR_CONTAINER}"
|
|
--env "TMPDIR=${TMPDIR_CONTAINER}"
|
|
--env "TERM=xterm-256color"
|
|
--env "TZ=Asia/Shanghai"
|
|
--env "npm_config_store_dir=/workspace/kimi-code/node_modules/.pnpm-store"
|
|
--env "npm_config_package_import_method=copy"
|
|
--volume "${REPO_ROOT}:/workspace/kimi-code:ro"
|
|
--volume "${KIMI_HOME_HOST}:${KIMI_HOME_CONTAINER}"
|
|
--volume "${REPORT_ROOT_HOST}:${REPORT_ROOT_CONTAINER}"
|
|
)
|
|
|
|
for mount in "${workspace_node_modules[@]}"; do
|
|
docker_args+=(--volume "${NM_ROOT}/${mount%%:*}:${mount#*:}")
|
|
done
|
|
|
|
echo "[server-e2e:docker] running ${IMAGE} without host port publishing"
|
|
set +e
|
|
docker "${docker_args[@]}" "${IMAGE}" bash -lc "${container_script}"
|
|
status=$?
|
|
set -e
|
|
|
|
echo "[server-e2e:docker] report: ${REPORT_DIR_HOST}/index.html"
|
|
echo "[server-e2e:docker] server log: ${REPORT_ROOT_HOST}/server.log"
|
|
exit "${status}"
|