juneau 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -534,14 +534,17 @@ const {
534
534
  isLoading, // boolean — true while streaming
535
535
  isConnecting, // boolean — true from send until first token arrives
536
536
  error, // string | null — last error, cleared on next send
537
- reset, // () => void — clear all messages and abort any stream
538
- confirmProposal, // (id: string, payload: unknown) => void
539
- cancelProposal, // (id: string) => void
537
+ reset, // (nextMessages?: AiMessage[]) => void — clear (or replace) messages, abort any stream
538
+ confirmProposal, // (id: string, payload: unknown) => void — marks proposal resolved + fires callback
539
+ cancelProposal, // (id: string) => void — marks proposal resolved + fires callback
540
540
  } = useAiChat({
541
541
  adapter, // required
542
542
  context, // optional — forwarded to every adapter.sendMessage call
543
543
  onProposalConfirm, // optional — called by confirmProposal
544
544
  onProposalCancel, // optional — called by cancelProposal
545
+ initialMessages, // optional — restored conversation to start with (see Chat history)
546
+ historyLimit, // optional — max messages sent to the adapter per request (token saving)
547
+ onMessagesChange, // optional — called when the conversation settles; use to persist
545
548
  });
546
549
  ```
547
550
 
@@ -722,6 +725,71 @@ yield {
722
725
 
723
726
  ---
724
727
 
728
+ ## Chat history
729
+
730
+ Juneau is storage-agnostic: it defines the exact data contract and renders restored conversations (including tables, proposals, and custom parts), but never touches storage itself. You persist chats wherever you want — localStorage, a database — and hand Juneau plain data.
731
+
732
+ **Persist a conversation:**
733
+
734
+ ```tsx
735
+ import { useAiChat, serializeForStorage } from 'juneau';
736
+
737
+ const chat = useAiChat({
738
+ adapter,
739
+ historyLimit: 20, // send at most 20 messages to the adapter per request (token saving)
740
+ onMessagesChange: (messages) => {
741
+ // called when the conversation settles — never per streamed token
742
+ localStorage.setItem('chat', JSON.stringify(serializeForStorage(messages)));
743
+ },
744
+ });
745
+ ```
746
+
747
+ `serializeForStorage` prepares messages for persistence:
748
+ - `createdAt` dates become ISO strings
749
+ - unresolved proposals are marked `resolved: 'expired'` — a restored proposal card renders disabled and can never fire callbacks against a stale payload
750
+ - `running` activity parts are dropped (they'd look permanently stuck)
751
+
752
+ **Restore a conversation:**
753
+
754
+ ```tsx
755
+ import { deserializeMessages } from 'juneau';
756
+
757
+ const stored = JSON.parse(localStorage.getItem('chat') ?? '[]');
758
+ const chat = useAiChat({ adapter, initialMessages: deserializeMessages(stored) });
759
+ ```
760
+
761
+ All rich parts re-render exactly as they streamed in — no reconstruction needed. The restored history is also sent to the adapter, so the AI keeps full context.
762
+
763
+ **Rendering trims nothing.** `historyLimit` only caps what is *sent to the adapter*; the cut keeps the most recent messages and never splits a user/assistant exchange, so alternation stays valid.
764
+
765
+ **Multiple chats:**
766
+
767
+ Juneau supports a multi-chat UX via `AiChatSummary` and the `AiChatHistoryList` component. You own the chat list and per-chat storage; Juneau renders the list and switches conversations via `reset(nextMessages)`:
768
+
769
+ ```tsx
770
+ import { AiChatHistoryList, trimChats } from 'juneau';
771
+
772
+ <AiChatHistoryList
773
+ chats={trimChats(myChats, 10)} // keep the 10 most recently updated
774
+ activeChatId={currentChatId}
775
+ onSelect={(chatId) => chat.reset(loadMessagesFor(chatId))}
776
+ onDelete={(chatId) => deleteChat(chatId)} // optional — omit to hide delete buttons
777
+ />
778
+ ```
779
+
780
+ ```ts
781
+ type AiChatSummary = {
782
+ id: string;
783
+ title: string;
784
+ createdAt: Date;
785
+ updatedAt: Date;
786
+ };
787
+ ```
788
+
789
+ `trimChats(chats, limit)` returns the `limit` most recently updated chats (sorted newest first) — delete the rest from your storage to enforce an overall chats limit.
790
+
791
+ ---
792
+
725
793
  ## Theming
726
794
 
727
795
  All visual values are CSS custom properties prefixed `--juneau-`. Override them via `JuneauProvider`:
@@ -793,7 +861,12 @@ Pass any `Partial<JuneauLabels>` — omitted keys fall back to English:
793
861
  | `emptyStateHint` | `Try: "Show me the data" or "Can you suggest something?"` | `AiMessageList` empty state hint |
794
862
  | `proposalConfirm` | `Confirm` | `AiProposalCard` fallback confirm label |
795
863
  | `proposalCancel` | `Cancel` | `AiProposalCard` fallback cancel label |
864
+ | `proposalConfirmed` | `Confirmed` | `AiProposalCard` badge after confirm |
865
+ | `proposalCancelled` | `Cancelled` | `AiProposalCard` badge after cancel |
866
+ | `proposalExpired` | `No longer available` | `AiProposalCard` badge for restored proposals |
796
867
  | `errorDismiss` | `Dismiss` | `AiError` dismiss button |
868
+ | `historyEmpty` | `No previous chats` | `AiChatHistoryList` empty state |
869
+ | `historyDeleteChat` | `Delete chat` | `AiChatHistoryList` delete button |
797
870
  | `actionAddFile` | `Add file` | `AiInput` toolbar |
798
871
  | `actionQuickActions` | `Quick actions` | `AiInput` toolbar |
799
872
  | `actionNew` | `New` | `AiInput` toolbar |
@@ -0,0 +1,14 @@
1
+ import type { AiChatSummary } from '../../core/types';
2
+ type Props = {
3
+ /** Stored chats to display — most recently updated first is recommended (see `trimChats`) */
4
+ chats: AiChatSummary[];
5
+ /** Called with the chat id when the user picks a chat */
6
+ onSelect: (chatId: string) => void;
7
+ /** Highlights the currently open chat, if any */
8
+ activeChatId?: string;
9
+ /** If provided, shows a delete button on each row */
10
+ onDelete?: (chatId: string) => void;
11
+ };
12
+ export declare function AiChatHistoryList({ chats, onSelect, activeChatId, onDelete }: Props): import("react").JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=AiChatHistoryList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AiChatHistoryList.d.ts","sourceRoot":"","sources":["../../../src/components/AiChatHistoryList/AiChatHistoryList.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAItD,KAAK,KAAK,GAAG;IACX,6FAA6F;IAC7F,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,yDAAyD;IACzD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,iDAAiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAmCnF"}
@@ -1 +1 @@
1
- {"version":3,"file":"AiProposalCard.d.ts","sourceRoot":"","sources":["../../../src/components/parts/AiProposalCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,KAAK,+BA+BlE"}
1
+ {"version":3,"file":"AiProposalCard.d.ts","sourceRoot":"","sources":["../../../src/components/parts/AiProposalCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,SAAS,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1D,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACxC,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,KAAK,+BAyClE"}
@@ -0,0 +1,46 @@
1
+ import type { AiChatSummary, AiMessage, AiMessagePart, AiProposalPart, AiSerializedMessage } from './types';
2
+ /**
3
+ * Narrows a part to a proposal. Needed because `AiCustomPart`'s index
4
+ * signature keeps TypeScript from narrowing the union on `type` alone.
5
+ */
6
+ export declare function isProposalPart(part: AiMessagePart): part is AiProposalPart;
7
+ /**
8
+ * Prepares messages for persistence. Returns plain JSON-safe objects:
9
+ *
10
+ * - `createdAt` dates become ISO strings
11
+ * - unresolved proposals are marked `resolved: 'expired'` so a restored card
12
+ * can never fire callbacks against a stale payload
13
+ * - `running` activity parts are dropped — a restored "in progress" row would
14
+ * look permanently stuck
15
+ *
16
+ * @example
17
+ * localStorage.setItem('chat', JSON.stringify(serializeForStorage(messages)));
18
+ */
19
+ export declare function serializeForStorage(messages: AiMessage[]): AiSerializedMessage[];
20
+ /**
21
+ * Restores messages persisted with {@link serializeForStorage} back into the
22
+ * live `AiMessage[]` shape Juneau expects — revives `createdAt` dates.
23
+ * Accepts the parsed JSON value, not the raw string.
24
+ *
25
+ * @example
26
+ * const stored = JSON.parse(localStorage.getItem('chat') ?? '[]');
27
+ * const messages = deserializeMessages(stored);
28
+ */
29
+ export declare function deserializeMessages(stored: AiSerializedMessage[]): AiMessage[];
30
+ /**
31
+ * Trims a conversation to at most `limit` messages for sending to the model,
32
+ * keeping the most recent ones. Purely a token-saving measure — rendering is
33
+ * never trimmed.
34
+ *
35
+ * The cut never lands mid-exchange: if the oldest surviving message is an
36
+ * assistant turn, it is dropped too, so the history always starts with a user
37
+ * (or system) message and alternation stays valid.
38
+ */
39
+ export declare function trimHistory(messages: AiMessage[], limit: number): AiMessage[];
40
+ /**
41
+ * Enforces an overall chats limit: returns the `limit` most recently updated
42
+ * chats. Use the returned list to know which chats to keep; delete the rest
43
+ * from your storage.
44
+ */
45
+ export declare function trimChats(chats: AiChatSummary[], limit: number): AiChatSummary[];
46
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/core/history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,cAAc,EACd,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,IAAI,cAAc,CAE1E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,mBAAmB,EAAE,CAQhF;AASD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,EAAE,GAAG,SAAS,EAAE,CAK9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,CAO7E;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE,CAGhF"}
@@ -8,6 +8,13 @@ export type AiTablePart = {
8
8
  columns: string[];
9
9
  rows: Record<string, unknown>[];
10
10
  };
11
+ /**
12
+ * Lifecycle state of a proposal.
13
+ * - `confirmed` / `cancelled` — the user acted on it
14
+ * - `expired` — the proposal was persisted to history without being acted on;
15
+ * restored proposals must never fire callbacks against stale payloads
16
+ */
17
+ export type AiProposalResolution = 'confirmed' | 'cancelled' | 'expired';
11
18
  export type AiProposal = {
12
19
  id: string;
13
20
  title: string;
@@ -16,6 +23,8 @@ export type AiProposal = {
16
23
  payload?: unknown;
17
24
  confirmLabel?: string;
18
25
  cancelLabel?: string;
26
+ /** Set once the proposal is acted on or expired — renders the card disabled */
27
+ resolved?: AiProposalResolution;
19
28
  };
20
29
  export type AiProposalPart = {
21
30
  type: 'proposal';
@@ -55,6 +64,21 @@ export type AiMessage = {
55
64
  parts: AiMessagePart[];
56
65
  createdAt: Date;
57
66
  };
67
+ /**
68
+ * Lightweight descriptor for one stored chat — what a chat history list needs
69
+ * to render. The consumer stores the full `AiMessage[]` per chat separately
70
+ * and loads it on selection.
71
+ */
72
+ export type AiChatSummary = {
73
+ id: string;
74
+ title: string;
75
+ createdAt: Date;
76
+ updatedAt: Date;
77
+ };
78
+ /** JSON-safe form of {@link AiMessage} — dates as ISO strings. */
79
+ export type AiSerializedMessage = Omit<AiMessage, 'createdAt'> & {
80
+ createdAt: string;
81
+ };
58
82
  export type AiStreamTextEvent = {
59
83
  type: 'text';
60
84
  text: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,25 @@ export type UseAiChatOptions = {
7
7
  onProposalConfirm?: (proposalId: string, payload: unknown) => void;
8
8
  /** Called when a proposal is cancelled */
9
9
  onProposalCancel?: (proposalId: string) => void;
10
+ /**
11
+ * Restored conversation to start with — typically the output of
12
+ * `deserializeMessages`. Read once on mount; switch chats later via
13
+ * `reset(nextMessages)`.
14
+ */
15
+ initialMessages?: AiMessage[];
16
+ /**
17
+ * Maximum number of messages sent to the adapter per request — a
18
+ * token-saving measure. Rendering is never trimmed; the cut keeps the most
19
+ * recent messages and never splits a user/assistant exchange. Unlimited by
20
+ * default.
21
+ */
22
+ historyLimit?: number;
23
+ /**
24
+ * Called whenever the conversation settles: an exchange finishes streaming,
25
+ * a proposal is resolved, or the chat is reset. Never called per streamed
26
+ * token. Use this to persist the conversation (see `serializeForStorage`).
27
+ */
28
+ onMessagesChange?: (messages: AiMessage[]) => void;
10
29
  };
11
30
  export type UseAiChatReturn = {
12
31
  messages: AiMessage[];
@@ -31,9 +50,13 @@ export type UseAiChatReturn = {
31
50
  */
32
51
  isConnecting: boolean;
33
52
  error: string | null;
34
- reset: () => void;
53
+ /**
54
+ * Clears the conversation and aborts any in-flight stream. Pass
55
+ * `nextMessages` to load a different stored chat instead of starting empty.
56
+ */
57
+ reset: (nextMessages?: AiMessage[]) => void;
35
58
  confirmProposal: (proposalId: string, payload: unknown) => void;
36
59
  cancelProposal: (proposalId: string) => void;
37
60
  };
38
- export declare function useAiChat({ adapter, context, onProposalConfirm, onProposalCancel }: UseAiChatOptions): UseAiChatReturn;
61
+ export declare function useAiChat({ adapter, context, onProposalConfirm, onProposalCancel, initialMessages, historyLimit, onMessagesChange }: UseAiChatOptions): UseAiChatReturn;
39
62
  //# sourceMappingURL=useAiChat.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAiChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiChat.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,SAAS,EAET,gBAAgB,EAEjB,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACnE,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,mHAAmH;IACnH,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD;;;;OAIG;IACH,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,kEAAkE;IAClE,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChE,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EACjB,EAAE,gBAAgB,GAAG,eAAe,CAsOpC"}
1
+ {"version":3,"file":"useAiChat.d.ts","sourceRoot":"","sources":["../../src/hooks/useAiChat.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,SAAS,EAET,gBAAgB,EAEjB,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACnE,0CAA0C;IAC1C,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,eAAe,CAAC,EAAE,SAAS,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,mHAAmH;IACnH,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD;;;;OAIG;IACH,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,kEAAkE;IAClE,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB;;;OAGG;IACH,KAAK,EAAE,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC5C,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChE,cAAc,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF,wBAAgB,SAAS,CAAC,EACxB,OAAO,EACP,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,gBAAgB,EACjB,EAAE,gBAAgB,GAAG,eAAe,CA2QpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"cs.d.ts","sourceRoot":"","sources":["../../../src/i18n/locales/cs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,eAAO,MAAM,QAAQ,EAAE,YAsBtB,CAAC"}
1
+ {"version":3,"file":"cs.d.ts","sourceRoot":"","sources":["../../../src/i18n/locales/cs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,eAAO,MAAM,QAAQ,EAAE,YA2BtB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../src/i18n/locales/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,eAAO,MAAM,QAAQ,EAAE,YAsBtB,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../../src/i18n/locales/en.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,eAAO,MAAM,QAAQ,EAAE,YA2BtB,CAAC"}
@@ -25,6 +25,11 @@ export type JuneauLabels = {
25
25
  emptyStateHint: string;
26
26
  proposalConfirm: string;
27
27
  proposalCancel: string;
28
+ proposalConfirmed: string;
29
+ proposalCancelled: string;
30
+ proposalExpired: string;
28
31
  errorDismiss: string;
32
+ historyEmpty: string;
33
+ historyDeleteChat: string;
29
34
  };
30
35
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IAEzB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IAGtB,SAAS,EAAE,MAAM,CAAC;IAGlB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAGpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IAGvB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IAGvB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/i18n/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IAEzB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IAGtB,SAAS,EAAE,MAAM,CAAC;IAGlB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IAGpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAGpB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IAGvB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IAEvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IAGxB,YAAY,EAAE,MAAM,CAAC;IAGrB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAAC"}