@codeam/shared 2.61.77 → 2.61.79

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.
package/dist/index.mjs CHANGED
@@ -1428,28 +1428,34 @@ var INTEGRATION_REGISTRY = {
1428
1428
  name: "Convex",
1429
1429
  icon: "convex",
1430
1430
  category: "database",
1431
- // LIVE — OAuth 2.0 (authorization code, Confidential). authorize
1432
- // dashboard.convex.dev/oauth/authorize/team (the scope is the URL PATH
1433
- // `team` for team-wide accessNOT a query param); token
1434
- // api.convex.dev/oauth/token (form-urlencoded, client creds in the BODY).
1435
- // ⚠️ Convex issues NO refresh token and the team-scoped application token
1436
- // does not expire, so there is nothing to rotate (refresh() is a re-link
1437
- // surface). The OAuth app (Team Settings OAuth Applications) is registered
1438
- // and CONVEX_OAUTH_CLIENT_ID/SECRET/REDIRECT_URI are in Secret Manager
1439
- // (prod+dev); the config-gated 503 keeps this safe mid-rollout.
1431
+ // LIVE — api_key rail (the user pastes a Convex DEPLOY KEY).
1432
+ // ⚠️ Convex's OAuth application token was tried first and DOES NOT WORK with
1433
+ // the MCP: it's a narrow Management-API credentialverified live it fails
1434
+ // `convex mcp start` as BOTH CONVEX_DEPLOY_KEY and CONVEX_OVERRIDE_ACCESS_TOKEN,
1435
+ // and can't even enumerate the team's deployments ("requires a Personal
1436
+ // Access Token"). The Convex MCP's DOCUMENTED headless credential is a
1437
+ // DEPLOY KEY (CONVEX_DEPLOY_KEY=dev:…|… / prod:… / project:…), so the user
1438
+ // pastes one (Convex Dashboard Project Settings → Deploy Keys), exactly
1439
+ // like Azure DevOps / Datadog / Trello. No OAuth app, no GSM secret.
1440
1440
  enabled: true,
1441
1441
  auth: {
1442
- kind: "oauth_redirect",
1443
- // ⚠️ Convex's scope is the authorize URL path (`/team`), NOT sent in the
1444
- // authorize URL as a query param — this list is informational.
1445
- scopes: []
1442
+ kind: "api_key",
1443
+ fields: [
1444
+ {
1445
+ key: "accessToken",
1446
+ label: "Convex deploy key",
1447
+ placeholder: "prod:happy-animal-123|eyJ2\u2026",
1448
+ secret: true,
1449
+ help: "Convex Dashboard \u2192 Project Settings \u2192 Deploy Keys \u2192 Generate a deploy key."
1450
+ }
1451
+ ]
1446
1452
  },
1447
1453
  delivery: {
1448
1454
  mcp: {
1449
1455
  // Convex's OFFICIAL MCP server ships inside the `convex` npm package
1450
- // (`convex mcp start`). The team-scoped OAuth application token doubles
1451
- // as the CLI/MCP deploy key fed via CONVEX_DEPLOY_KEY (env only, never
1452
- // argv). Version PINNED; bump only after re-verifying headless.
1456
+ // (`convex mcp start`). The pasted deploy key is fed via CONVEX_DEPLOY_KEY
1457
+ // (env only, never argv) its documented non-interactive credential.
1458
+ // Version PINNED; bump only after re-verifying headless.
1453
1459
  command: "npx",
1454
1460
  args: ["-y", "convex@1.42.3", "mcp", "start"],
1455
1461
  envMapping: {
@@ -1896,6 +1902,145 @@ function getIntegrationBranding(id) {
1896
1902
  return INTEGRATION_BRANDING[id] ?? null;
1897
1903
  }
1898
1904
 
1905
+ // src/integrations/stack-detect.ts
1906
+ var DEP_TO_INTEGRATION = {
1907
+ // errors / observability
1908
+ "@sentry/node": "sentry",
1909
+ "@sentry/react": "sentry",
1910
+ "@sentry/nextjs": "sentry",
1911
+ "@sentry/browser": "sentry",
1912
+ "sentry-sdk": "sentry",
1913
+ "dd-trace": "datadog",
1914
+ "datadog-api-client": "datadog",
1915
+ "datadog-metrics": "datadog",
1916
+ // analytics
1917
+ "posthog-js": "posthog",
1918
+ "posthog-node": "posthog",
1919
+ posthog: "posthog",
1920
+ mixpanel: "mixpanel",
1921
+ "mixpanel-browser": "mixpanel",
1922
+ // database / backend platforms
1923
+ convex: "convex",
1924
+ "@supabase/supabase-js": "supabase",
1925
+ "supabase": "supabase",
1926
+ // infra / deploy
1927
+ vercel: "vercel",
1928
+ "@vercel/node": "vercel",
1929
+ wrangler: "cloudflare",
1930
+ // comms
1931
+ "@slack/web-api": "slack",
1932
+ "@slack/bolt": "slack",
1933
+ "discord.js": "discord",
1934
+ "discord-py": "discord",
1935
+ "discord": "discord",
1936
+ // trackers / docs / design
1937
+ "@linear/sdk": "linear",
1938
+ "@notionhq/client": "notion",
1939
+ "jira.js": "jira",
1940
+ jira: "jira",
1941
+ newman: "postman",
1942
+ "figma-api": "figma",
1943
+ "figma-js": "figma",
1944
+ // email / automation
1945
+ resend: "resend",
1946
+ n8n: "n8n"
1947
+ };
1948
+ var DEP_PREFIX_TO_INTEGRATION = [
1949
+ ["@sentry/", "sentry"],
1950
+ ["@vercel/", "vercel"],
1951
+ ["@cloudflare/", "cloudflare"],
1952
+ ["@supabase/", "supabase"],
1953
+ ["@slack/", "slack"],
1954
+ ["@datadog/", "datadog"],
1955
+ ["@linear/", "linear"],
1956
+ ["@notionhq/", "notion"]
1957
+ ];
1958
+ var FRONTEND_MARKERS = [
1959
+ "react",
1960
+ "react-dom",
1961
+ "next",
1962
+ "vue",
1963
+ "nuxt",
1964
+ "@angular/core",
1965
+ "svelte",
1966
+ "@sveltejs/kit",
1967
+ "solid-js",
1968
+ "astro",
1969
+ "gatsby",
1970
+ "remix",
1971
+ "@remix-run/react"
1972
+ ];
1973
+ var MOBILE_MARKERS = ["react-native", "expo", "@react-native/core", "@ionic/core", "flutter"];
1974
+ var BACKEND_MARKERS = [
1975
+ "express",
1976
+ "fastify",
1977
+ "@nestjs/core",
1978
+ "koa",
1979
+ "@hapi/hapi",
1980
+ "django",
1981
+ "flask",
1982
+ "fastapi",
1983
+ "rails",
1984
+ "sinatra",
1985
+ "gin-gonic",
1986
+ "laravel/framework",
1987
+ "actix-web",
1988
+ "spring-boot"
1989
+ ];
1990
+ function hasAny(deps, markers) {
1991
+ for (const m of markers) if (deps.has(m)) return true;
1992
+ return false;
1993
+ }
1994
+ function classifyStack(depNames) {
1995
+ const deps = new Set(depNames);
1996
+ const mobile = hasAny(deps, MOBILE_MARKERS);
1997
+ if (mobile) return "mobile";
1998
+ const frontend = hasAny(deps, FRONTEND_MARKERS);
1999
+ const backend = hasAny(deps, BACKEND_MARKERS);
2000
+ if (frontend && backend) return "fullstack";
2001
+ if (frontend) return "frontend";
2002
+ if (backend) return "backend";
2003
+ return "unknown";
2004
+ }
2005
+ function detectedIntegrationsFromDeps(depNames) {
2006
+ const out = [];
2007
+ const seen = /* @__PURE__ */ new Set();
2008
+ const push = (id) => {
2009
+ if (!seen.has(id)) {
2010
+ seen.add(id);
2011
+ out.push(id);
2012
+ }
2013
+ };
2014
+ for (const name of depNames) {
2015
+ const exact = DEP_TO_INTEGRATION[name];
2016
+ if (exact) {
2017
+ push(exact);
2018
+ continue;
2019
+ }
2020
+ for (const [prefix, id] of DEP_PREFIX_TO_INTEGRATION) {
2021
+ if (name.startsWith(prefix)) {
2022
+ push(id);
2023
+ break;
2024
+ }
2025
+ }
2026
+ }
2027
+ return out;
2028
+ }
2029
+ var STACK_TO_RECOMMENDED = {
2030
+ frontend: ["figma", "sentry", "posthog", "vercel"],
2031
+ backend: ["sentry", "datadog", "supabase", "convex", "cloudflare"],
2032
+ fullstack: ["sentry", "posthog", "vercel", "supabase", "convex"],
2033
+ mobile: ["sentry", "posthog"],
2034
+ unknown: []
2035
+ };
2036
+ function recommendForDeps(depNames) {
2037
+ const stack = classifyStack(depNames);
2038
+ const detected = detectedIntegrationsFromDeps(depNames);
2039
+ const detectedSet = new Set(detected);
2040
+ const recommended = STACK_TO_RECOMMENDED[stack].filter((id) => !detectedSet.has(id));
2041
+ return { stack, detected, recommended, source: "scan" };
2042
+ }
2043
+
1899
2044
  // src/skills/code-review.ts
1900
2045
  var CODE_REVIEW_BODY = `Use this skill when reviewing a pull request. It defines what a high-signal
1901
2046
  review looks like so your inline comments are worth the author's time.
@@ -2330,6 +2475,14 @@ var USER_EVENTS = {
2330
2475
  INTEGRATION_LINKED: "integration_linked",
2331
2476
  INTEGRATION_UNLINKED: "integration_unlinked",
2332
2477
  INTEGRATION_CREDENTIAL_INVALID: "integration_credential_invalid",
2478
+ // Session Tools — add/remove Agent Toolkit integrations on an ALREADY-ACTIVE
2479
+ // session. The backend publishes SESSION_INTEGRATIONS_CHANGED after it persists
2480
+ // the new attached set + relays `integrations_sync` to the box (the CLI rewrites
2481
+ // the manifest + reprovisions the live agent, answered synchronously via the
2482
+ // command result). Drives live UI on the sending device AND any other paired
2483
+ // device on the same session. Mirrored in repo A. (`integrations_detect` is a
2484
+ // pure request/response over the relay — no event.)
2485
+ SESSION_INTEGRATIONS_CHANGED: "session_integrations_changed",
2333
2486
  // CodeRabbit reviewer — the CLI posts these to /api/coderabbit/events; the
2334
2487
  // backend re-publishes them on the per-user SSE bus (mirrored in repo A).
2335
2488
  CODERABBIT_PROGRESS: "coderabbit_progress",
@@ -2395,6 +2548,7 @@ OUTPUT JSON ONLY. NO MARKDOWN. NO COMMENTARY.
2395
2548
  export {
2396
2549
  AGENT_REGISTRY,
2397
2550
  DEFAULT_API_BASE_URL,
2551
+ DEP_TO_INTEGRATION,
2398
2552
  DEV_API_BASE_URL,
2399
2553
  HEADROOM_BACKEND_ENV,
2400
2554
  HEADROOM_EXTRAS_BY_SURFACE,
@@ -2419,10 +2573,13 @@ export {
2419
2573
  PUBLIC_TO_INTERNAL,
2420
2574
  SKILL_REGISTRY,
2421
2575
  SSE_SOCKET_TIMEOUT_MS,
2576
+ STACK_TO_RECOMMENDED,
2422
2577
  TERMINAL_AGENT_PREFIX,
2423
2578
  UNKNOWN_MODEL_PRICING,
2424
2579
  UPCOMING_INTEGRATION_IDS,
2425
2580
  USER_EVENTS,
2581
+ classifyStack,
2582
+ detectedIntegrationsFromDeps,
2426
2583
  getAgent,
2427
2584
  getContextWindow,
2428
2585
  getEnabledAgents,
@@ -2445,6 +2602,7 @@ export {
2445
2602
  isSkillId,
2446
2603
  normalizeAgentId,
2447
2604
  publicToInternal,
2605
+ recommendForDeps,
2448
2606
  renderToLines,
2449
2607
  resolveApiBaseUrl,
2450
2608
  skillHasRail,