@tangle-network/agent-app 0.43.24 → 0.43.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/app-auth/index.d.ts +163 -0
  2. package/dist/app-auth/index.js +166 -0
  3. package/dist/app-auth/index.js.map +1 -0
  4. package/dist/assets/index.d.ts +2 -2
  5. package/dist/assistant/index.d.ts +2 -0
  6. package/dist/assistant/index.js +3 -1
  7. package/dist/assistant/index.js.map +1 -1
  8. package/dist/chat-routes/index.d.ts +276 -0
  9. package/dist/chat-routes/index.js +564 -0
  10. package/dist/chat-routes/index.js.map +1 -0
  11. package/dist/chat-store/index.d.ts +194 -0
  12. package/dist/chat-store/index.js +198 -0
  13. package/dist/chat-store/index.js.map +1 -0
  14. package/dist/chunk-4TXDD6P2.js +163 -0
  15. package/dist/chunk-4TXDD6P2.js.map +1 -0
  16. package/dist/chunk-5EQCITY3.js +20 -0
  17. package/dist/chunk-5EQCITY3.js.map +1 -0
  18. package/dist/chunk-5SV5PSU7.js +80 -0
  19. package/dist/chunk-5SV5PSU7.js.map +1 -0
  20. package/dist/chunk-7LNGJDNA.js +1 -0
  21. package/dist/chunk-7LNGJDNA.js.map +1 -0
  22. package/dist/{chunk-77RLNLFP.js → chunk-ATRJULKZ.js} +41 -5
  23. package/dist/chunk-ATRJULKZ.js.map +1 -0
  24. package/dist/{chunk-VMY4TKMN.js → chunk-FCQP75JT.js} +936 -436
  25. package/dist/chunk-FCQP75JT.js.map +1 -0
  26. package/dist/chunk-I2R2XT4M.js +62 -0
  27. package/dist/chunk-I2R2XT4M.js.map +1 -0
  28. package/dist/{chunk-3PK3T4KD.js → chunk-JJGZ54EB.js} +44 -1
  29. package/dist/chunk-JJGZ54EB.js.map +1 -0
  30. package/dist/chunk-TKVJE63N.js +304 -0
  31. package/dist/chunk-TKVJE63N.js.map +1 -0
  32. package/dist/{chunk-SAOAAA3S.js → chunk-UHXQ3KNX.js} +1 -22
  33. package/dist/chunk-UHXQ3KNX.js.map +1 -0
  34. package/dist/chunk-Y4QHNQ75.js +203 -0
  35. package/dist/chunk-Y4QHNQ75.js.map +1 -0
  36. package/dist/contract-DYbTzEDf.d.ts +122 -0
  37. package/dist/core-7qIM7svy.d.ts +21 -0
  38. package/dist/index.d.ts +6 -2
  39. package/dist/index.js +179 -92
  40. package/dist/interactions/index.d.ts +141 -0
  41. package/dist/interactions/index.js +60 -0
  42. package/dist/interactions/index.js.map +1 -0
  43. package/dist/parts-BcbitSNp.d.ts +176 -0
  44. package/dist/platform/index.d.ts +2 -270
  45. package/dist/platform/index.js +14 -278
  46. package/dist/platform/index.js.map +1 -1
  47. package/dist/preset-cloudflare/index.d.ts +0 -10
  48. package/dist/preset-cloudflare/index.js +1 -1
  49. package/dist/profile/index.d.ts +33 -2
  50. package/dist/profile/index.js +37 -1
  51. package/dist/profile/index.js.map +1 -1
  52. package/dist/sandbox/index.d.ts +47 -1
  53. package/dist/sandbox/index.js +11 -1
  54. package/dist/sso-CNOsARMJ.d.ts +285 -0
  55. package/dist/stream/index.js +1 -1
  56. package/dist/teams/index.js +9 -9
  57. package/dist/teams/invitations-api.js +3 -3
  58. package/dist/web-react/index.d.ts +229 -99
  59. package/dist/web-react/index.js +72 -22
  60. package/dist/wire-BaUF66AS.d.ts +61 -0
  61. package/package.json +25 -1
  62. package/dist/chunk-3PK3T4KD.js.map +0 -1
  63. package/dist/chunk-77RLNLFP.js.map +0 -1
  64. package/dist/chunk-SAOAAA3S.js.map +0 -1
  65. package/dist/chunk-VMY4TKMN.js.map +0 -1
@@ -0,0 +1,176 @@
1
+ import { Part } from '@tangle-network/agent-interface';
2
+ import { a as ChatInteractionField, b as ChatInteractionStatus, N as NoticeKind } from './contract-DYbTzEDf.js';
3
+
4
+ /**
5
+ * The stored shape of `message.parts` — one typed vocabulary for every part a
6
+ * product persists into a chat transcript. NOT an ad-hoc union reverse-
7
+ * engineered from product schemas; each member is matched field-for-field to
8
+ * its canonical source:
9
+ *
10
+ * - `text` / `reasoning` / `tool`: the persisted projection `/stream`'s
11
+ * `normalizePersistedPart` produces from the harness lane's
12
+ * `message.part.updated` events (ADC sidecar
13
+ * `apps/sidecar/src/events/session-events.ts:56` wraps the canonical part in
14
+ * an `{id, sessionID, messageID}` envelope; the projection strips the
15
+ * session/message ids and keeps the per-segment part id).
16
+ * - `file` / `image` / `step-start` / `step-finish`: the sidecar's canonical
17
+ * `MessagePartSchema` members (ADC
18
+ * `apps/sidecar/src/schemas/agent-schemas.ts:50-154`); `step-finish` carries
19
+ * the harness's per-step usage receipt — tokens
20
+ * `{total, input, output, reasoning, cache{write, read}}` + `cost` — which is
21
+ * also the shape the message-level token/cost columns mirror.
22
+ * - `subtask`: `@tangle-network/agent-interface`'s `SubtaskPart` (a spawned
23
+ * sub-agent task).
24
+ * - `interaction` / `notice`: the persisted-part codecs in
25
+ * `/web-react`'s chat-interactions contract (`interactionToPersistedPart`,
26
+ * `noticePart`) — type-only imports, one source of truth for their statuses
27
+ * and field shapes.
28
+ *
29
+ * `@tangle-network/agent-interface` exports the canonical wire `Part` union,
30
+ * but its `PartBase` requires the `sessionID`/`messageID` stream envelope that
31
+ * is deliberately NOT persisted, so the stored union is defined here as the
32
+ * envelope-free projection (a type-level coverage check against the peer's
33
+ * `Part['type']` lives in the tests). Contribute-down candidate: if
34
+ * agent-interface grows envelope-free persisted-part types, re-export them
35
+ * here and delete these definitions.
36
+ *
37
+ * Two transport lanes serialize into this SAME stored shape:
38
+ * - harness lane: canonical `message.part.updated` parts, merged/normalized by
39
+ * `/stream` (`mergePersistedPart`, `finalizeAssistantParts`);
40
+ * - router/openai-compat lane: `text_delta`/`tool_call` stream events are
41
+ * mapped INTO canonical part events first (`/runtime`'s `toLoopEvents` +
42
+ * `/stream`'s `normalizeToolEvent`) and then persisted identically — the
43
+ * store never sees a router-specific shape.
44
+ */
45
+
46
+ /** Start/end wall-clock millis, as normalized by `/stream`'s `normalizeTime`. */
47
+ interface ChatPartTime {
48
+ start?: number;
49
+ end?: number;
50
+ }
51
+ /** `id` is the harness's per-segment identity; absent on legacy/router parts,
52
+ * which collapse to a single logical text stream. Never invented client-side. */
53
+ interface ChatTextPart {
54
+ type: 'text';
55
+ text: string;
56
+ id?: string;
57
+ }
58
+ interface ChatReasoningPart {
59
+ type: 'reasoning';
60
+ text: string;
61
+ id?: string;
62
+ time?: ChatPartTime;
63
+ }
64
+ /** Superset of the sidecar's status enum (`pending|running|completed|failed`)
65
+ * and agent-interface's `ToolState` statuses; `error` is the persisted
66
+ * terminal form `/stream`'s `normalizePersistedPart` settles on. */
67
+ type ChatToolStatus = 'pending' | 'running' | 'completed' | 'error' | 'failed';
68
+ interface ChatToolState {
69
+ status: ChatToolStatus;
70
+ input?: unknown;
71
+ output?: unknown;
72
+ error?: string;
73
+ title?: string;
74
+ metadata?: Record<string, unknown>;
75
+ time?: ChatPartTime;
76
+ }
77
+ interface ChatToolPart {
78
+ type: 'tool';
79
+ id: string;
80
+ tool: string;
81
+ callID?: string;
82
+ state: ChatToolState;
83
+ }
84
+ /** Union of the sidecar's legacy (path-based) and AI-SDK (url-based) file
85
+ * shapes; response-side every field besides `type` is optional. */
86
+ interface ChatFilePart {
87
+ type: 'file';
88
+ id?: string;
89
+ filename?: string;
90
+ mediaType?: string;
91
+ url?: string;
92
+ path?: string;
93
+ content?: string;
94
+ }
95
+ interface ChatImagePart {
96
+ type: 'image';
97
+ filename?: string;
98
+ mediaType?: string;
99
+ url?: string;
100
+ path?: string;
101
+ }
102
+ interface ChatSubtaskPart {
103
+ type: 'subtask';
104
+ prompt: string;
105
+ description: string;
106
+ agent: string;
107
+ id?: string;
108
+ }
109
+ /** OpenCode step-boundary marker — no renderable text; preserved so mappers
110
+ * never coerce it into a "[object Object]" text part. */
111
+ interface ChatStepStartPart {
112
+ type: 'step-start';
113
+ }
114
+ /** Per-step usage receipt as the harness reports it (sidecar
115
+ * `StepFinishPartSchema`). The message-level token/cost columns are this
116
+ * shape flattened. */
117
+ interface ChatUsageTokens {
118
+ total?: number;
119
+ input?: number;
120
+ output?: number;
121
+ reasoning?: number;
122
+ cache?: {
123
+ write?: number;
124
+ read?: number;
125
+ };
126
+ }
127
+ interface ChatStepFinishPart {
128
+ type: 'step-finish';
129
+ reason?: string;
130
+ tokens?: ChatUsageTokens;
131
+ cost?: number;
132
+ }
133
+ /** Persisted human-in-the-loop ask — byte-matches
134
+ * `interactionToPersistedPart` in `/web-react`'s chat-interactions contract. */
135
+ interface ChatInteractionPart {
136
+ type: 'interaction';
137
+ id: string;
138
+ kind: string;
139
+ title: string;
140
+ body?: string;
141
+ answerSpec: {
142
+ fields: ChatInteractionField[];
143
+ };
144
+ status: ChatInteractionStatus;
145
+ cancelReason?: string;
146
+ }
147
+ /** Persisted one-line transcript notice — byte-matches `noticePart` in
148
+ * `/web-react`'s chat-interactions contract. */
149
+ interface ChatNoticePart {
150
+ type: 'notice';
151
+ id: string;
152
+ noticeKind: NoticeKind;
153
+ text: string;
154
+ }
155
+ type ChatMessagePart = ChatTextPart | ChatReasoningPart | ChatToolPart | ChatFilePart | ChatImagePart | ChatSubtaskPart | ChatStepStartPart | ChatStepFinishPart | ChatInteractionPart | ChatNoticePart;
156
+ /** Every canonical harness wire-part kind must be storable — compile-time
157
+ * guarantee that a new agent-interface part kind cannot silently fall out of
158
+ * the persisted vocabulary. */
159
+ type StorableHarnessPartKind = Part['type'] & ChatMessagePart['type'];
160
+ /**
161
+ * The typed projection at the `/stream` → `/chat-store` boundary. The stream
162
+ * normalizers (`normalizePersistedPart`/`mergePersistedPart`/
163
+ * `finalizeAssistantParts`) deliberately produce untyped `JsonRecord`s — they
164
+ * normalize wire shapes and do not own the stored vocabulary. THIS module
165
+ * owns it, so this is where rows gain the `ChatMessagePart` type: each entry
166
+ * is validated against its kind's required fields and narrowed, junk is
167
+ * dropped, and — enforced by the exhaustiveness check below — no storable
168
+ * kind can silently fall out (the step-finish/interaction trap).
169
+ */
170
+ declare function toChatMessageParts(parts: Array<Record<string, unknown>>): ChatMessagePart[];
171
+ declare function isChatToolPart(part: ChatMessagePart): part is ChatToolPart;
172
+ declare function isChatTextPart(part: ChatMessagePart): part is ChatTextPart;
173
+ declare function isChatInteractionPart(part: ChatMessagePart): part is ChatInteractionPart;
174
+ declare function isChatStepFinishPart(part: ChatMessagePart): part is ChatStepFinishPart;
175
+
176
+ export { type ChatFilePart as C, type StorableHarnessPartKind as S, type ChatImagePart as a, type ChatInteractionPart as b, type ChatMessagePart as c, type ChatNoticePart as d, type ChatPartTime as e, type ChatReasoningPart as f, type ChatStepFinishPart as g, type ChatStepStartPart as h, type ChatSubtaskPart as i, type ChatTextPart as j, type ChatToolPart as k, type ChatToolState as l, type ChatToolStatus as m, type ChatUsageTokens as n, isChatInteractionPart as o, isChatStepFinishPart as p, isChatTextPart as q, isChatToolPart as r, toChatMessageParts as t };
@@ -1,217 +1,7 @@
1
+ export { c as AdminGuardOptions, d as AssertBillableBalanceOptions, A as AuthGuard, e as AuthGuardOptions, B as BetterAuthSessionCookieMinterOptions, f as BetterAuthSessionCookieSource, g as BillableBalanceState, G as GuardResolution, S as SsoStateConfig, b as TangleSsoAccountStore, a as TangleSsoAuthClient, h as TangleSsoExchangeResult, i as TangleSsoHandlerOptions, T as TangleSsoHandlers, j as TangleSsoSessionCookieArgs, k as TangleSsoUserCreateError, l as assertBillableBalance, m as createAdminGuard, n as createAuthGuard, o as createBetterAuthSessionCookieMinter, p as createSignedSsoState, q as createTangleSsoHandlers, r as guardResolution, s as parseAdminEmails, t as signSessionCookieValue, v as verifySignedSsoState } from '../sso-CNOsARMJ.js';
1
2
  import { f as TangleExecutionEnvironment, j as TangleExecutionKeySource } from '../model-dF2h4xT9.js';
2
3
  import { PlatformIdentity, PlatformBillingClient } from '../billing/index.js';
3
4
 
4
- /**
5
- * Cross-site Tangle SSO for agent apps: signed-state CSRF cookies plus the
6
- * full start/callback orchestration against the platform's /cross-site
7
- * bridge. The platform wire client and account persistence are structural
8
- * seams (`TangleSsoAuthClient` / `TangleSsoAccountStore`), so this module
9
- * never imports agent-runtime, an auth framework, or a database driver.
10
- * WebCrypto only — runs in workerd without node compatibility flags.
11
- */
12
- interface SsoStateConfig {
13
- /** HMAC-SHA256 secret (e.g. the app's auth secret). */
14
- secret: string;
15
- /** State lifetime in ms. Default 600 000. */
16
- ttlMs?: number;
17
- /** Injectable clock (ms since epoch). Default Date.now. */
18
- now?: () => number;
19
- }
20
- /** Mint a `<randomHex32>.<timestamp36>.<hmacHex>` state value. The timestamp
21
- * is inside the signed payload, so expiry survives cookie-attribute tampering. */
22
- declare function createSignedSsoState(config: SsoStateConfig): Promise<string>;
23
- /** Verify the MAC (constant-time) and the signed TTL. */
24
- declare function verifySignedSsoState(state: string, config: SsoStateConfig): Promise<boolean>;
25
- interface TangleSsoExchangeResult {
26
- apiKey: string;
27
- user: {
28
- id: string;
29
- email: string;
30
- name?: string | null;
31
- };
32
- plan?: {
33
- tier: string;
34
- } | null;
35
- }
36
- /** Structural mirror of the platform auth wire client — any object with these
37
- * two methods satisfies it without this module importing the concrete class. */
38
- interface TangleSsoAuthClient {
39
- authorizeUrl(options: {
40
- state: string;
41
- redirectUri?: string;
42
- }): string;
43
- exchange(code: string): Promise<TangleSsoExchangeResult>;
44
- }
45
- /** Thrown by `upsertUserByEmail` when the app-local user row cannot be
46
- * created; the callback handler maps it to `?error=tangle_user_create_failed`.
47
- * Any other store error propagates. */
48
- declare class TangleSsoUserCreateError extends Error {
49
- constructor(message?: string);
50
- }
51
- /**
52
- * Account persistence seam. Covers both storage styles in use: link-table
53
- * apps (a per-user platform-link row) and session-column apps (the key on the
54
- * session row) — `saveTangleLink` receives both `userId` and `sessionToken`,
55
- * and each app persists with the key it needs. `createSession` runs first so
56
- * the token is always available to `saveTangleLink`.
57
- */
58
- interface TangleSsoAccountStore {
59
- /** Find-or-create the app-local user. `tangleUserId` is the platform's
60
- * stable user id — match on it first when the app stores it (emails are
61
- * mutable on the platform; the id is not), falling back to email for
62
- * first-time logins. */
63
- upsertUserByEmail(input: {
64
- email: string;
65
- name: string | null;
66
- tangleUserId: string;
67
- }): Promise<{
68
- userId: string;
69
- }>;
70
- /** Create an app session row; returns the session-cookie token value. */
71
- createSession(input: {
72
- userId: string;
73
- expiresAt: Date;
74
- ipAddress: string | null;
75
- userAgent: string | null;
76
- }): Promise<{
77
- token: string;
78
- }>;
79
- /** Persist the platform link (API key + platform identity). */
80
- saveTangleLink(input: {
81
- userId: string;
82
- sessionToken: string;
83
- tangleUserId: string;
84
- email: string;
85
- name: string | null;
86
- apiKey: string;
87
- planTier: string | null;
88
- }): Promise<void>;
89
- }
90
- /** Successful-login context handed to the `setSessionCookie` seam. */
91
- interface TangleSsoSessionCookieArgs {
92
- /** Session token returned by `store.createSession`. */
93
- token: string;
94
- /** Session expiry (now + `sessionTtlSeconds`). */
95
- expiresAt: Date;
96
- /** Mirrors `sessionTtlSeconds` after defaulting. */
97
- ttlSeconds: number;
98
- /** Mirrors `TangleSsoHandlerOptions.secureCookies`. */
99
- secure: boolean;
100
- }
101
- /**
102
- * Sign a session token to better-call's signed-cookie contract — the value
103
- * better-auth's `getSignedCookie` verifies: `<token>.<signature>` where the
104
- * signature is the raw HMAC-SHA256 of the token under `secret`, encoded as
105
- * STANDARD base64 WITH padding (32 bytes → 44 chars ending `=`; better-call
106
- * rejects any other length or suffix, so url-safe/unpadded variants read back
107
- * as a null session). The joined value is percent-encoded once at cookie
108
- * serialization, matching better-call's `serializeSignedCookie` byte-exactly.
109
- */
110
- declare function signSessionCookieValue(token: string, secret: string): Promise<string>;
111
- /** Structural slice of a `betterAuth()` instance — only what cookie minting
112
- * reads. No better-auth import: the signing contract is implemented by
113
- * `signSessionCookieValue`, byte-compatible with better-auth's own
114
- * `makeSignature`. */
115
- interface BetterAuthSessionCookieSource {
116
- $context: PromiseLike<{
117
- secret: string;
118
- authCookies: {
119
- sessionToken: {
120
- /** Final cookie name — better-auth decides the `__Secure-` prefix
121
- * (and any `advanced.cookiePrefix`) once at `betterAuth()` init. */
122
- name: string;
123
- attributes: {
124
- secure?: boolean;
125
- sameSite?: string;
126
- path?: string;
127
- httpOnly?: boolean;
128
- domain?: string;
129
- };
130
- };
131
- };
132
- }>;
133
- }
134
- interface BetterAuthSessionCookieMinterOptions {
135
- /** Receives the shadowed-cookie-name warning (see below). Default
136
- * console.warn. */
137
- warn?: (message: string) => void;
138
- }
139
- /**
140
- * Canonical `setSessionCookie` wiring for better-auth apps: mint the session
141
- * Set-Cookie exactly as better-auth's own login flows do — name + attributes
142
- * from `auth.$context.authCookies.sessionToken` (better-auth stays
143
- * authoritative over prefix/name/attributes) and the value signed to
144
- * better-call's `getSignedCookie` contract. A raw unprefixed
145
- * `better-auth.session_token` left by an earlier login is explicitly expired
146
- * so it cannot shadow the real cookie.
147
- *
148
- * Warns when the app's session cookie still has better-auth's DEFAULT name:
149
- * the Tangle platform (id.tangle.tools) sets a `Domain=.tangle.tools` cookie
150
- * under that exact name, and equal-path cookies are sent oldest-first — the
151
- * platform's cookie is always older (the user signs in there before the app's
152
- * callback runs), so the app reads the platform's token, fails its own
153
- * signature check, and every fresh login lands logged-out. Per-app
154
- * `advanced.cookiePrefix` is the fix.
155
- *
156
- * Throws on a domain-scoped session cookie for the same reason: a
157
- * `Domain=`-wide session cookie is exactly the shadowing footgun.
158
- */
159
- declare function createBetterAuthSessionCookieMinter(auth: BetterAuthSessionCookieSource, options?: BetterAuthSessionCookieMinterOptions): (args: TangleSsoSessionCookieArgs) => Promise<string[]>;
160
- interface TangleSsoHandlerOptions {
161
- auth: TangleSsoAuthClient;
162
- store: TangleSsoAccountStore;
163
- /** HMAC secret for the state cookie. */
164
- stateSecret: string;
165
- /** Absolute callback URL registered with the platform. */
166
- callbackUrl: string;
167
- stateCookieName: string;
168
- /** Default 'better-auth.session_token'. Ignored when `setSessionCookie` is
169
- * provided. The default path prepends `__Secure-` iff `secureCookies`. */
170
- sessionCookieName?: string;
171
- /** Mint the host auth framework's own session cookie(s); return complete
172
- * Set-Cookie header values (the handler appends them verbatim and sets no
173
- * session cookie itself). Supply this when the framework should stay
174
- * authoritative over name/prefix/signing/attributes — e.g. better-auth:
175
- * `auth.$context.authCookies.sessionToken` + `makeSignature`. */
176
- setSessionCookie?: (args: TangleSsoSessionCookieArgs) => readonly string[] | Promise<readonly string[]>;
177
- /** HMAC-SHA256 secret the host auth framework verifies session cookies with
178
- * (better-auth: its `secret`). Required when `setSessionCookie` is absent —
179
- * the default cookie is minted to better-call's signed contract via
180
- * `signSessionCookieValue`; an unsigned or mis-signed value reads back as a
181
- * null session, so there is deliberately no fallback to `stateSecret`
182
- * (which is not guaranteed to be the auth secret). */
183
- sessionCookieSecret?: string;
184
- /** Adds `Secure` to every cookie this module sets, and (default session
185
- * cookie only) the `__Secure-` name prefix. Must match the auth
186
- * framework's own secure-cookie decision (better-auth: https `baseURL` /
187
- * `advanced.useSecureCookies`), or it will look up a different cookie name
188
- * than the one set here. */
189
- secureCookies: boolean;
190
- /** Default 604 800 (7 days). */
191
- sessionTtlSeconds?: number;
192
- /** Default 600. Applies to both the cookie Max-Age and the signed TTL. */
193
- stateTtlSeconds?: number;
194
- /** Default '/app'. */
195
- defaultRedirectPath?: string;
196
- /** Default '/login'. */
197
- loginPath?: string;
198
- /** Failure log hook (e.g. console.error). Default no-op. */
199
- log?: (message: string, error?: unknown) => void;
200
- now?: () => number;
201
- }
202
- interface TangleSsoHandlers {
203
- /** GET start route: mint + sign state, set the state cookie, 302 to the
204
- * platform authorize URL. `?redirect=` carries the post-login path. */
205
- start(request: Request): Promise<Response>;
206
- /** GET callback route: verify state, exchange the code, upsert the user,
207
- * create the session, save the platform link, set the session cookie
208
- * (via the `setSessionCookie` seam, else signed to better-call's contract
209
- * with `sessionCookieSecret`), 302 to the saved redirect. Every failure
210
- * 302s to `loginPath?error=…` with the state cookie cleared. */
211
- callback(request: Request): Promise<Response>;
212
- }
213
- declare function createTangleSsoHandlers(opts: TangleSsoHandlerOptions): TangleSsoHandlers;
214
-
215
5
  /**
216
6
  * Integrations-hub proxy routes: the app-side surface that forwards an
217
7
  * authenticated user's requests to the platform's `/v1/integrations/*` API
@@ -473,62 +263,4 @@ interface PlatformIdentityStore {
473
263
  * `createPlatformBalanceManager` (from `/billing`). */
474
264
  declare function createTanglePlatformBillingClient(http: PlatformBillingHttp, identity: PlatformIdentityStore): PlatformBillingClient<TanglePlanTier>;
475
265
 
476
- /**
477
- * Request guards for agent-app routes: session auth (302 redirect for pages,
478
- * JSON 401 for APIs), admin allowlisting (404 — the route stays invisible to
479
- * non-admins), and the billable-balance gate (402 with a stable code).
480
- * Session resolution is a seam; thrown Responses follow the router convention
481
- * of surfacing a thrown Response as the route result.
482
- */
483
- interface AuthGuardOptions<Session> {
484
- /** e.g. a better-auth `auth.api.getSession` wrapped by the app. */
485
- getSession(request: Request): Promise<Session | null | undefined>;
486
- /** Default '/login'. */
487
- loginPath?: string;
488
- }
489
- interface AuthGuard<Session> {
490
- /** Page guard — throws a 302 redirect Response to `loginPath`. */
491
- requireUser(request: Request): Promise<Session>;
492
- /** API guard — throws JSON 401 `{ error: 'Unauthorized', code: 'auth.unauthenticated' }`. */
493
- requireApiUser(request: Request): Promise<Session>;
494
- /** `apiResponse` selects the 401 JSON path over the redirect. */
495
- requireSession(request: Request, opts?: {
496
- apiResponse?: boolean;
497
- }): Promise<Session>;
498
- getOptionalSession(request: Request): Promise<Session | null>;
499
- }
500
- declare function createAuthGuard<Session>(opts: AuthGuardOptions<Session>): AuthGuard<Session>;
501
- /** Comma/whitespace separated → trimmed, lowercased, empties dropped. */
502
- declare function parseAdminEmails(raw: string | null | undefined): string[];
503
- interface AdminGuardOptions<Session> {
504
- requireUser(request: Request): Promise<Session>;
505
- emailOf(session: Session): string | null | undefined;
506
- /** Resolved per request; an EMPTY allowlist refuses everyone. */
507
- allowedEmails(): string[];
508
- }
509
- /** Non-admins (and empty allowlists) get 404, keeping the route invisible —
510
- * better than a "forbidden" footprint that advertises its existence. */
511
- declare function createAdminGuard<Session>(opts: AdminGuardOptions<Session>): (request: Request) => Promise<Session>;
512
- interface BillableBalanceState {
513
- overageAllowed: boolean;
514
- remainingBalanceUsd: number;
515
- }
516
- interface AssertBillableBalanceOptions {
517
- env?: Record<string, string | undefined>;
518
- /** App-specific enforcement override flag (e.g. 'GTM_BILLING_ENFORCEMENT'),
519
- * fed to `isTangleBillingEnforcementDisabled`. */
520
- enforcementEnvVar?: string;
521
- /** Default 'Add balance or upgrade your plan to invoke this agent.'. */
522
- errorMessage?: string;
523
- /** Merged into the 402 JSON body (e.g. `{ organizationId }`). */
524
- errorBody?: Record<string, unknown>;
525
- }
526
- /**
527
- * Gate a billable turn: passes when enforcement is disabled (dev default),
528
- * the tier allows overage, or remaining balance is positive. Otherwise throws
529
- * a 402 Response with the stable `billing.balance_required` code so clients
530
- * can route to the billing screen.
531
- */
532
- declare function assertBillableBalance(state: BillableBalanceState, opts?: AssertBillableBalanceOptions): void;
533
-
534
- export { type AdminGuardOptions, type AssertBillableBalanceOptions, type AuthGuard, type AuthGuardOptions, type BetterAuthSessionCookieMinterOptions, type BetterAuthSessionCookieSource, type BillableBalanceState, DEFAULT_SEAT_BILLING_ENABLED_ENV_VAR, DEFAULT_TANGLE_TIER_POLICY, FREE_TIER_SPEND_CAP_USD, type HubClientLike, type HubProxyContext, type HubProxyRouteArgs, type HubProxyRoutes, type PlatformBalanceSnapshot, type PlatformBillingHttp, PlatformBillingHttpError, type PlatformBillingHttpOptions, type PlatformIdentityStore, type PlatformSubscriptionInfo, type PlatformUsageProductRow, type ProductEntitlement, type ResolveUserTangleHubBearerForUserOptions, type ResolveUserTangleHubBearerOptions, type ResolvedTangleHubBearer, type SeatBillingFlagOptions, type SeatStatus, type SsoStateConfig, TangleBearerMissingError, type TangleHubBearerSource, type TanglePlanTier, type TangleSsoAccountStore, type TangleSsoAuthClient, type TangleSsoExchangeResult, type TangleSsoHandlerOptions, type TangleSsoHandlers, type TangleSsoSessionCookieArgs, TangleSsoUserCreateError, type TangleTierPolicy, type TangleTierState, assertBillableBalance, createAdminGuard, createAuthGuard, createBetterAuthSessionCookieMinter, createHubProxyRoutes, createPlatformBillingHttp, createSignedSsoState, createTanglePlatformBillingClient, createTangleSsoHandlers, getProductEntitlement, isPlatformBillingHttpError, isPlatformHubErrorLike, isProductEntitled, isSeatBillingEnabled, isTangleBearerMissingError, normalizeTanglePlanTier, parseAdminEmails, readTangleTierState, resolveUserTangleHubBearer, resolveUserTangleHubBearerForUser, seatCheckoutUrl, signSessionCookieValue, verifySignedSsoState };
266
+ export { DEFAULT_SEAT_BILLING_ENABLED_ENV_VAR, DEFAULT_TANGLE_TIER_POLICY, FREE_TIER_SPEND_CAP_USD, type HubClientLike, type HubProxyContext, type HubProxyRouteArgs, type HubProxyRoutes, type PlatformBalanceSnapshot, type PlatformBillingHttp, PlatformBillingHttpError, type PlatformBillingHttpOptions, type PlatformIdentityStore, type PlatformSubscriptionInfo, type PlatformUsageProductRow, type ProductEntitlement, type ResolveUserTangleHubBearerForUserOptions, type ResolveUserTangleHubBearerOptions, type ResolvedTangleHubBearer, type SeatBillingFlagOptions, type SeatStatus, TangleBearerMissingError, type TangleHubBearerSource, type TanglePlanTier, type TangleTierPolicy, type TangleTierState, createHubProxyRoutes, createPlatformBillingHttp, createTanglePlatformBillingClient, getProductEntitlement, isPlatformBillingHttpError, isPlatformHubErrorLike, isProductEntitled, isSeatBillingEnabled, isTangleBearerMissingError, normalizeTanglePlanTier, readTangleTierState, resolveUserTangleHubBearer, resolveUserTangleHubBearerForUser, seatCheckoutUrl };