@cosmoops/connect-sdk 0.6.0 → 0.9.0

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 (138) hide show
  1. package/CHANGELOG.md +165 -0
  2. package/README.md +273 -91
  3. package/dist/cjs/cli/doctor.js +3 -3
  4. package/dist/cjs/cli/init.js +3 -3
  5. package/dist/cjs/client/components/access-gate.js +42 -7
  6. package/dist/cjs/client/components/account-sessions.js +3 -3
  7. package/dist/cjs/client/components/ai-format.js +135 -0
  8. package/dist/cjs/client/components/ai-widgets.js +232 -0
  9. package/dist/cjs/client/components/app-shell.js +9 -8
  10. package/dist/cjs/client/components/apps-grid.js +3 -3
  11. package/dist/cjs/client/components/ask-ai.js +334 -0
  12. package/dist/cjs/client/components/feature-gate.js +2 -2
  13. package/dist/cjs/client/components/integrations-modal.js +1 -1
  14. package/dist/cjs/client/components/logo.js +3 -3
  15. package/dist/cjs/client/components/nav.js +1 -1
  16. package/dist/cjs/client/components/plan-pricing.js +1 -1
  17. package/dist/cjs/client/components/plans.js +6 -6
  18. package/dist/cjs/client/components/readiness.js +3 -3
  19. package/dist/cjs/client/components/side-nav.js +1 -1
  20. package/dist/cjs/client/components/subscribe-dialog.js +2 -2
  21. package/dist/cjs/client/components/subscription.js +1 -1
  22. package/dist/cjs/client/components/usage-meter.js +1 -1
  23. package/dist/cjs/client/components/user-menu.js +31 -8
  24. package/dist/cjs/client/components/workspace-type-gate.js +48 -0
  25. package/dist/cjs/client/index.js +32 -4
  26. package/dist/cjs/client/mark.js +1 -1
  27. package/dist/cjs/client/provider.js +50 -7
  28. package/dist/cjs/client/use-checkout.js +3 -3
  29. package/dist/cjs/errors.js +4 -4
  30. package/dist/cjs/helpers.js +1 -1
  31. package/dist/cjs/index.js +1 -1
  32. package/dist/cjs/next/index.js +2 -2
  33. package/dist/cjs/server/client.js +15 -15
  34. package/dist/cjs/server/handler.js +56 -13
  35. package/dist/cjs/server/http.js +47 -25
  36. package/dist/cjs/server/resources/access.js +3 -3
  37. package/dist/cjs/server/resources/ai.js +1 -1
  38. package/dist/cjs/server/resources/analytics.js +2 -2
  39. package/dist/cjs/server/resources/apps.js +4 -4
  40. package/dist/cjs/server/resources/billing.js +5 -5
  41. package/dist/cjs/server/resources/drive.js +4 -4
  42. package/dist/cjs/server/resources/entitlements.js +48 -7
  43. package/dist/cjs/server/resources/identity.js +6 -4
  44. package/dist/cjs/server/resources/integrations.js +13 -13
  45. package/dist/cjs/server/resources/logs.js +3 -3
  46. package/dist/cjs/server/resources/sessions.js +6 -6
  47. package/dist/cjs/server/webhooks.js +4 -4
  48. package/dist/cjs/types.js +1 -1
  49. package/dist/esm/cli/doctor.js +3 -3
  50. package/dist/esm/cli/init.js +3 -3
  51. package/dist/esm/client/components/access-gate.js +43 -8
  52. package/dist/esm/client/components/account-sessions.js +3 -3
  53. package/dist/esm/client/components/ai-format.js +129 -0
  54. package/dist/esm/client/components/ai-widgets.js +223 -0
  55. package/dist/esm/client/components/app-shell.js +8 -7
  56. package/dist/esm/client/components/apps-grid.js +3 -3
  57. package/dist/esm/client/components/ask-ai.js +331 -0
  58. package/dist/esm/client/components/feature-gate.js +2 -2
  59. package/dist/esm/client/components/integrations-modal.js +1 -1
  60. package/dist/esm/client/components/logo.js +3 -3
  61. package/dist/esm/client/components/nav.js +1 -1
  62. package/dist/esm/client/components/plan-pricing.js +1 -1
  63. package/dist/esm/client/components/plans.js +6 -6
  64. package/dist/esm/client/components/readiness.js +3 -3
  65. package/dist/esm/client/components/side-nav.js +1 -1
  66. package/dist/esm/client/components/subscribe-dialog.js +2 -2
  67. package/dist/esm/client/components/subscription.js +1 -1
  68. package/dist/esm/client/components/usage-meter.js +1 -1
  69. package/dist/esm/client/components/user-menu.js +31 -8
  70. package/dist/esm/client/components/workspace-type-gate.js +45 -0
  71. package/dist/esm/client/index.js +14 -3
  72. package/dist/esm/client/mark.js +1 -1
  73. package/dist/esm/client/provider.js +48 -7
  74. package/dist/esm/client/use-checkout.js +3 -3
  75. package/dist/esm/errors.js +4 -4
  76. package/dist/esm/helpers.js +1 -1
  77. package/dist/esm/index.js +1 -1
  78. package/dist/esm/next/index.js +2 -2
  79. package/dist/esm/server/client.js +15 -15
  80. package/dist/esm/server/handler.js +56 -13
  81. package/dist/esm/server/http.js +47 -25
  82. package/dist/esm/server/resources/access.js +3 -3
  83. package/dist/esm/server/resources/ai.js +1 -1
  84. package/dist/esm/server/resources/analytics.js +2 -2
  85. package/dist/esm/server/resources/apps.js +4 -4
  86. package/dist/esm/server/resources/billing.js +5 -5
  87. package/dist/esm/server/resources/drive.js +4 -4
  88. package/dist/esm/server/resources/entitlements.js +48 -7
  89. package/dist/esm/server/resources/identity.js +6 -4
  90. package/dist/esm/server/resources/integrations.js +13 -13
  91. package/dist/esm/server/resources/logs.js +3 -3
  92. package/dist/esm/server/resources/sessions.js +6 -6
  93. package/dist/esm/server/webhooks.js +4 -4
  94. package/dist/esm/types.js +1 -1
  95. package/dist/theme.css +87 -0
  96. package/dist/types/client/components/access-gate.d.ts +18 -4
  97. package/dist/types/client/components/account-sessions.d.ts +1 -1
  98. package/dist/types/client/components/ai-format.d.ts +24 -0
  99. package/dist/types/client/components/ai-widgets.d.ts +42 -0
  100. package/dist/types/client/components/app-shell.d.ts +25 -9
  101. package/dist/types/client/components/apps-grid.d.ts +1 -1
  102. package/dist/types/client/components/ask-ai.d.ts +73 -0
  103. package/dist/types/client/components/feature-gate.d.ts +1 -1
  104. package/dist/types/client/components/integrations-modal.d.ts +1 -1
  105. package/dist/types/client/components/logo.d.ts +5 -5
  106. package/dist/types/client/components/nav.d.ts +3 -3
  107. package/dist/types/client/components/plan-pricing.d.ts +2 -2
  108. package/dist/types/client/components/readiness.d.ts +2 -2
  109. package/dist/types/client/components/side-nav.d.ts +1 -1
  110. package/dist/types/client/components/subscribe-dialog.d.ts +3 -3
  111. package/dist/types/client/components/usage-meter.d.ts +1 -1
  112. package/dist/types/client/components/user-menu.d.ts +4 -3
  113. package/dist/types/client/components/workspace-type-gate.d.ts +48 -0
  114. package/dist/types/client/index.d.ts +11 -4
  115. package/dist/types/client/mark.d.ts +1 -1
  116. package/dist/types/client/provider.d.ts +52 -9
  117. package/dist/types/client/use-checkout.d.ts +3 -3
  118. package/dist/types/errors.d.ts +4 -4
  119. package/dist/types/helpers.d.ts +1 -1
  120. package/dist/types/index.d.ts +1 -1
  121. package/dist/types/next/index.d.ts +1 -1
  122. package/dist/types/server/client.d.ts +13 -13
  123. package/dist/types/server/handler.d.ts +2 -2
  124. package/dist/types/server/http.d.ts +6 -1
  125. package/dist/types/server/resources/access.d.ts +3 -3
  126. package/dist/types/server/resources/ai.d.ts +2 -2
  127. package/dist/types/server/resources/analytics.d.ts +2 -2
  128. package/dist/types/server/resources/apps.d.ts +4 -4
  129. package/dist/types/server/resources/billing.d.ts +4 -4
  130. package/dist/types/server/resources/drive.d.ts +4 -4
  131. package/dist/types/server/resources/entitlements.d.ts +37 -5
  132. package/dist/types/server/resources/identity.d.ts +2 -2
  133. package/dist/types/server/resources/integrations.d.ts +9 -9
  134. package/dist/types/server/resources/logs.d.ts +3 -3
  135. package/dist/types/server/resources/sessions.d.ts +5 -5
  136. package/dist/types/server/webhooks.d.ts +4 -4
  137. package/dist/types/types.d.ts +235 -61
  138. package/package.json +8 -2
@@ -0,0 +1,24 @@
1
+ import type { AiValue, AiValueFormat } from "../../types.js";
2
+ /**
3
+ * The one place a model-supplied value becomes a string.
4
+ *
5
+ * Ask AI's presentation tools send raw values with a `format` tag beside them
6
+ * rather than pre-formatted strings (see `AiValueFormat`), and this is the half
7
+ * that makes that worth doing: an amount renders in the viewer's own locale, a
8
+ * table sorts numerically, and the same figure reads identically on a chart
9
+ * axis, in a tooltip and in a metric tile.
10
+ *
11
+ * Every branch is total. A value that cannot be formatted the way it was
12
+ * tagged - a `date` that is not a date, a `currency` that is not a number -
13
+ * falls back to its plain string rather than throwing inside a render.
14
+ */
15
+ /** Renders in place of a missing value - an em dash, not the word "null". */
16
+ export declare const AI_EMPTY_VALUE = "\u2014";
17
+ export declare function formatAiValue(value: AiValue, format?: AiValueFormat): string;
18
+ /** Numeric columns read far better right-aligned; everything else stays with the text. */
19
+ export declare function isNumericAiFormat(format?: AiValueFormat): boolean;
20
+ export type AiStatusTone = "neutral" | "positive" | "warning" | "danger";
21
+ export declare function aiStatusTone(value: AiValue): AiStatusTone;
22
+ /** HeroUI semantic tokens only, so these inherit whatever theme the host defined. */
23
+ export declare const AI_TONE_CHIP: Record<AiStatusTone, string>;
24
+ export declare const AI_TONE_DOT: Record<AiStatusTone, string>;
@@ -0,0 +1,42 @@
1
+ import { type ReactNode } from "react";
2
+ import type { AiChartInput, AiDetailsInput, AiMetricsInput, AiSourcesInput, AiStepsInput, AiTableInput, AiTimelineInput } from "../../types.js";
3
+ /**
4
+ * `showTable`. Sorting and CSV are what a table is *for* - once an answer is
5
+ * tabular the next thing anyone wants is to reorder it or take it elsewhere,
6
+ * and a markdown table can do neither. Both work off the raw values, so
7
+ * "₹12,500" sorts as 12500 and the export carries numbers a spreadsheet can add.
8
+ */
9
+ export declare function AiTable({ title, columns, rows, caption }: Readonly<AiTableInput>): import("react").JSX.Element;
10
+ /**
11
+ * `showChart`. Cartesian kinds are drawn as SVG against a fixed viewBox and
12
+ * scaled by the browser, which is why there is no resize observer here: the
13
+ * chart is resolution-independent, so "responsive" costs nothing at runtime.
14
+ *
15
+ * `pie` is deliberately *not* a pie. In a 400px column a pie plus its legend
16
+ * is smaller than the labels it needs, and reading angles is worse than
17
+ * reading lengths at any size - so proportions render as a labelled bar list,
18
+ * which answers the same question and stays legible.
19
+ */
20
+ export declare function AiChart({ title, kind, xLabel, yLabel, valueFormat, series, caption }: Readonly<AiChartInput>): import("react").JSX.Element;
21
+ /**
22
+ * `showMetrics`. A delta is coloured by `deltaMeaning`, not by its sign -
23
+ * churn rising is bad and revenue rising is good, and painting both green
24
+ * because the arrow points up is exactly the confidently-wrong signal a
25
+ * dashboard must never send. The arrow still shows direction, so meaning and
26
+ * direction stay two separate channels.
27
+ */
28
+ export declare function AiMetrics({ title, metrics }: Readonly<AiMetricsInput>): import("react").JSX.Element;
29
+ /** `showTimeline`: dated events, oldest first, on a single rail. */
30
+ export declare function AiTimeline({ title, events }: Readonly<AiTimelineInput>): import("react").JSX.Element;
31
+ /** `showDetails`: one entity's fields, as a definition list rather than a one-row table. */
32
+ export declare function AiDetails({ title, fields }: Readonly<AiDetailsInput>): import("react").JSX.Element;
33
+ /** `showSteps`: an ordered procedure. `renderDetail` is how the panel feeds each step back through its markdown renderer. */
34
+ export declare function AiSteps({ title, steps, renderDetail, }: Readonly<AiStepsInput & {
35
+ renderDetail?: (markdown: string) => ReactNode;
36
+ }>): import("react").JSX.Element;
37
+ /**
38
+ * `showSources`: what a grounded answer actually rested on. The point of a
39
+ * citation is that it can be opened, so a source with a `uri` is a link and one
40
+ * without is still a named row - never a marker with nothing behind it.
41
+ */
42
+ export declare function AiSources({ sources }: Readonly<AiSourcesInput>): import("react").JSX.Element;
@@ -1,10 +1,11 @@
1
1
  import { type ReactNode } from "react";
2
+ import { type ConnectAskAiProps } from "./ask-ai.js";
2
3
  import { type ConnectLinkRenderer, type ConnectNav } from "./nav.js";
3
4
  import type { ThemeMode } from "../../types.js";
4
- export interface ConnectAppShellProps {
5
- /** This service's name, in the `cosmo·ops VOICE` lockup. See `ConnectLogo`. */
5
+ export interface AppShellProps {
6
+ /** This application's name, in the `cosmo·ops VOICE` lockup. See `ConnectLogo`. */
6
7
  name: string;
7
- /** This service's glyph, drawn on the CosmoOps badge. Falls back to the Connect rings. */
8
+ /** This application's glyph, drawn on the CosmoOps badge. Falls back to the Connect rings. */
8
9
  icon?: ReactNode;
9
10
  /** Where the lockup links. Defaults to `/`. */
10
11
  homeHref?: string;
@@ -61,18 +62,33 @@ export interface ConnectAppShellProps {
61
62
  * say. Prefix-matched, same as the nav's active resolution.
62
63
  */
63
64
  gateExemptRoutes?: string[];
65
+ /**
66
+ * Mount `ConnectAskAi` - a chat panel grounded in the signed-in workspace's
67
+ * Context Index, streamed through your own bridge. Pass an object to
68
+ * override its heading, copy or markdown plugins.
69
+ *
70
+ * **On by default**, like `gate`, and for the same reason: a family of
71
+ * application platforms should answer questions the same way, and a feature
72
+ * every partner has to remember to switch on is a feature most of them do
73
+ * not have. It stays inert until it can actually work - the trigger renders
74
+ * nothing for a signed-out visitor, and a workspace whose Context Index is
75
+ * off gets a message in the panel rather than a broken answer.
76
+ *
77
+ * Set `false` for an application that should not offer it at all.
78
+ */
79
+ askAi?: boolean | ConnectAskAiProps;
64
80
  className?: string;
65
81
  /** Classes on the scrolling content pane - override the default max-width and padding here. */
66
82
  contentClassName?: string;
67
83
  children: ReactNode;
68
84
  }
69
85
  /**
70
- * The application frame every CosmoOps service platform runs inside: a
86
+ * The application frame every CosmoOps application platform runs inside: a
71
87
  * collapsible sidebar, a top bar carrying the app launcher and the account
72
88
  * menu, and your pages in the middle.
73
89
  *
74
90
  * This is the piece each partner was otherwise writing by hand, and writing
75
- * slightly differently - which is how a family of services stops looking like
91
+ * slightly differently - which is how a family of applications stops looking like
76
92
  * one product. Everything that should be identical across platforms (the
77
93
  * lockup, the rail geometry, the active-route treatment, the launcher, the
78
94
  * account menu, the access gate) lives here; everything that genuinely
@@ -82,12 +98,12 @@ export interface ConnectAppShellProps {
82
98
  * "use client";
83
99
  * import Link from "next/link";
84
100
  * import { usePathname } from "next/navigation";
85
- * import { ConnectAppShell } from "@cosmoops/connect-sdk/client";
101
+ * import { AppShell } from "@cosmoops/connect-sdk/client";
86
102
  * import { LayoutDashboard, Truck } from "lucide-react";
87
103
  *
88
104
  * export function Shell({ children }: { children: React.ReactNode }) {
89
105
  * return (
90
- * <ConnectAppShell
106
+ * <AppShell
91
107
  * name="Dispatch"
92
108
  * icon={<Truck />}
93
109
  * activePath={usePathname()}
@@ -98,7 +114,7 @@ export interface ConnectAppShellProps {
98
114
  * ]}
99
115
  * >
100
116
  * {children}
101
- * </ConnectAppShell>
117
+ * </AppShell>
102
118
  * );
103
119
  * }
104
120
  * ```
@@ -112,4 +128,4 @@ export interface ConnectAppShellProps {
112
128
  * so a page with a shell, a plan table and a usage meter still makes one
113
129
  * session read.
114
130
  */
115
- export declare function ConnectAppShell({ name, icon, homeHref, nav, activePath, renderLink, title, headerActions, sidebarFooter, footer, defaultCollapsed, collapsed: controlledCollapsed, onCollapsedChange, collapsible, showAppsGrid, showAuthButtons, theme, onThemeChange, gate, gateExemptRoutes, className, contentClassName, children, }: ConnectAppShellProps): import("react").JSX.Element;
131
+ export declare function AppShell({ name, icon, homeHref, nav, activePath, renderLink, title, headerActions, sidebarFooter, footer, defaultCollapsed, collapsed: controlledCollapsed, onCollapsedChange, collapsible, showAppsGrid, showAuthButtons, theme, onThemeChange, gate, gateExemptRoutes, askAi, className, contentClassName, children, }: AppShellProps): import("react").JSX.Element;
@@ -6,7 +6,7 @@ export interface ConnectAppsGridProps {
6
6
  }
7
7
  /**
8
8
  * The Google-style app launcher: a grid icon in your top bar that opens a
9
- * modal of every Connect service this organization can actually open.
9
+ * modal of every Connect application this workspace can actually open.
10
10
  *
11
11
  * Only launchable apps appear, so no tile is a dead end - a paused
12
12
  * subscription still shows, badged, because a dunning cycle should not make a
@@ -0,0 +1,73 @@
1
+ import { type StreamdownProps } from "streamdown";
2
+ export interface ConnectAskAiProps {
3
+ /** Panel heading. Defaults to `"Ask AI"`. */
4
+ title?: string;
5
+ /** Byline over each assistant turn. Defaults to `"Assistant"`. */
6
+ assistantName?: string;
7
+ /** Composer placeholder. */
8
+ placeholder?: string;
9
+ /** Shown once, above an empty conversation. */
10
+ hint?: string;
11
+ /** Start open. The panel owns its state after that. */
12
+ defaultOpen?: boolean;
13
+ /**
14
+ * Streamdown plugins - syntax highlighting, KaTeX, Mermaid, CJK.
15
+ *
16
+ * Off unless you pass them, because each is a package of its own and several
17
+ * are large (Mermaid alone dwarfs this SDK). Prose, GFM tables, task lists
18
+ * and plain code fences all render without any of them.
19
+ *
20
+ * ```tsx
21
+ * import { code } from "@streamdown/code";
22
+ * import { mermaid } from "@streamdown/mermaid";
23
+ *
24
+ * <ConnectAskAi markdownPlugins={{ code, mermaid }} />
25
+ * ```
26
+ *
27
+ * Hoist the object to module scope: Streamdown compares this prop by
28
+ * reference, so an inline literal defeats its block memoisation.
29
+ */
30
+ markdownPlugins?: StreamdownProps["plugins"];
31
+ }
32
+ /**
33
+ * Ask AI - a chat panel grounded in the signed-in workspace's Context Index,
34
+ * streamed through your own bridge.
35
+ *
36
+ * Answers are not only prose. Connect's model can call a small set of
37
+ * presentation tools - `showTable`, `showChart`, `showMetrics`, `showTimeline`,
38
+ * `showDetails`, `showSteps`, `showSources` - and this panel renders each one
39
+ * natively: a sortable table with a CSV download, a chart, a row of metric
40
+ * tiles. Values arrive raw with a format tag, so they are formatted here rather
41
+ * than by the model, which is what lets a column sort numerically.
42
+ *
43
+ * Nothing here holds a credential: it POSTs to `${basePath}/ai/chat` on your
44
+ * own origin, and `createConnectHandler` is what reaches Connect. The workspace
45
+ * is resolved from the caller's session there, never sent from the browser - so
46
+ * a user can only ever ask about the workspace they are signed into.
47
+ *
48
+ * ```tsx
49
+ * <AppShell name="Dispatch" nav={nav}>
50
+ * {children}
51
+ * </AppShell>
52
+ * ```
53
+ *
54
+ * `AppShell` mounts it by default. Mount it directly only when you are not
55
+ * using the shell: it renders a fixed corner trigger plus a panel that is an
56
+ * *in-flow flex sibling* at `lg` and up, so opening it pushes your content
57
+ * aside rather than covering it. That requires it to be the last child of a
58
+ * `flex` row owning the viewport height - which is exactly what `AppShell` is.
59
+ * Below `lg` it is a full-screen sheet with a backdrop instead; there is no
60
+ * room to push anything on a phone.
61
+ *
62
+ * **Host setup:** markdown rendering needs `streamdown` installed, one Tailwind
63
+ * `@source "…/node_modules/streamdown/dist/*.js"` line so its utility classes
64
+ * are generated, and `import "streamdown/styles.css"` for the streaming
65
+ * animation. The colour tokens Streamdown expects are already mapped in this
66
+ * SDK's `theme.css`.
67
+ *
68
+ * Answers require the workspace's Context Index to be turned on (a workspace
69
+ * admin toggle in Connect) and your API key to carry the `ai:chat` scope.
70
+ * Neither is something the browser can discover, so both surface as a message
71
+ * in the panel rather than as a hidden button.
72
+ */
73
+ export declare function ConnectAskAi({ title, assistantName, placeholder, hint, defaultOpen, markdownPlugins, }: ConnectAskAiProps): import("react").JSX.Element | null;
@@ -48,7 +48,7 @@ export interface ConnectFeatureGateProps {
48
48
  *
49
49
  * Like every gate in this package, it is a **UX gate, not a security
50
50
  * boundary**: the entitlement is read through your own origin and the browser
51
- * can ignore it. Check `client.entitlements.hasFeature(orgId, feature)` on the
51
+ * can ignore it. Check `client.entitlements.hasFeature(workspaceId, feature)` on the
52
52
  * server before doing the thing the feature unlocks.
53
53
  *
54
54
  * Renders `loading` - not `fallback` - while the answer is unknown, so a paying
@@ -5,7 +5,7 @@ export interface ConnectIntegrationsModalProps {
5
5
  label?: string;
6
6
  }
7
7
  /**
8
- * A grid of every Composio-hosted toolkit this organization can connect -
8
+ * A grid of every Composio-hosted toolkit this workspace can connect -
9
9
  * Google Calendar, Slack, Twitter/X, whatever a platform admin enabled in
10
10
  * Connect's own Console. Each tile carries its own connect/reconnect/
11
11
  * disconnect action and its own pending state, independent of every other
@@ -1,12 +1,12 @@
1
1
  import type { ReactNode } from "react";
2
2
  export interface ConnectLogoProps {
3
3
  /**
4
- * This service's name - rendered as the sub-brand beneath the `cosmo·ops`
4
+ * This application's name - rendered as the sub-brand beneath the `cosmo·ops`
5
5
  * wordmark, in the house `cosmo·ops VOICE` treatment.
6
6
  */
7
7
  name: string;
8
8
  /**
9
- * This service's own glyph, drawn inside the accent badge. Any node - a
9
+ * This application's own glyph, drawn inside the accent badge. Any node - a
10
10
  * `lucide-react` icon, an `<img>`, an inline `<svg>`. Paint it with
11
11
  * `currentColor` and it inherits `--accent-foreground` from the badge, so it
12
12
  * stays legible when a host app changes the accent.
@@ -19,10 +19,10 @@ export interface ConnectLogoProps {
19
19
  className?: string;
20
20
  }
21
21
  /**
22
- * The shared platform lockup: a service's own glyph on the CosmoOps badge,
23
- * `cosmo·ops` beside it, and the service name underneath.
22
+ * The shared platform lockup: an application's own glyph on the CosmoOps badge,
23
+ * `cosmo·ops` beside it, and the application name underneath.
24
24
  *
25
- * This is what makes a family of service platforms look like one product. Each
25
+ * This is what makes a family of application platforms look like one product. Each
26
26
  * platform passes only what differs - its `name` and its `icon` - and inherits
27
27
  * the mark geometry, the wordmark treatment, the separator, and the accent from
28
28
  * one place. Change the lockup here and every platform follows.
@@ -28,7 +28,7 @@ export interface ConnectNavItem {
28
28
  items?: ConnectNavItem[];
29
29
  /**
30
30
  * Leave this route *outside* `ConnectAccessGate` - see
31
- * `ConnectAppShellProps.gate`. Declared here, next to the route it applies
31
+ * `AppShellProps.gate`. Declared here, next to the route it applies
32
32
  * to, rather than as a second list somewhere else that has to be kept in
33
33
  * step with this one.
34
34
  */
@@ -40,7 +40,7 @@ export interface ConnectNavSection {
40
40
  items: ConnectNavItem[];
41
41
  }
42
42
  /**
43
- * What `ConnectAppShell`/`ConnectSideNav` accept for `nav`: a flat list of
43
+ * What `AppShell`/`ConnectSideNav` accept for `nav`: a flat list of
44
44
  * items, a list of sections, or a mix. Consecutive bare items fold into one
45
45
  * untitled section, so the common case is just an array of items.
46
46
  */
@@ -106,5 +106,5 @@ export declare function resolveActivePath(pathname: string, nav: ConnectNav): st
106
106
  * lights up on every app's home route. External items are never active.
107
107
  */
108
108
  export declare function isNavItemActive(item: ConnectNavItem, activeHref: string | null): boolean;
109
- /** Hrefs declared `gateExempt` - the routes `ConnectAppShell` renders outside its `ConnectAccessGate`. */
109
+ /** Hrefs declared `gateExempt` - the routes `AppShell` renders outside its `ConnectAccessGate`. */
110
110
  export declare function gateExemptPaths(nav: ConnectNav): string[];
@@ -4,7 +4,7 @@
4
4
  * an upgrade while the card behind it said downgrade would be worse than
5
5
  * either label being wrong on its own.
6
6
  *
7
- * Mirrors `packages/data/src/services/catalog.ts` and
7
+ * Mirrors `packages/data/src/applications/catalog.ts` and
8
8
  * `packages/data/src/payments/plan-change.ts`, which are the copies Connect's
9
9
  * own UI uses and which decide which use-case actually runs. The duplication
10
10
  * is deliberate and load-bearing: this package carries no dependency on
@@ -81,7 +81,7 @@ export declare function groupPlansByTier(plans: readonly Plan[]): PlanTier[];
81
81
  */
82
82
  export declare function annualSaving(monthly: Plan | null | undefined, annual: Plan | null | undefined): number | null;
83
83
  /**
84
- * What moving to `plan` would be, given what the org is on today.
84
+ * What moving to `plan` would be, given what the workspace is on today.
85
85
  *
86
86
  * `switch-to-annual`/`switch-to-monthly` exist because a change of *cadence*
87
87
  * is neither an upgrade nor a downgrade, and calling it one is not a wording
@@ -6,7 +6,7 @@ export interface ConnectReadinessBannerProps {
6
6
  className?: string;
7
7
  }
8
8
  /**
9
- * Every gate between this workspace and your service, with the way out of each.
9
+ * Every gate between this workspace and your application, with the way out of each.
10
10
  *
11
11
  * This is the component that keeps a blocked customer from staring at a broken
12
12
  * app. `getReadiness` resolves subscription state, KYC/KYB, a chargeable
@@ -14,7 +14,7 @@ export interface ConnectReadinessBannerProps {
14
14
  * `resolveUrl` into the exact Connect screen that fixes it** - so being blocked
15
15
  * comes with somewhere to go rather than a refusal.
16
16
  *
17
- * Render it high on any page your service gates. It draws nothing at all when
17
+ * Render it high on any page your application gates. It draws nothing at all when
18
18
  * the workspace is ready, so it is safe to leave mounted permanently.
19
19
  *
20
20
  * Two deliberate refusals:
@@ -23,7 +23,7 @@ export interface ConnectSideNavProps {
23
23
  * The sidebar's nav column on its own - sections, items, one level of
24
24
  * children, and the active highlight.
25
25
  *
26
- * `ConnectAppShell` renders this inside its rail and its mobile drawer, and it
26
+ * `AppShell` renders this inside its rail and its mobile drawer, and it
27
27
  * is exported for a host that wants the shell's navigation without its
28
28
  * chrome: the same items, the same active resolution, dropped into a layout
29
29
  * you already have.
@@ -5,11 +5,11 @@ export interface ConnectSubscribeDialogProps {
5
5
  plan: Plan | null;
6
6
  /** Which of subscribe / upgrade / downgrade this is - decides the headline and what the notice says about money. */
7
7
  action: PlanAction;
8
- /** The org's live subscription, for the "from" side of a plan change. */
8
+ /** The workspace's live subscription, for the "from" side of a plan change. */
9
9
  current: SubscriptionResponse | null;
10
10
  /** Coupon typed into the plan grid, echoed here so it is visible before the hand-off carries it. */
11
11
  coupon?: string;
12
- /** Whether this org's `plan.trialDays` still applies is Connect's call, not this component's - see the notice below. */
12
+ /** Whether this workspace's `plan.trialDays` still applies is Connect's call, not this component's - see the notice below. */
13
13
  onClose(): void;
14
14
  onConfirm(): void;
15
15
  }
@@ -26,7 +26,7 @@ export interface ConnectSubscribeDialogProps {
26
26
  * The authoritative price is computed by Connect against the real cart:
27
27
  * proration is priced against the actual cycle, a coupon is validated
28
28
  * against the plan it is being applied to, trial eligibility depends on
29
- * whether this organization has ever subscribed to this service before, and
29
+ * whether this workspace has ever subscribed to this application before, and
30
30
  * an accumulated credit is deducted. None of that is knowable from the
31
31
  * partner's origin, so this component states the list price and says where
32
32
  * the final figure comes from rather than quietly guessing at one.
@@ -11,7 +11,7 @@ export interface ConnectUsageMeterProps {
11
11
  *
12
12
  * Reads the balance Connect actually debits, so the number here and the number
13
13
  * `consumeAddon` enforces cannot disagree. Before the `addons:read` endpoint
14
- * existed this component was impossible to write honestly: a service could
14
+ * existed this component was impossible to write honestly: an application could
15
15
  * spend an allowance down on every request and the only thing the API exposed
16
16
  * was the list of add-on *ids* on the subscription.
17
17
  *
@@ -26,7 +26,7 @@ export interface ConnectUserMenuProps {
26
26
  * in place, which is why it sits alone in the footer rather than as a fourth
27
27
  * item in the same list as three navigations.
28
28
  *
29
- * The session list is account-wide, not scoped to this service - see
29
+ * The session list is account-wide, not scoped to this application - see
30
30
  * `ConnectUserSession`'s doc comment in `types.ts`. Appearance only renders
31
31
  * when both `theme` and `onThemeChange` are supplied.
32
32
  *
@@ -55,7 +55,7 @@ export declare function ConnectManageSubscriptionButton({ className }: Readonly<
55
55
  * Invoices and payment history, on Connect.
56
56
  *
57
57
  * A deep link rather than a component that lists them, and that is not a
58
- * placeholder: nothing in `/api/v1/service/*` exposes invoices, so an SDK-side
58
+ * placeholder: nothing in `/api/v1/application/*` exposes invoices, so an SDK-side
59
59
  * list would have nothing to read. It is also the right answer regardless -
60
60
  * a GST tax invoice is a legal document with a fixed format, downloadable and
61
61
  * emailed from one place, and a partner-rendered copy of one would be a second
@@ -70,7 +70,8 @@ export declare function ConnectInvoicesButton({ className }: Readonly<{
70
70
  * `ConnectHomeButton`.
71
71
  *
72
72
  * It was reachable only from inside `ConnectUserMenu`, which meant an app that
73
- * builds its own account menu had to hardcode `${appUrl}/profile` to offer it.
73
+ * builds its own account menu had to hardcode `${appUrl}/profile` to offer it -
74
+ * and got no `return_to`, so the user had no way back.
74
75
  */
75
76
  export declare function ConnectProfileButton({ className }: Readonly<{
76
77
  className?: string;
@@ -0,0 +1,48 @@
1
+ import type { ReactNode } from "react";
2
+ import type { WorkspaceType } from "../../types.js";
3
+ export interface ConnectWorkspaceTypeGateProps {
4
+ /**
5
+ * The workspace type this subtree is for. Pass an array to accept either -
6
+ * which is the same as not using the gate at all, so it exists only to keep
7
+ * a `type={someVariable}` call site from having to special-case "both".
8
+ */
9
+ type: WorkspaceType | WorkspaceType[];
10
+ children: ReactNode;
11
+ /**
12
+ * Rendered for a workspace of the other type. Defaults to `null` - hiding
13
+ * the subtree, which is what this gate is normally for.
14
+ */
15
+ fallback?: ReactNode;
16
+ /** Shown until the session read settles. Defaults to nothing. */
17
+ loading?: ReactNode;
18
+ }
19
+ /**
20
+ * Renders `children` only for a workspace of the given type.
21
+ *
22
+ * ```tsx
23
+ * <ConnectWorkspaceTypeGate type="business">
24
+ * <TeamMembersTable />
25
+ * </ConnectWorkspaceTypeGate>
26
+ * ```
27
+ *
28
+ * The point is dead controls, not access: an `"individual"` workspace has
29
+ * exactly one seat and can never have another, so a members table, an invite
30
+ * button and a seat meter are all things that can only ever fail there.
31
+ * Hiding them is a better answer than letting someone press one and read an
32
+ * error about an account shape they did not choose.
33
+ *
34
+ * This is emphatically **not** the audience gate. It does not know what your
35
+ * application is sold to and will happily render a business-only subtree to a
36
+ * business workspace that has no business being in your application at all -
37
+ * that is `<ConnectAccessGate>`'s job, off the `audience_mismatch` readiness
38
+ * blocker. Use this one *inside* an application both audiences can reach, to
39
+ * vary what each sees.
40
+ *
41
+ * Like every gate in this package it is a **UX gate, not a security
42
+ * boundary**: the browser can ignore it. Anything that must not happen for an
43
+ * individual workspace has to be refused on your server too.
44
+ *
45
+ * Renders `loading` - not `fallback` - while the session is unknown, so a
46
+ * business account never flickers through the individual-account layout.
47
+ */
48
+ export declare function ConnectWorkspaceTypeGate({ type, children, fallback, loading, }: ConnectWorkspaceTypeGateProps): import("react").JSX.Element;
@@ -7,10 +7,10 @@
7
7
  *
8
8
  * Styling is HeroUI v3 semantic tokens only (`accent`, `muted`, `surface`,
9
9
  * `separator`, ...), never a hardcoded colour - so these components inherit
10
- * whatever theme the host service platform already configured, and one theme
10
+ * whatever theme the host application platform already configured, and one theme
11
11
  * change lands identically in all of them.
12
12
  */
13
- export { ConnectProvider, useConnect, useConnectUser, useConnectEntitlements, useConnectPlans, useConnectApps, useConnectAddonUsage, useConnectSessions, useConnectIntegrations, useConnectResource, CONNECT_APP_URL, } from "./provider.js";
13
+ export { ConnectProvider, useConnect, useConnectUser, useConnectWorkspaceType, useConnectAudience, useConnectEntitlements, useConnectPlans, useConnectApps, useConnectAddonUsage, useConnectSessions, useConnectIntegrations, useConnectResource, CONNECT_APP_URL, } from "./provider.js";
14
14
  export type { ConnectProviderProps, ConnectContextValue, ConnectSession } from "./provider.js";
15
15
  export { blockingBlockers, normalizePlanFeatures } from "../helpers.js";
16
16
  export type { WirePlanFeature } from "../helpers.js";
@@ -25,8 +25,8 @@ export { ConnectUserMenu, ConnectManageSubscriptionButton, ConnectInvoicesButton
25
25
  export { ConnectAccountSessions } from "./components/account-sessions.js";
26
26
  export type { ConnectAccountSessionsProps } from "./components/account-sessions.js";
27
27
  export type { ConnectUserMenuProps } from "./components/user-menu.js";
28
- export { ConnectAppShell } from "./components/app-shell.js";
29
- export type { ConnectAppShellProps } from "./components/app-shell.js";
28
+ export { AppShell } from "./components/app-shell.js";
29
+ export type { AppShellProps } from "./components/app-shell.js";
30
30
  export { ConnectSideNav } from "./components/side-nav.js";
31
31
  export type { ConnectSideNavProps } from "./components/side-nav.js";
32
32
  export { useActivePath } from "./use-active-path.js";
@@ -34,6 +34,11 @@ export { normalizeNav, flattenNav, normalizePath, resolveActivePath, isNavItemAc
34
34
  export type { ConnectNav, ConnectNavItem, ConnectNavSection, ConnectNavLinkProps, ConnectLinkRenderer, } from "./components/nav.js";
35
35
  export { ConnectAppsGrid } from "./components/apps-grid.js";
36
36
  export type { ConnectAppsGridProps } from "./components/apps-grid.js";
37
+ export { ConnectAskAi } from "./components/ask-ai.js";
38
+ export type { ConnectAskAiProps } from "./components/ask-ai.js";
39
+ export { AiTable, AiChart, AiMetrics, AiTimeline, AiDetails, AiSteps, AiSources, } from "./components/ai-widgets.js";
40
+ export { formatAiValue, isNumericAiFormat, aiStatusTone, AI_EMPTY_VALUE, AI_TONE_CHIP, AI_TONE_DOT, } from "./components/ai-format.js";
41
+ export type { AiStatusTone } from "./components/ai-format.js";
37
42
  export { ConnectIntegrationsModal } from "./components/integrations-modal.js";
38
43
  export type { ConnectIntegrationsModalProps } from "./components/integrations-modal.js";
39
44
  export { ConnectPlans } from "./components/plans.js";
@@ -48,6 +53,8 @@ export { ConnectAccessGate, useConnectAccessGate } from "./components/access-gat
48
53
  export type { ConnectAccessGateProps, ConnectAccessGateState, ConnectAccessGateResult, } from "./components/access-gate.js";
49
54
  export { ConnectFeatureGate, useConnectFeature } from "./components/feature-gate.js";
50
55
  export type { ConnectFeatureGateProps } from "./components/feature-gate.js";
56
+ export { ConnectWorkspaceTypeGate } from "./components/workspace-type-gate.js";
57
+ export type { ConnectWorkspaceTypeGateProps } from "./components/workspace-type-gate.js";
51
58
  export { ConnectUsageMeter } from "./components/usage-meter.js";
52
59
  export type { ConnectUsageMeterProps } from "./components/usage-meter.js";
53
60
  export { ConnectPlansPage } from "./components/plans-page.js";
@@ -2,7 +2,7 @@
2
2
  * The Connect mark - concentric rings on a solid accent badge.
3
3
  *
4
4
  * Painted from `--accent` / `--accent-foreground`, the same HeroUI tokens the
5
- * host app themes, so the badge tracks whatever palette a service platform has
5
+ * host app themes, so the badge tracks whatever palette an application platform has
6
6
  * configured rather than carrying a hardcoded CosmoOps green into someone
7
7
  * else's brand.
8
8
  */
@@ -1,10 +1,16 @@
1
1
  import type { ReactNode } from "react";
2
- import type { AddonUsageResponse, ConnectUser, IntegrationsListResponse, OrganizationApp, PlansResponse, ReadinessResponse, ServiceRole, SessionsListResponse, SessionSubscription, SubscriptionResponse } from "../types.js";
2
+ import type { AddonUsageResponse, ConnectUser, IntegrationsListResponse, WorkspaceApp, PlansResponse, ReadinessResponse, ApplicationRole, SessionsListResponse, SessionSubscription, SessionAudience, SubscriptionResponse, WorkspaceType } from "../types.js";
3
3
  export declare const CONNECT_APP_URL = "https://connect.cosmoops.com";
4
4
  export interface ConnectSession {
5
5
  user: ConnectUser | null;
6
6
  subscription: SessionSubscription | null;
7
- serviceRole: ServiceRole | null;
7
+ applicationRole: ApplicationRole | null;
8
+ /**
9
+ * `null` when signed out, for the same reason the three above are: there is
10
+ * no workspace to compare an audience against yet. Never `null` on a
11
+ * signed-in session.
12
+ */
13
+ audience: SessionAudience | null;
8
14
  }
9
15
  export interface ConnectContextValue {
10
16
  /**
@@ -58,10 +64,26 @@ export interface ConnectContextValue {
58
64
  * page.
59
65
  */
60
66
  invalidateResource(path: string): void;
67
+ /**
68
+ * POST through the bridge and hand back the raw `Response`, unread and
69
+ * uncached - the seam `<ConnectAskAi>` streams server-sent events over.
70
+ *
71
+ * Separate from `mutateResource` rather than a flag on it, because the two
72
+ * differ in every respect that matters: this one must not `await
73
+ * response.json()` (that buffers the whole stream and defeats the point),
74
+ * must not touch the resource cache (a conversation is not a resource), and
75
+ * takes an `AbortSignal` so a "Stop" button can actually stop generation.
76
+ *
77
+ * Throws on a non-2xx, having read the error envelope - which is safe,
78
+ * because a failure never has a stream behind it.
79
+ */
80
+ streamResource(path: string, body: unknown, options?: {
81
+ signal?: AbortSignal;
82
+ }): Promise<Response>;
61
83
  }
62
84
  export interface ConnectProviderProps {
63
85
  /**
64
- * This service's public `client_id`, from its Integration tab in Connect.
86
+ * This application's public `client_id`, from its Integration tab in Connect.
65
87
  *
66
88
  * Not needed for the default sign-in flow: `signIn()` with no `redirectUri`
67
89
  * bounces the browser to your own `/signin` route, which already knows
@@ -128,6 +150,27 @@ export declare function ConnectProvider({ clientId, basePath, redirectUri, appUr
128
150
  export declare function useConnect(): ConnectContextValue;
129
151
  /** The signed-in user, or `null`. Sugar over `useConnect().session`. */
130
152
  export declare function useConnectUser(): ConnectUser | null;
153
+ /**
154
+ * Whether the signed-in workspace is a one-seat personal account or a team -
155
+ * `null` while the session is loading or signed out.
156
+ *
157
+ * Branch on this to stop rendering team UI at a solo account: a members
158
+ * table, an invite button and a seat meter are all dead controls on an
159
+ * `"individual"` workspace, which has exactly one seat and cannot gain
160
+ * another. `<ConnectWorkspaceTypeGate>` is the declarative form.
161
+ */
162
+ export declare function useConnectWorkspaceType(): WorkspaceType | null;
163
+ /**
164
+ * Whether this account is the kind your application is sold to - `null` while
165
+ * the session is loading or signed out.
166
+ *
167
+ * `audience.matches === false` is a hard block, not a hint: readiness reports
168
+ * `audience_mismatch` and subscribing is refused. `<ConnectAccessGate>`
169
+ * already blocks the shell on it, so reach for this only when you need the
170
+ * verdict somewhere the gate does not run - a marketing page, say, or a
171
+ * sign-up CTA you would rather not show to an account that cannot complete it.
172
+ */
173
+ export declare function useConnectAudience(): SessionAudience | null;
131
174
  /** Readiness gates and the live subscription, fetched on first use. */
132
175
  export declare function useConnectEntitlements(): {
133
176
  data: {
@@ -148,7 +191,7 @@ export declare function useConnectEntitlements(): {
148
191
  /**
149
192
  * What is left of every consumable add-on on this workspace's subscription.
150
193
  *
151
- * The read half of `client.billing.consumeAddon` - a service that meters its
194
+ * The read half of `client.billing.consumeAddon` - an application that meters its
152
195
  * own end users had no way to show them what remained until this existed.
153
196
  * Empty `addons` means there is nothing to meter, which is not an error.
154
197
  */
@@ -165,7 +208,7 @@ export declare function useConnectAddonUsage(): {
165
208
  */
166
209
  refetch(): void;
167
210
  };
168
- /** This service's plan catalog. */
211
+ /** This application's plan catalog. */
169
212
  export declare function useConnectPlans(): {
170
213
  data: PlansResponse | null;
171
214
  isLoading: boolean;
@@ -179,10 +222,10 @@ export declare function useConnectPlans(): {
179
222
  */
180
223
  refetch(): void;
181
224
  };
182
- /** The apps this organization can open. */
225
+ /** The apps this workspace can open. */
183
226
  export declare function useConnectApps(): {
184
227
  data: {
185
- apps: OrganizationApp[];
228
+ apps: WorkspaceApp[];
186
229
  } | null;
187
230
  isLoading: boolean;
188
231
  error: string | null;
@@ -195,7 +238,7 @@ export declare function useConnectApps(): {
195
238
  */
196
239
  refetch(): void;
197
240
  };
198
- /** Enabled Composio-hosted toolkits and this organization's connection status for each. */
241
+ /** Enabled Composio-hosted toolkits and this workspace's connection status for each. */
199
242
  export declare function useConnectIntegrations(): {
200
243
  data: IntegrationsListResponse | null;
201
244
  isLoading: boolean;
@@ -211,7 +254,7 @@ export declare function useConnectIntegrations(): {
211
254
  };
212
255
  /**
213
256
  * This Connect account's own login sessions - account-wide, not scoped to
214
- * this service, see `SessionsListResponse`'s doc comment. The component
257
+ * this application, see `SessionsListResponse`'s doc comment. The component
215
258
  * that calls this is also the one that must own any revoke actions and call
216
259
  * the returned `refetch()` afterward - see `mutateResource`'s doc comment
217
260
  * for why nothing does that automatically.