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.

178 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(
42 writeAgentChoice(() => store, "codex"),
43 true,
44 );
45 assert.equal(store.map.get(AGENT_STORAGE_KEY), "codex");
46 assert.equal(
47 readAgentChoice(() => store),
48 "codex",
49 );
50});
51
52test("no choice, an unknown one, or storage that throws falls back to the default", () => {
53 assert.equal(
54 readAgentChoice(() => memory()),
55 DEFAULT_AGENT,
56 );
57 const store = memory();
58 store.setItem(AGENT_STORAGE_KEY, "notepad");
59 assert.equal(
60 readAgentChoice(() => store),
61 DEFAULT_AGENT,
62 );
63 assert.equal(
64 readAgentChoice(() => throwing),
65 DEFAULT_AGENT,
66 );
67 assert.equal(
68 readAgentChoice(() => null),
69 DEFAULT_AGENT,
70 );
71 assert.equal(
72 readAgentChoice(() => {
73 throw new Error("no localStorage");
74 }),
75 DEFAULT_AGENT,
76 );
77 assert.equal(
78 writeAgentChoice(() => throwing, "cursor"),
79 false,
80 );
81 assert.equal(
82 writeAgentChoice(() => null, "cursor"),
83 false,
84 );
85});
86
87test("every toggle on the page follows the last choice", () => {
88 const store = memory();
89 let heard = 0;
90 const stop = subscribeAgentChoice(() => heard++);
91 setAgentChoice("opencode", () => store);
92 assert.equal(getAgentChoice(), "opencode");
93 assert.equal(store.map.get(AGENT_STORAGE_KEY), "opencode");
94 assert.equal(heard, 1);
95 // Storage that refuses still changes the page.
96 setAgentChoice("cursor", () => throwing);
97 assert.equal(getAgentChoice(), "cursor");
98 assert.equal(heard, 2);
99 stop();
100 setAgentChoice("codex", () => store);
101 assert.equal(heard, 2);
102});
103
104test("parseAgent accepts only known agents", () => {
105 for (const id of AGENT_IDS) assert.equal(parseAgent(id), id);
106 assert.equal(parseAgent("Claude Code"), null);
107 assert.equal(parseAgent(null), null);
108});
109
110test("every snippet points at the MCP server", () => {
111 // Claude Code's is g1t's plugin, which adds the server itself.
112 for (const id of AGENT_IDS) if (id !== "claude-code") assert.ok(AGENTS[id].code.includes(MCP_URL), id);
113 assert.match(AGENTS["claude-code"].code, /^claude plugin marketplace add https:\/\/g1t\.sh\/flagon-io\/g1t-plugins\.git\nclaude plugin install g1t@g1t$/);
114 assert.match(AGENTS["claude-code"].then, /plugin:g1t:g1t/);
115 assert.deepEqual(JSON.parse(AGENTS.cursor.code), { mcpServers: { g1t: { url: MCP_URL } } });
116 assert.equal(JSON.parse(AGENTS.opencode.code).mcp.g1t.type, "remote");
117 const config = new URL(cursorInstallLink()).searchParams.get("config");
118 assert.deepEqual(JSON.parse(atob(config ?? "")), { url: MCP_URL });
119});
120
121test("the snippets can point at another MCP server", () => {
122 const mcp = "http://localhost:8790/mcp";
123 const agents = agentsFor(mcp);
124 for (const id of AGENT_IDS) {
125 assert.ok(agents[id].code.includes(mcp), id);
126 assert.ok(!agents[id].code.includes(MCP_URL), id);
127 }
128 const config = new URL(cursorInstallLink(mcp)).searchParams.get("config");
129 assert.deepEqual(JSON.parse(atob(config ?? "")), { url: mcp });
130});
131
132test("the first configured provider supplies the default without reordering", () => {
133 assert.equal(agentForProviders([]), DEFAULT_AGENT);
134 assert.equal(agentForProviders([{ provider: "openai" }]), "codex");
135 assert.equal(agentForProviders([{ provider: "anthropic" }]), "claude-code");
136 assert.equal(agentForProviders([{ provider: "gemini" }]), "gemini");
137 assert.equal(agentForProviders([{ provider: "xai" }]), "grok");
138 assert.equal(agentForProviders([{ provider: "openai_endpoint" }]), "open-webui");
139 assert.equal(agentForProviders([{ provider: "openrouter" }, { provider: "openai" }]), "opencode");
140 assert.equal(agentForProviders([{ provider: "openai" }, { provider: "anthropic" }]), "codex");
141 assert.equal(agentForProviders([{ provider: "anthropic_endpoint" }]), "claude-code");
142 assert.equal(agentForProviders([{ provider: "azure_openai" }]), "codex");
143});
144
145test("explicit choices beat provider defaults, and defaults are not saved as choices", () => {
146 const store = memory();
147 assert.equal(
148 readAgentChoice(() => store, "codex"),
149 "codex",
150 );
151 assert.equal(
152 readAgentChoice(() => store, "gemini"),
153 "gemini",
154 );
155 assert.equal(store.map.size, 0);
156 writeAgentChoice(() => store, "cursor");
157 assert.equal(
158 readAgentChoice(() => store, "codex"),
159 "cursor",
160 );
161 assert.equal(
162 readAgentChoice(() => throwing, "gemini"),
163 "gemini",
164 );
165});
166
167test("chat clients have distinct setup instructions and LibreChat uses per-user OAuth", () => {
168 for (const id of ["claude-chat", "grok", "open-webui"] as const) {
169 assert.equal(AGENTS[id].lang, "text");
170 assert.equal(AGENTS[id].code, MCP_URL);
171 }
172 assert.match(AGENTS.grok.then, /New Connector > Custom/);
173 assert.match(AGENTS["claude-chat"].then, /Register automatically/);
174 assert.match(AGENTS["open-webui"].then, /OAuth 2.1/);
175 assert.match(AGENTS.librechat.code, /type: streamable-http/);
176 assert.match(AGENTS.librechat.code, /requiresOAuth: true/);
177 assert.ok(!AGENTS.librechat.code.includes("Bearer"));
178});