@mitralab.io/platform-sdk 1.1.2 → 1.1.4-beta.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/CHANGELOG.md +124 -57
- package/README.md +95 -8
- package/dist/index.cjs +263 -67
- package/dist/index.d.cts +77 -16
- package/dist/index.d.ts +77 -16
- package/dist/index.js +263 -67
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,57 +1,124 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project are documented in this file.
|
|
4
|
-
|
|
5
|
-
## 1.1.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
## 1.1.4-beta.0
|
|
6
|
+
|
|
7
|
+
- On the direct channel the message and the interrupt are written on the box socket, as the
|
|
8
|
+
client frames the box already reads, instead of `POST /copilot/api/v1/tasks/{id}/inputs`. The
|
|
9
|
+
box asks the Copilot for admission itself and answers on the same socket, so the Copilot's host
|
|
10
|
+
socket buffer no longer bounds the message: the only limit is the box channel's own. REST stays
|
|
11
|
+
for a chat with no box socket, for a socket not open at the moment of the send, a redial in
|
|
12
|
+
progress included, and for every approval answer. A frame written on a socket that closes
|
|
13
|
+
before the box acknowledges it is not resent over REST, since the box may have admitted the
|
|
14
|
+
turn already; the redial's replay recovers it.
|
|
15
|
+
|
|
16
|
+
## 1.1.3
|
|
17
|
+
|
|
18
|
+
- A chat created through `session({ create: true })` over the `auto` or `websocket` transport is
|
|
19
|
+
born on the T3 box: the create request carries `runtime: "T3"`. A chat created with
|
|
20
|
+
`transport: "http"` stays on the runner, and an explicit `runtime` is forwarded as given.
|
|
21
|
+
- The box channel is asked for once. The Copilot now holds the channel request while the box
|
|
22
|
+
boots, so the 2 s polling on a 202 answer is gone; a 202 from an older Copilot means the chat
|
|
23
|
+
follows the Copilot socket.
|
|
24
|
+
- Depend on `@mitralab.io/sdk-core@0.2.4`, which carries the `runtime` session option into the
|
|
25
|
+
create request, exports `AgentTaskRuntime`, and sends a prompt whose task already exists even
|
|
26
|
+
when the session was closed inside its `taskCreated` handler.
|
|
27
|
+
|
|
28
|
+
## 1.2.0-beta.1
|
|
29
|
+
|
|
30
|
+
- Add `signInWithEmail()`: the platform auth page collects the address and the one-time code, and
|
|
31
|
+
the single-use exchange code it returns is redeemed at IAM's `/auth/magic-link/exchange` for the
|
|
32
|
+
same app session Google and Microsoft SSO already produce.
|
|
33
|
+
- Add `completeEmailSignInRedirect()`, which finishes both the mobile redirect and the tab opened
|
|
34
|
+
by the link in the message.
|
|
35
|
+
- Keep the pending email request, the one-time state and the auth page URL and never a token, in
|
|
36
|
+
`localStorage` for 10 minutes, so the tab opened by the link in the message finishes the flow
|
|
37
|
+
through the same state check the redirect uses. Writing it is best effort for a popup and
|
|
38
|
+
required for a redirect.
|
|
39
|
+
- Consume a fragment of the flow's own provider even when it cannot be completed, so a rejected or
|
|
40
|
+
expired redirect is reported once instead of on every reload. A fragment of another flow stays
|
|
41
|
+
untouched, and a pending request is still dropped only when it expires.
|
|
42
|
+
- Name the flow in the one-time state (`google.<random>`, `microsoft.<random>`, `email.<random>`),
|
|
43
|
+
which the auth page echoes verbatim, so every `complete*SignInRedirect()` recognizes its own
|
|
44
|
+
fragment: a fragment from another method returns `null` untouched, whatever this browser has
|
|
45
|
+
pending, and an application that offers all three can call all three at startup in any order. A
|
|
46
|
+
fragment that names this flow without matching its pending request is rejected as forged.
|
|
47
|
+
- Generalize the auth page handshake into `AuthPageFlow`, parameterized by provider, exchange
|
|
48
|
+
route, and where the pending request lives, instead of a second copy for email.
|
|
49
|
+
- Upgrading mid-flow: a redirect started by an earlier version stored a state without the provider
|
|
50
|
+
name, so the completion after the upgrade returns `null` and the person signs in again. Nothing
|
|
51
|
+
is lost beyond that one attempt, and only for redirects in flight during the upgrade.
|
|
52
|
+
- Give each provider its own popup window name.
|
|
53
|
+
- Point the deprecated `signIn` and `signUp` failures at `signInWithEmail()`.
|
|
54
|
+
- Add `mitra.emailLoginEnabled`, read from `/info` during `init()` next to `allowSignup`, so an
|
|
55
|
+
application only offers "sign in with email" when this app is inside the platform's rollout.
|
|
56
|
+
A Code Studio older than the field answers without it, and any value that is not a boolean is
|
|
57
|
+
read as `false`, so `init()` keeps working and an app that cannot prove it is enabled stops
|
|
58
|
+
offering the option.
|
|
59
|
+
|
|
60
|
+
## 1.1.2
|
|
61
|
+
|
|
62
|
+
- Move the `@mitralab.io/sdk-core` pin from `0.2.1` to `0.2.2`: same surface, published with the
|
|
63
|
+
contract corpus that consumers pin, so every SDK released that day sits on the same core.
|
|
64
|
+
|
|
65
|
+
## 1.1.1
|
|
66
|
+
|
|
67
|
+
- Depend on `@mitralab.io/sdk-core@0.2.1`, which replays `textChunk` and late deltas after an
|
|
68
|
+
interrupted turn.
|
|
69
|
+
- Serve the Agent chat from the T3 box over the direct channel when the Copilot offers it.
|
|
70
|
+
- Treat a half-open Agent session channel as a disconnect instead of a live one.
|
|
71
|
+
|
|
72
|
+
## 1.1.0-beta.2
|
|
73
|
+
|
|
74
|
+
`1.1.0-beta.1` was published from `main` before this change landed, so it still depends on Core `0.2.0-beta.0`; use `1.1.0-beta.2`.
|
|
75
|
+
|
|
76
|
+
- Depend on `@mitralab.io/sdk-core@0.2.0-beta.1`, which reads back integration configs with a
|
|
77
|
+
null `templateId` (configs born from an inline definition). The browser adapter still only
|
|
78
|
+
lists and executes integration configs; authoring stays in the studio SDK and the MCP.
|
|
79
|
+
|
|
80
|
+
## 1.1.0-beta.0
|
|
81
|
+
|
|
82
|
+
- Complete native Function sync, async, polling, cancellation, and anonymous public execution.
|
|
83
|
+
- Expose browser-safe Agent Tasks, restricted Agent Credentials, and model discovery through Core 0.2 contracts.
|
|
84
|
+
- Compose the Core-owned Agent task session manager with Platform WebSocket and HTTP/SSE adapters.
|
|
85
|
+
- Add native anonymous polling for executions created by the public async Function route.
|
|
86
|
+
- Keep business-Agent administration out of the browser adapter according to the app-role permission matrix.
|
|
87
|
+
- Expose app-scoped integration config listing and execution by alias from Core 0.2.
|
|
88
|
+
- Document the missing producer contract for native record selection by `jdbcConnectionConfigId` instead of inventing a browser-side translation.
|
|
89
|
+
- Document that entity `update` already implements the producer's partial PUT semantics, so no duplicate PATCH method is needed.
|
|
90
|
+
- Derive Function execution, integration proxy input, and custom query result types directly from Core without narrowing nullable or producer-returned fields.
|
|
91
|
+
- Preserve the complete Data Manager record envelope and execute Custom Queries with only
|
|
92
|
+
producer parameters, without a caller-selected Data Source or an `init()` precondition.
|
|
93
|
+
|
|
94
|
+
- Refresh app sessions proactively through IAM before authenticated native requests, with a 30-second JWT expiry heuristic and one shared refresh flight.
|
|
95
|
+
- Preserve sessions on transient refresh failures, clear them on definitive IAM client failures, and retain the one-time reactive `401` retry.
|
|
96
|
+
- Rotate both tokens without fetching the current user or notifying public auth-state listeners, while keeping the legacy bridge synchronized.
|
|
97
|
+
- Reject decodable access and refresh tokens whose app scope is missing or differs from the configured app while keeping opaque tokens server-authoritative.
|
|
98
|
+
- Fence refresh responses by session generation so late success or failure cannot undo sign-out or overwrite a newer login or bridged session.
|
|
99
|
+
- Bind reactive `401` handling to the token used by the rejected request so an old response cannot refresh or clear a replacement session.
|
|
100
|
+
- Redact values under sensitive credential field names from recursive API error details.
|
|
101
|
+
- Preserve the retained session when `auth.me()` reaches `401` after transient proactive and reactive refresh failures.
|
|
102
|
+
- Add native Google SSO through popup and redirect flows with direct IAM code exchange.
|
|
103
|
+
- Validate Google SSO origin, popup source, one-time state, cancellation, timeout, and token response shape.
|
|
104
|
+
- Require redirect errors to bind to the stored state before exposing or consuming them.
|
|
105
|
+
- Keep Google options limited to popup or redirect mode; account creation and locale remain producer concerns.
|
|
106
|
+
- Leave legacy-only `returnTo` and `title` on the deprecated aliases because the old runtime did not implement them as native Google controls.
|
|
107
|
+
- Preserve the email/password methods already public in Platform SDK 1.0.9 without presenting them as the new template flow.
|
|
108
|
+
- Route deprecated calls and legacy authentication through `${apiUrl}/legacy`.
|
|
109
|
+
- Apply the native auth page URL precedence to the deprecated SSO bridge.
|
|
110
|
+
- Propagate native sign-in, refresh, token changes, and sign-out to the legacy SDK session.
|
|
111
|
+
- Re-export the deprecated `mitra-interactions-sdk` surface from the package entrypoint.
|
|
112
|
+
- Mark every legacy type alias as deprecated in generated declarations.
|
|
113
|
+
- Share one session between this SDK and the legacy SDK in both directions.
|
|
114
|
+
- Make the SonarCloud job wait for the Quality Gate result.
|
|
115
|
+
- Align the public package metadata and ESM, CommonJS, and TypeScript artifacts.
|
|
116
|
+
- Add package shape checks and public tarball smoke coverage.
|
|
117
|
+
- Correct public imports and required configuration in documentation examples.
|
|
118
|
+
- Add the MIT license.
|
|
119
|
+
|
|
120
|
+
## 1.0.8
|
|
121
|
+
|
|
122
|
+
- Share environment-neutral API contracts through `@mitralab.io/sdk-core`.
|
|
123
|
+
- Preserve the Platform SDK 1.x browser authentication and entity facade.
|
|
124
|
+
- Validate redirects, API errors, sensitive-value redaction, and package consumers.
|
package/README.md
CHANGED
|
@@ -30,10 +30,10 @@ await mitra.init()
|
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
`init()` resolves the application's public Code Studio configuration, including nullable
|
|
33
|
-
`dataSourceId` and `
|
|
34
|
-
compatibility flow; native Entities and Custom Queries resolve the current app through
|
|
35
|
-
authenticated request. Call `init()` during application startup before the compatibility
|
|
36
|
-
method needs `allowSignup`.
|
|
33
|
+
`dataSourceId`, `allowSignup`, and `emailLoginEnabled`. The Data Source value remains part of the
|
|
34
|
+
Platform 1.x compatibility flow; native Entities and Custom Queries resolve the current app through
|
|
35
|
+
the authenticated request. Call `init()` during application startup before the compatibility
|
|
36
|
+
sign-up method needs `allowSignup` or the login screen needs `emailLoginEnabled`.
|
|
37
37
|
|
|
38
38
|
## Configuration
|
|
39
39
|
|
|
@@ -50,7 +50,7 @@ The client derives service endpoints from `apiUrl`: `/iam`, `/data-manager`, `/f
|
|
|
50
50
|
|
|
51
51
|
The Platform SDK owns:
|
|
52
52
|
|
|
53
|
-
- browser Google SSO, logout, and session refresh
|
|
53
|
+
- browser Google and Microsoft SSO, browser email sign-in, logout, and session refresh
|
|
54
54
|
- trusted session adoption for the embedded app preview
|
|
55
55
|
- session persistence in `localStorage`
|
|
56
56
|
- auth-state listeners
|
|
@@ -76,7 +76,7 @@ unsubscribe()
|
|
|
76
76
|
|
|
77
77
|
Authentication state is stored under `mitra_auth_{appId}`. Before each authenticated native request, the SDK checks a JWT's `exp` claim with a 30-second safety window and refreshes directly through IAM when needed. Opaque tokens, malformed JWTs, and JWTs without a numeric `exp` remain server-authoritative and proceed to the request. A `401` still triggers reactive recovery and at most one retry. If another login or bridged session replaced the token while the request was in flight, the retry uses that current token without refreshing its session. If sign-out cleared the token, the old `401` neither refreshes nor retries.
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
A generated application signs people in with Google SSO, Microsoft SSO, or email. The old native `signIn` and `signUp` names fail locally with `UNSUPPORTED_AUTH_METHOD` because IAM has no email/password endpoints; `signInWithEmail()` is the email flow that replaced them. Deprecated login bindings remain available only through the legacy reexports.
|
|
80
80
|
|
|
81
81
|
### Signing in as a process
|
|
82
82
|
|
|
@@ -158,6 +158,89 @@ const mitra = createClient({
|
|
|
158
158
|
})
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
+
### Signing in with email
|
|
162
|
+
|
|
163
|
+
Email sign-in needs neither a password nor an SSO account. The same platform page opens, a popup
|
|
164
|
+
by default, collects the address, sends a six-digit code, and IAM answers with a single-use
|
|
165
|
+
exchange code that the SDK redeems at `/iam/api/v1/auth/magic-link/exchange`. What comes back is
|
|
166
|
+
the app session SSO already returns, persisted and refreshed the same way:
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const user = await mitra.auth.signInWithEmail()
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Not every app is in the rollout. `mitra.emailLoginEnabled` is this app's own verdict, read from
|
|
173
|
+
`/info` during `init()`, and it is what a login screen should offer the option on:
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
await mitra.init()
|
|
177
|
+
|
|
178
|
+
if (mitra.emailLoginEnabled) {
|
|
179
|
+
// render "sign in with email"
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
It is `false` before `init()` runs, `false` when the server answers without the field or with
|
|
184
|
+
something that is not a boolean, and `false` is the safe answer: the app is outside the rollout,
|
|
185
|
+
IAM answers a request neutrally without sending anything, and the person would wait for a message
|
|
186
|
+
that never arrives. Calling `signInWithEmail()` anyway is not blocked by the SDK; the verdict is
|
|
187
|
+
there so the application does not offer a door that does not open.
|
|
188
|
+
|
|
189
|
+
Redirect mode navigates the current page instead of opening a popup, and is completed during
|
|
190
|
+
startup like the SSO redirect:
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
await mitra.auth.signInWithEmail({ mode: "redirect" })
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
```typescript
|
|
197
|
+
const emailUser = await mitra.auth.completeEmailSignInRedirect()
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Call `completeEmailSignInRedirect()` at startup even when sign-in was started as a popup, because
|
|
201
|
+
the message carries a link as well as the code, and that link opens a **new tab**. That tab never
|
|
202
|
+
saw the popup, so the pending request has to outlive the tab that opened it: the one-time state
|
|
203
|
+
and the resolved auth page URL are written to `localStorage` under `mitra_email_redirect_{appId}`
|
|
204
|
+
for 10 minutes, dropped when the flow completes, or discarded as stale the next time a result is read. `sessionStorage`,
|
|
205
|
+
which the SSO redirect uses, is scoped to a single tab and cannot answer for another one. The link still has
|
|
206
|
+
to be opened in the same browser that started the sign-in: another browser or device has no pending request,
|
|
207
|
+
refuses the fragment, and the exchange code was already spent by the page. On another device, use the
|
|
208
|
+
six-digit code in the popup instead.
|
|
209
|
+
|
|
210
|
+
**No token is written there.** What is persisted is only the record of a request already in
|
|
211
|
+
flight, which is the smallest thing that lets the other tab finish it, and it expires on its own.
|
|
212
|
+
The tab opened by the link comes back with the same one-time state the flow started with, so it
|
|
213
|
+
is completed by exactly the check the redirect uses; a request older than 10 minutes is discarded
|
|
214
|
+
rather than completed. Writing the request is best effort for a popup: without `localStorage` the
|
|
215
|
+
popup still signs in and only the completion from the link is lost, while redirect mode, which has
|
|
216
|
+
nowhere else to keep it, fails at the start.
|
|
217
|
+
|
|
218
|
+
When the person finishes in the tab the link opened, the `signInWithEmail()` call still waiting in
|
|
219
|
+
the original tab eventually times out. Treat that rejection as a cancelled popup: the session is
|
|
220
|
+
already established wherever the application called `completeEmailSignInRedirect()`.
|
|
221
|
+
|
|
222
|
+
One fragment belongs to one flow, and an application that offers more than one method can call
|
|
223
|
+
every completion at startup, in any order:
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
const user =
|
|
227
|
+
(await mitra.auth.completeEmailSignInRedirect()) ??
|
|
228
|
+
(await mitra.auth.completeGoogleSignInRedirect()) ??
|
|
229
|
+
(await mitra.auth.completeMicrosoftSignInRedirect())
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
A chain like that propagates a rejection: an expired request or a forged fragment on the first
|
|
233
|
+
completion keeps the others from running. Wrap each call in `try`/`catch` when the application
|
|
234
|
+
should still try the remaining methods after one of them refuses a fragment.
|
|
235
|
+
|
|
236
|
+
The one-time state each flow generates names that flow, as in `google.<random>` or
|
|
237
|
+
`email.<random>`, and the auth page echoes it verbatim, so a completion recognizes its own
|
|
238
|
+
fragment. A fragment from another method returns `null` and leaves the fragment and that other
|
|
239
|
+
flow's pending request untouched, whatever this browser has pending. A fragment that does name
|
|
240
|
+
this flow but does not match its pending request is rejected as forged, and the fragment is
|
|
241
|
+
removed from the URL on the way out, so the rejection is reported once instead of on every
|
|
242
|
+
reload.
|
|
243
|
+
|
|
161
244
|
## Entities
|
|
162
245
|
|
|
163
246
|
```typescript
|
|
@@ -246,7 +329,11 @@ unsubscribe()
|
|
|
246
329
|
session.close()
|
|
247
330
|
```
|
|
248
331
|
|
|
249
|
-
|
|
332
|
+
A chat created with `create: true` over the `auto` or `websocket` transport is born on the T3 box (`runtime: "T3"` in the create request), so the first open does not wait for the box to adopt it; a chat created with `transport: "http"` stays on the Copilot runner. Pass `runtime: "RUNNER"` or `runtime: "T3"` to decide explicitly.
|
|
333
|
+
|
|
334
|
+
Open an existing task with `session({ taskId })`. The default `auto` transport refreshes before connecting, asks the Copilot once where the chat is served, and opens whichever channel it names: the box that runs the agent when one is offered, `/copilot/ws/tasks/{taskId}` otherwise. The Copilot holds that request while the box boots and answers only once the box is ready or cannot be had; the SDK does not poll. The choice belongs to the server, never to application configuration, so a Copilot that stops offering the box leaves every application on the Copilot socket without a republish. Opening the box never asks it to replay, whether the conversation is new to the session or is being opened again after an idle close: what an idle conversation missed is history, which the application loads over REST. A box socket that drops in the middle of a turn is redialed by the SDK itself, with a bounded backoff (1, 2, 4, 8 and 16 seconds) and the replay from the last position seen on that socket, so the answer keeps streaming; a position taken on one box is forgotten when the Copilot points the conversation to another box; replayed `textChunk` frames reach the `delta` event like live text. While that happens the session emits `raw` events of type `channelReconnecting` (payload `attempt`, `maxAttempts`, `reason`) and `channelConnected` (payload `attempt`); the session `status` stays `streaming`, because Core has no reconnecting status. The disconnect reaches Core, and with it the `error` event, only when the attempts run out or the Copilot no longer offers the box. A drop with no turn in flight, a channel taken over by another tab (close code 4409), and any close of the Copilot socket the session did not ask for are reported at once, whatever the code, so the next send reopens the channel instead of waiting on a socket that is gone. Recovery through persisted history plus the HTTP/SSE channel is unchanged. Set `transport: "http"` when WebSockets are unavailable. Messages sent during a turn enter a FIFO queue with a maximum of 10 items; the session also exposes edit, remove, clear, approval, cancel, history, close, and typed events.
|
|
335
|
+
|
|
336
|
+
On the direct channel the message and the interrupt are written on the box socket itself, as the frames the box reads from a client: `{ "type": "message", "content", "agentType"?, "reasoningEffort"? }` and `{ "type": "interrupt" }`. The box asks the Copilot to admit the turn and the Copilot records the history; the admission, its refusal and the turn itself come back on that same socket as the events the session already handles, so a message the box refuses surfaces through the `error` event with the box's code. `POST /copilot/api/v1/tasks/{taskId}/inputs` is the path when there is no box socket: a chat served by the Copilot socket or by SSE, a box socket that is not open at the moment of the send (a drop being redialed included), and every approval answer. A frame written on a socket that closes before the box acknowledges it is not sent again over REST, because the box may already have admitted the turn; the redial replays the box log, as it does for a turn started over REST.
|
|
250
337
|
|
|
251
338
|
A prompt sent while the browser says it is offline (`navigator.onLine === false`) does not enter Core at all, because Core opens the channel and reads the turn baseline before the prompt goes out and every one of those requests would fail first: the session keeps the prompt in an outbox, emits a `raw` event of type `inputUnsent` (payload `attempt` 0, `reason`, `waitingForOnline` true) and hands it to Core, in order, when the browser fires `online`; the turn starts then. A prompt whose `POST /inputs` went out but got no response at all is kept the same way: the session sends the same request again when the browser fires `online` or on a bounded backoff (2, 5, 10, 20 and 40 seconds), while the turn stays `streaming`, with `inputUnsent` events (payload `attempt`, `reason`, `waitingForOnline`, `retryInMs` when a timer is armed) and, once it goes through, `inputSent` (payload `attempts`). A response from the server, an error included, is never retried: the prompt fails through the `error` event as before. A session closed with a prompt still waiting emits `error` with code `INPUT_UNSENT` before it goes quiet, and `sendAndWait` rejects. The retry cannot tell a request the server never received from one whose response was lost on the way back, so a prompt may reach the server twice in that case; the Copilot's `/inputs` accepts no client message id yet. The public `agentTasks.sendInput` primitive is not held back: it fails immediately, as it always did.
|
|
252
339
|
|
|
@@ -324,7 +411,7 @@ await loginWithGoogleMitra()
|
|
|
324
411
|
console.log(mitra.auth.accessToken)
|
|
325
412
|
```
|
|
326
413
|
|
|
327
|
-
Google
|
|
414
|
+
Google, Microsoft and e-mail sign-in have native replacements: `mitra.auth.signInWithGoogle`, `mitra.auth.signInWithMicrosoft` and `mitra.auth.signInWithEmail`, each with its `complete...SignInRedirect` counterpart. Agent tasks, Agent credentials, public Functions, entities, custom queries, Function execution, and integrations also have native replacements. Only `loginMitra('mitra')` still has no native equivalent and remains available through the deprecated re-export surface.
|
|
328
415
|
|
|
329
416
|
`createClient` configures the legacy SDK with both `baseURL` and `authUrl` set to `${apiUrl}/legacy`, after removing trailing slashes, plus `projectId: appId`. This keeps deprecated calls and legacy login routed through the BFF while the new modules call their native APIs directly. Its `authPageUrl` uses the same precedence as native Google SSO: explicit client config, `window.__mitraEnv.authPageUrl`, then `/sdk-auth.html` on the `apiUrl` origin. Existing query parameters are preserved.
|
|
330
417
|
|