@sideboard-ai/core 0.1.35 → 0.1.37

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.
@@ -2174,11 +2174,83 @@ async function getPrDetails(cwd, selector) {
2174
2174
  };
2175
2175
  }
2176
2176
  async function fetchPrHead(repoPath, number, localBranch) {
2177
- await git(
2178
- ["fetch", "origin", `pull/${number}/head:${localBranch}`],
2179
- repoPath,
2180
- { reject: false }
2181
- );
2177
+ const slug = await resolveGithubRepoSlug(repoPath);
2178
+ const refspec = `+pull/${number}/head:${localBranch}`;
2179
+ const errors = [];
2180
+ const tryFetch = async (remote) => {
2181
+ const result = await git(["fetch", remote, refspec], repoPath, {
2182
+ reject: false
2183
+ });
2184
+ if (result.exitCode === 0) return true;
2185
+ const detail = (result.stderr || result.stdout).trim();
2186
+ if (detail) errors.push(`${remote}: ${detail}`);
2187
+ return false;
2188
+ };
2189
+ let fetched = await tryFetch("origin");
2190
+ if (!fetched && slug) {
2191
+ fetched = await tryFetch(`https://github.com/${slug}.git`);
2192
+ }
2193
+ const localOk = async () => {
2194
+ const verify = await git(["rev-parse", "--verify", localBranch], repoPath, {
2195
+ reject: false
2196
+ });
2197
+ return verify.exitCode === 0;
2198
+ };
2199
+ if (!await localOk()) {
2200
+ const viewArgs = [
2201
+ "pr",
2202
+ "view",
2203
+ String(number),
2204
+ "--json",
2205
+ "headRefOid"
2206
+ ];
2207
+ if (slug) viewArgs.push("--repo", slug);
2208
+ const view = await gh(viewArgs, repoPath, { reject: false });
2209
+ let oid = "";
2210
+ if (view.exitCode === 0 && view.stdout.trim()) {
2211
+ try {
2212
+ oid = String(
2213
+ JSON.parse(view.stdout).headRefOid ?? ""
2214
+ ).trim();
2215
+ } catch {
2216
+ oid = "";
2217
+ }
2218
+ }
2219
+ if (oid) {
2220
+ const ensureOid = async (remote) => {
2221
+ const got = await git(["fetch", remote, oid], repoPath, {
2222
+ reject: false
2223
+ });
2224
+ return got.exitCode === 0;
2225
+ };
2226
+ let haveObject = (await git(["cat-file", "-e", `${oid}^{commit}`], repoPath, {
2227
+ reject: false
2228
+ })).exitCode === 0;
2229
+ if (!haveObject) haveObject = await ensureOid("origin");
2230
+ if (!haveObject && slug) {
2231
+ haveObject = await ensureOid(`https://github.com/${slug}.git`);
2232
+ }
2233
+ if (haveObject) {
2234
+ const branched = await git(["branch", "-f", localBranch, oid], repoPath, {
2235
+ reject: false
2236
+ });
2237
+ if (branched.exitCode !== 0) {
2238
+ const detail = (branched.stderr || branched.stdout).trim();
2239
+ if (detail) errors.push(`branch -f: ${detail}`);
2240
+ }
2241
+ } else {
2242
+ errors.push(`could not fetch commit ${oid.slice(0, 12)}`);
2243
+ }
2244
+ } else if (view.stderr.trim()) {
2245
+ errors.push(view.stderr.trim());
2246
+ }
2247
+ }
2248
+ if (!await localOk()) {
2249
+ const hint = errors.length ? ` (${errors.join(" | ")})` : "";
2250
+ throw new Error(
2251
+ `Failed to fetch PR #${number} head into ${localBranch}${hint}`
2252
+ );
2253
+ }
2182
2254
  }
2183
2255
  async function resolveWorktreeStartPoint(repoPath, sourceRef) {
2184
2256
  const ref = sourceRef.trim();
@@ -2188,6 +2260,7 @@ async function resolveWorktreeStartPoint(repoPath, sourceRef) {
2188
2260
  reject: false
2189
2261
  });
2190
2262
  if (ok.exitCode === 0) return ref;
2263
+ throw new Error(`Invalid git reference: ${ref}`);
2191
2264
  }
2192
2265
  const remote = `origin/${ref}`;
2193
2266
  const remoteOk = await git(["rev-parse", "--verify", remote], repoPath, {
@@ -2198,7 +2271,10 @@ async function resolveWorktreeStartPoint(repoPath, sourceRef) {
2198
2271
  reject: false
2199
2272
  });
2200
2273
  if (localOk.exitCode === 0) return ref;
2201
- return ref;
2274
+ throw new Error(`Invalid git reference: ${ref}`);
2275
+ }
2276
+ function isLocalPrFetchBranch(ref) {
2277
+ return /^sideboard-pr-\d+$/.test(ref.trim());
2202
2278
  }
2203
2279
  async function createThreadWorktree(opts) {
2204
2280
  let branchName = `thread/${opts.slug}`;
@@ -2208,7 +2284,7 @@ async function createThreadWorktree(opts) {
2208
2284
  }
2209
2285
  await ensureGhPreferOrigin(opts.repoPath);
2210
2286
  await git(["fetch", "origin", "--prune"], opts.repoPath, { reject: false });
2211
- if (!opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
2287
+ if (!isLocalPrFetchBranch(opts.sourceRef) && !opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
2212
2288
  await git(["fetch", "origin", opts.sourceRef], opts.repoPath, {
2213
2289
  reject: false
2214
2290
  });
@@ -2507,6 +2583,8 @@ __export(app_settings_exports, {
2507
2583
  claudeChromeEnabled: () => claudeChromeEnabled,
2508
2584
  claudeUserSettingsPath: () => claudeUserSettingsPath,
2509
2585
  deleteBranchOnPurgeEnabled: () => deleteBranchOnPurgeEnabled,
2586
+ getDefaultAgent: () => getDefaultAgent,
2587
+ getDefaultModel: () => getDefaultModel,
2510
2588
  getIssueSource: () => getIssueSource,
2511
2589
  getLinearApiKey: () => getLinearApiKey,
2512
2590
  harnessEnvKey: () => harnessEnvKey,
@@ -2515,11 +2593,13 @@ __export(app_settings_exports, {
2515
2593
  maxConcurrentAgents: () => maxConcurrentAgents,
2516
2594
  resolveClaudeExecutable: () => resolveClaudeExecutable,
2517
2595
  resolveEffectiveIssueSource: () => resolveEffectiveIssueSource,
2596
+ resolveThreadDefaults: () => resolveThreadDefaults,
2518
2597
  saveAppSettings: () => saveAppSettings,
2519
2598
  updateAdvancedSettings: () => updateAdvancedSettings,
2520
2599
  updateAppEnvironment: () => updateAppEnvironment,
2521
2600
  updateBrightsySettings: () => updateBrightsySettings,
2522
2601
  updateClaudeSettings: () => updateClaudeSettings,
2602
+ updateDefaultsSettings: () => updateDefaultsSettings,
2523
2603
  updateIntegrationsSettings: () => updateIntegrationsSettings
2524
2604
  });
2525
2605
  function appSettingsPath() {
@@ -2566,6 +2646,19 @@ function normalizeIntegrations(raw) {
2566
2646
  }
2567
2647
  return out;
2568
2648
  }
2649
+ function normalizeDefaults(raw) {
2650
+ if (!raw || typeof raw !== "object") return {};
2651
+ const source = raw;
2652
+ const out = {};
2653
+ if (typeof source.agent === "string" && DEFAULT_AGENTS.has(source.agent)) {
2654
+ out.agent = source.agent;
2655
+ }
2656
+ if (typeof source.model === "string") {
2657
+ const model = source.model.trim();
2658
+ if (model) out.model = model;
2659
+ }
2660
+ return out;
2661
+ }
2569
2662
  function normalizeAdvanced(raw) {
2570
2663
  if (!raw || typeof raw !== "object") return {};
2571
2664
  const source = raw;
@@ -2610,6 +2703,7 @@ function normalizeSettings(raw) {
2610
2703
  let claude = {};
2611
2704
  let brightsy = {};
2612
2705
  let integrations = {};
2706
+ let defaults = {};
2613
2707
  let advanced = {};
2614
2708
  if (raw && typeof raw === "object") {
2615
2709
  if ("environment" in raw) {
@@ -2633,11 +2727,14 @@ function normalizeSettings(raw) {
2633
2727
  raw.integrations
2634
2728
  );
2635
2729
  }
2730
+ if ("defaults" in raw) {
2731
+ defaults = normalizeDefaults(raw.defaults);
2732
+ }
2636
2733
  if ("advanced" in raw) {
2637
2734
  advanced = normalizeAdvanced(raw.advanced);
2638
2735
  }
2639
2736
  }
2640
- return { environment: env, claude, brightsy, integrations, advanced };
2737
+ return { environment: env, claude, brightsy, integrations, defaults, advanced };
2641
2738
  }
2642
2739
  function loadAppSettings() {
2643
2740
  const path = appSettingsPath();
@@ -2721,6 +2818,38 @@ function updateIntegrationsSettings(patch) {
2721
2818
  }
2722
2819
  return saveAppSettings({ ...current, integrations });
2723
2820
  }
2821
+ function updateDefaultsSettings(patch) {
2822
+ const current = loadAppSettings();
2823
+ const defaults = { ...current.defaults };
2824
+ if ("agent" in patch) {
2825
+ if (patch.agent == null) {
2826
+ delete defaults.agent;
2827
+ } else if (DEFAULT_AGENTS.has(patch.agent)) {
2828
+ defaults.agent = patch.agent;
2829
+ }
2830
+ }
2831
+ if ("model" in patch) {
2832
+ if (patch.model == null || patch.model.trim() === "") {
2833
+ delete defaults.model;
2834
+ } else {
2835
+ defaults.model = patch.model.trim();
2836
+ }
2837
+ }
2838
+ return saveAppSettings({ ...current, defaults });
2839
+ }
2840
+ function getDefaultAgent(settings = loadAppSettings()) {
2841
+ return settings.defaults.agent ?? "claude";
2842
+ }
2843
+ function getDefaultModel(settings = loadAppSettings()) {
2844
+ const model = settings.defaults.model?.trim();
2845
+ return model || null;
2846
+ }
2847
+ function resolveThreadDefaults(settings = loadAppSettings()) {
2848
+ return {
2849
+ agent: getDefaultAgent(settings),
2850
+ model: getDefaultModel(settings)
2851
+ };
2852
+ }
2724
2853
  function isLinearConnected(settings = loadAppSettings()) {
2725
2854
  return Boolean(settings.integrations.linearApiKey?.trim());
2726
2855
  }
@@ -2835,7 +2964,7 @@ function childEnvWithAppSettings(extra) {
2835
2964
  function harnessEnvKey(harness) {
2836
2965
  return HARNESS_ENV_KEYS[harness];
2837
2966
  }
2838
- var import_node_fs5, import_node_os4, import_node_path6, HARNESS_ENV_KEYS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, EMPTY_SETTINGS;
2967
+ var import_node_fs5, import_node_os4, import_node_path6, HARNESS_ENV_KEYS, DEFAULT_AGENTS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, EMPTY_SETTINGS;
2839
2968
  var init_app_settings = __esm({
2840
2969
  "src/store/app-settings.ts"() {
2841
2970
  "use strict";
@@ -2850,6 +2979,13 @@ var init_app_settings = __esm({
2850
2979
  opencode: null,
2851
2980
  brightsy: null
2852
2981
  };
2982
+ DEFAULT_AGENTS = /* @__PURE__ */ new Set([
2983
+ "claude",
2984
+ "codex",
2985
+ "opencode",
2986
+ "brightsy",
2987
+ "cursor"
2988
+ ]);
2853
2989
  CLOUD_CONNECT_AGENTS = /* @__PURE__ */ new Set([
2854
2990
  "claude",
2855
2991
  "codex",
@@ -2862,6 +2998,7 @@ var init_app_settings = __esm({
2862
2998
  claude: {},
2863
2999
  brightsy: {},
2864
3000
  integrations: {},
3001
+ defaults: {},
2865
3002
  advanced: {}
2866
3003
  };
2867
3004
  }
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startMcpServer
4
- } from "../chunk-AL2GL5HJ.js";
5
- import "../chunk-PER4N6LS.js";
6
- import "../chunk-Y2EWQ4TL.js";
7
- import "../chunk-BMB7WCGF.js";
8
- import "../chunk-MULWZLDI.js";
4
+ } from "../chunk-E4TRCRKH.js";
5
+ import "../chunk-FVGRUZHI.js";
6
+ import "../chunk-IS3AGU33.js";
7
+ import "../chunk-PTASB7SJ.js";
8
+ import "../chunk-5KZLWNBS.js";
9
9
  import "../chunk-ILQK4P5R.js";
10
10
  import "../chunk-BSZX63TV.js";
11
- import "../chunk-3WF3X46L.js";
12
- import "../chunk-UFWEANLU.js";
11
+ import "../chunk-YZ23S32T.js";
12
+ import "../chunk-XBEQI5H4.js";
13
13
  import "../chunk-HYRHI3QU.js";
14
14
  import "../chunk-M37RITA6.js";
15
15
  import "../chunk-AJ6ROGD7.js";
@@ -4,10 +4,10 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-PER4N6LS.js";
8
- import "./chunk-Y2EWQ4TL.js";
9
- import "./chunk-BMB7WCGF.js";
10
- import "./chunk-UFWEANLU.js";
7
+ } from "./chunk-FVGRUZHI.js";
8
+ import "./chunk-IS3AGU33.js";
9
+ import "./chunk-PTASB7SJ.js";
10
+ import "./chunk-XBEQI5H4.js";
11
11
  import "./chunk-HYRHI3QU.js";
12
12
  import "./chunk-M37RITA6.js";
13
13
  import "./chunk-AJ6ROGD7.js";
@@ -41,7 +41,7 @@ import {
41
41
  worktreeDisplayLabel,
42
42
  worktreeDisplayLabelForGroup,
43
43
  worktreeNameFromPath
44
- } from "./chunk-UFWEANLU.js";
44
+ } from "./chunk-XBEQI5H4.js";
45
45
  import "./chunk-HYRHI3QU.js";
46
46
  import "./chunk-M37RITA6.js";
47
47
  import "./chunk-AJ6ROGD7.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",