@kenkaiiii/ggcoder 5.74.3 → 5.75.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +1 -1
  2. package/assets/skills/bulletproof/SKILL.md +1 -1
  3. package/assets/skills/clarify/SKILL.md +1 -1
  4. package/assets/skills/code-review/SKILL.md +1 -1
  5. package/assets/skills/compliance-guard/SKILL.md +1 -1
  6. package/assets/skills/durable/SKILL.md +1 -1
  7. package/assets/skills/evidence-led-ui/SKILL.md +1 -1
  8. package/assets/skills/lean/SKILL.md +1 -1
  9. package/assets/skills/refactoring/SKILL.md +1 -1
  10. package/assets/skills/root-cause/SKILL.md +1 -1
  11. package/assets/skills/shared-language/SKILL.md +1 -1
  12. package/assets/skills/tdd/SKILL.md +1 -1
  13. package/dist/app-sidecar/app-settings.d.ts +65 -0
  14. package/dist/app-sidecar/app-settings.js +147 -0
  15. package/dist/app-sidecar/app-settings.js.map +1 -0
  16. package/dist/app-sidecar/attachments.d.ts +11 -0
  17. package/dist/app-sidecar/attachments.js +47 -0
  18. package/dist/app-sidecar/attachments.js.map +1 -0
  19. package/dist/app-sidecar/auth-routes.d.ts +3 -0
  20. package/dist/app-sidecar/auth-routes.js +290 -0
  21. package/dist/app-sidecar/auth-routes.js.map +1 -0
  22. package/dist/app-sidecar/autopilot-runner.d.ts +61 -0
  23. package/dist/app-sidecar/autopilot-runner.js +367 -0
  24. package/dist/app-sidecar/autopilot-runner.js.map +1 -0
  25. package/dist/app-sidecar/file-search.d.ts +15 -0
  26. package/dist/app-sidecar/file-search.js +103 -0
  27. package/dist/app-sidecar/file-search.js.map +1 -0
  28. package/dist/app-sidecar/hf-pull-manager.d.ts +20 -0
  29. package/dist/app-sidecar/hf-pull-manager.js +224 -0
  30. package/dist/app-sidecar/hf-pull-manager.js.map +1 -0
  31. package/dist/app-sidecar/history-routes.d.ts +3 -0
  32. package/dist/app-sidecar/history-routes.js +375 -0
  33. package/dist/app-sidecar/history-routes.js.map +1 -0
  34. package/dist/app-sidecar/history.d.ts +67 -0
  35. package/dist/app-sidecar/history.js +23 -0
  36. package/dist/app-sidecar/history.js.map +1 -0
  37. package/dist/app-sidecar/http.d.ts +5 -0
  38. package/dist/app-sidecar/http.js +27 -0
  39. package/dist/app-sidecar/http.js.map +1 -0
  40. package/dist/app-sidecar/integration-routes.d.ts +3 -0
  41. package/dist/app-sidecar/integration-routes.js +286 -0
  42. package/dist/app-sidecar/integration-routes.js.map +1 -0
  43. package/dist/app-sidecar/json-mode.d.ts +10 -0
  44. package/dist/app-sidecar/json-mode.js +73 -0
  45. package/dist/app-sidecar/json-mode.js.map +1 -0
  46. package/dist/app-sidecar/keep-awake.d.ts +4 -0
  47. package/dist/app-sidecar/keep-awake.js +5 -0
  48. package/dist/app-sidecar/keep-awake.js.map +1 -0
  49. package/dist/app-sidecar/ken-context.d.ts +20 -0
  50. package/dist/app-sidecar/ken-context.js +55 -0
  51. package/dist/app-sidecar/ken-context.js.map +1 -0
  52. package/dist/app-sidecar/mcp-routes.d.ts +3 -0
  53. package/dist/app-sidecar/mcp-routes.js +185 -0
  54. package/dist/app-sidecar/mcp-routes.js.map +1 -0
  55. package/dist/app-sidecar/mcp-rows.d.ts +31 -0
  56. package/dist/app-sidecar/mcp-rows.js +77 -0
  57. package/dist/app-sidecar/mcp-rows.js.map +1 -0
  58. package/dist/app-sidecar/progress-manager.d.ts +10 -0
  59. package/dist/app-sidecar/progress-manager.js +116 -0
  60. package/dist/app-sidecar/progress-manager.js.map +1 -0
  61. package/dist/app-sidecar/prompt-routes.d.ts +3 -0
  62. package/dist/app-sidecar/prompt-routes.js +354 -0
  63. package/dist/app-sidecar/prompt-routes.js.map +1 -0
  64. package/dist/app-sidecar/route-context.d.ts +145 -0
  65. package/dist/app-sidecar/route-context.js +2 -0
  66. package/dist/app-sidecar/route-context.js.map +1 -0
  67. package/dist/app-sidecar/run-control-routes.d.ts +3 -0
  68. package/dist/app-sidecar/run-control-routes.js +430 -0
  69. package/dist/app-sidecar/run-control-routes.js.map +1 -0
  70. package/dist/app-sidecar/session-routes.d.ts +3 -0
  71. package/dist/app-sidecar/session-routes.js +115 -0
  72. package/dist/app-sidecar/session-routes.js.map +1 -0
  73. package/dist/app-sidecar/session-types.d.ts +39 -0
  74. package/dist/app-sidecar/session-types.js +5 -0
  75. package/dist/app-sidecar/session-types.js.map +1 -0
  76. package/dist/app-sidecar/task-routes.d.ts +3 -0
  77. package/dist/app-sidecar/task-routes.js +149 -0
  78. package/dist/app-sidecar/task-routes.js.map +1 -0
  79. package/dist/app-sidecar/usage.d.ts +19 -0
  80. package/dist/app-sidecar/usage.js +153 -0
  81. package/dist/app-sidecar/usage.js.map +1 -0
  82. package/dist/app-sidecar/workspace-routes.d.ts +3 -0
  83. package/dist/app-sidecar/workspace-routes.js +244 -0
  84. package/dist/app-sidecar/workspace-routes.js.map +1 -0
  85. package/dist/app-sidecar.js +440 -3720
  86. package/dist/app-sidecar.js.map +1 -1
  87. package/dist/cli.js +2 -2
  88. package/dist/cli.js.map +1 -1
  89. package/dist/config.js +1 -1
  90. package/dist/core/acceptance-checks.js +3 -9
  91. package/dist/core/acceptance-checks.js.map +1 -1
  92. package/dist/core/agent-session/helpers.d.ts +26 -0
  93. package/dist/core/agent-session/helpers.js +47 -0
  94. package/dist/core/agent-session/helpers.js.map +1 -0
  95. package/dist/core/agent-session/mcp-tools.d.ts +68 -0
  96. package/dist/core/agent-session/mcp-tools.js +195 -0
  97. package/dist/core/agent-session/mcp-tools.js.map +1 -0
  98. package/dist/core/agent-session/run-loop-monitor.d.ts +63 -0
  99. package/dist/core/agent-session/run-loop-monitor.js +164 -0
  100. package/dist/core/agent-session/run-loop-monitor.js.map +1 -0
  101. package/dist/core/agent-session/transcript-markers.d.ts +57 -0
  102. package/dist/core/agent-session/transcript-markers.js +166 -0
  103. package/dist/core/agent-session/transcript-markers.js.map +1 -0
  104. package/dist/core/agent-session/verification-tracker.d.ts +46 -0
  105. package/dist/core/agent-session/verification-tracker.js +246 -0
  106. package/dist/core/agent-session/verification-tracker.js.map +1 -0
  107. package/dist/core/agent-session.d.ts +21 -87
  108. package/dist/core/agent-session.js +141 -712
  109. package/dist/core/agent-session.js.map +1 -1
  110. package/dist/core/auth-providers.js +3 -3
  111. package/dist/core/auth-providers.js.map +1 -1
  112. package/dist/core/bundled-agents.js +6 -6
  113. package/dist/core/bundled-agents.js.map +1 -1
  114. package/dist/core/checklist-git.d.ts +19 -0
  115. package/dist/core/checklist-git.js +54 -0
  116. package/dist/core/checklist-git.js.map +1 -0
  117. package/dist/core/checklist-items.d.ts +10 -1
  118. package/dist/core/checklist-items.js +22 -0
  119. package/dist/core/checklist-items.js.map +1 -1
  120. package/dist/core/checklist-prompt.d.ts +5 -1
  121. package/dist/core/checklist-prompt.js +16 -5
  122. package/dist/core/checklist-prompt.js.map +1 -1
  123. package/dist/core/checklist-snapshot.d.ts +5 -1
  124. package/dist/core/checklist-snapshot.js +19 -2
  125. package/dist/core/checklist-snapshot.js.map +1 -1
  126. package/dist/core/context-limits.js +1 -1
  127. package/dist/core/context-limits.js.map +1 -1
  128. package/dist/core/skills.js +6 -9
  129. package/dist/core/skills.js.map +1 -1
  130. package/dist/core/style-packs/index.js +2 -11
  131. package/dist/core/style-packs/index.js.map +1 -1
  132. package/dist/core/style-packs/packs.d.ts +3 -12
  133. package/dist/core/style-packs/packs.js +132 -173
  134. package/dist/core/style-packs/packs.js.map +1 -1
  135. package/dist/system-prompt.js +55 -78
  136. package/dist/system-prompt.js.map +1 -1
  137. package/dist/tools/ask-user.js +13 -74
  138. package/dist/tools/ask-user.js.map +1 -1
  139. package/dist/tools/bash.js +13 -78
  140. package/dist/tools/bash.js.map +1 -1
  141. package/dist/tools/checklist.d.ts +2 -10
  142. package/dist/tools/checklist.js +7 -39
  143. package/dist/tools/checklist.js.map +1 -1
  144. package/dist/tools/code-nav.js +7 -29
  145. package/dist/tools/code-nav.js.map +1 -1
  146. package/dist/tools/edit.d.ts +3 -9
  147. package/dist/tools/edit.js +66 -65
  148. package/dist/tools/edit.js.map +1 -1
  149. package/dist/tools/enter-plan.js +2 -7
  150. package/dist/tools/enter-plan.js.map +1 -1
  151. package/dist/tools/exit-plan.js +2 -3
  152. package/dist/tools/exit-plan.js.map +1 -1
  153. package/dist/tools/find.js +3 -4
  154. package/dist/tools/find.js.map +1 -1
  155. package/dist/tools/grep.js +6 -18
  156. package/dist/tools/grep.js.map +1 -1
  157. package/dist/tools/ls.js +3 -3
  158. package/dist/tools/ls.js.map +1 -1
  159. package/dist/tools/prompt-hints.js +34 -47
  160. package/dist/tools/prompt-hints.js.map +1 -1
  161. package/dist/tools/read.js +8 -20
  162. package/dist/tools/read.js.map +1 -1
  163. package/dist/tools/search-code.js +4 -12
  164. package/dist/tools/search-code.js.map +1 -1
  165. package/dist/tools/skill.js +13 -7
  166. package/dist/tools/skill.js.map +1 -1
  167. package/dist/tools/subagent-control.js +7 -22
  168. package/dist/tools/subagent-control.js.map +1 -1
  169. package/dist/tools/subagent.js +4 -7
  170. package/dist/tools/subagent.js.map +1 -1
  171. package/dist/tools/task-output.js +4 -15
  172. package/dist/tools/task-output.js.map +1 -1
  173. package/dist/tools/task-send.js +5 -17
  174. package/dist/tools/task-send.js.map +1 -1
  175. package/dist/tools/task-stop.js +2 -2
  176. package/dist/tools/task-stop.js.map +1 -1
  177. package/dist/tools/tool-search.js +2 -7
  178. package/dist/tools/tool-search.js.map +1 -1
  179. package/dist/tools/tool-tiers.d.ts +17 -4
  180. package/dist/tools/tool-tiers.js +38 -15
  181. package/dist/tools/tool-tiers.js.map +1 -1
  182. package/dist/tools/web-fetch.js +7 -33
  183. package/dist/tools/web-fetch.js.map +1 -1
  184. package/dist/tools/write.js +3 -4
  185. package/dist/tools/write.js.map +1 -1
  186. package/dist/ui/components/Footer.js +1 -2
  187. package/dist/ui/components/Footer.js.map +1 -1
  188. package/package.json +7 -4
  189. package/dist/core/api-benchmark.d.ts +0 -63
  190. package/dist/core/api-benchmark.js +0 -381
  191. package/dist/core/api-benchmark.js.map +0 -1
  192. package/dist/core/bash-spawn-benchmark.d.ts +0 -1
  193. package/dist/core/bash-spawn-benchmark.js +0 -139
  194. package/dist/core/bash-spawn-benchmark.js.map +0 -1
  195. package/dist/core/cache-warm-benchmark.d.ts +0 -21
  196. package/dist/core/cache-warm-benchmark.js +0 -170
  197. package/dist/core/cache-warm-benchmark.js.map +0 -1
  198. package/dist/core/fast-apply-benchmark.d.ts +0 -25
  199. package/dist/core/fast-apply-benchmark.js +0 -284
  200. package/dist/core/fast-apply-benchmark.js.map +0 -1
  201. package/dist/core/hashline-edit-benchmark.d.ts +0 -88
  202. package/dist/core/hashline-edit-benchmark.js +0 -518
  203. package/dist/core/hashline-edit-benchmark.js.map +0 -1
  204. package/dist/core/semantic-search-benchmark.d.ts +0 -36
  205. package/dist/core/semantic-search-benchmark.js +0 -211
  206. package/dist/core/semantic-search-benchmark.js.map +0 -1
  207. package/dist/core/speed-benchmark.d.ts +0 -132
  208. package/dist/core/speed-benchmark.js +0 -410
  209. package/dist/core/speed-benchmark.js.map +0 -1
@@ -0,0 +1,185 @@
1
+ import { log } from "../core/logger.js";
2
+ import { addServer, removeServer, getServer, parseMcpAddCommand, MCPClientManager, McpOAuthStore, } from "../core/mcp/index.js";
3
+ import { readBody, json } from "./http.js";
4
+ import { buildMcpRows, probeMcp } from "./mcp-rows.js";
5
+ export function handleMcpRoutes(ctx, req, res, url, method) {
6
+ // ── MCP server management (mirrors `ggcoder mcp`) ──────────────────
7
+ // `targetCwd` (project scope) overrides the window cwd so a server can be
8
+ // added/removed for ANY discovered project, not just this window's. Global
9
+ // scope ignores it (always ~/.gg/mcp.json).
10
+ if (method === "GET" && (url === "/mcp" || url.startsWith("/mcp?"))) {
11
+ const targetCwd = new URL(url, `http://${ctx.host}`).searchParams.get("cwd") ?? ctx.cwd;
12
+ void buildMcpRows(targetCwd, ctx.paths.settingsFile)
13
+ .then((servers) => json(res, 200, { servers }))
14
+ .catch((err) => {
15
+ log("ERROR", "app-sidecar", "buildMcpRows failed", {
16
+ message: err instanceof Error ? err.message : String(err),
17
+ });
18
+ json(res, 200, { servers: [] });
19
+ });
20
+ return true;
21
+ }
22
+ if (method === "POST" && url === "/mcp/add") {
23
+ void readBody(req, res).then(async (raw) => {
24
+ if (raw === null)
25
+ return;
26
+ let line;
27
+ let scopeValue;
28
+ let bodyCwd;
29
+ try {
30
+ const body = JSON.parse(raw);
31
+ line = body.line ?? "";
32
+ scopeValue = body.scope ?? "global";
33
+ bodyCwd = body.cwd;
34
+ }
35
+ catch {
36
+ json(res, 400, { error: "invalid JSON body" });
37
+ return;
38
+ }
39
+ const scope = scopeValue === "project" ? "project" : "global";
40
+ if (scope === "project" && !bodyCwd) {
41
+ json(res, 400, { error: "project scope requires a project (cwd)." });
42
+ return;
43
+ }
44
+ const targetCwd = bodyCwd ?? ctx.cwd;
45
+ const parsed = parseMcpAddCommand(line);
46
+ if (!parsed.ok) {
47
+ json(res, 400, { error: parsed.error });
48
+ return;
49
+ }
50
+ const config = parsed.value.config;
51
+ try {
52
+ // Best-effort probe — never blocks the save. A failed connect is
53
+ // surfaced to the UI but the config is still persisted (mirrors the
54
+ // CLI). probeMcp swallows connect errors; the try/catch guards the
55
+ // persist step so a write failure returns a 500 instead of becoming
56
+ // an unhandled rejection that would crash the sidecar.
57
+ const probe = await probeMcp(config);
58
+ const saved = await addServer(config, scope, targetCwd, true);
59
+ if (!saved.ok) {
60
+ json(res, 400, { error: saved.error });
61
+ return;
62
+ }
63
+ // Adding a project-scope server is an explicit trust signal — the
64
+ // user chose to put a server in this repo's .gg/mcp.json. Auto-trust
65
+ // the project so all project-scope servers connect on next load.
66
+ if (scope === "project") {
67
+ await ctx.session.trustProject(targetCwd);
68
+ }
69
+ json(res, 200, {
70
+ ok: true,
71
+ name: config.name,
72
+ connected: probe.ok,
73
+ toolCount: probe.toolCount,
74
+ error: probe.error,
75
+ requiresAuth: probe.requiresAuth,
76
+ });
77
+ }
78
+ catch (err) {
79
+ json(res, 500, {
80
+ error: err instanceof Error ? err.message : String(err),
81
+ });
82
+ }
83
+ });
84
+ return true;
85
+ }
86
+ if (method === "POST" && url === "/mcp/remove") {
87
+ void readBody(req, res).then(async (raw) => {
88
+ if (raw === null)
89
+ return;
90
+ let name;
91
+ let scopeValue;
92
+ let bodyCwd;
93
+ try {
94
+ const body = JSON.parse(raw);
95
+ name = body.name ?? "";
96
+ scopeValue = body.scope ?? "global";
97
+ bodyCwd = body.cwd;
98
+ }
99
+ catch {
100
+ json(res, 400, { error: "invalid JSON body" });
101
+ return;
102
+ }
103
+ if (!name.trim()) {
104
+ json(res, 400, { error: "missing server name" });
105
+ return;
106
+ }
107
+ const scope = scopeValue === "project" ? "project" : "global";
108
+ if (scope === "project" && !bodyCwd) {
109
+ json(res, 400, { error: "project scope requires a project (cwd)." });
110
+ return;
111
+ }
112
+ const targetCwd = bodyCwd ?? ctx.cwd;
113
+ const removed = await removeServer(name, scope, targetCwd);
114
+ // Drop any saved OAuth tokens for this server so a re-add starts clean.
115
+ await new McpOAuthStore().clear(name).catch(() => { });
116
+ json(res, 200, { removed });
117
+ });
118
+ return true;
119
+ }
120
+ // Interactive OAuth login for a remote (HTTP) MCP server. The browser is
121
+ // opened by the webview in response to the broadcast `mcp_auth_url` event;
122
+ // progress + outcome stream via `mcp_auth_status` / `mcp_auth_done` /
123
+ // `mcp_auth_error`. Responds 202 immediately and runs the flow in the
124
+ // background (the browser round-trip can take a while).
125
+ if (method === "POST" && url === "/mcp/login") {
126
+ void readBody(req, res).then(async (raw) => {
127
+ if (raw === null)
128
+ return;
129
+ let name;
130
+ let scopeValue;
131
+ let bodyCwd;
132
+ try {
133
+ const body = JSON.parse(raw);
134
+ name = body.name ?? "";
135
+ scopeValue = body.scope ?? "global";
136
+ bodyCwd = body.cwd;
137
+ }
138
+ catch {
139
+ json(res, 400, { error: "invalid JSON body" });
140
+ return;
141
+ }
142
+ if (!name.trim()) {
143
+ json(res, 400, { error: "missing server name" });
144
+ return;
145
+ }
146
+ const scope = scopeValue === "project" ? "project" : "global";
147
+ const targetCwd = bodyCwd ?? ctx.cwd;
148
+ const scoped = await getServer(name, targetCwd);
149
+ if (!scoped || scoped.scope !== scope) {
150
+ json(res, 404, { error: `No "${name}" server found.` });
151
+ return;
152
+ }
153
+ if (!scoped.config.url) {
154
+ json(res, 400, { error: "Login is only supported for HTTP MCP servers." });
155
+ return;
156
+ }
157
+ json(res, 202, { accepted: true });
158
+ ctx.broadcast("mcp_auth_status", { name, message: "Starting login\u2026" });
159
+ const manager = new MCPClientManager();
160
+ try {
161
+ const result = await manager.login(scoped.config, (authUrl) => {
162
+ ctx.broadcast("mcp_auth_url", { name, url: authUrl });
163
+ });
164
+ if (result.ok) {
165
+ ctx.broadcast("mcp_auth_done", { name, toolCount: result.toolCount });
166
+ }
167
+ else {
168
+ ctx.broadcast("mcp_auth_error", { name, message: result.error ?? "Login failed." });
169
+ }
170
+ }
171
+ catch (err) {
172
+ ctx.broadcast("mcp_auth_error", {
173
+ name,
174
+ message: err instanceof Error ? err.message : String(err),
175
+ });
176
+ }
177
+ finally {
178
+ await manager.dispose().catch(() => { });
179
+ }
180
+ });
181
+ return true;
182
+ }
183
+ return false;
184
+ }
185
+ //# sourceMappingURL=mcp-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-routes.js","sourceRoot":"","sources":["../../src/app-sidecar/mcp-routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type MCPScope, type MCPServerConfig } from "../core/mcp/index.js";
2
+ /** One wire row for the MCP list: a server config joined with its live status. */
3
+ export interface McpWireRow {
4
+ name: string;
5
+ scope: MCPScope;
6
+ ok: boolean;
7
+ toolCount: number;
8
+ error?: string;
9
+ kind: "stdio" | "http";
10
+ summary: string;
11
+ /** True when the server needs an interactive OAuth login before it connects. */
12
+ requiresAuth?: boolean;
13
+ }
14
+ /** A short transport summary for display (URL for http/sse, command+args for stdio). */
15
+ export declare function mcpRowSummary(config: MCPServerConfig): string;
16
+ /** Load + connect every server, returning one wire row per server. Mirrors the
17
+ * CLI dashboard's buildRows (connectAllDetailed, then dispose). Empty list
18
+ * short-circuits before spawning any stdio process / opening any HTTP conn.
19
+ * Project-scope servers run repo-controlled commands, so unless the user
20
+ * trusts them (trustProjectMcpServers) they are reported blocked WITHOUT
21
+ * being connected — even a status probe would spawn the process. */
22
+ export declare function buildMcpRows(cwd: string, settingsFile: string): Promise<McpWireRow[]>;
23
+ /** Probe a single server's connection before persisting it. Never throws — a
24
+ * failed probe returns ok:false with a human-readable error so the config can
25
+ * still be saved. Mirrors the CLI's probeServer. */
26
+ export declare function probeMcp(config: MCPServerConfig): Promise<{
27
+ ok: boolean;
28
+ toolCount: number;
29
+ error?: string;
30
+ requiresAuth?: boolean;
31
+ }>;
@@ -0,0 +1,77 @@
1
+ import { loadSavedSettings, projectScopeAllowed } from "../config.js";
2
+ import { loadServers, MCPClientManager, } from "../core/mcp/index.js";
3
+ /** A short transport summary for display (URL for http/sse, command+args for stdio). */
4
+ export function mcpRowSummary(config) {
5
+ if (config.url)
6
+ return config.url;
7
+ return [config.command, ...(config.args ?? [])].filter(Boolean).join(" ");
8
+ }
9
+ /** Load + connect every server, returning one wire row per server. Mirrors the
10
+ * CLI dashboard's buildRows (connectAllDetailed, then dispose). Empty list
11
+ * short-circuits before spawning any stdio process / opening any HTTP conn.
12
+ * Project-scope servers run repo-controlled commands, so unless the user
13
+ * trusts them (trustProjectMcpServers) they are reported blocked WITHOUT
14
+ * being connected — even a status probe would spawn the process. */
15
+ export async function buildMcpRows(cwd, settingsFile) {
16
+ const scoped = await loadServers(cwd);
17
+ if (scoped.length === 0)
18
+ return [];
19
+ const settings = loadSavedSettings(settingsFile);
20
+ const allowProject = projectScopeAllowed(settings.trustProjectMcpServers, settings.trustedProjects, cwd);
21
+ const connectable = scoped.filter((s) => allowProject || s.scope !== "project");
22
+ const blocked = scoped.filter((s) => !allowProject && s.scope === "project");
23
+ const manager = new MCPClientManager();
24
+ try {
25
+ const results = connectable.length > 0
26
+ ? await manager.connectAllDetailed(connectable.map((s) => s.config))
27
+ : [];
28
+ return [
29
+ ...connectable.map((s) => {
30
+ const result = results.find((r) => r.name === s.config.name);
31
+ return {
32
+ name: s.config.name,
33
+ scope: s.scope,
34
+ ok: result?.ok ?? false,
35
+ toolCount: result?.toolCount ?? 0,
36
+ error: result?.error,
37
+ kind: s.config.url ? "http" : "stdio",
38
+ summary: mcpRowSummary(s.config),
39
+ requiresAuth: result?.requiresAuth,
40
+ };
41
+ }),
42
+ ...blocked.map((s) => ({
43
+ name: s.config.name,
44
+ scope: s.scope,
45
+ ok: false,
46
+ toolCount: 0,
47
+ error: "Project-scope server not connected — this repo's .gg/mcp.json runs " +
48
+ "repo-controlled commands. Add or re-add a server in this project via " +
49
+ "the MCP modal to trust it.",
50
+ kind: (s.config.url ? "http" : "stdio"),
51
+ summary: mcpRowSummary(s.config),
52
+ })),
53
+ ];
54
+ }
55
+ finally {
56
+ await manager.dispose();
57
+ }
58
+ }
59
+ /** Probe a single server's connection before persisting it. Never throws — a
60
+ * failed probe returns ok:false with a human-readable error so the config can
61
+ * still be saved. Mirrors the CLI's probeServer. */
62
+ export async function probeMcp(config) {
63
+ const manager = new MCPClientManager();
64
+ try {
65
+ const result = await manager.probe(config);
66
+ return {
67
+ ok: result.ok,
68
+ toolCount: result.toolCount,
69
+ error: result.error,
70
+ requiresAuth: result.requiresAuth,
71
+ };
72
+ }
73
+ finally {
74
+ await manager.dispose();
75
+ }
76
+ }
77
+ //# sourceMappingURL=mcp-rows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-rows.js","sourceRoot":"","sources":["../../src/app-sidecar/mcp-rows.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ProgressSnapshot } from "../core/progress/types.js";
2
+ export interface ProgressManager {
3
+ /** Current snapshot for GET /progress + the SSE ready path. */
4
+ snapshot: () => ProgressSnapshot;
5
+ /** Award XP for one successfully completed run (prompt + any new commits). */
6
+ awardRun: (cwd: string, runStartedAt: number, originId?: string) => Promise<void>;
7
+ /** Close the ~/.gg fs.watch + clear any pending debounce (leak-free shutdown). */
8
+ dispose: () => void;
9
+ }
10
+ export declare function createProgressManager(agentDir: string, broadcastAll: (snapshot: ProgressSnapshot, originId?: string) => void): Promise<ProgressManager>;
@@ -0,0 +1,116 @@
1
+ import { watch as fsWatch } from "node:fs";
2
+ import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { CHAT_AGENT_IDS, chatAgentSessionsDir } from "../chat-agents/index.js";
5
+ import { log } from "../core/logger.js";
6
+ import { buildSnapshot, levelForXp, rankForLevel } from "../core/progress/ranks.js";
7
+ import { loadProgress, peekProgress, updateProgress } from "../core/progress/store.js";
8
+ import { awardPrompt, awardCommits } from "../core/progress/engine.js";
9
+ import { detectNewCommits, repoKey } from "../core/progress/git-xp.js";
10
+ import { rebuildFromSessions } from "../core/progress/rebuild.js";
11
+ export async function createProgressManager(agentDir, broadcastAll) {
12
+ // Boot: recovery chain main → backup → coding + chat session rebuild → empty.
13
+ const coderSessionsDir = path.join(agentDir, "sessions");
14
+ let file = await loadProgress({
15
+ rebuild: () => rebuildFromSessions([
16
+ coderSessionsDir,
17
+ ...CHAT_AGENT_IDS.map((agentId) => chatAgentSessionsDir(coderSessionsDir, agentId)),
18
+ ]),
19
+ });
20
+ // Don't re-celebrate an old levelUp event on boot.
21
+ let lastSeenNonce = file.lastEvent?.nonce ?? null;
22
+ log("INFO", "app-sidecar", "progress loaded", {
23
+ xp: String(file.xp),
24
+ level: String(levelForXp(file.xp)),
25
+ });
26
+ function snapshot() {
27
+ return buildSnapshot(file);
28
+ }
29
+ async function awardRun(cwd, runStartedAt, originId) {
30
+ try {
31
+ const now = Date.now();
32
+ const updated = await updateProgress(async (f) => {
33
+ const levelBefore = levelForXp(f.xp);
34
+ awardPrompt(f, now, cwd);
35
+ // Commit XP: probe repo root + HEAD, then score lastHead..HEAD bounded
36
+ // by the run window. First sight of a repo records HEAD, scores nothing.
37
+ const probe = await detectNewCommits(cwd, undefined, runStartedAt);
38
+ if (probe) {
39
+ const key = repoKey(probe.repoRoot);
40
+ const lastHead = f.repos[key]?.lastHead;
41
+ if (lastHead && lastHead !== probe.head) {
42
+ const detected = await detectNewCommits(cwd, lastHead, runStartedAt);
43
+ if (detected && detected.commits.length > 0) {
44
+ awardCommits(f, detected.commits, now, cwd);
45
+ }
46
+ }
47
+ f.repos[key] = { lastHead: probe.head };
48
+ }
49
+ // One combined lastEvent per run so other windows celebrate exactly once.
50
+ const levelAfter = levelForXp(f.xp);
51
+ const levelUp = levelAfter > levelBefore
52
+ ? { from: levelBefore, to: levelAfter, rankName: rankForLevel(levelAfter).name }
53
+ : null;
54
+ f.lastEvent = { nonce: randomUUID(), levelUp };
55
+ return { file: f, levelledUp: levelUp !== null };
56
+ });
57
+ file = updated;
58
+ lastSeenNonce = updated.lastEvent?.nonce ?? null;
59
+ broadcastAll(buildSnapshot(updated), originId);
60
+ }
61
+ catch (err) {
62
+ log("DEBUG", "app-sidecar", "progress award failed", {
63
+ message: err instanceof Error ? err.message : String(err),
64
+ });
65
+ }
66
+ }
67
+ // Watch ~/.gg (dir watch survives the atomic tmp+rename) for progress.json
68
+ // writes from other daemon processes; debounce, reload read-only, dedupe by nonce.
69
+ let watchDebounce = null;
70
+ let progressWatcher = null;
71
+ try {
72
+ const watcher = fsWatch(agentDir, (_event, filename) => {
73
+ if (filename !== "progress.json")
74
+ return;
75
+ if (watchDebounce)
76
+ clearTimeout(watchDebounce);
77
+ watchDebounce = setTimeout(() => {
78
+ void (async () => {
79
+ const reloaded = await peekProgress();
80
+ if (!reloaded)
81
+ return;
82
+ const nonce = reloaded.lastEvent?.nonce ?? null;
83
+ if (nonce === lastSeenNonce)
84
+ return;
85
+ file = reloaded;
86
+ lastSeenNonce = nonce;
87
+ broadcastAll(buildSnapshot(reloaded));
88
+ })();
89
+ }, 150);
90
+ });
91
+ watcher.unref();
92
+ progressWatcher = watcher;
93
+ }
94
+ catch (err) {
95
+ log("DEBUG", "app-sidecar", "progress watch unavailable", {
96
+ message: err instanceof Error ? err.message : String(err),
97
+ });
98
+ }
99
+ // Dispose closes the fs.watch handle (baseline #8: it was previously never
100
+ // closed — a per-daemon leak) and clears any pending debounce timer.
101
+ function dispose() {
102
+ if (watchDebounce) {
103
+ clearTimeout(watchDebounce);
104
+ watchDebounce = null;
105
+ }
106
+ try {
107
+ progressWatcher?.close();
108
+ }
109
+ catch {
110
+ // Already closed / never opened — nothing to do.
111
+ }
112
+ progressWatcher = null;
113
+ }
114
+ return { snapshot, awardRun, dispose };
115
+ }
116
+ //# sourceMappingURL=progress-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-manager.js","sourceRoot":"","sources":["../../src/app-sidecar/progress-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type http from "node:http";
2
+ import type { SessionRouteContext } from "./route-context.js";
3
+ export declare function handlePromptRoutes(ctx: SessionRouteContext, req: http.IncomingMessage, res: http.ServerResponse, url: string, method: string): boolean;