@kenkaiiii/ggcoder 5.19.4 → 5.19.5

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.
@@ -64,6 +64,7 @@ import { loadProgress, peekProgress, updateProgress } from "./core/progress/stor
64
64
  import { awardPrompt, awardCommits } from "./core/progress/engine.js";
65
65
  import { detectNewCommits, repoKey } from "./core/progress/git-xp.js";
66
66
  import { rebuildFromSessions } from "./core/progress/rebuild.js";
67
+ import { captureSidecarError, flushSidecarErrors, wrapSidecarHandler, } from "./core/sidecar-error-reporter.js";
67
68
  const ALL_PROVIDERS = [
68
69
  // US
69
70
  "anthropic",
@@ -169,6 +170,7 @@ async function persistModelSelection(settingsFile, provider, model) {
169
170
  await sm.set("defaultModel", model);
170
171
  }
171
172
  catch (err) {
173
+ captureSidecarError(err, "app-sidecar.settings.persist-model");
172
174
  log("WARN", "app-sidecar", "failed to persist model selection", { err: String(err) });
173
175
  }
174
176
  }
@@ -185,6 +187,7 @@ async function persistThinkingLevel(settingsFile, level) {
185
187
  await sm.set("thinkingLevel", level);
186
188
  }
187
189
  catch (err) {
190
+ captureSidecarError(err, "app-sidecar.settings.persist-thinking");
188
191
  log("WARN", "app-sidecar", "failed to persist thinking level", { err: String(err) });
189
192
  }
190
193
  }
@@ -452,7 +455,11 @@ async function runJsonModeIfRequested() {
452
455
  maxTurns: maxTurnsRaw ? parseInt(maxTurnsRaw, 10) : undefined,
453
456
  allowedTools,
454
457
  promptCacheKey: values["prompt-cache-key"],
455
- }).catch((err) => {
458
+ }).catch(async (err) => {
459
+ captureSidecarError(err, "app-sidecar.json-mode", {
460
+ provider: String(values.provider ?? "anthropic"),
461
+ });
462
+ await flushSidecarErrors();
456
463
  process.stderr.write((err instanceof Error ? err.message : String(err)) + "\n");
457
464
  process.exit(1);
458
465
  });
@@ -590,6 +597,7 @@ async function main() {
590
597
  }
591
598
  catch (error) {
592
599
  const message = error instanceof Error ? error.message : String(error);
600
+ captureSidecarError(error, "app-sidecar.usage.fetch", { provider });
593
601
  log("WARN", "app-sidecar", "subscription usage fetch failed", { provider, message });
594
602
  if (error instanceof SubscriptionUsageError && error.status === 429) {
595
603
  usageRateLimitedUntil.set(provider, Date.now() + USAGE_RATE_LIMIT_BACKOFF_MS);
@@ -649,7 +657,7 @@ async function main() {
649
657
  return null;
650
658
  }
651
659
  }
652
- const server = http.createServer((req, res) => {
660
+ const server = http.createServer(wrapSidecarHandler((req, res) => {
653
661
  const url = req.url ?? "/";
654
662
  const method = req.method ?? "GET";
655
663
  // CORS preflight — the webview origin differs from 127.0.0.1.
@@ -693,6 +701,7 @@ async function main() {
693
701
  }
694
702
  catch (err) {
695
703
  const message = err instanceof Error ? err.message : String(err);
704
+ captureSidecarError(err, "app-sidecar.session.create");
696
705
  log("ERROR", "app-sidecar", "session create failed", { message });
697
706
  daemonJson(res, 500, { error: message });
698
707
  }
@@ -729,6 +738,7 @@ async function main() {
729
738
  }
730
739
  daemonJson(res, 200, await subscriptionUsage(provider));
731
740
  })().catch((error) => {
741
+ captureSidecarError(error, "app-sidecar.usage.request");
732
742
  log("ERROR", "app-sidecar", "subscription usage request failed", {
733
743
  message: error instanceof Error ? error.message : String(error),
734
744
  });
@@ -744,7 +754,7 @@ async function main() {
744
754
  return;
745
755
  }
746
756
  ctx.handle(req, res, url, method);
747
- });
757
+ }, "app-sidecar.http"));
748
758
  server.listen(port, host, () => {
749
759
  const addr = server.address();
750
760
  // The Rust shell reads this line to learn the daemon port.
@@ -889,6 +899,7 @@ async function createProgressManager(agentDir, broadcastAll) {
889
899
  broadcastAll(buildSnapshot(updated), originId);
890
900
  }
891
901
  catch (err) {
902
+ captureSidecarError(err, "app-sidecar.progress.award");
892
903
  log("DEBUG", "app-sidecar", "progress award failed", {
893
904
  message: err instanceof Error ? err.message : String(err),
894
905
  });
@@ -920,6 +931,7 @@ async function createProgressManager(agentDir, broadcastAll) {
920
931
  watcher.unref();
921
932
  }
922
933
  catch (err) {
934
+ captureSidecarError(err, "app-sidecar.progress.watch");
923
935
  log("DEBUG", "app-sidecar", "progress watch unavailable", {
924
936
  message: err instanceof Error ? err.message : String(err),
925
937
  });
@@ -1010,6 +1022,11 @@ async function createSession(deps, opts) {
1010
1022
  const f = formatError(err);
1011
1023
  const message = f.message ? desktopGuidance(f.message) : undefined;
1012
1024
  const guidance = desktopGuidance(f.guidance);
1025
+ captureSidecarError(err, `app-sidecar.${logLabel.replaceAll(" ", "-")}`, {
1026
+ scope: type,
1027
+ ...(f.provider ? { provider: f.provider } : {}),
1028
+ ...(f.statusCode != null ? { status: String(f.statusCode) } : {}),
1029
+ });
1013
1030
  log("ERROR", "app-sidecar", logLabel, {
1014
1031
  headline: f.headline,
1015
1032
  source: f.source,
@@ -1067,6 +1084,7 @@ async function createSession(deps, opts) {
1067
1084
  chatAgent = nextAgent;
1068
1085
  broadcast("chat_agent_change", { chatAgent: nextAgent });
1069
1086
  await session.persistAppMarker("agent_handoff", { chatAgent: nextAgent }).catch((error) => {
1087
+ captureSidecarError(error, "app-sidecar.chat-agent.persist-handoff");
1070
1088
  log("WARN", "app-sidecar", "agent handoff marker persist failed", {
1071
1089
  message: error instanceof Error ? error.message : String(error),
1072
1090
  });
@@ -1185,6 +1203,7 @@ async function createSession(deps, opts) {
1185
1203
  .catch(() => false)
1186
1204
  .then(() => syncApprovedPlanProgress(generation))
1187
1205
  .catch((error) => {
1206
+ captureSidecarError(error, "app-sidecar.plan.refresh-progress");
1188
1207
  log("WARN", "app-sidecar", "plan progress refresh failed", {
1189
1208
  message: error instanceof Error ? error.message : String(error),
1190
1209
  });
@@ -1239,6 +1258,11 @@ async function createSession(deps, opts) {
1239
1258
  session.eventBus.on("tool_call_end", (d) => {
1240
1259
  const name = toolCallNames.get(d.toolCallId) ?? "unknown";
1241
1260
  toolCallNames.delete(d.toolCallId);
1261
+ if (d.isError) {
1262
+ // Tool output can contain private project data. Report the failure and tool
1263
+ // identity without shipping the raw result body to Error Mom.
1264
+ captureSidecarError(new Error(`Tool ${name} failed`), `tool.${name}`, { tool: name });
1265
+ }
1242
1266
  log(d.isError ? "ERROR" : "INFO", "tool", `Tool call ended: ${name}`, {
1243
1267
  id: d.toolCallId,
1244
1268
  durationMs: String(d.durationMs),
@@ -1579,6 +1603,7 @@ async function createSession(deps, opts) {
1579
1603
  catch (error) {
1580
1604
  // Keep tracking when prompt cleanup fails; hiding the widget here
1581
1605
  // would claim completion while the approved-plan contract remained.
1606
+ captureSidecarError(error, "app-sidecar.plan.cleanup");
1582
1607
  log("WARN", "app-sidecar", "completed plan cleanup failed", {
1583
1608
  message: error instanceof Error ? error.message : String(error),
1584
1609
  });
@@ -2058,7 +2083,10 @@ async function createSession(deps, opts) {
2058
2083
  void memoryStore
2059
2084
  .snapshot()
2060
2085
  .then((snapshot) => json(res, 200, snapshot))
2061
- .catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
2086
+ .catch((error) => {
2087
+ captureSidecarError(error, "app-sidecar.memory.snapshot");
2088
+ json(res, 500, { error: error instanceof Error ? error.message : String(error) });
2089
+ });
2062
2090
  return;
2063
2091
  }
2064
2092
  if (method === "DELETE" && url.startsWith("/memories/")) {
@@ -2071,14 +2099,20 @@ async function createSession(deps, opts) {
2071
2099
  .forget(id)
2072
2100
  .then(() => memoryStore.snapshot())
2073
2101
  .then((snapshot) => json(res, 200, snapshot))
2074
- .catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
2102
+ .catch((error) => {
2103
+ captureSidecarError(error, "app-sidecar.memory.forget");
2104
+ json(res, 500, { error: error instanceof Error ? error.message : String(error) });
2105
+ });
2075
2106
  return;
2076
2107
  }
2077
2108
  if (method === "GET" && url === "/jiwa") {
2078
2109
  void jiwaStore
2079
2110
  .snapshot()
2080
2111
  .then((snapshot) => json(res, 200, snapshot))
2081
- .catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
2112
+ .catch((error) => {
2113
+ captureSidecarError(error, "app-sidecar.jiwa.snapshot");
2114
+ json(res, 500, { error: error instanceof Error ? error.message : String(error) });
2115
+ });
2082
2116
  return;
2083
2117
  }
2084
2118
  if (method === "DELETE" && url.startsWith("/jiwa/")) {
@@ -2091,7 +2125,10 @@ async function createSession(deps, opts) {
2091
2125
  .forget(id)
2092
2126
  .then(() => jiwaStore.snapshot())
2093
2127
  .then((snapshot) => json(res, 200, snapshot))
2094
- .catch((error) => json(res, 500, { error: error instanceof Error ? error.message : String(error) }));
2128
+ .catch((error) => {
2129
+ captureSidecarError(error, "app-sidecar.jiwa.forget");
2130
+ json(res, 500, { error: error instanceof Error ? error.message : String(error) });
2131
+ });
2095
2132
  return;
2096
2133
  }
2097
2134
  if (method === "GET" && (url === "/events" || url.startsWith("/events?"))) {
@@ -2204,6 +2241,7 @@ async function createSession(deps, opts) {
2204
2241
  json(res, 200, { path: dir });
2205
2242
  }
2206
2243
  catch (err) {
2244
+ captureSidecarError(err, "app-sidecar.project.create");
2207
2245
  json(res, 500, { error: err instanceof Error ? err.message : String(err) });
2208
2246
  }
2209
2247
  });
@@ -2214,6 +2252,7 @@ async function createSession(deps, opts) {
2214
2252
  void discoverProjects()
2215
2253
  .then((projects) => json(res, 200, { projects }))
2216
2254
  .catch((err) => {
2255
+ captureSidecarError(err, "app-sidecar.projects.discover");
2217
2256
  log("ERROR", "app-sidecar", "discoverProjects failed", {
2218
2257
  message: err instanceof Error ? err.message : String(err),
2219
2258
  });
@@ -2247,7 +2286,10 @@ async function createSession(deps, opts) {
2247
2286
  .map(({ item }) => item);
2248
2287
  json(res, 200, { sessions: recent });
2249
2288
  })
2250
- .catch(() => json(res, 200, { sessions: [] }));
2289
+ .catch((error) => {
2290
+ captureSidecarError(error, "app-sidecar.sessions.list-chat");
2291
+ json(res, 200, { sessions: [] });
2292
+ });
2251
2293
  return;
2252
2294
  }
2253
2295
  // The picker may be served by a sidecar currently running in Chat mode.
@@ -2258,7 +2300,10 @@ async function createSession(deps, opts) {
2258
2300
  : paths.sessionsDir;
2259
2301
  void listRecentSessions(target, 5, sessionsDir)
2260
2302
  .then((sessions) => json(res, 200, { sessions }))
2261
- .catch(() => json(res, 200, { sessions: [] }));
2303
+ .catch((error) => {
2304
+ captureSidecarError(error, "app-sidecar.sessions.list");
2305
+ json(res, 200, { sessions: [] });
2306
+ });
2262
2307
  return;
2263
2308
  }
2264
2309
  if (method === "GET" && url.startsWith("/files")) {
@@ -2266,6 +2311,7 @@ async function createSession(deps, opts) {
2266
2311
  void searchProjectFiles(cwd, q)
2267
2312
  .then((files) => json(res, 200, { files }))
2268
2313
  .catch((err) => {
2314
+ captureSidecarError(err, "app-sidecar.files.search");
2269
2315
  log("ERROR", "app-sidecar", "searchProjectFiles failed", {
2270
2316
  message: err instanceof Error ? err.message : String(err),
2271
2317
  });
@@ -2833,6 +2879,7 @@ async function createSession(deps, opts) {
2833
2879
  }
2834
2880
  catch (err) {
2835
2881
  const message = err instanceof Error ? err.message : String(err);
2882
+ captureSidecarError(err, "app-sidecar.prompt-enhancer");
2836
2883
  log("ERROR", "app-sidecar", "enhance failed", { message });
2837
2884
  json(res, 500, { error: message });
2838
2885
  }
@@ -3158,6 +3205,7 @@ async function createSession(deps, opts) {
3158
3205
  drained,
3159
3206
  });
3160
3207
  })().catch((error) => {
3208
+ captureSidecarError(error, "app-sidecar.run.cancel");
3161
3209
  broadcast("cancel_failed", { error: "cancel_failed", runState: runLifecycle.state });
3162
3210
  json(res, 500, {
3163
3211
  error: "cancel_failed",
@@ -3185,6 +3233,7 @@ async function createSession(deps, opts) {
3185
3233
  json(res, 200, { ok: true });
3186
3234
  })
3187
3235
  .catch((err) => {
3236
+ captureSidecarError(err, "app-sidecar.session.new");
3188
3237
  json(res, 500, { error: err instanceof Error ? err.message : String(err) });
3189
3238
  });
3190
3239
  return;
@@ -3239,6 +3288,7 @@ async function createSession(deps, opts) {
3239
3288
  json(res, 200, { ok: true, planTotal });
3240
3289
  }
3241
3290
  catch (err) {
3291
+ captureSidecarError(err, "app-sidecar.plan.accept");
3242
3292
  json(res, 500, { error: err instanceof Error ? err.message : String(err) });
3243
3293
  }
3244
3294
  });
@@ -3335,6 +3385,7 @@ async function createSession(deps, opts) {
3335
3385
  broadcast("auth_done", { provider });
3336
3386
  }
3337
3387
  catch (err) {
3388
+ captureSidecarError(err, "app-sidecar.auth.oauth", { provider });
3338
3389
  broadcast("auth_error", {
3339
3390
  provider,
3340
3391
  message: err instanceof Error ? err.message : String(err),
@@ -3476,6 +3527,7 @@ async function createSession(deps, opts) {
3476
3527
  }
3477
3528
  catch (err) {
3478
3529
  serveController = null;
3530
+ captureSidecarError(err, "app-sidecar.serve.start", { provider: st.provider });
3479
3531
  json(res, 400, { error: err instanceof Error ? err.message : String(err) });
3480
3532
  }
3481
3533
  })();
@@ -3502,6 +3554,7 @@ async function createSession(deps, opts) {
3502
3554
  void buildMcpRows(targetCwd)
3503
3555
  .then((servers) => json(res, 200, { servers }))
3504
3556
  .catch((err) => {
3557
+ captureSidecarError(err, "app-sidecar.mcp.list");
3505
3558
  log("ERROR", "app-sidecar", "buildMcpRows failed", {
3506
3559
  message: err instanceof Error ? err.message : String(err),
3507
3560
  });
@@ -3558,6 +3611,7 @@ async function createSession(deps, opts) {
3558
3611
  });
3559
3612
  }
3560
3613
  catch (err) {
3614
+ captureSidecarError(err, "app-sidecar.mcp.add", { server: config.name });
3561
3615
  json(res, 500, {
3562
3616
  error: err instanceof Error ? err.message : String(err),
3563
3617
  });
@@ -3647,6 +3701,7 @@ async function createSession(deps, opts) {
3647
3701
  }
3648
3702
  }
3649
3703
  catch (err) {
3704
+ captureSidecarError(err, "app-sidecar.mcp.login", { server: name });
3650
3705
  broadcast("mcp_auth_error", {
3651
3706
  name,
3652
3707
  message: err instanceof Error ? err.message : String(err),
@@ -3693,7 +3748,9 @@ async function createSession(deps, opts) {
3693
3748
  dispose,
3694
3749
  };
3695
3750
  }
3696
- main().catch((err) => {
3751
+ main().catch(async (err) => {
3752
+ captureSidecarError(err, "app-sidecar.main", { severity: "fatal" });
3753
+ await flushSidecarErrors();
3697
3754
  const message = err instanceof Error ? err.message : String(err);
3698
3755
  process.stderr.write(`GG_APP_FATAL ${message}\n`);
3699
3756
  process.exit(1);