@possibl/rcrt-sdk 0.1.1 → 0.1.3

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 (87) hide show
  1. package/CHANGELOG.md +23 -67
  2. package/LICENSE +21 -0
  3. package/README.md +2 -20
  4. package/dist/auth.d.ts +45 -0
  5. package/dist/auth.d.ts.map +1 -0
  6. package/{src/auth.ts → dist/auth.js} +9 -24
  7. package/dist/auth.js.map +1 -0
  8. package/dist/authn.d.ts +84 -0
  9. package/dist/authn.d.ts.map +1 -0
  10. package/dist/authn.js +75 -0
  11. package/dist/authn.js.map +1 -0
  12. package/dist/breadcrumbs.d.ts +32 -0
  13. package/dist/breadcrumbs.d.ts.map +1 -0
  14. package/dist/breadcrumbs.js +96 -0
  15. package/dist/breadcrumbs.js.map +1 -0
  16. package/dist/cards.d.ts +28 -0
  17. package/dist/cards.d.ts.map +1 -0
  18. package/dist/cards.js +106 -0
  19. package/dist/cards.js.map +1 -0
  20. package/dist/chat.d.ts +50 -0
  21. package/dist/chat.d.ts.map +1 -0
  22. package/dist/chat.js +58 -0
  23. package/dist/chat.js.map +1 -0
  24. package/dist/client.d.ts +45 -0
  25. package/dist/client.d.ts.map +1 -0
  26. package/dist/client.js +69 -0
  27. package/dist/client.js.map +1 -0
  28. package/dist/errors.d.ts +32 -0
  29. package/dist/errors.d.ts.map +1 -0
  30. package/dist/errors.js +76 -0
  31. package/dist/errors.js.map +1 -0
  32. package/dist/generated/conformance.d.ts +48 -0
  33. package/dist/generated/conformance.d.ts.map +1 -0
  34. package/dist/generated/conformance.js +24 -0
  35. package/dist/generated/conformance.js.map +1 -0
  36. package/dist/generated/index.d.ts +34 -0
  37. package/dist/generated/index.d.ts.map +1 -0
  38. package/dist/generated/index.js +34 -0
  39. package/dist/generated/index.js.map +1 -0
  40. package/dist/generated/openapi.d.ts +3900 -0
  41. package/dist/generated/openapi.d.ts.map +1 -0
  42. package/dist/generated/openapi.js +6 -0
  43. package/dist/generated/openapi.js.map +1 -0
  44. package/dist/grants.d.ts +41 -0
  45. package/dist/grants.d.ts.map +1 -0
  46. package/dist/grants.js +50 -0
  47. package/dist/grants.js.map +1 -0
  48. package/dist/index.d.ts +23 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +18 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/internal/fetch.d.ts +41 -0
  53. package/dist/internal/fetch.d.ts.map +1 -0
  54. package/dist/internal/fetch.js +106 -0
  55. package/dist/internal/fetch.js.map +1 -0
  56. package/dist/internal/sse.d.ts +82 -0
  57. package/dist/internal/sse.d.ts.map +1 -0
  58. package/dist/internal/sse.js +161 -0
  59. package/dist/internal/sse.js.map +1 -0
  60. package/dist/types/breadcrumb.d.ts +70 -0
  61. package/dist/types/breadcrumb.d.ts.map +1 -0
  62. package/dist/types/breadcrumb.js +8 -0
  63. package/dist/types/breadcrumb.js.map +1 -0
  64. package/dist/types/card.d.ts +251 -0
  65. package/dist/types/card.d.ts.map +1 -0
  66. package/dist/types/card.js +10 -0
  67. package/dist/types/card.js.map +1 -0
  68. package/dist/types/index.d.ts +3 -0
  69. package/dist/types/index.d.ts.map +1 -0
  70. package/{src/types/index.ts → dist/types/index.js} +1 -0
  71. package/dist/types/index.js.map +1 -0
  72. package/package.json +35 -6
  73. package/src/authn.ts +0 -159
  74. package/src/breadcrumbs.ts +0 -111
  75. package/src/capabilities.ts +0 -93
  76. package/src/cards.ts +0 -109
  77. package/src/chat.ts +0 -83
  78. package/src/client.ts +0 -97
  79. package/src/errors.ts +0 -101
  80. package/src/files.ts +0 -135
  81. package/src/grants.ts +0 -99
  82. package/src/index.ts +0 -103
  83. package/src/internal/fetch.ts +0 -133
  84. package/src/internal/sse.ts +0 -236
  85. package/src/sessions.ts +0 -110
  86. package/src/types/breadcrumb.ts +0 -77
  87. package/src/types/card.ts +0 -298
package/CHANGELOG.md CHANGED
@@ -1,76 +1,32 @@
1
- # Changelog
1
+ # @possibl/rcrt-sdk — Changelog
2
2
 
3
- All notable changes to `@possibl/rcrt-sdk` are documented here. The
4
- format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
- this package follows [SemVer](https://semver.org/spec/v2.0.0.html) once
6
- published.
3
+ All notable changes are documented here. Follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) + [semver](https://semver.org/).
7
4
 
8
- ## [0.1.1] — 2026-04-30
5
+ ## 0.1.0-alpha.1 — 2026-04-23
9
6
 
10
- Patch release. The SDK ships TypeScript source directly (`main:
11
- ./src/index.ts`), which means consumer tsconfigs compile it. Stricter
12
- consumer settings (e.g. `noUnusedLocals: true` in
13
- `possibl-ai/ritual-app`) caught a stray unused import in `cards.ts`
14
- that the SDK's own tsconfig let pass.
7
+ First publish. Breaking changes are expected during the `alpha` line — pin exact versions. Do not use in production until `0.1.0` stable.
15
8
 
16
- ### Fixed
9
+ ### Included
17
10
 
18
- - Removed unused `ApiError` import in `src/cards.ts`. Consumers with
19
- `noUnusedLocals: true` no longer fail the type-check on the SDK's
20
- source.
11
+ - `RcrtClient` with auth, chat (send + stream), breadcrumbs (CRUD + tag query + semantic search), service grants, cards, identity modules.
12
+ - Pluggable `TokenProvider` interface SDK never touches Firebase / Auth0 / Clerk directly.
13
+ - Pluggable `EventSource` — React Native consumers inject `react-native-sse`; browser + Node 18+ use native.
14
+ - Typed error envelope via `ApiError.detail.code` / `KnownErrorCode`. Accepts both the canonical `{error: {code, message, details}}` and legacy `{error: "string"}` shapes during the migration window.
15
+ - Domain types (`Card`, `Breadcrumb`, `Row`, `ChartSpec`, ...) under the main export.
16
+ - OpenAPI-generated types (`paths`, `operations`, `components`) under `@possibl/rcrt-sdk/generated` for raw fetch-level type safety.
21
17
 
22
- ### Internal
18
+ ### Known gaps
23
19
 
24
- - Added `noUnusedLocals: true` + `noUnusedParameters: true` to the
25
- SDK's own `tsconfig.json` so future bumps can't ship the same class
26
- of issue. CI catches it before publish.
20
+ - No integration test suite against a live backend yet. Smoke tests (9/9) cover the mock surface. Integration harness is queued.
21
+ - The backend's error-envelope migration is in progress (tracked in `packages/docs/guides/07-error-handling.md`). Any handler still returning `{error: "string"}` is normalised by the SDK's `parseErrorBody`.
22
+ - React hooks / a card renderer are deliberately out of scope. See `packages/docs/recipes/react.md` for copy-pasteable patterns.
27
23
 
28
- ## [0.1.0] — 2026-04-30
24
+ ### Support matrix
29
25
 
30
- First public release. Drops the `-alpha.1` suffix; signals the SDK is
31
- ready for frontend consumption (canonical RCRT mobile + web template
32
- imports it directly).
33
-
34
- ### Added modules
35
-
36
- - **`FilesModule`** (`client.files`) multipart upload, list, get,
37
- signed-URL download, server-side text extraction, soft delete.
38
- Defaults to `tenant` scope; supports `org` / `user` for cross-
39
- workspace assets.
40
- - **`SessionsModule`** (`client.sessions`) — `getConstellation()`
41
- graph view of related sessions, `listParticipants` /
42
- `addParticipant` / `removeParticipant` for multi-agent sessions.
43
- - **`CapabilitiesModule`** (`client.capabilities`) — `list(type)` for
44
- tools / agents / services / knowledge, plus `getChattableAgents()`
45
- helper that filters `interpret:promptable` to entries tagged
46
- `interface:chat` / `interface:chat-default`.
47
- - **`IdentityModule.getUserProfile` / `updateUserProfile`** — workspace-
48
- scoped editable profile breadcrumb. Returns `null` (instead of
49
- throwing) when no profile has been written yet.
50
- - **`GrantsModule.resolveService(name)`** — server-side credential
51
- resolution for tools that need to act on behalf of a workspace's
52
- active service grant.
53
-
54
- ### Notes
55
-
56
- - `IdentityModule.listPendingInvitations` / `acceptInvitation` /
57
- `declineInvitation` were already shipped in the alpha — no change.
58
- - Global-events SSE (`/v1/events`) is exposed as `chat.globalStream`
59
- rather than its own module — an extra module would have meant a
60
- duplicate config builder.
61
- - Tenant admin endpoints (members, resource overrides) deliberately
62
- out of scope for `0.1.0`. Will land in a `0.2.x` once a consumer
63
- needs them.
64
-
65
- ### Dependencies
66
-
67
- - No runtime deps. The SDK is fetch + EventSource + plain TS. Bring
68
- your own `EventSource` polyfill on React Native (see README).
69
-
70
- ### Compatibility
71
-
72
- - Node 18+ (native fetch + WHATWG URL).
73
- - Browsers with `fetch`, `URL`, `URLSearchParams`, `EventSource`.
74
- - React Native — pass an `eventSource` constructor in
75
- `chat.sessionStream({ eventSource })` and bring a fetch polyfill if
76
- using a runtime older than RN 0.74.
26
+ | Runtime | Supported |
27
+ | --- | --- |
28
+ | Browser (Chrome 103+, Firefox 102+, Safari 16+) | Yes |
29
+ | Node 18+ | Yes |
30
+ | React Native + `react-native-sse` polyfill | Yes |
31
+ | Deno 1.40+ | Untested, should work |
32
+ | Bun 1.0+ | Untested, should work |
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Possibl AI Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -99,21 +99,6 @@ const stream = rcrt.chat.sessionStream(sessionId, handlers, {
99
99
 
100
100
  Browse `src/index.ts` for the full re-export list.
101
101
 
102
- ### Module surface on `RcrtClient`
103
-
104
- ```ts
105
- const rcrt = new RcrtClient({ apiUrl, tokenProvider });
106
-
107
- rcrt.auth // identity, tenants, invitations, user profile
108
- rcrt.breadcrumbs // CRUD + tag query + semantic search
109
- rcrt.chat // send + sessionStream (per-session SSE) + globalStream (/v1/events)
110
- rcrt.cards // JIT-UI card resolve + helpers
111
- rcrt.grants // OAuth grants + initiate + resolveService
112
- rcrt.files // upload / list / get / signed download / text extract / delete
113
- rcrt.sessions // constellation + participants
114
- rcrt.capabilities // tools / agents / services / knowledge discovery
115
- ```
116
-
117
102
  ## Design notes
118
103
 
119
104
  - **Isomorphic**: zero DOM or Node-only APIs in the core. The only
@@ -142,13 +127,10 @@ Full narrative + concepts + operations playbook in
142
127
 
143
128
  ## Status
144
129
 
145
- **0.1.0** — first public release. Used by `possibl-ai/rcrt-template-mobile`
146
- and downstream apps (e.g. `possibl-ai/ritual-app`, `possibl-ai/properlii-mobile`)
147
- as their canonical RCRT client. Surface stable; minor adjustments
130
+ **0.1.0-alpha** — first published alongside the OpenAPI v1 draft.
131
+ Shape is stable for the documented surface; minor adjustments
148
132
  possible before 1.0.
149
133
 
150
- See [`CHANGELOG.md`](./CHANGELOG.md) for what's new in this release.
151
-
152
134
  ## Licence
153
135
 
154
136
  MIT.
package/dist/auth.d.ts ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * TokenProvider — the seam between RCRT and your identity source.
3
+ *
4
+ * The SDK never talks to Firebase / Auth0 / Clerk directly. You wire
5
+ * up whichever IdP you use by implementing this interface once. On
6
+ * every request the SDK calls `getIdToken()` to get a fresh bearer.
7
+ *
8
+ * The provider owns refresh. If your IdP supports it (Firebase does),
9
+ * it should return a token that's valid for at least the next ~60s;
10
+ * the SDK doesn't track expiry itself.
11
+ *
12
+ * Example Firebase (web):
13
+ *
14
+ * import { getAuth } from 'firebase/auth';
15
+ * const auth = getAuth();
16
+ * const tokenProvider: TokenProvider = {
17
+ * async getIdToken() {
18
+ * const u = auth.currentUser;
19
+ * if (!u) throw new SdkError('NOT_SIGNED_IN', 'Sign in first');
20
+ * return u.getIdToken(false);
21
+ * },
22
+ * };
23
+ *
24
+ * Example test stub:
25
+ *
26
+ * const tokenProvider: TokenProvider = {
27
+ * async getIdToken() { return 'tk_test_workspace_api_key'; },
28
+ * };
29
+ */
30
+ export interface TokenProvider {
31
+ /**
32
+ * Return a bearer token for the next request. Throws or rejects if
33
+ * the user isn't signed in / the key is missing.
34
+ *
35
+ * Implementations SHOULD refresh transparently if they know the
36
+ * token is close to expiry. The SDK calls this per-request and
37
+ * doesn't cache.
38
+ */
39
+ getIdToken(): Promise<string>;
40
+ /** Optional hook: called on 401. Implementations can force a refresh. */
41
+ onUnauthorized?(): Promise<void>;
42
+ }
43
+ /** Convenience: a provider that returns a static string. For workspace API keys or tests. */
44
+ export declare function staticTokenProvider(token: string): TokenProvider;
45
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,MAAM,WAAW,aAAa;IAC5B;;;;;;;OAOG;IACH,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE9B,yEAAyE;IACzE,cAAc,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAOhE"}
@@ -27,30 +27,15 @@
27
27
  * async getIdToken() { return 'tk_test_workspace_api_key'; },
28
28
  * };
29
29
  */
30
-
31
30
  import { SdkError } from './errors.js';
32
-
33
- export interface TokenProvider {
34
- /**
35
- * Return a bearer token for the next request. Throws or rejects if
36
- * the user isn't signed in / the key is missing.
37
- *
38
- * Implementations SHOULD refresh transparently if they know the
39
- * token is close to expiry. The SDK calls this per-request and
40
- * doesn't cache.
41
- */
42
- getIdToken(): Promise<string>;
43
-
44
- /** Optional hook: called on 401. Implementations can force a refresh. */
45
- onUnauthorized?(): Promise<void>;
46
- }
47
-
48
31
  /** Convenience: a provider that returns a static string. For workspace API keys or tests. */
49
- export function staticTokenProvider(token: string): TokenProvider {
50
- if (!token) throw new SdkError('EMPTY_TOKEN', 'staticTokenProvider called with empty token');
51
- return {
52
- async getIdToken() {
53
- return token;
54
- },
55
- };
32
+ export function staticTokenProvider(token) {
33
+ if (!token)
34
+ throw new SdkError('EMPTY_TOKEN', 'staticTokenProvider called with empty token');
35
+ return {
36
+ async getIdToken() {
37
+ return token;
38
+ },
39
+ };
56
40
  }
41
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiBvC,6FAA6F;AAC7F,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,QAAQ,CAAC,aAAa,EAAE,6CAA6C,CAAC,CAAC;IAC7F,OAAO;QACL,KAAK,CAAC,UAAU;YACd,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Identity module — `/v1/auth/*` endpoints.
3
+ *
4
+ * Distinct from the TokenProvider abstraction: this is the server-side
5
+ * identity surface that runs _after_ you've presented a bearer token.
6
+ * See `packages/docs/guides/02-auth.md`.
7
+ */
8
+ import type { FetchContext } from './internal/fetch.js';
9
+ export interface MeResponse {
10
+ user: {
11
+ id: string;
12
+ email: string;
13
+ name?: string;
14
+ picture?: string;
15
+ };
16
+ is_platform_admin: boolean;
17
+ organizations: Array<{
18
+ id: string;
19
+ name: string;
20
+ role: string;
21
+ }>;
22
+ tenants: Array<{
23
+ id: string;
24
+ name: string;
25
+ role: string;
26
+ }>;
27
+ active_tenant?: {
28
+ id: string;
29
+ name: string;
30
+ role: string;
31
+ };
32
+ permissions?: string[];
33
+ grants?: unknown[];
34
+ }
35
+ export interface Tenant {
36
+ id: string;
37
+ name: string;
38
+ org_id?: string;
39
+ role?: string;
40
+ }
41
+ export interface PendingInvitation {
42
+ id: string;
43
+ org_id?: string | null;
44
+ tenant_id?: string | null;
45
+ email: string;
46
+ role: string;
47
+ status: 'pending' | 'accepted' | 'declined' | 'expired' | 'cancelled';
48
+ expires_at: string;
49
+ invited_by?: {
50
+ id: string;
51
+ name?: string;
52
+ };
53
+ }
54
+ export declare class IdentityModule {
55
+ private readonly ctx;
56
+ constructor(ctx: FetchContext);
57
+ /**
58
+ * `GET /v1/auth/me` — returns identity + all accessible workspaces.
59
+ *
60
+ * Creates the user row on first sign-in. Call this before any other
61
+ * RCRT endpoint for brand-new Firebase users.
62
+ */
63
+ me(): Promise<MeResponse>;
64
+ /** List workspaces the current user is a member of. */
65
+ listTenants(): Promise<Tenant[]>;
66
+ /** Confirm workspace membership. Client code is still responsible for setting X-Tenant-ID. */
67
+ selectTenant(tenantId: string): Promise<void>;
68
+ /** `POST /v1/auth/logout` — server-side no-op; included for symmetry + audit. */
69
+ logout(): Promise<void>;
70
+ /**
71
+ * `POST /v1/auth/delete-account` — cascading account deletion.
72
+ *
73
+ * **NOT YET ON `development`** at publish time — pending a follow-up
74
+ * PR. The SDK method exists so consumer code can compile against the
75
+ * intended shape; invoking it against a gateway that lacks the
76
+ * handler returns 404.
77
+ */
78
+ deleteAccount(): Promise<void>;
79
+ /** Pending invitations keyed by the caller's email. */
80
+ listPendingInvitations(): Promise<PendingInvitation[]>;
81
+ acceptInvitation(token: string): Promise<void>;
82
+ declineInvitation(invitationId: string): Promise<void>;
83
+ }
84
+ //# sourceMappingURL=authn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authn.d.ts","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3D,aAAa,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3D,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,CAAC;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,YAAY;IAE9C;;;;;OAKG;IACG,EAAE,IAAI,OAAO,CAAC,UAAU,CAAC;IAI/B,uDAAuD;IACjD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOtC,8FAA8F;IACxF,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOnD,iFAAiF;IAC3E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAO7B;;;;;;;OAOG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC,uDAAuD;IACjD,sBAAsB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAOtD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAK7D"}
package/dist/authn.js ADDED
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Identity module — `/v1/auth/*` endpoints.
3
+ *
4
+ * Distinct from the TokenProvider abstraction: this is the server-side
5
+ * identity surface that runs _after_ you've presented a bearer token.
6
+ * See `packages/docs/guides/02-auth.md`.
7
+ */
8
+ import { request } from './internal/fetch.js';
9
+ export class IdentityModule {
10
+ ctx;
11
+ constructor(ctx) {
12
+ this.ctx = ctx;
13
+ }
14
+ /**
15
+ * `GET /v1/auth/me` — returns identity + all accessible workspaces.
16
+ *
17
+ * Creates the user row on first sign-in. Call this before any other
18
+ * RCRT endpoint for brand-new Firebase users.
19
+ */
20
+ async me() {
21
+ return request(this.ctx, '/v1/auth/me', { skipTenant: true });
22
+ }
23
+ /** List workspaces the current user is a member of. */
24
+ async listTenants() {
25
+ const res = await request(this.ctx, '/v1/auth/tenants', {
26
+ skipTenant: true,
27
+ });
28
+ return Array.isArray(res) ? res : (res.tenants ?? []);
29
+ }
30
+ /** Confirm workspace membership. Client code is still responsible for setting X-Tenant-ID. */
31
+ async selectTenant(tenantId) {
32
+ await request(this.ctx, `/v1/auth/tenants/${tenantId}/select`, {
33
+ method: 'POST',
34
+ skipTenant: true,
35
+ });
36
+ }
37
+ /** `POST /v1/auth/logout` — server-side no-op; included for symmetry + audit. */
38
+ async logout() {
39
+ await request(this.ctx, '/v1/auth/logout', {
40
+ method: 'POST',
41
+ skipTenant: true,
42
+ });
43
+ }
44
+ /**
45
+ * `POST /v1/auth/delete-account` — cascading account deletion.
46
+ *
47
+ * **NOT YET ON `development`** at publish time — pending a follow-up
48
+ * PR. The SDK method exists so consumer code can compile against the
49
+ * intended shape; invoking it against a gateway that lacks the
50
+ * handler returns 404.
51
+ */
52
+ async deleteAccount() {
53
+ await request(this.ctx, '/v1/auth/delete-account', {
54
+ method: 'POST',
55
+ skipTenant: true,
56
+ });
57
+ }
58
+ /** Pending invitations keyed by the caller's email. */
59
+ async listPendingInvitations() {
60
+ const res = await request(this.ctx, '/v1/invitations/pending');
61
+ return Array.isArray(res) ? res : (res.invitations ?? []);
62
+ }
63
+ async acceptInvitation(token) {
64
+ await request(this.ctx, '/v1/invitations/accept', {
65
+ method: 'POST',
66
+ body: { token },
67
+ });
68
+ }
69
+ async declineInvitation(invitationId) {
70
+ await request(this.ctx, `/v1/invitations/${invitationId}/decline`, {
71
+ method: 'POST',
72
+ });
73
+ }
74
+ }
75
+ //# sourceMappingURL=authn.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authn.js","sourceRoot":"","sources":["../src/authn.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAmC9C,MAAM,OAAO,cAAc;IACI;IAA7B,YAA6B,GAAiB;QAAjB,QAAG,GAAH,GAAG,CAAc;IAAG,CAAC;IAElD;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QACN,OAAO,OAAO,CAAa,IAAI,CAAC,GAAG,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,MAAM,OAAO,CAAmC,IAAI,CAAC,GAAG,EAAE,kBAAkB,EAAE;YACxF,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;QACH,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,8FAA8F;IAC9F,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,oBAAoB,QAAQ,SAAS,EAAE;YACnE,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,MAAM;QACV,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE;YAC/C,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa;QACjB,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,yBAAyB,EAAE;YACvD,MAAM,EAAE,MAAM;YACd,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC;IACL,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,sBAAsB;QAC1B,MAAM,GAAG,GAAG,MAAM,OAAO,CAEvB,IAAI,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC;QACvC,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAa;QAClC,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,wBAAwB,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,KAAK,EAAE;SAChB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,YAAoB;QAC1C,MAAM,OAAO,CAAO,IAAI,CAAC,GAAG,EAAE,mBAAmB,YAAY,UAAU,EAAE;YACvE,MAAM,EAAE,MAAM;SACf,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Breadcrumbs module — CRUD + tag query + semantic search.
3
+ *
4
+ * See `packages/docs/guides/04-breadcrumbs.md` for the narrative
5
+ * description of each operation.
6
+ */
7
+ import type { FetchContext } from './internal/fetch.js';
8
+ import type { Breadcrumb, CreateBreadcrumbRequest, UpdateBreadcrumbRequest, QueryByTagsOptions, SemanticSearchOptions } from './types/breadcrumb.js';
9
+ export declare class BreadcrumbsModule {
10
+ private readonly ctx;
11
+ constructor(ctx: FetchContext);
12
+ /** `POST /v1/breadcrumbs` */
13
+ create(req: CreateBreadcrumbRequest): Promise<Breadcrumb>;
14
+ /** `GET /v1/breadcrumbs?tags=...` — AND semantics. */
15
+ queryByTags(tags: string[], options?: QueryByTagsOptions): Promise<Breadcrumb[]>;
16
+ /** `GET /v1/breadcrumbs/search?q=...` — cosine-similarity semantic search. */
17
+ search(q: string, options?: SemanticSearchOptions): Promise<Breadcrumb[]>;
18
+ /** `GET /v1/breadcrumbs/{id}` */
19
+ get(id: string): Promise<Breadcrumb>;
20
+ /**
21
+ * `PATCH /v1/breadcrumbs/{id}` — optimistic-locking update.
22
+ *
23
+ * If `req.version` is wrong, the server returns 409. Pass
24
+ * `autoRetryConflict: true` to have the SDK refetch + retry once.
25
+ */
26
+ update(id: string, req: UpdateBreadcrumbRequest, opts?: {
27
+ autoRetryConflict?: boolean;
28
+ }): Promise<Breadcrumb>;
29
+ /** `DELETE /v1/breadcrumbs/{id}` — soft delete. */
30
+ delete(id: string): Promise<void>;
31
+ }
32
+ //# sourceMappingURL=breadcrumbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EACV,UAAU,EAEV,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAG/B,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,YAAY;IAE9C,6BAA6B;IACvB,MAAM,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,UAAU,CAAC;IAU/D,sDAAsD;IAChD,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAgB1F,8EAA8E;IACxE,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAUnF,iCAAiC;IAC3B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAI1C;;;;;OAKG;IACG,MAAM,CACV,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,uBAAuB,EAC5B,IAAI,GAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAO,GACzC,OAAO,CAAC,UAAU,CAAC;IAyBtB,mDAAmD;IAC7C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQxC"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Breadcrumbs module — CRUD + tag query + semantic search.
3
+ *
4
+ * See `packages/docs/guides/04-breadcrumbs.md` for the narrative
5
+ * description of each operation.
6
+ */
7
+ import { request } from './internal/fetch.js';
8
+ import { ApiError, SdkError } from './errors.js';
9
+ export class BreadcrumbsModule {
10
+ ctx;
11
+ constructor(ctx) {
12
+ this.ctx = ctx;
13
+ }
14
+ /** `POST /v1/breadcrumbs` */
15
+ async create(req) {
16
+ const res = await request(this.ctx, '/v1/breadcrumbs', {
17
+ method: 'POST',
18
+ body: req,
19
+ });
20
+ return 'breadcrumb' in res
21
+ ? res.breadcrumb
22
+ : res;
23
+ }
24
+ /** `GET /v1/breadcrumbs?tags=...` — AND semantics. */
25
+ async queryByTags(tags, options = {}) {
26
+ if (tags.length === 0) {
27
+ throw new SdkError('EMPTY_TAGS', 'queryByTags requires at least one tag');
28
+ }
29
+ const res = await request(this.ctx, '/v1/breadcrumbs', {
30
+ query: {
31
+ tags,
32
+ limit: options.limit,
33
+ offset: options.offset,
34
+ name: options.name,
35
+ order: options.order,
36
+ },
37
+ });
38
+ return Array.isArray(res) ? res : (res.breadcrumbs ?? []);
39
+ }
40
+ /** `GET /v1/breadcrumbs/search?q=...` — cosine-similarity semantic search. */
41
+ async search(q, options = {}) {
42
+ const query = {
43
+ q,
44
+ limit: options.limit,
45
+ };
46
+ if (options.tags?.length)
47
+ query.tags = options.tags;
48
+ const res = await request(this.ctx, '/v1/breadcrumbs/search', { query });
49
+ return Array.isArray(res) ? res : (res.breadcrumbs ?? []);
50
+ }
51
+ /** `GET /v1/breadcrumbs/{id}` */
52
+ async get(id) {
53
+ return request(this.ctx, `/v1/breadcrumbs/${id}`);
54
+ }
55
+ /**
56
+ * `PATCH /v1/breadcrumbs/{id}` — optimistic-locking update.
57
+ *
58
+ * If `req.version` is wrong, the server returns 409. Pass
59
+ * `autoRetryConflict: true` to have the SDK refetch + retry once.
60
+ */
61
+ async update(id, req, opts = {}) {
62
+ const refetchBeforeRetry = opts.autoRetryConflict
63
+ ? async () => {
64
+ const fresh = await this.get(id);
65
+ return {
66
+ body: {
67
+ ...req,
68
+ version: fresh.version,
69
+ },
70
+ };
71
+ }
72
+ : undefined;
73
+ const res = await request(this.ctx, `/v1/breadcrumbs/${id}`, {
74
+ method: 'PATCH',
75
+ body: req,
76
+ ...(refetchBeforeRetry
77
+ ? { maxConflictRetries: 2, refetchBeforeRetry }
78
+ : {}),
79
+ });
80
+ return 'breadcrumb' in res
81
+ ? res.breadcrumb
82
+ : res;
83
+ }
84
+ /** `DELETE /v1/breadcrumbs/{id}` — soft delete. */
85
+ async delete(id) {
86
+ try {
87
+ await request(this.ctx, `/v1/breadcrumbs/${id}`, { method: 'DELETE' });
88
+ }
89
+ catch (err) {
90
+ if (err instanceof ApiError && err.status === 404)
91
+ return; // idempotent
92
+ throw err;
93
+ }
94
+ }
95
+ }
96
+ //# sourceMappingURL=breadcrumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Cards module — resolve an `interpret:pending-action` breadcrumb.
3
+ *
4
+ * The card's footer action ids correspond to values the SDK writes
5
+ * to `content.status`. See
6
+ * `packages/docs/guides/06-rendering-cards.md`.
7
+ */
8
+ import type { FetchContext } from './internal/fetch.js';
9
+ import type { Breadcrumb } from './types/breadcrumb.js';
10
+ import type { Card, ResolveRequest } from './types/card.js';
11
+ export declare class CardsModule {
12
+ private readonly ctx;
13
+ constructor(ctx: FetchContext);
14
+ /**
15
+ * PATCH the card breadcrumb with a resolution. Handles optimistic
16
+ * locking transparently — refetches + retries on 409.
17
+ */
18
+ resolve(breadcrumbId: string, resolution: ResolveRequest): Promise<Breadcrumb>;
19
+ /** Pending cards for the current user's current workspace. */
20
+ listPending(limit?: number): Promise<Breadcrumb[]>;
21
+ /**
22
+ * Extract the Card object from a breadcrumb's content, normalising
23
+ * over legacy shapes (old breadcrumbs stored `card.type` + flat
24
+ * fields instead of `card.layout` + structured body).
25
+ */
26
+ static extractCard(bc: Breadcrumb): Card | undefined;
27
+ }
28
+ //# sourceMappingURL=cards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../src/cards.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG5D,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,EAAE,YAAY;IAE9C;;;OAGG;IACG,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAmCpF,8DAA8D;IACxD,WAAW,CAAC,KAAK,SAAK,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAOpD;;;;OAIG;IACH,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS;CAkBrD"}