chore: retire unmaintained workspace runtimes
ci-arm64-advisory / fast-checks (pull_request) Waiting to run
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Successful in 9s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
Check migration collisions / Migration version collision check (pull_request) Successful in 10s
CI / Detect changes (pull_request) Successful in 7s
CI / Python Lint & Test (pull_request) Successful in 5s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 7s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 5s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 10s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Has been skipped
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 4s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Successful in 33s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Successful in 50s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 8s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 58s
gate-check-v3 / gate-check (pull_request) Successful in 4s
qa-review / approved (pull_request) Successful in 3s
security-review / approved (pull_request) Successful in 3s
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 4s
sop-checklist / review-refire (pull_request) Has been skipped
sop-tier-check / tier-check (pull_request) Successful in 4s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 1m6s
E2E Staging External Runtime / E2E Staging External Runtime (pull_request) Successful in 5m25s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 20s
E2E Chat / E2E Chat (pull_request) Successful in 33s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 11s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 1m58s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m44s
Harness Replays / Harness Replays (pull_request) Successful in 6s
CI / Platform (Go) (pull_request) Successful in 6m9s
CI / Canvas (Next.js) (pull_request) Successful in 7m41s
CI / all-required (pull_request) Successful in 32m0s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
audit-force-merge / audit (pull_request) Successful in 32s

This commit is contained in:
claude-ceo-assistant
2026-05-23 23:33:21 -07:00
parent 2e027df890
commit f7e2976324
54 changed files with 256 additions and 400 deletions
+4 -8
View File
@@ -301,16 +301,13 @@ export function deriveProvidersFromModels(models: ModelSpec[]): string[] {
// config.yaml` on the container is a separate runtime-internal file,
// not this one.
const RUNTIMES_WITH_OWN_CONFIG = new Set<string>(["external", "kimi", "kimi-cli", "openclaw"]);
const SUPPORTED_RUNTIME_VALUES = new Set(["claude-code", "codex", "openclaw", "hermes"]);
const FALLBACK_RUNTIME_OPTIONS: RuntimeOption[] = [
{ value: "", label: "LangGraph (default)", models: [], providers: [] },
{ value: "claude-code", label: "Claude Code", models: [], providers: [] },
{ value: "crewai", label: "CrewAI", models: [], providers: [] },
{ value: "autogen", label: "AutoGen", models: [], providers: [] },
{ value: "deepagents", label: "DeepAgents", models: [], providers: [] },
{ value: "codex", label: "Codex", models: [], providers: [] },
{ value: "openclaw", label: "OpenClaw", models: [], providers: [] },
{ value: "hermes", label: "Hermes", models: [], providers: [] },
{ value: "gemini-cli", label: "Gemini CLI", models: [], providers: [] },
];
export function ConfigTab({ workspaceId }: Props) {
@@ -499,10 +496,9 @@ export function ConfigTab({ workspaceId }: Props) {
.then((rows) => {
if (cancelled || !Array.isArray(rows)) return;
const byRuntime = new Map<string, RuntimeOption>();
byRuntime.set("", { value: "", label: "LangGraph (default)", models: [], providers: [] });
for (const r of rows) {
const v = (r.runtime || "").trim();
if (!v || v === "langgraph") continue;
if (!SUPPORTED_RUNTIME_VALUES.has(v)) continue;
// Last template wins if two templates share a runtime — rare, and the
// one with the richer models list is probably newer.
const existing = byRuntime.get(v);
@@ -512,7 +508,7 @@ export function ConfigTab({ workspaceId }: Props) {
byRuntime.set(v, { value: v, label: r.name || v, models, providers });
}
}
if (byRuntime.size > 1) setRuntimeOptions(Array.from(byRuntime.values()));
if (byRuntime.size > 0) setRuntimeOptions(Array.from(byRuntime.values()));
})
.catch(() => { /* keep fallback */ });
return () => { cancelled = true; };
@@ -12,47 +12,35 @@ import { resolveRuntime } from "../deploy-preflight";
describe("resolveRuntime", () => {
describe("explicit runtime-map entries", () => {
it('maps "langgraph" to "langgraph"', () => {
expect(resolveRuntime("langgraph")).toBe("langgraph");
});
it('maps "claude-code-default" to "claude-code"', () => {
expect(resolveRuntime("claude-code-default")).toBe("claude-code");
});
it('maps "codex" to "codex"', () => {
expect(resolveRuntime("codex")).toBe("codex");
});
it('maps "hermes" to "hermes"', () => {
expect(resolveRuntime("hermes")).toBe("hermes");
});
it('maps "openclaw" to "openclaw"', () => {
expect(resolveRuntime("openclaw")).toBe("openclaw");
});
it('maps "deepagents" to "deepagents"', () => {
expect(resolveRuntime("deepagents")).toBe("deepagents");
});
it('maps "crewai" to "crewai"', () => {
expect(resolveRuntime("crewai")).toBe("crewai");
});
it('maps "autogen" to "autogen"', () => {
expect(resolveRuntime("autogen")).toBe("autogen");
});
});
describe("identity fallback for modern template ids", () => {
it("returns the id unchanged when not in the map", () => {
expect(resolveRuntime("hermes")).toBe("hermes");
});
it("strips trailing -default suffix as fallback", () => {
expect(resolveRuntime("hermes-default")).toBe("hermes");
});
it("strips -default only when it is the suffix", () => {
// "default-something" should NOT strip
expect(resolveRuntime("default-langgraph")).toBe("default-langgraph");
expect(resolveRuntime("default-custom")).toBe("default-custom");
});
it("returns the id unchanged when id has no -default suffix", () => {
expect(resolveRuntime("gemini-cli")).toBe("gemini-cli");
expect(resolveRuntime("custom-runtime")).toBe("custom-runtime");
});
it("handles custom template ids from community templates", () => {
@@ -13,11 +13,9 @@ import { runtimeDisplayName } from "../runtime-names";
describe("runtimeDisplayName", () => {
it.each([
["claude-code", "Claude Code"],
["langgraph", "LangGraph"],
["deepagents", "DeepAgents"],
["codex", "Codex"],
["hermes", "Hermes"],
["openclaw", "OpenClaw"],
["crewai", "CrewAI"],
["autogen", "AutoGen"],
])("known runtime %q maps to %q", (input, expected) => {
expect(runtimeDisplayName(input)).toBe(expected);
});
@@ -25,7 +23,6 @@ describe("runtimeDisplayName", () => {
it("unknown runtime falls back to the input string verbatim", () => {
// A future runtime not yet in the lookup map should render with
// its own id — better than a generic placeholder for ops debugging.
expect(runtimeDisplayName("hermes")).toBe("hermes");
expect(runtimeDisplayName("custom-runtime-9000")).toBe(
"custom-runtime-9000",
);
@@ -43,6 +40,6 @@ describe("runtimeDisplayName", () => {
// the input "for safety" doesn't silently change behavior — the
// upstream slug is already normalized lowercase.
expect(runtimeDisplayName("Claude-Code")).toBe("Claude-Code");
expect(runtimeDisplayName("LANGGRAPH")).toBe("LANGGRAPH");
expect(runtimeDisplayName("CODEX")).toBe("CODEX");
});
});
+2 -4
View File
@@ -63,12 +63,10 @@ export interface Template extends TemplateLike {
* id needs a non-identity mapping. */
export function resolveRuntime(templateId: string): string {
const runtimeMap: Record<string, string> = {
langgraph: "langgraph",
"claude-code-default": "claude-code",
codex: "codex",
hermes: "hermes",
openclaw: "openclaw",
deepagents: "deepagents",
crewai: "crewai",
autogen: "autogen",
};
return runtimeMap[templateId] ?? templateId.replace(/-default$/, "");
}
+2 -4
View File
@@ -4,11 +4,9 @@
const RUNTIME_NAMES: Record<string, string> = {
"claude-code": "Claude Code",
langgraph: "LangGraph",
deepagents: "DeepAgents",
codex: "Codex",
hermes: "Hermes",
openclaw: "OpenClaw",
crewai: "CrewAI",
autogen: "AutoGen",
kimi: "Kimi",
"kimi-cli": "Kimi CLI",
};
+1 -1
View File
@@ -49,7 +49,7 @@ export interface RuntimeProfile {
}
/** The floor every runtime inherits unless it overrides. Calibrated for
* docker-local fast runtimes (claude-code, langgraph, crewai) where cold
* docker-local fast runtimes (claude-code, codex, openclaw) where cold
* boot is 30-90s. */
export const DEFAULT_RUNTIME_PROFILE: Required<
Pick<RuntimeProfile, "provisionTimeoutMs">