@kenkaiiii/ggcoder 5.34.0 → 5.34.1

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.
@@ -94,6 +94,12 @@ const ALL_PROVIDERS = [
94
94
  "sakana",
95
95
  "openrouter",
96
96
  ];
97
+ function stringArray(value) {
98
+ if (!Array.isArray(value))
99
+ return undefined;
100
+ const out = value.filter((v) => typeof v === "string" && v.trim().length > 0);
101
+ return out.length > 0 ? out : undefined;
102
+ }
97
103
  function appSettingsFile() {
98
104
  return path.join(os.homedir(), ".gg", "gg-app.json");
99
105
  }
@@ -117,6 +123,8 @@ async function loadAppSettings() {
117
123
  projectModels: raw.projectModels && typeof raw.projectModels === "object" ? raw.projectModels : undefined,
118
124
  autopilot: raw.autopilot && typeof raw.autopilot === "object" ? raw.autopilot : undefined,
119
125
  kenModels: raw.kenModels && typeof raw.kenModels === "object" ? raw.kenModels : undefined,
126
+ projectRoots: stringArray(raw.projectRoots),
127
+ hiddenProjects: stringArray(raw.hiddenProjects),
120
128
  };
121
129
  }
122
130
  catch {
@@ -2640,9 +2648,55 @@ async function createSession(deps, opts) {
2640
2648
  });
2641
2649
  return;
2642
2650
  }
2651
+ // Dismiss a project from the picker (or restore it with hidden:false). The
2652
+ // path is kept rather than the row: sessions in scratch dirs keep
2653
+ // re-surfacing, so the user's decision has to outlive any one scan.
2654
+ if (method === "POST" && url === "/projects/hidden") {
2655
+ void readBody(req, res).then(async (raw) => {
2656
+ if (raw === null)
2657
+ return;
2658
+ let body;
2659
+ try {
2660
+ body = JSON.parse(raw);
2661
+ }
2662
+ catch {
2663
+ json(res, 400, { error: "invalid JSON body" });
2664
+ return;
2665
+ }
2666
+ const target = body.path?.trim();
2667
+ if (!target) {
2668
+ json(res, 400, { error: "path is required" });
2669
+ return;
2670
+ }
2671
+ const key = path.resolve(target);
2672
+ try {
2673
+ const settings = await loadAppSettings();
2674
+ const current = new Set((settings.hiddenProjects ?? []).map((p) => path.resolve(p)));
2675
+ if (body.hidden === false)
2676
+ current.delete(key);
2677
+ else
2678
+ current.add(key);
2679
+ settings.hiddenProjects = current.size > 0 ? Array.from(current) : undefined;
2680
+ await saveAppSettings(settings);
2681
+ json(res, 200, { hidden: Array.from(current) });
2682
+ }
2683
+ catch (err) {
2684
+ captureSidecarError(err, "app-sidecar.projects.hidden");
2685
+ json(res, 500, { error: err instanceof Error ? err.message : String(err) });
2686
+ }
2687
+ });
2688
+ return;
2689
+ }
2643
2690
  if (method === "GET" && url === "/projects") {
2644
- // Scan ggcoder + Claude Code + Codex session stores for known projects.
2645
- void discoverProjects()
2691
+ // Session stores (ggcoder + Claude Code + Codex) for projects with
2692
+ // history, plus a filesystem scan of the configured projects folder so
2693
+ // projects you have not opened yet are still listed.
2694
+ void loadAppSettings()
2695
+ .then(({ projectsRoot, projectRoots, hiddenProjects }) => discoverProjects({
2696
+ projectsRoot,
2697
+ extraRoots: projectRoots,
2698
+ hiddenPaths: hiddenProjects,
2699
+ }))
2646
2700
  .then((projects) => json(res, 200, { projects }))
2647
2701
  .catch((err) => {
2648
2702
  captureSidecarError(err, "app-sidecar.projects.discover");