@sideboard-ai/core 0.1.157 → 0.1.159

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 (38) hide show
  1. package/dist/{abletime-BEIDJG7W.js → abletime-HOQBDQC4.js} +2 -2
  2. package/dist/{abletime-GWZE6OYM.js → abletime-LK7GV556.js} +2 -2
  3. package/dist/{agents-LCDXN2B2.js → agents-5HY76BCR.js} +4 -4
  4. package/dist/{agents-C55LAEUR.js → agents-67ZBH5OE.js} +5 -5
  5. package/dist/{app-settings-VRQI3FIE.js → app-settings-BJ5GFAE5.js} +13 -17
  6. package/dist/{app-settings-H3INSR67.js → app-settings-YWJ4MVYM.js} +13 -17
  7. package/dist/{chunk-NVXVEGGM.js → chunk-5U4NZLBH.js} +4 -0
  8. package/dist/{chunk-DVJBO3M7.js → chunk-AGLPYXDT.js} +1 -1
  9. package/dist/{chunk-KQ4JOGUH.js → chunk-DWUOKF3W.js} +11 -5
  10. package/dist/{chunk-D7EGJ3EI.js → chunk-EQIJ5MHR.js} +119 -110
  11. package/dist/{chunk-3BWVOUQG.js → chunk-FLG4A5FJ.js} +119 -110
  12. package/dist/{chunk-2SDMENAL.js → chunk-JV4VNFMS.js} +1 -1
  13. package/dist/{chunk-LQMFCS54.js → chunk-KEDHHXKW.js} +3 -13
  14. package/dist/{chunk-CJQLPPEJ.js → chunk-MEZXWELT.js} +4 -14
  15. package/dist/{chunk-CVR4RJ6G.js → chunk-O7RWWPMR.js} +12 -13
  16. package/dist/{chunk-GWEEGE6L.js → chunk-OYOXLY6B.js} +404 -115
  17. package/dist/{chunk-4I4VKAPZ.js → chunk-SIMFKJIB.js} +13 -14
  18. package/dist/{chunk-SUCJAWV4.js → chunk-TGU3LSDG.js} +402 -113
  19. package/dist/{chunk-N27GVFZY.js → chunk-UBMCEZRE.js} +1 -1
  20. package/dist/{chunk-TIJ6QVX5.js → chunk-V4R6L2ZL.js} +15 -6
  21. package/dist/{coordinator-prompt-AM47SATF.js → coordinator-prompt-7NKY7QRK.js} +4 -4
  22. package/dist/{coordinator-prompt-26IJU2AV.js → coordinator-prompt-CNI6AK65.js} +3 -3
  23. package/dist/{global-workspace-QV7CC7SK.js → global-workspace-FKAJZHO5.js} +4 -4
  24. package/dist/{global-workspace-5BIW26YR.js → global-workspace-IJYCUO4M.js} +3 -3
  25. package/dist/index.cjs +1037 -648
  26. package/dist/index.d.cts +71 -57
  27. package/dist/index.d.ts +71 -57
  28. package/dist/index.js +339 -250
  29. package/dist/mcp/run-stdio.cjs +967 -575
  30. package/dist/mcp/run-stdio.js +283 -187
  31. package/dist/{orchestrator-BUH3LJLL.js → orchestrator-KFLS5BTP.js} +5 -5
  32. package/dist/{orchestrator-KQO4MXBI.js → orchestrator-NSVP7DJH.js} +7 -7
  33. package/dist/{plan-file-OZEBFSGQ.js → plan-file-I24VJVP2.js} +2 -2
  34. package/dist/{workspaces-NYSM2EPX.js → workspaces-D2M3AM2M.js} +3 -3
  35. package/dist/{workspaces-Q2VCHIAS.js → workspaces-OFSDJ7PZ.js} +4 -4
  36. package/dist/{worktree-PEWDAX5O.js → worktree-BQE5KLRY.js} +3 -3
  37. package/dist/{worktree-T4SWFSTT.js → worktree-EA6AD6D6.js} +2 -2
  38. package/package.json +1 -1
@@ -64,42 +64,34 @@ function unwrapStrippedElectronLaunch(command, args) {
64
64
  }
65
65
 
66
66
  // src/store/account-profile.ts
67
- var ACCOUNT_ROLE_PRESETS = ["engineering", "design", "product"];
68
- var ACCOUNT_ROLES = ACCOUNT_ROLE_PRESETS;
69
- var ACCOUNT_ROLE_MAX = 16;
70
67
  var PROFILE_NOTES_MAX = 2e3;
71
- var ACCOUNT_ROLE_LABELS = {
68
+ var LEGACY_ROLE_LABELS = {
72
69
  engineering: "Engineering",
73
70
  design: "Design",
74
71
  product: "Product",
75
72
  qa: "QA"
76
73
  };
77
- var ROLE_TEAM_HINTS = {
78
- engineering: ["engineering-team", "engineering", "eng-team"],
79
- design: ["design-team", "design"],
80
- product: ["product-team", "product"]
81
- };
82
- function accountRoleLabel(role) {
83
- const known = ACCOUNT_ROLE_LABELS[role];
74
+ function legacyRoleLabel(role) {
75
+ const known = LEGACY_ROLE_LABELS[role];
84
76
  if (known) return known;
85
77
  return role.split("-").filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
86
78
  }
87
- function normalizeAccountRole(value) {
79
+ function normalizeLegacyRole(value) {
88
80
  const key = (value ?? "").trim().toLowerCase().replace(/[_\s]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
89
81
  if (key === "both") return void 0;
90
82
  if (key.length < 2 || key.length > 40) return void 0;
91
83
  if (!/^[a-z][a-z0-9-]*$/.test(key)) return void 0;
92
84
  return key;
93
85
  }
94
- function normalizeAccountRoles(roles, legacyRole) {
86
+ function legacyRoleLabels(roles, legacyRole) {
95
87
  const raw = Array.isArray(roles) ? roles : [];
96
88
  const out = [];
97
89
  const seen = /* @__PURE__ */ new Set();
98
90
  const push = (value) => {
99
- const role = normalizeAccountRole(typeof value === "string" ? value : "");
100
- if (!role || seen.has(role) || out.length >= ACCOUNT_ROLE_MAX) return;
91
+ const role = normalizeLegacyRole(typeof value === "string" ? value : "");
92
+ if (!role || seen.has(role) || out.length >= 16) return;
101
93
  seen.add(role);
102
- out.push(role);
94
+ out.push(legacyRoleLabel(role));
103
95
  };
104
96
  for (const item of raw) push(item);
105
97
  if (out.length === 0) push(legacyRole);
@@ -109,97 +101,71 @@ function normalizeProfileNotes(value) {
109
101
  if (typeof value !== "string") return "";
110
102
  return value.replace(/\r\n/g, "\n").trim().slice(0, PROFILE_NOTES_MAX);
111
103
  }
112
- function reviewTeamHintsForRoles(roles) {
113
- const seen = /* @__PURE__ */ new Set();
114
- const out = [];
115
- for (const role of roles) {
116
- const hints = ROLE_TEAM_HINTS[role] ?? teamHintsForCustomRole(role);
117
- for (const hint of hints) {
118
- const key = hint.toLowerCase();
119
- if (seen.has(key)) continue;
120
- seen.add(key);
121
- out.push(hint);
122
- }
123
- }
124
- return out;
125
- }
126
- function teamHintsForCustomRole(role) {
127
- const slug = role.trim().toLowerCase();
128
- if (!slug) return [];
129
- if (slug.endsWith("-team") || slug.endsWith("-squad")) return [slug];
130
- return [`${slug}-team`, slug];
104
+ function foldLegacyRolesIntoNotes(roles, legacyRole, notes) {
105
+ const text = normalizeProfileNotes(notes);
106
+ const labels = legacyRoleLabels(roles, legacyRole);
107
+ if (!labels.length) return text;
108
+ if (text.toLowerCase().startsWith("roles:")) return text;
109
+ const prefix = `Roles: ${labels.join(", ")}`;
110
+ return text ? `${prefix}. ${text}` : prefix;
131
111
  }
132
112
  function resolveAccountProfile(input) {
133
113
  return resolveViewerProfile(input);
134
114
  }
135
115
  function resolveViewerProfile(account, project) {
136
- const accountRoles = normalizeAccountRoles(account?.roles, account?.role);
137
- const projectRoles = normalizeAccountRoles(project?.roles, project?.role);
138
- const rolesFromProject = projectRoles.length > 0;
139
- const roles = rolesFromProject ? projectRoles : accountRoles;
140
- const accountNotes = normalizeProfileNotes(account?.notes);
141
- const projectNotes = normalizeProfileNotes(project?.notes);
142
- const notes = [accountNotes, projectNotes].filter(Boolean).join("\n");
116
+ const accountNotes = foldLegacyRolesIntoNotes(
117
+ account?.roles,
118
+ account?.role,
119
+ account?.notes
120
+ );
121
+ const projectNotes = foldLegacyRolesIntoNotes(
122
+ project?.roles,
123
+ project?.role,
124
+ project?.notes
125
+ );
143
126
  return {
144
- roles,
145
- roleLabels: roles.map((role) => accountRoleLabel(role)),
146
- reviewTeamHints: reviewTeamHintsForRoles(roles),
147
- notes,
127
+ notes: [accountNotes, projectNotes].filter(Boolean).join("\n"),
148
128
  accountNotes,
149
- projectNotes,
150
- rolesFromProject
129
+ projectNotes
151
130
  };
152
131
  }
153
- function preferTeamsForRole(viewerTeams, hints) {
154
- const teams = viewerTeams.map((t) => t.trim()).filter(Boolean);
155
- const want = hints.map((t) => t.trim()).filter(Boolean);
156
- if (!want.length) return teams;
157
- if (!teams.length) return want;
158
- const hintKeys = want.map((t) => t.toLowerCase());
159
- const matched = teams.filter((team) => {
160
- const key = team.toLowerCase();
161
- return hintKeys.some((hint) => key === hint || key.includes(hint) || hint.includes(key));
162
- });
163
- return matched.length ? matched : teams;
164
- }
165
132
  function compactNotes(notes, max = 160) {
166
133
  const oneLine = notes.replace(/\s+/g, " ").trim();
167
134
  if (oneLine.length <= max) return oneLine;
168
135
  return `${oneLine.slice(0, max - 1).trimEnd()}\u2026`;
169
136
  }
170
137
  function formatAccountProfilePlaybookLine(profile) {
171
- if (profile.roleLabels.length === 0 && !profile.notes) return "";
172
- const parts = [];
173
- if (profile.roleLabels.length) {
174
- parts.push(
175
- `roles ${profile.roleLabels.join(", ")} (tickets to work on / PRs to review; prefer those teams)`
176
- );
177
- }
178
- if (profile.notes) {
179
- parts.push(`notes: ${compactNotes(profile.notes)}`);
180
- }
181
- return `- Viewer profile: ${parts.join(". ")}. A team review request is not a claim \u2014 only an individual reviewer is. When they ask to find work, use these notes with list_issues (tickets) and list_prs(queue=review) (reviews) and show the options. Only create_thread and start when they also asked to start.`;
138
+ if (!profile.accountNotes) return "";
139
+ return `- Account context (Settings \u2192 Agents): ${compactNotes(profile.accountNotes)}. When they ask to find work, use this with list_issues (tickets) and list_prs(queue=review) (reviews) and show the options. Only create_thread and start when they also asked to start. To change it, show the proposed text, ask_user (Save this context / Do not save), wait, then update_viewer_context(scope=account, confirmed=true).`;
182
140
  }
183
141
  function formatProjectProfilePlaybookLines(projects) {
184
142
  const lines = projects.map((project) => {
185
- const roles = (project.roleLabels ?? []).filter(Boolean);
186
143
  const notes = normalizeProfileNotes(project.notes);
187
- if (!roles.length && !notes) return "";
188
- const bits = [];
189
- if (roles.length) bits.push(`roles ${roles.join(", ")}`);
190
- if (notes) bits.push(compactNotes(notes, 120));
191
- return `- ${project.name}: ${bits.join(". ")}`;
144
+ if (!notes) return "";
145
+ return `- ${project.name}: ${compactNotes(notes, 120)}`;
192
146
  }).filter(Boolean);
193
147
  if (!lines.length) return "";
194
- return ["Project overrides (Settings \u2192 Projects; empty roles inherit account):", ...lines].join(
195
- "\n"
196
- );
148
+ return [
149
+ "Project context (Settings \u2192 Projects; adds to account context):",
150
+ ...lines
151
+ ].join("\n");
197
152
  }
198
153
  function formatWorkspaceProfileSuffix(profile) {
199
- const bits = [];
200
- if (profile.roles.length) bits.push(`roles:${profile.roles.join(",")}`);
201
- if (profile.projectNotes) bits.push(`notes:${compactNotes(profile.projectNotes, 80)}`);
202
- return bits.length ? ` ${bits.join(" ")}` : "";
154
+ if (!profile.projectNotes) return "";
155
+ return ` context:${compactNotes(profile.projectNotes, 80)}`;
156
+ }
157
+ function formatViewerContextDirective(profile) {
158
+ const account = profile.accountNotes || "(empty)";
159
+ const project = profile.projectNotes || "(empty \u2014 account context applies)";
160
+ return [
161
+ "Viewer context (Settings \u2192 Agents / Projects) \u2014 how to find this user\u2019s tickets and review PRs:",
162
+ `- Account: ${compactNotes(profile.accountNotes || account, 240)}`,
163
+ `- This project: ${compactNotes(profile.projectNotes || project, 240)}`,
164
+ "To change these, show the proposed text in chat, call ask_user (Save this context / Do not save), wait for the answer, then update_viewer_context with confirmed=true. Never write context without confirmation. get_viewer_context reads the current values."
165
+ ].join("\n");
166
+ }
167
+ function formatViewerContextReminder() {
168
+ return "Viewer context: get_viewer_context to read; update_viewer_context only after ask_user confirms (Save this context / Do not save).";
203
169
  }
204
170
 
205
171
  // src/store/secret-vault.ts
@@ -682,9 +648,7 @@ function normalizeDefaults(raw) {
682
648
  if (typeof source.fast === "boolean") {
683
649
  out.fast = source.fast;
684
650
  }
685
- const roles = normalizeAccountRoles(source.roles, source.role);
686
- if (roles.length) out.roles = roles;
687
- const notes = normalizeProfileNotes(source.notes);
651
+ const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
688
652
  if (notes) out.notes = notes;
689
653
  return out;
690
654
  }
@@ -695,11 +659,9 @@ function normalizeProjectProfile(raw) {
695
659
  if (!raw || typeof raw !== "object") return void 0;
696
660
  const source = raw;
697
661
  const out = {};
698
- const roles = normalizeAccountRoles(source.roles, source.role);
699
- if (roles.length) out.roles = roles;
700
- const notes = normalizeProfileNotes(source.notes);
662
+ const notes = foldLegacyRolesIntoNotes(source.roles, source.role, source.notes);
701
663
  if (notes) out.notes = notes;
702
- return out.roles || out.notes ? out : void 0;
664
+ return out.notes ? out : void 0;
703
665
  }
704
666
  function normalizeProjects(raw) {
705
667
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
@@ -1269,17 +1231,13 @@ function updateDefaultsSettings(patch) {
1269
1231
  defaults.fast = Boolean(patch.fast);
1270
1232
  }
1271
1233
  }
1272
- if ("roles" in patch) {
1273
- const roles = normalizeAccountRoles(patch.roles);
1274
- if (!roles.length) delete defaults.roles;
1275
- else defaults.roles = roles;
1276
- delete defaults.role;
1277
- }
1278
1234
  if ("notes" in patch) {
1279
1235
  const notes = normalizeProfileNotes(patch.notes);
1280
1236
  if (!notes) delete defaults.notes;
1281
1237
  else defaults.notes = notes;
1282
1238
  }
1239
+ delete defaults.roles;
1240
+ delete defaults.role;
1283
1241
  return saveAppSettings({ ...current, defaults });
1284
1242
  }
1285
1243
  function updateProjectProfileSettings(repoPath, patch) {
@@ -1289,17 +1247,14 @@ function updateProjectProfileSettings(repoPath, patch) {
1289
1247
  const projects = { ...current.projects };
1290
1248
  const existing = projects[key] ?? {};
1291
1249
  const next = { ...existing };
1292
- if ("roles" in patch) {
1293
- const roles = normalizeAccountRoles(patch.roles);
1294
- if (!roles.length) delete next.roles;
1295
- else next.roles = roles;
1296
- }
1297
1250
  if ("notes" in patch) {
1298
1251
  const notes = normalizeProfileNotes(patch.notes);
1299
1252
  if (!notes) delete next.notes;
1300
1253
  else next.notes = notes;
1301
1254
  }
1302
- if (!next.roles?.length && !next.notes) delete projects[key];
1255
+ delete next.roles;
1256
+ delete next.role;
1257
+ if (!next.notes) delete projects[key];
1303
1258
  else projects[key] = next;
1304
1259
  return saveAppSettings({ ...current, projects });
1305
1260
  }
@@ -1324,6 +1279,62 @@ function resolveViewerProfileForRepo(repoPath, settings = loadAppSettings()) {
1324
1279
  const project = key ? settings.projects[key] : void 0;
1325
1280
  return resolveViewerProfile(settings.defaults, project);
1326
1281
  }
1282
+ function readViewerContext(repoPath) {
1283
+ const settings = loadAppSettings();
1284
+ const key = findProjectProfileKey(settings.projects, repoPath);
1285
+ const resolved = resolveViewerProfile(
1286
+ settings.defaults,
1287
+ key ? settings.projects[key] : void 0
1288
+ );
1289
+ return {
1290
+ account: resolved.accountNotes,
1291
+ project: resolved.projectNotes,
1292
+ combined: resolved.notes,
1293
+ repoPath: key ?? (repoPath?.trim() ? profileRepoKey(repoPath) : null)
1294
+ };
1295
+ }
1296
+ var CONFIRM_ACCOUNT = "Show the user the proposed account context, call ask_user (Save this context / Do not save), wait for their answer, then retry with confirmed=true.";
1297
+ var CONFIRM_PROJECT = "Show the user the proposed project context, call ask_user (Save this context / Do not save), wait for their answer, then retry with confirmed=true.";
1298
+ function writeViewerContext(input) {
1299
+ const proposed = normalizeProfileNotes(input.context);
1300
+ if (input.scope === "project") {
1301
+ const settings = loadAppSettings();
1302
+ const key = findProjectProfileKey(settings.projects, input.repoPath) ?? profileRepoKey(input.repoPath ?? "");
1303
+ if (!key) {
1304
+ return {
1305
+ ok: false,
1306
+ error: "repoPath required",
1307
+ message: "Pass repoPath (or run from a registered worktree) when updating project context.",
1308
+ current: "",
1309
+ proposed
1310
+ };
1311
+ }
1312
+ const current2 = resolveViewerProfileForRepo(key, settings).projectNotes;
1313
+ if (!input.confirmed) {
1314
+ return {
1315
+ ok: false,
1316
+ error: "Confirmation required",
1317
+ message: CONFIRM_PROJECT,
1318
+ current: current2,
1319
+ proposed
1320
+ };
1321
+ }
1322
+ updateProjectProfileSettings(key, { notes: proposed || null });
1323
+ return { ok: true, scope: "project", context: proposed, repoPath: key };
1324
+ }
1325
+ const current = resolveAccountProfileFromSettings().accountNotes;
1326
+ if (!input.confirmed) {
1327
+ return {
1328
+ ok: false,
1329
+ error: "Confirmation required",
1330
+ message: CONFIRM_ACCOUNT,
1331
+ current,
1332
+ proposed
1333
+ };
1334
+ }
1335
+ updateDefaultsSettings({ notes: proposed || null });
1336
+ return { ok: true, scope: "account", context: proposed };
1337
+ }
1327
1338
  function resolveThreadDefaults(settings = loadAppSettings()) {
1328
1339
  return {
1329
1340
  agent: getDefaultAgent(settings),
@@ -1687,19 +1698,15 @@ export {
1687
1698
  readSecureJson,
1688
1699
  writeSecureJson,
1689
1700
  isSecureFileEncrypted,
1690
- ACCOUNT_ROLE_PRESETS,
1691
- ACCOUNT_ROLES,
1692
- ACCOUNT_ROLE_MAX,
1693
1701
  PROFILE_NOTES_MAX,
1694
- ACCOUNT_ROLE_LABELS,
1695
- accountRoleLabel,
1696
- reviewTeamHintsForRoles,
1702
+ foldLegacyRolesIntoNotes,
1697
1703
  resolveAccountProfile,
1698
1704
  resolveViewerProfile,
1699
- preferTeamsForRole,
1700
1705
  formatAccountProfilePlaybookLine,
1701
1706
  formatProjectProfilePlaybookLines,
1702
1707
  formatWorkspaceProfileSuffix,
1708
+ formatViewerContextDirective,
1709
+ formatViewerContextReminder,
1703
1710
  ISSUE_SOURCE_LABELS,
1704
1711
  issueSourceLabel,
1705
1712
  HARNESS_ENV_KEYS,
@@ -1726,6 +1733,8 @@ export {
1726
1733
  getDefaultFast,
1727
1734
  resolveAccountProfileFromSettings,
1728
1735
  resolveViewerProfileForRepo,
1736
+ readViewerContext,
1737
+ writeViewerContext,
1729
1738
  resolveThreadDefaults,
1730
1739
  resolveNewThreadOptions,
1731
1740
  isLinearConnected,