@nauticana/sail 1.1.33 → 1.1.34

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 (34) hide show
  1. package/README.md +17 -11
  2. package/package.json +1 -1
  3. package/src/agent/component/approval_inbox.html +63 -0
  4. package/src/agent/component/approval_inbox.ts +91 -0
  5. package/src/agent/component/decision_timeline.html +4 -4
  6. package/src/agent/component/decision_timeline.ts +2 -0
  7. package/src/agent/component/prompt_section_editor.html +4 -3
  8. package/src/agent/component/prompt_section_editor.ts +12 -5
  9. package/src/agent/component/release_sections.html +1 -1
  10. package/src/agent/component/release_sections.ts +2 -1
  11. package/src/agent/component/studio_page.html +269 -0
  12. package/src/agent/component/studio_page.ts +346 -0
  13. package/src/agent/component/studio_tab.ts +14 -0
  14. package/src/agent/component/turn_event_list.html +9 -0
  15. package/src/agent/index.ts +6 -0
  16. package/src/agent/model/agent_studio.ts +122 -9
  17. package/src/agent/model/approval.ts +42 -0
  18. package/src/agent/model/conversation.ts +9 -1
  19. package/src/agent/model/decision.ts +2 -1
  20. package/src/agent/model/turn_event.ts +10 -0
  21. package/src/agent/service/agent_studio.service.ts +36 -1
  22. package/src/agent/service/approval.service.ts +18 -0
  23. package/src/agent/util/release_diff.ts +33 -0
  24. package/src/agent/util/studio_errors.ts +11 -0
  25. package/src/agent/util/turn_timeline.ts +7 -1
  26. package/src/component/login/account_deletion.html +17 -4
  27. package/src/component/login/account_deletion.ts +35 -28
  28. package/src/component/login/social_login.ts +6 -5
  29. package/src/index.ts +1 -0
  30. package/src/model/auth.ts +17 -2
  31. package/src/service/auth.service.ts +10 -4
  32. package/src/service/caption_pipe.ts +26 -0
  33. package/src/service/label.service.ts +5 -4
  34. package/src/service/rest_url.ts +1 -0
package/src/model/auth.ts CHANGED
@@ -115,11 +115,19 @@ export interface UserProfile {
115
115
 
116
116
  // ── Re-authentication credentials ──
117
117
  // Required by Setup2FA, Disable2FA, DeleteAccount, LogoutEverywhere — server
118
- // rejects with 401 if neither `password` nor `twoFactorCode` is supplied.
119
- // Disable2FA additionally requires the current TOTP `code` alongside password.
118
+ // rejects with 401 unless one is supplied. `reauthCode` comes from
119
+ // sendReauthCode(). Disable2FA additionally requires the current TOTP `code`.
120
120
  export interface ReauthCredentials {
121
121
  password?: string;
122
122
  twoFactorCode?: string;
123
+ reauthCode?: string;
124
+ }
125
+
126
+ export type ReauthChannel = 'email' | 'phone';
127
+
128
+ export interface ReauthSendResponse {
129
+ channel: ReauthChannel;
130
+ resendCountdownSec: number;
123
131
  }
124
132
 
125
133
  // ── Social login (ID token flow) ──
@@ -144,6 +152,13 @@ export interface LoginResponseSocial {
144
152
  isNewUser: boolean;
145
153
  singleDeviceSession?: boolean;
146
154
  previousDeviceRevoked?: boolean;
155
+ // Client-side: the name Apple returns only on first authorization, never in the ID token.
156
+ socialName?: SocialName;
157
+ }
158
+
159
+ export interface SocialName {
160
+ firstName?: string;
161
+ lastName?: string;
147
162
  }
148
163
 
149
164
  // ── Push notification tokens ──
@@ -7,7 +7,7 @@ import {
7
7
  LoginResponseSocial,
8
8
  OtpRequest, OtpResendRequest, OtpResponse, OtpVerifyRequest, OtpVerifyResponse,
9
9
  PushPlatform, PushRegisterRequest,
10
- ReauthCredentials,
10
+ ReauthChannel, ReauthCredentials, ReauthSendResponse,
11
11
  SignupConsent, SocialLoginRequest, SocialProvider,
12
12
  UserProfile,
13
13
  } from '../model/auth';
@@ -112,6 +112,7 @@ export abstract class BaseAuthService extends BaseRestService {
112
112
  protected get loginSocialUrl() { return this.url(RestURL.loginSocialURL); }
113
113
  protected get logoutEverywhereUrl() { return this.url(RestURL.logoutEverywhereURL); }
114
114
  protected get deleteAccountUrl() { return this.url(RestURL.deleteAccountURL); }
115
+ protected get reauthSendUrl() { return this.url(RestURL.reauthSendURL); }
115
116
  protected get pushRegisterUrl() { return this.url(RestURL.pushRegisterURL); }
116
117
  protected get pushRevokeUrl() { return this.url(RestURL.pushRevokeURL); }
117
118
  protected get profileUrl() { return this.url(RestURL.profileURL); }
@@ -625,9 +626,14 @@ export abstract class BaseAuthService extends BaseRestService {
625
626
 
626
627
  // ── Account lifecycle ──
627
628
 
629
+ /** Send a one-time code for ReauthCredentials.reauthCode; no channel prefers email. */
630
+ sendReauthCode(channel?: ReauthChannel): Observable<ReauthSendResponse> {
631
+ return this.http.post<ReauthSendResponse>(this.reauthSendUrl, { channel });
632
+ }
633
+
628
634
  /**
629
635
  * Soft-delete the caller's account. Requires recent re-authentication —
630
- * pass current `password` and/or `twoFactorCode`. Server anonymizes
636
+ * pass `password`, `twoFactorCode` or `reauthCode`. Server anonymizes
631
637
  * user_account, revokes all tokens / trusted devices / social links.
632
638
  * Clears local session on success.
633
639
  */
@@ -640,8 +646,8 @@ export abstract class BaseAuthService extends BaseRestService {
640
646
 
641
647
  /**
642
648
  * Revoke every active refresh token for this user (sign out everywhere).
643
- * Requires recent re-authentication — pass current `password` and/or
644
- * `twoFactorCode`.
649
+ * Requires recent re-authentication — pass `password`, `twoFactorCode`
650
+ * or `reauthCode`.
645
651
  */
646
652
  logoutEverywhere(reauth: ReauthCredentials): Observable<void> {
647
653
  return this.http.post<void>(this.logoutEverywhereUrl, reauth);
@@ -0,0 +1,26 @@
1
+ import { DestroyRef, Pipe, PipeTransform, inject, signal } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { LabelService } from './label.service';
4
+
5
+ /**
6
+ * `{{ code | sailCaption:'constant_id' }}` — the backend caption of a constant code, the code
7
+ * itself until its domain loads or when the domain lacks it. Impure so it re-renders on load.
8
+ */
9
+ @Pipe({ name: 'sailCaption', pure: false })
10
+ export class CaptionPipe implements PipeTransform {
11
+ private readonly labels = inject(LabelService);
12
+ private readonly destroyRef = inject(DestroyRef);
13
+ private readonly requested = new Set<string>();
14
+ private readonly loaded = signal(0);
15
+
16
+ transform(code: string | null | undefined, constantId: string): string {
17
+ if (!code) return '';
18
+ this.loaded();
19
+ if (!this.requested.has(constantId)) {
20
+ this.requested.add(constantId);
21
+ this.labels.loadLabels(constantId).pipe(takeUntilDestroyed(this.destroyRef))
22
+ .subscribe({ next: () => this.loaded.update((n) => n + 1), error: () => this.requested.delete(constantId) });
23
+ }
24
+ return this.labels.getLabel(constantId, code);
25
+ }
26
+ }
@@ -36,9 +36,10 @@ export class LabelService {
36
36
  }
37
37
 
38
38
  /**
39
- * Load one backend-provided `constant_value` domain from ApplicationData.
40
- * Completed and concurrent requests are cached; a failed application-data
41
- * load is evicted so a later call can retry.
39
+ * Load one caption map from ApplicationData: a `constant_value` domain by its
40
+ * constant id, or a catalog table registered in `foreign_key_lookup` by its
41
+ * table name. Completed and concurrent requests are cached; a failed
42
+ * application-data load is evicted so a later call can retry.
42
43
  */
43
44
  loadLabels(constantId: string): Observable<void> {
44
45
  const domain = constantId.trim();
@@ -53,7 +54,7 @@ export class LabelService {
53
54
  tap({
54
55
  next: (data) => this.labels.set(
55
56
  domain,
56
- new Map(Object.entries(data.ConstantCache?.[domain] ?? {})),
57
+ new Map(Object.entries(data.ConstantCache?.[domain] ?? data.TableCache?.[domain] ?? {})),
57
58
  ),
58
59
  error: () => this.pendingLoads.delete(domain),
59
60
  }),
@@ -45,6 +45,7 @@ export const RestURL = {
45
45
  ssoSamlMetadataURL: '/public/sso/saml/metadata',
46
46
  logoutEverywhereURL: '/api/user/logout-everywhere',
47
47
  deleteAccountURL: '/api/user/account',
48
+ reauthSendURL: '/api/user/reauth/send',
48
49
  // Self-service profile (keel ProfileHandler). GET profileURL reads the
49
50
  // current profile; POST updates name/locale. Email/phone are verify-before-
50
51
  // apply (request → confirm). A consumer whose backend mounts these under a