@aindy/ui-kit 1.0.5 → 2.0.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.
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @aindy/ui-kit
2
+
3
+ Shared UI components, React contexts, and API core for **AINDY platform** frontends.
4
+
5
+ `@aindy/ui-kit` is the client-side counterpart to the [`aindy-runtime`](https://pypi.org/project/aindy-runtime/)
6
+ backend: it centralizes the authenticated HTTP layer, the canonical backend route table,
7
+ auth/session contexts, and a small set of shared components and UI primitives so every
8
+ frontend built on the runtime talks to it the same way. It is published to npm and consumed
9
+ as a compiled bundle (`dist/` is built at publish time, not committed).
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install @aindy/ui-kit
15
+ ```
16
+
17
+ **Peer dependencies** (provided by the host app):
18
+
19
+ - `react` ^19
20
+ - `react-dom` ^19
21
+ - `react-router-dom` ^6
22
+
23
+ ## What it exports
24
+
25
+ ### API core (`./api/_core.js`)
26
+
27
+ The authenticated request layer against the runtime. `buildApiUrl` prepends `API_BASE` to a
28
+ `ROUTES` value; the `request` family attaches the stored token and returns the parsed body.
29
+
30
+ | Export | Purpose |
31
+ |---|---|
32
+ | `request`, `authRequest`, `adminRequest`, `taggedRequest`, `requestAbsolute` | HTTP calls (auth-scoped / admin-scoped / cache-tagged / absolute-URL variants) |
33
+ | `buildApiUrl` | Resolve a `ROUTES` value against `API_BASE` |
34
+ | `getStoredToken`, `setStoredToken`, `clearStoredToken` | JWT storage |
35
+ | `unwrapEnvelope` | Unwrap the runtime's `{ data: … }` response envelope |
36
+ | `ApiError` | Typed error carrying status + body |
37
+ | `API_BASE` | Build-time API base (`VITE_API_BASE_URL`, default `""` — relative to origin) |
38
+
39
+ ### Routes (`./api/_routes.js`)
40
+
41
+ - `ROUTES` — the canonical backend route table. **Every runtime/platform route carries the
42
+ full `/platform` prefix** (e.g. `ROUTES.OPERATOR.FLOW_STRATEGIES` → `/platform/flows/strategies`).
43
+ A value that drops the prefix segment 404s.
44
+ - `FEATURE_FLAGS` — NavLink gates for routes that are conditionally served; flip a flag to
45
+ `true` when its backing runtime route lands.
46
+
47
+ > **Runtime routes vs app routes.** `ROUTES` should carry **runtime/platform** paths only —
48
+ > these are shared by every consumer, and the runtime's authoritative list lives in
49
+ > [`aindy-runtime` `docs/runtime/UI_CONTRACT.md`](https://github.com/Masterplanner25/aindy-runtime/blob/main/docs/runtime/UI_CONTRACT.md).
50
+ > **App-domain** paths (e.g. `/compute/*` analytics, `/seo/*`) are **not** runtime routes and
51
+ > must not be baked into this shared kit; a consuming app owns those in its own route map that
52
+ > spreads and extends `ROUTES` (mirroring the backend's runtime/app split).
53
+
54
+ ### Auth (`./api/auth.js`)
55
+
56
+ `bootIdentity`, `loginUser`, `registerUser`.
57
+
58
+ > **Invariant:** all three must `.then(unwrapEnvelope)` — `bootIdentity` populates
59
+ > `system.runtime.boot_mode` (read by the post-login redirect); returning the raw envelope
60
+ > silently breaks it.
61
+
62
+ ### Contexts
63
+
64
+ - `AuthProvider` / `useAuth` — session + identity.
65
+ - `SystemProvider` / `useSystem` — runtime system state (incl. `boot_mode`).
66
+
67
+ ### Components
68
+
69
+ `AppShell`, `ProtectedRoute`, `VersionMismatchBanner`, `Toast`, `LoadingPanel`,
70
+ `DomainError`, `AdminAccessRequired` (+ `useAdminApiGuard`), `EmptyState`.
71
+
72
+ ### UI primitives
73
+
74
+ `Button` (+ `buttonVariants`), the `Card` family (`Card`, `CardHeader`, `CardTitle`,
75
+ `CardDescription`, `CardContent`, `CardFooter`), the `Tooltip` family (`Tooltip`,
76
+ `TooltipTrigger`, `TooltipContent`, `TooltipProvider`).
77
+
78
+ ### Utilities
79
+
80
+ `cn` (class merge), `APPROVAL_EVENT`, `useApiCall`, `useToast`, `safeArray`, `safeMap`.
81
+
82
+ ## Usage
83
+
84
+ ```jsx
85
+ import {
86
+ AuthProvider, SystemProvider, ProtectedRoute, AppShell,
87
+ ROUTES, request, unwrapEnvelope,
88
+ } from "@aindy/ui-kit";
89
+
90
+ function App() {
91
+ return (
92
+ <AuthProvider>
93
+ <SystemProvider>
94
+ <AppShell>{/* routes */}</AppShell>
95
+ </SystemProvider>
96
+ </AuthProvider>
97
+ );
98
+ }
99
+
100
+ // A backend call through the canonical route table:
101
+ const strategies = await request(ROUTES.OPERATOR.FLOW_STRATEGIES).then(unwrapEnvelope);
102
+ ```
103
+
104
+ ## Development
105
+
106
+ ```bash
107
+ npm run build # vite build → dist/ (index.js, index.cjs, index.d.ts)
108
+ npm run lint # eslint src
109
+ npm test # vitest
110
+ ```
111
+
112
+ ## Versioning & the runtime
113
+
114
+ `@aindy/ui-kit` and `aindy-runtime` are **independently versioned**. This package *consumes*
115
+ the runtime's HTTP contract; the runtime does not depend on it. A ui-kit release does **not**
116
+ require a runtime release (and vice versa) — a runtime bump is only relevant when a ui-kit
117
+ change depends on a *new* runtime route or behavior. Keep `ROUTES` in sync with the runtime's
118
+ `docs/runtime/UI_CONTRACT.md`; a route that drifts from a served backend path is the
119
+ `UIKIT-ROUTE-DRIFT-1` failure mode.
120
+
121
+ ## Publishing
122
+
123
+ `dist/` is gitignored and built fresh at publish:
124
+
125
+ ```bash
126
+ npm version patch # e.g. 1.0.5 → 1.0.6
127
+ npm run build
128
+ npm publish
129
+ ```
@@ -1,7 +1,18 @@
1
+ export const FEATURE_FLAGS: Readonly<{
2
+ OPERATOR_FLOW_STRATEGIES: true;
3
+ OPERATOR_AUTOMATION_LOGS: false;
4
+ OPERATOR_SCHEDULER_STATUS: false;
5
+ RIPPLETRACE_VIEWER: false;
6
+ }>;
1
7
  export const ROUTES: Readonly<{
2
8
  AUTH: Readonly<{
3
9
  LOGIN: "/auth/login";
4
10
  REGISTER: "/auth/register";
11
+ LOGOUT: "/auth/logout";
12
+ VERIFY_EMAIL: "/auth/verify-email";
13
+ PASSWORD_CHANGE: "/auth/password/change";
14
+ PASSWORD_FORGOT: "/auth/password/forgot";
15
+ PASSWORD_RESET: "/auth/password/reset";
5
16
  }>;
6
17
  TASKS: Readonly<{
7
18
  LIST: "/tasks/list";
@@ -23,6 +34,8 @@ export const ROUTES: Readonly<{
23
34
  RUN: (runId: any) => string;
24
35
  APPROVE: (runId: any) => string;
25
36
  REJECT: (runId: any) => string;
37
+ RECOVER: (runId: any) => string;
38
+ REPLAY: (runId: any) => string;
26
39
  STEPS: (runId: any) => string;
27
40
  EVENTS: (runId: any) => string;
28
41
  TOOLS: "/apps/agent/tools";
@@ -142,14 +155,15 @@ export const ROUTES: Readonly<{
142
155
  FLOW_RUN_RESUME: (runId: any) => string;
143
156
  FLOW_REGISTRY: "/platform/flows/registry";
144
157
  FLOW_STRATEGIES: "/platform/flows/strategies";
145
- AUTOMATION_LOGS: "/automation/logs";
146
- AUTOMATION_LOG: (logId: any) => string;
147
- AUTOMATION_REPLAY: (logId: any) => string;
148
- SCHEDULER_STATUS: "/platform/observability/scheduler/status";
158
+ RIPPLETRACE_STATUS: "/platform/observability/rippletrace/status";
149
159
  OBSERVABILITY_REQUESTS: "/platform/observability/requests";
150
160
  OBSERVABILITY_DASHBOARD: "/platform/observability/dashboard";
151
161
  CLIENT_ERROR: "/client/error";
152
162
  CLIENT_VITALS: "/client/vitals";
163
+ AUTOMATION_LOGS: "/automation/logs";
164
+ AUTOMATION_LOG: (logId: any) => string;
165
+ AUTOMATION_REPLAY: (logId: any) => string;
166
+ SCHEDULER_STATUS: "/platform/observability/scheduler/status";
153
167
  }>;
154
168
  PLATFORM: Readonly<{
155
169
  DASHBOARD_OVERVIEW: "/dashboard/overview";
@@ -1,3 +1,36 @@
1
1
  export function loginUser(credentials: any): Promise<any>;
2
+ /**
3
+ * Begin registration. Against runtime >= 2.0.0 this resolves to
4
+ * `{ status: "verification_sent" }` and **carries no access token** — the response is
5
+ * deliberately identical whether or not the address was already registered, which is what
6
+ * closes the account-enumeration oracle. The token is issued by `verifyEmail` once the
7
+ * emailed link is followed.
8
+ */
2
9
  export function registerUser(credentials: any): Promise<any>;
10
+ /** Consume an emailed verification token and receive the access token. */
11
+ export function verifyEmail(token: any): Promise<any>;
12
+ /**
13
+ * Rotate the signed-in user's password.
14
+ *
15
+ * Returns a freshly-versioned access token. **It must be stored** — the change invalidates
16
+ * every session including this one, so keeping the old token 401s on the next request.
17
+ */
18
+ export function changePassword(currentPassword: any, newPassword: any, token?: string): Promise<any>;
19
+ /**
20
+ * Begin password recovery.
21
+ *
22
+ * Resolves identically whether or not the address is registered — do not branch on the
23
+ * result to tell the user whether an account exists, that is the oracle this avoids. A 503
24
+ * means the deployment has no email channel configured, which is about the deployment and
25
+ * not about any account.
26
+ */
27
+ export function forgotPassword(email: any): Promise<any>;
28
+ /**
29
+ * Complete password recovery with an emailed token.
30
+ *
31
+ * Returns no access token — unlike `changePassword`, the caller has not proven they hold a
32
+ * session, so they sign in afresh.
33
+ */
34
+ export function resetPassword(token: any, newPassword: any): Promise<any>;
35
+ export function logoutUser(token?: string): Promise<any>;
3
36
  export function bootIdentity(token?: string): Promise<any>;
@@ -1,3 +1,3 @@
1
1
  export { ROUTES } from './_routes.js';
2
2
  export { ApiError, adminRequest, authRequest, authRequestExternal, buildApiUrl, clearStoredToken, getStoredToken, request, requestAbsolute, setStoredToken, taggedRequest, unwrapEnvelope, API_BASE } from './_core.js';
3
- export { bootIdentity, loginUser, registerUser } from './auth.js';
3
+ export { bootIdentity, changePassword, forgotPassword, loginUser, registerUser, resetPassword, verifyEmail } from './auth.js';