@sideboard-ai/core 0.1.287 → 0.1.289

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 (65) hide show
  1. package/dist/{abletime-I4RODUKT.js → abletime-4WJUVE64.js} +4 -4
  2. package/dist/{abletime-4CH2IOX5.js → abletime-VFKYNSJT.js} +4 -4
  3. package/dist/{abletime-oauth-7OZZ3ABX.js → abletime-oauth-FW24YHYX.js} +3 -3
  4. package/dist/{abletime-oauth-C2HN2Q6F.js → abletime-oauth-ICMB2XV2.js} +3 -3
  5. package/dist/{abletime-rest-E4LBRFLM.js → abletime-rest-HFMRTUDT.js} +3 -3
  6. package/dist/{abletime-rest-WFI2HWBU.js → abletime-rest-OGWC7BC6.js} +3 -3
  7. package/dist/agents/cursor-runner.js +3 -3
  8. package/dist/{agents-D3PU4UCP.js → agents-4BBCKITL.js} +20 -18
  9. package/dist/{agents-KU4QPB3Y.js → agents-XAKSP653.js} +18 -16
  10. package/dist/{app-settings-EQQZQNYD.js → app-settings-EHMXHNG5.js} +1 -1
  11. package/dist/{app-settings-NI4X5HW3.js → app-settings-MR2U6AXN.js} +1 -1
  12. package/dist/{chunk-K5XSTHHP.js → chunk-2IXKTAIT.js} +2 -2
  13. package/dist/{chunk-YNTXWFXT.js → chunk-36J3IZBS.js} +12 -12
  14. package/dist/{chunk-IJMUYHPT.js → chunk-3E4NOIXN.js} +3 -3
  15. package/dist/chunk-4BXRRHDC.js +139 -0
  16. package/dist/{chunk-5MGLNVNK.js → chunk-5HPMKLJ7.js} +2 -2
  17. package/dist/{chunk-VOIWX5HA.js → chunk-7UUILVMV.js} +1 -1
  18. package/dist/chunk-AF2DMY3K.js +295 -0
  19. package/dist/{chunk-5QOLFOAX.js → chunk-AFLNFGGB.js} +1 -1
  20. package/dist/{chunk-5T4YWFLD.js → chunk-AHH5USEA.js} +2 -2
  21. package/dist/{chunk-6CVVNAIU.js → chunk-B3BPLPKQ.js} +2 -2
  22. package/dist/{chunk-LKVP7JCB.js → chunk-C546EOEF.js} +35 -315
  23. package/dist/{chunk-QPBR5SAL.js → chunk-EBGJXOXT.js} +27 -129
  24. package/dist/{chunk-RFPMTOV2.js → chunk-G74TSBJ3.js} +6 -6
  25. package/dist/{chunk-L65YT2SC.js → chunk-GBAACE3C.js} +7 -7
  26. package/dist/{chunk-VQEARG5H.js → chunk-GU6DT6NO.js} +5 -5
  27. package/dist/{chunk-S2OOM7AU.js → chunk-K6IOJI3L.js} +1 -1
  28. package/dist/{chunk-UFJLNCOF.js → chunk-LUQ7MIVD.js} +8 -298
  29. package/dist/{chunk-U6QDXT4K.js → chunk-MIVX7QKI.js} +1 -1
  30. package/dist/{chunk-WRIMAEF2.js → chunk-MVZO7QZ2.js} +12 -12
  31. package/dist/{chunk-LS4FFCPL.js → chunk-MYJYINTS.js} +3 -3
  32. package/dist/{chunk-DEJALWKM.js → chunk-NFPWLDCH.js} +5 -5
  33. package/dist/chunk-NXXQFLNQ.js +300 -0
  34. package/dist/{chunk-KLAQ4G34.js → chunk-O4324MXE.js} +4 -4
  35. package/dist/chunk-OH4EN323.js +89 -0
  36. package/dist/{chunk-ZGAMETNF.js → chunk-V3BSO2O6.js} +4 -4
  37. package/dist/{chunk-Z3EE3PUZ.js → chunk-VNCPRMIK.js} +10 -300
  38. package/dist/chunk-W2KZTDET.js +302 -0
  39. package/dist/{chunk-TMM4FEZ5.js → chunk-Y67TBJD5.js} +3 -3
  40. package/dist/{chunk-XSDCLM3F.js → chunk-YSLCWCMJ.js} +1 -1
  41. package/dist/{conductor-FOKYVMUE.js → conductor-5MNGC25D.js} +6 -6
  42. package/dist/{conductor-KDUL6AMD.js → conductor-UFJXJPTF.js} +7 -7
  43. package/dist/{coordinator-prompt-GU5PGLG6.js → coordinator-prompt-5Q66Y5KW.js} +4 -4
  44. package/dist/{coordinator-prompt-YARYX53V.js → coordinator-prompt-BYPEW6DE.js} +4 -4
  45. package/dist/{global-workspace-SMCPOWE5.js → global-workspace-BTH2YGDZ.js} +4 -4
  46. package/dist/{global-workspace-C5HMC66E.js → global-workspace-YKOYXSB2.js} +4 -4
  47. package/dist/index.cjs +618 -323
  48. package/dist/index.d.cts +42 -10
  49. package/dist/index.d.ts +42 -10
  50. package/dist/index.js +494 -281
  51. package/dist/mcp/run-stdio.cjs +602 -225
  52. package/dist/mcp/run-stdio.js +334 -188
  53. package/dist/optional-cli-6SW4OOX3.js +23 -0
  54. package/dist/optional-cli-FRUZSZ3U.js +98 -0
  55. package/dist/{orchestrator-2UAVOXTN.js → orchestrator-IG4VU7MT.js} +13 -11
  56. package/dist/{orchestrator-NWKE56BW.js → orchestrator-MKF3YBNK.js} +10 -8
  57. package/dist/{thread-store-7XBOUQ5K.js → thread-store-DPKESDFR.js} +1 -1
  58. package/dist/{thread-store-ZQZDREVH.js → thread-store-X6S2GIR5.js} +1 -1
  59. package/dist/{workspaces-KHQ5ETSQ.js → workspaces-ELO2YVTU.js} +4 -4
  60. package/dist/{workspaces-DQMDCRB2.js → workspaces-RFD6I4FM.js} +4 -4
  61. package/dist/{worktree-NKLNVNXX.js → worktree-ADVQ6X6C.js} +3 -3
  62. package/dist/{worktree-YTZC3UQN.js → worktree-TN7DZDJZ.js} +3 -3
  63. package/package.json +1 -1
  64. /package/dist/{chunk-N5UGX3JL.js → chunk-QB5MDOHL.js} +0 -0
  65. /package/dist/{chunk-JPH7PYSK.js → chunk-YRXV3E7J.js} +0 -0
@@ -0,0 +1,295 @@
1
+ import {
2
+ httpFetch
3
+ } from "./chunk-JAT3JFOS.js";
4
+ import {
5
+ loadAppSettings,
6
+ saveAppSettings
7
+ } from "./chunk-36J3IZBS.js";
8
+
9
+ // src/integrations/optional-services.ts
10
+ var OPTIONAL_SERVICE_IDS = ["vercel", "supabase", "posthog", "sentry"];
11
+ var OPTIONAL_SERVICES = [
12
+ {
13
+ id: "vercel",
14
+ label: "Vercel",
15
+ hint: "Deploys and project settings. Agents use the `vercel` CLI (`VERCEL_TOKEN`).",
16
+ tokenPlaceholder: "token from vercel.com/account/tokens",
17
+ tokenDocs: "https://vercel.com/account/tokens",
18
+ envKey: "VERCEL_TOKEN",
19
+ cli: "vercel",
20
+ npmPackage: "vercel"
21
+ },
22
+ {
23
+ id: "supabase",
24
+ label: "Supabase",
25
+ hint: "Database and project management. Agents use the `supabase` CLI (`SUPABASE_ACCESS_TOKEN`).",
26
+ tokenPlaceholder: "sbp_\u2026",
27
+ tokenDocs: "https://supabase.com/dashboard/account/tokens",
28
+ envKey: "SUPABASE_ACCESS_TOKEN",
29
+ cli: "supabase",
30
+ npmPackage: "supabase"
31
+ },
32
+ {
33
+ id: "posthog",
34
+ label: "PostHog",
35
+ hint: "Product analytics. Agents call `posthog_api` on the Sideboard MCP server.",
36
+ tokenPlaceholder: "phx_\u2026",
37
+ tokenDocs: "https://app.posthog.com/settings/user-api-keys",
38
+ envKey: "POSTHOG_PERSONAL_API_KEY",
39
+ hostEnvKey: "POSTHOG_HOST",
40
+ defaultHost: "https://us.posthog.com",
41
+ hostPlaceholder: "https://us.posthog.com"
42
+ },
43
+ {
44
+ id: "sentry",
45
+ label: "Sentry",
46
+ hint: "Error tracking. Agents use `sentry-cli` (`SENTRY_AUTH_TOKEN`).",
47
+ tokenPlaceholder: "sntrys_\u2026 or auth token",
48
+ tokenDocs: "https://sentry.io/settings/account/api/auth-tokens/",
49
+ envKey: "SENTRY_AUTH_TOKEN",
50
+ cli: "sentry-cli",
51
+ npmPackage: "@sentry/cli",
52
+ hostEnvKey: "SENTRY_URL",
53
+ defaultHost: "https://sentry.io",
54
+ hostPlaceholder: "https://sentry.io"
55
+ }
56
+ ];
57
+ function optionalServiceSpec(id) {
58
+ const spec = OPTIONAL_SERVICES.find((s) => s.id === id);
59
+ if (!spec) throw new Error(`Unknown optional service: ${id}`);
60
+ return spec;
61
+ }
62
+ function isOptionalServiceId(value) {
63
+ return typeof value === "string" && OPTIONAL_SERVICE_IDS.includes(value);
64
+ }
65
+ function normalizeServiceOrigin(raw, fallback) {
66
+ const trimmed = raw?.trim() || fallback;
67
+ try {
68
+ const url = new URL(trimmed.includes("://") ? trimmed : `https://${trimmed}`);
69
+ if (url.protocol !== "http:" && url.protocol !== "https:") return fallback;
70
+ return `${url.protocol}//${url.host}`;
71
+ } catch {
72
+ return fallback;
73
+ }
74
+ }
75
+ function asRecord(value) {
76
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
77
+ }
78
+ function asString(value) {
79
+ return typeof value === "string" ? value.trim() : "";
80
+ }
81
+ function firstString(record, keys) {
82
+ if (!record) return "";
83
+ for (const key of keys) {
84
+ const value = asString(record[key]);
85
+ if (value) return value;
86
+ }
87
+ return "";
88
+ }
89
+ async function readJson(res) {
90
+ const text = await res.text();
91
+ if (!text.trim()) return null;
92
+ try {
93
+ return JSON.parse(text);
94
+ } catch {
95
+ return text;
96
+ }
97
+ }
98
+ async function authorizedGet(url, token) {
99
+ const res = await httpFetch(url, {
100
+ method: "GET",
101
+ headers: {
102
+ Authorization: `Bearer ${token}`,
103
+ Accept: "application/json"
104
+ }
105
+ });
106
+ const body = await readJson(res);
107
+ if (!res.ok) {
108
+ const record = asRecord(body);
109
+ const message = firstString(record, ["message", "error", "error_description", "detail"]) || (typeof body === "string" ? body.trim().slice(0, 160) : "");
110
+ throw new Error(
111
+ message ? `${res.status}: ${message}` : `Request failed (${res.status})`
112
+ );
113
+ }
114
+ return body;
115
+ }
116
+ async function verifyOptionalService(input) {
117
+ const token = input.token.trim();
118
+ if (!token) throw new Error("A token is required");
119
+ const spec = optionalServiceSpec(input.id);
120
+ try {
121
+ if (input.id === "vercel") {
122
+ const body2 = asRecord(await authorizedGet("https://api.vercel.com/v2/user", token));
123
+ const user = asRecord(body2?.user) ?? body2;
124
+ const name2 = firstString(user, ["username", "name", "email"]) || "Vercel user";
125
+ return { viewerName: name2 };
126
+ }
127
+ if (input.id === "supabase") {
128
+ const body2 = await authorizedGet("https://api.supabase.com/v1/organizations", token);
129
+ const list2 = Array.isArray(body2) ? body2 : [];
130
+ const first2 = asRecord(list2[0]);
131
+ const name2 = firstString(first2, ["name", "slug"]) || "Supabase";
132
+ return { viewerName: list2.length > 1 ? `${name2} +${list2.length - 1}` : name2 };
133
+ }
134
+ if (input.id === "posthog") {
135
+ const host2 = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://us.posthog.com");
136
+ const body2 = asRecord(await authorizedGet(`${host2}/api/users/@me/`, token));
137
+ const name2 = firstString(body2, ["email", "distinct_id"]) || [firstString(body2, ["first_name"]), firstString(body2, ["last_name"])].filter(Boolean).join(" ") || "PostHog user";
138
+ return { viewerName: name2, host: host2 };
139
+ }
140
+ const host = normalizeServiceOrigin(input.host, spec.defaultHost ?? "https://sentry.io");
141
+ const body = await authorizedGet(`${host}/api/0/organizations/`, token);
142
+ const list = Array.isArray(body) ? body : [];
143
+ const first = asRecord(list[0]);
144
+ const name = firstString(first, ["slug", "name"]) || "Sentry";
145
+ return { viewerName: list.length > 1 ? `${name} +${list.length - 1}` : name, host };
146
+ } catch (err) {
147
+ const detail = err instanceof Error ? err.message : String(err);
148
+ throw new Error(
149
+ `${spec.label} rejected this token. ${detail} Create a token at ${spec.tokenDocs}`
150
+ );
151
+ }
152
+ }
153
+ function applyConnection(integrations, id, input) {
154
+ if (id === "vercel") {
155
+ integrations.vercelToken = input.token;
156
+ if (input.viewerName) integrations.vercelViewerName = input.viewerName.slice(0, 120);
157
+ return;
158
+ }
159
+ if (id === "supabase") {
160
+ integrations.supabaseAccessToken = input.token;
161
+ if (input.viewerName) integrations.supabaseViewerName = input.viewerName.slice(0, 120);
162
+ return;
163
+ }
164
+ if (id === "posthog") {
165
+ integrations.posthogPersonalApiKey = input.token;
166
+ if (input.host) integrations.posthogHost = input.host;
167
+ if (input.viewerName) integrations.posthogViewerName = input.viewerName.slice(0, 120);
168
+ return;
169
+ }
170
+ integrations.sentryAuthToken = input.token;
171
+ if (input.host) integrations.sentryHost = input.host;
172
+ if (input.viewerName) integrations.sentryViewerName = input.viewerName.slice(0, 120);
173
+ }
174
+ function clearConnection(integrations, id) {
175
+ if (id === "vercel") {
176
+ delete integrations.vercelToken;
177
+ delete integrations.vercelViewerName;
178
+ return;
179
+ }
180
+ if (id === "supabase") {
181
+ delete integrations.supabaseAccessToken;
182
+ delete integrations.supabaseViewerName;
183
+ return;
184
+ }
185
+ if (id === "posthog") {
186
+ delete integrations.posthogPersonalApiKey;
187
+ delete integrations.posthogViewerName;
188
+ delete integrations.posthogHost;
189
+ return;
190
+ }
191
+ delete integrations.sentryAuthToken;
192
+ delete integrations.sentryViewerName;
193
+ delete integrations.sentryHost;
194
+ }
195
+ async function connectOptionalService(input) {
196
+ if (!isOptionalServiceId(input.id)) {
197
+ throw new Error("Unknown optional service");
198
+ }
199
+ const verified = await verifyOptionalService(input);
200
+ const current = loadAppSettings();
201
+ const integrations = { ...current.integrations };
202
+ applyConnection(integrations, input.id, {
203
+ token: input.token.trim(),
204
+ host: verified.host,
205
+ viewerName: verified.viewerName
206
+ });
207
+ return saveAppSettings({ ...current, integrations });
208
+ }
209
+ function disconnectOptionalService(id) {
210
+ if (!isOptionalServiceId(id)) {
211
+ throw new Error("Unknown optional service");
212
+ }
213
+ const current = loadAppSettings();
214
+ const integrations = { ...current.integrations };
215
+ clearConnection(integrations, id);
216
+ return saveAppSettings({ ...current, integrations });
217
+ }
218
+ function optionalServiceConnected(id, integrations) {
219
+ if (id === "vercel") return Boolean(integrations.vercelToken?.trim());
220
+ if (id === "supabase") return Boolean(integrations.supabaseAccessToken?.trim());
221
+ if (id === "posthog") return Boolean(integrations.posthogPersonalApiKey?.trim());
222
+ return Boolean(integrations.sentryAuthToken?.trim());
223
+ }
224
+ function connectedOptionalServices(integrations) {
225
+ return OPTIONAL_SERVICES.filter((spec) => optionalServiceConnected(spec.id, integrations));
226
+ }
227
+ function cliPresencePhrase(spec, cli) {
228
+ if (!spec.cli || !cli || !(spec.id in cli)) return "";
229
+ return cli[spec.id] ? " (installed)" : " (not installed \u2014 ask the user to press Install CLI in Settings \u2192 Connectors)";
230
+ }
231
+ function connectorDirectiveLine(spec, cli) {
232
+ const extras = spec.hostEnvKey ? ` / \`${spec.hostEnvKey}\`` : "";
233
+ if (spec.cli) {
234
+ return `- ${spec.label}: use \`${spec.cli}\` (\`${spec.envKey}\`${extras})${cliPresencePhrase(spec, cli)}. Do not add a ${spec.label} MCP.`;
235
+ }
236
+ return `- ${spec.label}: call \`posthog_api\`. Path must start with \`/api/\`. GET is the default. POST \`/api/projects/:id/query/\` or \`/api/environments/:id/query/\` is a read and does not need \`write=true\`. Other POST and PATCH require \`write=true\` only when the user asked to change data. Do not read the API key from the environment. Do not add a ${spec.label} MCP.`;
237
+ }
238
+ function connectorReminderBit(spec, cli) {
239
+ if (!spec.cli) return `${spec.label}: \`posthog_api\``;
240
+ const presence = cliPresencePhrase(spec, cli);
241
+ return `${spec.label}: \`${spec.cli}\`${presence}`;
242
+ }
243
+ function formatOptionalServicesDirective(integrations, cli) {
244
+ const connected = connectedOptionalServices(integrations);
245
+ if (connected.length === 0) return null;
246
+ const cliConnected = connected.some((spec) => spec.cli);
247
+ const lines = [
248
+ cliConnected ? "Optional connectors (connected \u2014 CLI tokens are already in this process env):" : "Optional connectors (connected):",
249
+ ...connected.map((spec) => connectorDirectiveLine(spec, cli)),
250
+ cliConnected ? "If a connector MCP is listed but needsAuth or returns unauthorized, do not sign in to that MCP. CLI tokens are already in this process. Do not read a PostHog key from the environment." : "If a connector MCP is listed but needsAuth or returns unauthorized, do not sign in to that MCP. Do not read a PostHog key from the environment.",
251
+ "Do not add a vendor MCP. When a binary is missing, ask the user to press Install CLI in Settings \u2192 Connectors.",
252
+ "When you shell a connector CLI, write bulky output to `.context/cli/` and read a slice."
253
+ ];
254
+ return lines.join("\n");
255
+ }
256
+ function formatOptionalServicesReminder(integrations, cli) {
257
+ const connected = connectedOptionalServices(integrations);
258
+ if (connected.length === 0) return null;
259
+ const bits = connected.map((spec) => connectorReminderBit(spec, cli)).join(". ");
260
+ const tokenBit = connected.some((spec) => spec.cli) ? "CLI tokens are already in this process. " : "";
261
+ return `Settings \u2192 Connectors: ${tokenBit}${bits}. If a connector MCP needsAuth or is unauthorized, ignore it and use the CLI or \`posthog_api\`. Do not add vendor MCPs. Do not read a PostHog key from the environment. Shell dumps from those CLIs go in \`.context/cli/\` \u2014 read a slice.`;
262
+ }
263
+ async function connectedCliPresence(integrations) {
264
+ const ids = connectedOptionalServices(integrations).filter((spec) => spec.cli).map((spec) => spec.id);
265
+ if (ids.length === 0) return void 0;
266
+ try {
267
+ const { optionalCliPresence } = await import("./optional-cli-6SW4OOX3.js");
268
+ return await optionalCliPresence(ids);
269
+ } catch {
270
+ return void 0;
271
+ }
272
+ }
273
+ async function formatOptionalServicesDirectiveForTurn(integrations) {
274
+ return formatOptionalServicesDirective(integrations, await connectedCliPresence(integrations));
275
+ }
276
+ async function formatOptionalServicesReminderForTurn(integrations) {
277
+ return formatOptionalServicesReminder(integrations, await connectedCliPresence(integrations));
278
+ }
279
+
280
+ export {
281
+ OPTIONAL_SERVICE_IDS,
282
+ OPTIONAL_SERVICES,
283
+ optionalServiceSpec,
284
+ isOptionalServiceId,
285
+ normalizeServiceOrigin,
286
+ verifyOptionalService,
287
+ connectOptionalService,
288
+ disconnectOptionalService,
289
+ optionalServiceConnected,
290
+ connectedOptionalServices,
291
+ formatOptionalServicesDirective,
292
+ formatOptionalServicesReminder,
293
+ formatOptionalServicesDirectiveForTurn,
294
+ formatOptionalServicesReminderForTurn
295
+ };
@@ -272,7 +272,7 @@ function humanizeAgentFailDetail(detail) {
272
272
  return "Cursor local file search failed (ripgrep / resource_exhausted). Wait a minute and retry; if it keeps happening, check Cursor usage.";
273
273
  }
274
274
  if (looksLikeCodexMcpError(raw)) {
275
- return `${raw} \u2014 skip that vendor MCP and continue (PostHog: Settings \u2192 Connectors + HTTP API).`;
275
+ return `${raw} \u2014 skip that vendor MCP and continue (PostHog: Settings \u2192 Connectors and posthog_api).`;
276
276
  }
277
277
  if (/invalid user api key|invalid api key|not logged in|not authenticated|unauthorized|authentication|please run.*login|codex login|claude auth|cursor api/.test(
278
278
  lower
@@ -6,14 +6,14 @@ import {
6
6
  normalizeAbleTimeCredential,
7
7
  normalizeAbleTimeHost,
8
8
  rewriteAbleTimeError
9
- } from "./chunk-VQEARG5H.js";
9
+ } from "./chunk-GU6DT6NO.js";
10
10
  import {
11
11
  httpFetch
12
12
  } from "./chunk-2GPQZZLY.js";
13
13
  import {
14
14
  getAbleTimeAccessToken,
15
15
  getAbleTimeHost
16
- } from "./chunk-WRIMAEF2.js";
16
+ } from "./chunk-MVZO7QZ2.js";
17
17
 
18
18
  // src/integrations/abletime-rest.ts
19
19
  var ABLETIME_REST_PREFIX = "/api/public/v2";
@@ -4,14 +4,14 @@ import {
4
4
  normalizeAbleTimeCredential,
5
5
  normalizeAbleTimeHost,
6
6
  rewriteAbleTimeError
7
- } from "./chunk-DEJALWKM.js";
7
+ } from "./chunk-NFPWLDCH.js";
8
8
  import {
9
9
  httpFetch
10
10
  } from "./chunk-JAT3JFOS.js";
11
11
  import {
12
12
  getAbleTimeAccessToken,
13
13
  getAbleTimeHost
14
- } from "./chunk-YNTXWFXT.js";
14
+ } from "./chunk-36J3IZBS.js";
15
15
 
16
16
  // src/integrations/abletime-rest.ts
17
17
  var ABLETIME_REST_PREFIX = "/api/public/v2";