Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

142 linesCodeBlameRaw
1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import {
5 AGENTS,
6 AGENT_IDS,
7 AGENT_STORAGE_KEY,
8 DEFAULT_AGENT,
9 MCP_URL,
10 agentsFor,
11 agentForProviders,
12 cursorInstallLink,
13 getAgentChoice,
14 parseAgent,
15 readAgentChoice,
16 setAgentChoice,
17 subscribeAgentChoice,
18 writeAgentChoice,
19} from "./agent-setup.ts";
20
21function memory() {
22 const map = new Map<string, string>();
23 return {
24 getItem: (key: string) => map.get(key) ?? null,
25 setItem: (key: string, value: string) => void map.set(key, value),
26 map,
27 };
28}
29
30const throwing = {
31 getItem: () => {
32 throw new Error("blocked");
33 },
34 setItem: () => {
35 throw new Error("blocked");
36 },
37};
38
39test("a choice is remembered and read back", () => {
40 const store = memory();
41 assert.equal(writeAgentChoice(() => store, "codex"), true);
42 assert.equal(store.map.get(AGENT_STORAGE_KEY), "codex");
43 assert.equal(readAgentChoice(() => store), "codex");
44});
45
46test("no choice, an unknown one, or storage that throws falls back to the default", () => {
47 assert.equal(readAgentChoice(() => memory()), DEFAULT_AGENT);
48 const store = memory();
49 store.setItem(AGENT_STORAGE_KEY, "notepad");
50 assert.equal(readAgentChoice(() => store), DEFAULT_AGENT);
51 assert.equal(readAgentChoice(() => throwing), DEFAULT_AGENT);
52 assert.equal(readAgentChoice(() => null), DEFAULT_AGENT);
53 assert.equal(
54 readAgentChoice(() => {
55 throw new Error("no localStorage");
56 }),
57 DEFAULT_AGENT,
58 );
59 assert.equal(writeAgentChoice(() => throwing, "cursor"), false);
60 assert.equal(writeAgentChoice(() => null, "cursor"), false);
61});
62
63test("every toggle on the page follows the last choice", () => {
64 const store = memory();
65 let heard = 0;
66 const stop = subscribeAgentChoice(() => heard++);
67 setAgentChoice("opencode", () => store);
68 assert.equal(getAgentChoice(), "opencode");
69 assert.equal(store.map.get(AGENT_STORAGE_KEY), "opencode");
70 assert.equal(heard, 1);
71 // Storage that refuses still changes the page.
72 setAgentChoice("cursor", () => throwing);
73 assert.equal(getAgentChoice(), "cursor");
74 assert.equal(heard, 2);
75 stop();
76 setAgentChoice("codex", () => store);
77 assert.equal(heard, 2);
78});
79
80test("parseAgent accepts only known agents", () => {
81 for (const id of AGENT_IDS) assert.equal(parseAgent(id), id);
82 assert.equal(parseAgent("Claude Code"), null);
83 assert.equal(parseAgent(null), null);
84});
85
86test("every snippet points at the MCP server", () => {
87 // Claude Code's is g1t's plugin, which adds the server itself.
88 for (const id of AGENT_IDS) if (id !== "claude-code") assert.ok(AGENTS[id].code.includes(MCP_URL), id);
89 assert.match(AGENTS["claude-code"].code, /^claude plugin marketplace add https:\/\/g1t\.sh\/flagon-io\/g1t-plugins\.git\nclaude plugin install g1t@g1t$/);
90 assert.match(AGENTS["claude-code"].then, /plugin:g1t:g1t/);
91 assert.deepEqual(JSON.parse(AGENTS.cursor.code), { mcpServers: { g1t: { url: MCP_URL } } });
92 assert.equal(JSON.parse(AGENTS.opencode.code).mcp.g1t.type, "remote");
93 const config = new URL(cursorInstallLink()).searchParams.get("config");
94 assert.deepEqual(JSON.parse(atob(config ?? "")), { url: MCP_URL });
95});
96
97test("the snippets can point at another MCP server", () => {
98 const mcp = "http://localhost:8790/mcp";
99 const agents = agentsFor(mcp);
100 for (const id of AGENT_IDS) {
101 assert.ok(agents[id].code.includes(mcp), id);
102 assert.ok(!agents[id].code.includes(MCP_URL), id);
103 }
104 const config = new URL(cursorInstallLink(mcp)).searchParams.get("config");
105 assert.deepEqual(JSON.parse(atob(config ?? "")), { url: mcp });
106});
107
108test("the first configured provider supplies the default without reordering", () => {
109 assert.equal(agentForProviders([]), DEFAULT_AGENT);
110 assert.equal(agentForProviders([{ provider: "openai" }]), "codex");
111 assert.equal(agentForProviders([{ provider: "anthropic" }]), "claude-code");
112 assert.equal(agentForProviders([{ provider: "gemini" }]), "gemini");
113 assert.equal(agentForProviders([{ provider: "xai" }]), "grok");
114 assert.equal(agentForProviders([{ provider: "openai_endpoint" }]), "open-webui");
115 assert.equal(agentForProviders([{ provider: "openrouter" }, { provider: "openai" }]), "opencode");
116 assert.equal(agentForProviders([{ provider: "openai" }, { provider: "anthropic" }]), "codex");
117 assert.equal(agentForProviders([{ provider: "anthropic_endpoint" }]), "claude-code");
118 assert.equal(agentForProviders([{ provider: "azure_openai" }]), "codex");
119});
120
121test("explicit choices beat provider defaults, and defaults are not saved as choices", () => {
122 const store = memory();
123 assert.equal(readAgentChoice(() => store, "codex"), "codex");
124 assert.equal(readAgentChoice(() => store, "gemini"), "gemini");
125 assert.equal(store.map.size, 0);
126 writeAgentChoice(() => store, "cursor");
127 assert.equal(readAgentChoice(() => store, "codex"), "cursor");
128 assert.equal(readAgentChoice(() => throwing, "gemini"), "gemini");
129});
130
131test("chat clients have distinct setup instructions and LibreChat uses per-user OAuth", () => {
132 for (const id of ["claude-chat", "grok", "open-webui"] as const) {
133 assert.equal(AGENTS[id].lang, "text");
134 assert.equal(AGENTS[id].code, MCP_URL);
135 }
136 assert.match(AGENTS.grok.then, /New Connector > Custom/);
137 assert.match(AGENTS["claude-chat"].then, /Register automatically/);
138 assert.match(AGENTS["open-webui"].then, /OAuth 2.1/);
139 assert.match(AGENTS.librechat.code, /type: streamable-http/);
140 assert.match(AGENTS.librechat.code, /requiresOAuth: true/);
141 assert.ok(!AGENTS.librechat.code.includes("Bearer"));
142});