@dudousxd/nestjs-agent-react 0.16.0 → 0.17.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/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as ai from 'ai';
2
2
  import { ChatTransport, UIMessage, UIMessageChunk, DataUIPart, UIDataTypes } from 'ai';
3
3
  import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
4
- import { ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaView, ModelCatalogView, AgentCatalogEntry, MessageFeedbackValue, MessageFeedback, ModelCatalogEntry, StoredMessage } from '@dudousxd/nestjs-agent-core';
4
+ import { ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaView, QuotaReport, ModelCatalogView, AgentCatalogEntry, MessageFeedbackValue, MessageFeedback, ModelCatalogEntry, QuotaWindow, QuotaBlock, StoredMessage } from '@dudousxd/nestjs-agent-core';
5
5
  export { ElicitationInput, ElicitationInputType, validateElicitationAnswer as validateAnswer, validateElicitationValue as validateAnswerValue } from '@dudousxd/nestjs-agent-core';
6
6
  import React__default from 'react';
7
7
  import { a as TranscriptBlock, U as UsageSummary, b as TimestampInfo, C as ChatStatus, M as MessageUsageInfo, c as ToolCatalog, A as ApproveOptions, d as AnyToolUIPart, e as TranscriptFile, T as TranscriptUiBlock } from './model-gHqjNjLJ.cjs';
@@ -106,6 +106,8 @@ interface AgentBackend {
106
106
  listTools?(agent?: string): Promise<ToolCatalogEntry[]>;
107
107
  listSkills?(threadId?: string): Promise<SkillCatalogEntry[]>;
108
108
  getQuotaToday?(): Promise<QuotaView>;
109
+ /** `GET <base>/quota` — every budget window, and which one blocks sends, if any. */
110
+ getQuota?(): Promise<QuotaReport>;
109
111
  /** `GET <base>/models?agent=` — what a model picker offers. */
110
112
  listModels?(agent?: string): Promise<ModelCatalogView>;
111
113
  /** `GET <base>/agents` — what an agent picker offers. */
@@ -347,6 +349,34 @@ interface ModelsState {
347
349
  */
348
350
  declare function useModels(options: UseModelsOptions): ModelsState;
349
351
 
352
+ interface UseQuotaOptions {
353
+ /** `useAgentChat(...).backend`, or your own. Must implement `getQuota`. */
354
+ backend: AgentBackend;
355
+ /** `false` holds the request. Default `true`. */
356
+ enabled?: boolean;
357
+ /** Re-read every `pollMs` ms as well. Default: only on mount, after runs, and on `refresh`. */
358
+ pollMs?: number;
359
+ }
360
+ interface QuotaState {
361
+ /** The full report, once loaded. */
362
+ report: QuotaReport | undefined;
363
+ windows: QuotaWindow[];
364
+ /** The `day` / `month` windows, when the server reports them. */
365
+ day: QuotaWindow | undefined;
366
+ month: QuotaWindow | undefined;
367
+ /** The window that blocks sends, or `null` — pass it to `useAgentChat({ blocked })`. */
368
+ blocked: QuotaBlock | null;
369
+ isLoading: boolean;
370
+ error: Error | null;
371
+ refresh: () => Promise<void>;
372
+ }
373
+ /**
374
+ * The caller's budget (`GET <base>/quota`): every window's usage against its ceilings, and which
375
+ * one — if any — blocks sends. Re-read after every run a chat on the same backend settles, so a
376
+ * meter moves with the conversation. Headless: draw the meter yourself.
377
+ */
378
+ declare function useQuota(options: UseQuotaOptions): QuotaState;
379
+
350
380
  interface UseMessageFeedbackOptions {
351
381
  /** `useAgentChat(...).backend`, or your own. Must implement `setMessageFeedback`. */
352
382
  backend: AgentBackend;
@@ -546,6 +576,8 @@ declare class AgentClient implements AgentBackend {
546
576
  listModels(agent?: string): Promise<ModelCatalogView>;
547
577
  /** `GET /agent/agents` — the registered agents, the default one flagged. */
548
578
  listAgents(): Promise<AgentCatalogEntry[]>;
579
+ /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
580
+ getQuota(): Promise<QuotaReport>;
549
581
  getQuotaToday(): Promise<QuotaToday>;
550
582
  cancelStream(runId: string): Promise<CancelResult>;
551
583
  /**
@@ -1373,6 +1405,12 @@ interface UseAgentChatOptions<B extends AgentBackend = AgentClient> {
1373
1405
  client?: B;
1374
1406
  /** Named agent to run each turn. */
1375
1407
  agent?: string;
1408
+ /**
1409
+ * The quota window blocking sends — `useQuota(...).blocked`. While set, `sendMessage` and
1410
+ * `regenerate` refuse with {@link QuotaBlockedError} instead of starting a turn the server would
1411
+ * refuse anyway.
1412
+ */
1413
+ blocked?: QuotaBlock | null;
1376
1414
  /**
1377
1415
  * Catalog model to run each turn on (see `useModels`), sent as the body's `model`. Read at every
1378
1416
  * send, so a picker can change it between turns. Omitted → the thread's pinned model, else the
@@ -1563,5 +1601,10 @@ declare function useAgentChat<B extends AgentBackend = AgentClient>(options: Use
1563
1601
  addToolApprovalResponse: ai.ChatAddToolApproveResponseFunction;
1564
1602
  clearError: () => void;
1565
1603
  };
1604
+ /** A send refused on the client because a quota window is exhausted (`useAgentChat({ blocked })`). */
1605
+ declare class QuotaBlockedError extends Error {
1606
+ readonly block: QuotaBlock;
1607
+ constructor(block: QuotaBlock);
1608
+ }
1566
1609
 
1567
- export { type AgentBackend, AgentBackendUnsupportedError, AgentChatTransport, type AgentChatTransportOptions, AgentClient, type AgentClientOptions, AgentHttpError, type AgentMessageMetadata, type AgentStreamMeta, type AgentsState, type AggregatedTurnUsage, AnyToolUIPart, type ApprovalCountdown, ApproveOptions, type AutocompleteInputProps, type AutocompleteItem, type AutocompleteListboxProps, type AutocompleteOptionProps, type AutocompleteSource, type BackgroundRun, type CancelResult, type ChatBackground, ChatInput, type ChatInputProps, ChatStatus, type ChatStreamRequest, type ChatStreamResponse, type ChatTranscript, type CompletionEdit, type ComposerAutocomplete, DEFAULT_SPEECH_LANG, type MessageFeedbackInput, type MessageFeedbackState, MessageItem, type MessageItemClassNames, type MessageItemProps, MessageItemView, type MessageItemViewProps, MessageList, type MessageListClassNames, type MessageListProps, MessageUsageInfo, type ModelOption, type ModelsState, type QuotaToday, type ReconnectOptions, type RenderFilesFn, type RenderReasoningFn, type RenderTextFn, type RenderToolGroupFn, type RenderToolPartFn, type RenderUiFn, type ResumeStreamRequest, SPEECH_LANGUAGES, type SkillSuggestionData, type SkillsSourceOptions, type SpeechLanguage, type SpeechRecognitionHook, type StickToBottom, type StickToBottomOptions, type StoredTurnMetadata, type StreamConnectionState, type ThreadPatch, type ThreadsEvent, type ThreadsState, TimestampInfo, ToolCatalog, type ToolCatalogState, type TranscriptActionState, TranscriptBlock, type TranscriptCopyState, type TranscriptEditState, TranscriptFile, type TranscriptItem, type TranscriptItemOptions, type TranscriptStopState, TranscriptUiBlock, type TranscriptWindow, type TriggerMatch, type TriggerPosition, type UploadAttachmentOptions, UsageSummary, type UseAgentChatOptions, type UseAgentsOptions, type UseApprovalCountdownOptions, type UseChatTranscriptOptions, type UseComposerAutocompleteOptions, type UseElapsedOptions, type UseMessageFeedbackOptions, type UseModelsOptions, type UseSpeechRecognitionOptions, type UseThreadsOptions, type UseToolCatalogOptions, type UseTranscriptItemOptions, applyCompletion, approvalCountdown, backgroundRunsFromThread, createSkillsSource, filterAutocompleteItems, findActiveTrigger, formatElapsed, loadStoredSpeechLang, notifyThreads, onThreadsEvent, persistSpeechLang, readReasoningMs, requireBackendMethod, storedMessageToUiMessage, storedThreadToUiMessages, useAgentChat, useAgents, useApprovalCountdown, useChatTranscript, useComposerAutocomplete, useElapsed, useMessageFeedback, useModels, useSpeechRecognition, useStickToBottom, useThreads, useToolCatalog, useTranscriptItem };
1610
+ export { type AgentBackend, AgentBackendUnsupportedError, AgentChatTransport, type AgentChatTransportOptions, AgentClient, type AgentClientOptions, AgentHttpError, type AgentMessageMetadata, type AgentStreamMeta, type AgentsState, type AggregatedTurnUsage, AnyToolUIPart, type ApprovalCountdown, ApproveOptions, type AutocompleteInputProps, type AutocompleteItem, type AutocompleteListboxProps, type AutocompleteOptionProps, type AutocompleteSource, type BackgroundRun, type CancelResult, type ChatBackground, ChatInput, type ChatInputProps, ChatStatus, type ChatStreamRequest, type ChatStreamResponse, type ChatTranscript, type CompletionEdit, type ComposerAutocomplete, DEFAULT_SPEECH_LANG, type MessageFeedbackInput, type MessageFeedbackState, MessageItem, type MessageItemClassNames, type MessageItemProps, MessageItemView, type MessageItemViewProps, MessageList, type MessageListClassNames, type MessageListProps, MessageUsageInfo, type ModelOption, type ModelsState, QuotaBlockedError, type QuotaState, type QuotaToday, type ReconnectOptions, type RenderFilesFn, type RenderReasoningFn, type RenderTextFn, type RenderToolGroupFn, type RenderToolPartFn, type RenderUiFn, type ResumeStreamRequest, SPEECH_LANGUAGES, type SkillSuggestionData, type SkillsSourceOptions, type SpeechLanguage, type SpeechRecognitionHook, type StickToBottom, type StickToBottomOptions, type StoredTurnMetadata, type StreamConnectionState, type ThreadPatch, type ThreadsEvent, type ThreadsState, TimestampInfo, ToolCatalog, type ToolCatalogState, type TranscriptActionState, TranscriptBlock, type TranscriptCopyState, type TranscriptEditState, TranscriptFile, type TranscriptItem, type TranscriptItemOptions, type TranscriptStopState, TranscriptUiBlock, type TranscriptWindow, type TriggerMatch, type TriggerPosition, type UploadAttachmentOptions, UsageSummary, type UseAgentChatOptions, type UseAgentsOptions, type UseApprovalCountdownOptions, type UseChatTranscriptOptions, type UseComposerAutocompleteOptions, type UseElapsedOptions, type UseMessageFeedbackOptions, type UseModelsOptions, type UseQuotaOptions, type UseSpeechRecognitionOptions, type UseThreadsOptions, type UseToolCatalogOptions, type UseTranscriptItemOptions, applyCompletion, approvalCountdown, backgroundRunsFromThread, createSkillsSource, filterAutocompleteItems, findActiveTrigger, formatElapsed, loadStoredSpeechLang, notifyThreads, onThreadsEvent, persistSpeechLang, readReasoningMs, requireBackendMethod, storedMessageToUiMessage, storedThreadToUiMessages, useAgentChat, useAgents, useApprovalCountdown, useChatTranscript, useComposerAutocomplete, useElapsed, useMessageFeedback, useModels, useQuota, useSpeechRecognition, useStickToBottom, useThreads, useToolCatalog, useTranscriptItem };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as ai from 'ai';
2
2
  import { ChatTransport, UIMessage, UIMessageChunk, DataUIPart, UIDataTypes } from 'ai';
3
3
  import * as _dudousxd_nestjs_agent_core from '@dudousxd/nestjs-agent-core';
4
- import { ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaView, ModelCatalogView, AgentCatalogEntry, MessageFeedbackValue, MessageFeedback, ModelCatalogEntry, StoredMessage } from '@dudousxd/nestjs-agent-core';
4
+ import { ThreadSummary, ThreadDetail, MessageAttachment, ToolCatalogEntry, SkillCatalogEntry, QuotaView, QuotaReport, ModelCatalogView, AgentCatalogEntry, MessageFeedbackValue, MessageFeedback, ModelCatalogEntry, QuotaWindow, QuotaBlock, StoredMessage } from '@dudousxd/nestjs-agent-core';
5
5
  export { ElicitationInput, ElicitationInputType, validateElicitationAnswer as validateAnswer, validateElicitationValue as validateAnswerValue } from '@dudousxd/nestjs-agent-core';
6
6
  import React__default from 'react';
7
7
  import { a as TranscriptBlock, U as UsageSummary, b as TimestampInfo, C as ChatStatus, M as MessageUsageInfo, c as ToolCatalog, A as ApproveOptions, d as AnyToolUIPart, e as TranscriptFile, T as TranscriptUiBlock } from './model-gHqjNjLJ.js';
@@ -106,6 +106,8 @@ interface AgentBackend {
106
106
  listTools?(agent?: string): Promise<ToolCatalogEntry[]>;
107
107
  listSkills?(threadId?: string): Promise<SkillCatalogEntry[]>;
108
108
  getQuotaToday?(): Promise<QuotaView>;
109
+ /** `GET <base>/quota` — every budget window, and which one blocks sends, if any. */
110
+ getQuota?(): Promise<QuotaReport>;
109
111
  /** `GET <base>/models?agent=` — what a model picker offers. */
110
112
  listModels?(agent?: string): Promise<ModelCatalogView>;
111
113
  /** `GET <base>/agents` — what an agent picker offers. */
@@ -347,6 +349,34 @@ interface ModelsState {
347
349
  */
348
350
  declare function useModels(options: UseModelsOptions): ModelsState;
349
351
 
352
+ interface UseQuotaOptions {
353
+ /** `useAgentChat(...).backend`, or your own. Must implement `getQuota`. */
354
+ backend: AgentBackend;
355
+ /** `false` holds the request. Default `true`. */
356
+ enabled?: boolean;
357
+ /** Re-read every `pollMs` ms as well. Default: only on mount, after runs, and on `refresh`. */
358
+ pollMs?: number;
359
+ }
360
+ interface QuotaState {
361
+ /** The full report, once loaded. */
362
+ report: QuotaReport | undefined;
363
+ windows: QuotaWindow[];
364
+ /** The `day` / `month` windows, when the server reports them. */
365
+ day: QuotaWindow | undefined;
366
+ month: QuotaWindow | undefined;
367
+ /** The window that blocks sends, or `null` — pass it to `useAgentChat({ blocked })`. */
368
+ blocked: QuotaBlock | null;
369
+ isLoading: boolean;
370
+ error: Error | null;
371
+ refresh: () => Promise<void>;
372
+ }
373
+ /**
374
+ * The caller's budget (`GET <base>/quota`): every window's usage against its ceilings, and which
375
+ * one — if any — blocks sends. Re-read after every run a chat on the same backend settles, so a
376
+ * meter moves with the conversation. Headless: draw the meter yourself.
377
+ */
378
+ declare function useQuota(options: UseQuotaOptions): QuotaState;
379
+
350
380
  interface UseMessageFeedbackOptions {
351
381
  /** `useAgentChat(...).backend`, or your own. Must implement `setMessageFeedback`. */
352
382
  backend: AgentBackend;
@@ -546,6 +576,8 @@ declare class AgentClient implements AgentBackend {
546
576
  listModels(agent?: string): Promise<ModelCatalogView>;
547
577
  /** `GET /agent/agents` — the registered agents, the default one flagged. */
548
578
  listAgents(): Promise<AgentCatalogEntry[]>;
579
+ /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
580
+ getQuota(): Promise<QuotaReport>;
549
581
  getQuotaToday(): Promise<QuotaToday>;
550
582
  cancelStream(runId: string): Promise<CancelResult>;
551
583
  /**
@@ -1373,6 +1405,12 @@ interface UseAgentChatOptions<B extends AgentBackend = AgentClient> {
1373
1405
  client?: B;
1374
1406
  /** Named agent to run each turn. */
1375
1407
  agent?: string;
1408
+ /**
1409
+ * The quota window blocking sends — `useQuota(...).blocked`. While set, `sendMessage` and
1410
+ * `regenerate` refuse with {@link QuotaBlockedError} instead of starting a turn the server would
1411
+ * refuse anyway.
1412
+ */
1413
+ blocked?: QuotaBlock | null;
1376
1414
  /**
1377
1415
  * Catalog model to run each turn on (see `useModels`), sent as the body's `model`. Read at every
1378
1416
  * send, so a picker can change it between turns. Omitted → the thread's pinned model, else the
@@ -1563,5 +1601,10 @@ declare function useAgentChat<B extends AgentBackend = AgentClient>(options: Use
1563
1601
  addToolApprovalResponse: ai.ChatAddToolApproveResponseFunction;
1564
1602
  clearError: () => void;
1565
1603
  };
1604
+ /** A send refused on the client because a quota window is exhausted (`useAgentChat({ blocked })`). */
1605
+ declare class QuotaBlockedError extends Error {
1606
+ readonly block: QuotaBlock;
1607
+ constructor(block: QuotaBlock);
1608
+ }
1566
1609
 
1567
- export { type AgentBackend, AgentBackendUnsupportedError, AgentChatTransport, type AgentChatTransportOptions, AgentClient, type AgentClientOptions, AgentHttpError, type AgentMessageMetadata, type AgentStreamMeta, type AgentsState, type AggregatedTurnUsage, AnyToolUIPart, type ApprovalCountdown, ApproveOptions, type AutocompleteInputProps, type AutocompleteItem, type AutocompleteListboxProps, type AutocompleteOptionProps, type AutocompleteSource, type BackgroundRun, type CancelResult, type ChatBackground, ChatInput, type ChatInputProps, ChatStatus, type ChatStreamRequest, type ChatStreamResponse, type ChatTranscript, type CompletionEdit, type ComposerAutocomplete, DEFAULT_SPEECH_LANG, type MessageFeedbackInput, type MessageFeedbackState, MessageItem, type MessageItemClassNames, type MessageItemProps, MessageItemView, type MessageItemViewProps, MessageList, type MessageListClassNames, type MessageListProps, MessageUsageInfo, type ModelOption, type ModelsState, type QuotaToday, type ReconnectOptions, type RenderFilesFn, type RenderReasoningFn, type RenderTextFn, type RenderToolGroupFn, type RenderToolPartFn, type RenderUiFn, type ResumeStreamRequest, SPEECH_LANGUAGES, type SkillSuggestionData, type SkillsSourceOptions, type SpeechLanguage, type SpeechRecognitionHook, type StickToBottom, type StickToBottomOptions, type StoredTurnMetadata, type StreamConnectionState, type ThreadPatch, type ThreadsEvent, type ThreadsState, TimestampInfo, ToolCatalog, type ToolCatalogState, type TranscriptActionState, TranscriptBlock, type TranscriptCopyState, type TranscriptEditState, TranscriptFile, type TranscriptItem, type TranscriptItemOptions, type TranscriptStopState, TranscriptUiBlock, type TranscriptWindow, type TriggerMatch, type TriggerPosition, type UploadAttachmentOptions, UsageSummary, type UseAgentChatOptions, type UseAgentsOptions, type UseApprovalCountdownOptions, type UseChatTranscriptOptions, type UseComposerAutocompleteOptions, type UseElapsedOptions, type UseMessageFeedbackOptions, type UseModelsOptions, type UseSpeechRecognitionOptions, type UseThreadsOptions, type UseToolCatalogOptions, type UseTranscriptItemOptions, applyCompletion, approvalCountdown, backgroundRunsFromThread, createSkillsSource, filterAutocompleteItems, findActiveTrigger, formatElapsed, loadStoredSpeechLang, notifyThreads, onThreadsEvent, persistSpeechLang, readReasoningMs, requireBackendMethod, storedMessageToUiMessage, storedThreadToUiMessages, useAgentChat, useAgents, useApprovalCountdown, useChatTranscript, useComposerAutocomplete, useElapsed, useMessageFeedback, useModels, useSpeechRecognition, useStickToBottom, useThreads, useToolCatalog, useTranscriptItem };
1610
+ export { type AgentBackend, AgentBackendUnsupportedError, AgentChatTransport, type AgentChatTransportOptions, AgentClient, type AgentClientOptions, AgentHttpError, type AgentMessageMetadata, type AgentStreamMeta, type AgentsState, type AggregatedTurnUsage, AnyToolUIPart, type ApprovalCountdown, ApproveOptions, type AutocompleteInputProps, type AutocompleteItem, type AutocompleteListboxProps, type AutocompleteOptionProps, type AutocompleteSource, type BackgroundRun, type CancelResult, type ChatBackground, ChatInput, type ChatInputProps, ChatStatus, type ChatStreamRequest, type ChatStreamResponse, type ChatTranscript, type CompletionEdit, type ComposerAutocomplete, DEFAULT_SPEECH_LANG, type MessageFeedbackInput, type MessageFeedbackState, MessageItem, type MessageItemClassNames, type MessageItemProps, MessageItemView, type MessageItemViewProps, MessageList, type MessageListClassNames, type MessageListProps, MessageUsageInfo, type ModelOption, type ModelsState, QuotaBlockedError, type QuotaState, type QuotaToday, type ReconnectOptions, type RenderFilesFn, type RenderReasoningFn, type RenderTextFn, type RenderToolGroupFn, type RenderToolPartFn, type RenderUiFn, type ResumeStreamRequest, SPEECH_LANGUAGES, type SkillSuggestionData, type SkillsSourceOptions, type SpeechLanguage, type SpeechRecognitionHook, type StickToBottom, type StickToBottomOptions, type StoredTurnMetadata, type StreamConnectionState, type ThreadPatch, type ThreadsEvent, type ThreadsState, TimestampInfo, ToolCatalog, type ToolCatalogState, type TranscriptActionState, TranscriptBlock, type TranscriptCopyState, type TranscriptEditState, TranscriptFile, type TranscriptItem, type TranscriptItemOptions, type TranscriptStopState, TranscriptUiBlock, type TranscriptWindow, type TriggerMatch, type TriggerPosition, type UploadAttachmentOptions, UsageSummary, type UseAgentChatOptions, type UseAgentsOptions, type UseApprovalCountdownOptions, type UseChatTranscriptOptions, type UseComposerAutocompleteOptions, type UseElapsedOptions, type UseMessageFeedbackOptions, type UseModelsOptions, type UseQuotaOptions, type UseSpeechRecognitionOptions, type UseThreadsOptions, type UseToolCatalogOptions, type UseTranscriptItemOptions, applyCompletion, approvalCountdown, backgroundRunsFromThread, createSkillsSource, filterAutocompleteItems, findActiveTrigger, formatElapsed, loadStoredSpeechLang, notifyThreads, onThreadsEvent, persistSpeechLang, readReasoningMs, requireBackendMethod, storedMessageToUiMessage, storedThreadToUiMessages, useAgentChat, useAgents, useApprovalCountdown, useChatTranscript, useComposerAutocomplete, useElapsed, useMessageFeedback, useModels, useQuota, useSpeechRecognition, useStickToBottom, useThreads, useToolCatalog, useTranscriptItem };
package/dist/index.js CHANGED
@@ -156,6 +156,10 @@ var AgentClient = class {
156
156
  listAgents() {
157
157
  return this.request("GET", "/agent/agents");
158
158
  }
159
+ /** `GET /agent/quota` — the caller's budget windows and the one blocking sends, if any. */
160
+ getQuota() {
161
+ return this.request("GET", "/agent/quota");
162
+ }
159
163
  getQuotaToday() {
160
164
  return this.request("GET", "/agent/quota/today");
161
165
  }
@@ -1103,6 +1107,74 @@ function useModels(options) {
1103
1107
  }
1104
1108
  __name(useModels, "useModels");
1105
1109
 
1110
+ // src/quota/use-quota.ts
1111
+ import { useEffect as useEffect3, useMemo as useMemo3 } from "react";
1112
+
1113
+ // src/threads/threads-events.ts
1114
+ var listeners = /* @__PURE__ */ new WeakMap();
1115
+ function notifyThreads(backend, event) {
1116
+ for (const listener of listeners.get(backend) ?? []) {
1117
+ listener(event);
1118
+ }
1119
+ }
1120
+ __name(notifyThreads, "notifyThreads");
1121
+ function onThreadsEvent(backend, listener) {
1122
+ let set = listeners.get(backend);
1123
+ if (set === void 0) {
1124
+ set = /* @__PURE__ */ new Set();
1125
+ listeners.set(backend, set);
1126
+ }
1127
+ set.add(listener);
1128
+ return () => {
1129
+ set.delete(listener);
1130
+ };
1131
+ }
1132
+ __name(onThreadsEvent, "onThreadsEvent");
1133
+
1134
+ // src/quota/use-quota.ts
1135
+ function useQuota(options) {
1136
+ const { backend, enabled = true, pollMs } = options;
1137
+ const { data, isLoading, error, refresh } = useResource(() => requireBackendMethod(backend, "getQuota")(), "", enabled);
1138
+ useEffect3(() => {
1139
+ if (!enabled) return;
1140
+ return onThreadsEvent(backend, (event) => {
1141
+ if (event.type === "changed") void refresh();
1142
+ });
1143
+ }, [
1144
+ backend,
1145
+ enabled,
1146
+ refresh
1147
+ ]);
1148
+ useEffect3(() => {
1149
+ if (!enabled || pollMs === void 0 || pollMs <= 0) return;
1150
+ const timer = setInterval(() => void refresh(), pollMs);
1151
+ return () => clearInterval(timer);
1152
+ }, [
1153
+ enabled,
1154
+ pollMs,
1155
+ refresh
1156
+ ]);
1157
+ return useMemo3(() => {
1158
+ const windows = data?.windows ?? [];
1159
+ return {
1160
+ report: data,
1161
+ windows,
1162
+ day: windows.find((window2) => window2.period === "day"),
1163
+ month: windows.find((window2) => window2.period === "month"),
1164
+ blocked: data?.blocked ?? null,
1165
+ isLoading,
1166
+ error,
1167
+ refresh
1168
+ };
1169
+ }, [
1170
+ data,
1171
+ isLoading,
1172
+ error,
1173
+ refresh
1174
+ ]);
1175
+ }
1176
+ __name(useQuota, "useQuota");
1177
+
1106
1178
  // src/feedback/use-message-feedback.ts
1107
1179
  import { useCallback as useCallback2, useRef as useRef3, useState as useState3 } from "react";
1108
1180
  function useMessageFeedback(options) {
@@ -1212,29 +1284,8 @@ function metadataOf(message) {
1212
1284
  }
1213
1285
  __name(metadataOf, "metadataOf");
1214
1286
 
1215
- // src/threads/threads-events.ts
1216
- var listeners = /* @__PURE__ */ new WeakMap();
1217
- function notifyThreads(backend, event) {
1218
- for (const listener of listeners.get(backend) ?? []) {
1219
- listener(event);
1220
- }
1221
- }
1222
- __name(notifyThreads, "notifyThreads");
1223
- function onThreadsEvent(backend, listener) {
1224
- let set = listeners.get(backend);
1225
- if (set === void 0) {
1226
- set = /* @__PURE__ */ new Set();
1227
- listeners.set(backend, set);
1228
- }
1229
- set.add(listener);
1230
- return () => {
1231
- set.delete(listener);
1232
- };
1233
- }
1234
- __name(onThreadsEvent, "onThreadsEvent");
1235
-
1236
1287
  // src/threads/use-threads.ts
1237
- import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef4, useState as useState4 } from "react";
1288
+ import { useCallback as useCallback3, useEffect as useEffect4, useRef as useRef4, useState as useState4 } from "react";
1238
1289
  function useThreads(options) {
1239
1290
  const { backend, enabled = true } = options;
1240
1291
  const [threads, setThreads] = useState4([]);
@@ -1260,7 +1311,7 @@ function useThreads(options) {
1260
1311
  }, [
1261
1312
  backend
1262
1313
  ]);
1263
- useEffect3(() => {
1314
+ useEffect4(() => {
1264
1315
  if (!enabled) return;
1265
1316
  void refresh();
1266
1317
  return onThreadsEvent(backend, (event) => {
@@ -1377,10 +1428,10 @@ function backgroundRunsFromThread(messages) {
1377
1428
  __name(backgroundRunsFromThread, "backgroundRunsFromThread");
1378
1429
 
1379
1430
  // src/components/chat-input.tsx
1380
- import React2, { useEffect as useEffect5, useState as useState6 } from "react";
1431
+ import React2, { useEffect as useEffect6, useState as useState6 } from "react";
1381
1432
 
1382
1433
  // src/components/use-speech-recognition.ts
1383
- import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef5, useState as useState5 } from "react";
1434
+ import { useCallback as useCallback4, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef5, useState as useState5 } from "react";
1384
1435
  function getRecognitionCtor() {
1385
1436
  if (typeof window === "undefined") return null;
1386
1437
  const scope = window;
@@ -1390,13 +1441,13 @@ __name(getRecognitionCtor, "getRecognitionCtor");
1390
1441
  function useSpeechRecognition({ lang = "en-US", onFinalTranscript, onInterimTranscript }) {
1391
1442
  const recognitionRef = useRef5(null);
1392
1443
  const [isListening, setIsListening] = useState5(false);
1393
- const ctor = useMemo3(() => getRecognitionCtor(), []);
1444
+ const ctor = useMemo4(() => getRecognitionCtor(), []);
1394
1445
  const isSupported = ctor !== null;
1395
1446
  const finalRef = useRef5(onFinalTranscript);
1396
1447
  const interimRef = useRef5(onInterimTranscript);
1397
1448
  finalRef.current = onFinalTranscript;
1398
1449
  interimRef.current = onInterimTranscript;
1399
- useEffect4(() => {
1450
+ useEffect5(() => {
1400
1451
  if (!ctor) return;
1401
1452
  const recognition = new ctor();
1402
1453
  recognition.lang = lang;
@@ -1476,7 +1527,7 @@ function ChatInput({ onSubmit, disabled, placeholder, rows = 2, enableSpeech = t
1476
1527
  }, "onFinalTranscript"),
1477
1528
  onInterimTranscript: /* @__PURE__ */ __name((text) => setInterim(text), "onInterimTranscript")
1478
1529
  });
1479
- useEffect5(() => {
1530
+ useEffect6(() => {
1480
1531
  if (!speech.isListening) setInterim("");
1481
1532
  }, [
1482
1533
  speech.isListening
@@ -1543,7 +1594,7 @@ __name(ChatInput, "ChatInput");
1543
1594
  import React3 from "react";
1544
1595
 
1545
1596
  // src/transcript/use-chat-transcript.ts
1546
- import { useCallback as useCallback6, useEffect as useEffect7, useRef as useRef7, useState as useState8 } from "react";
1597
+ import { useCallback as useCallback6, useEffect as useEffect8, useRef as useRef7, useState as useState8 } from "react";
1547
1598
 
1548
1599
  // src/transcript/model.ts
1549
1600
  import { readElicitationInput, validateElicitationAnswer as validateElicitationAnswer2 } from "@dudousxd/nestjs-agent-core";
@@ -2520,7 +2571,7 @@ function formatCostUsd(cost) {
2520
2571
  __name(formatCostUsd, "formatCostUsd");
2521
2572
 
2522
2573
  // src/transcript/use-stick-to-bottom.ts
2523
- import { useCallback as useCallback5, useEffect as useEffect6, useRef as useRef6, useState as useState7 } from "react";
2574
+ import { useCallback as useCallback5, useEffect as useEffect7, useRef as useRef6, useState as useState7 } from "react";
2524
2575
  function useStickToBottom({ contentKey, threshold = 32 }) {
2525
2576
  const containerRef = useRef6(null);
2526
2577
  const [isAtBottom, setIsAtBottom] = useState7(true);
@@ -2550,7 +2601,7 @@ function useStickToBottom({ contentKey, threshold = 32 }) {
2550
2601
  }, [
2551
2602
  measure
2552
2603
  ]);
2553
- useEffect6(() => {
2604
+ useEffect7(() => {
2554
2605
  if (isAtBottom) {
2555
2606
  scrollToBottom();
2556
2607
  }
@@ -2588,7 +2639,7 @@ function useChatTranscript(options) {
2588
2639
  const isStreaming = status === "streaming" || status === "reconnecting";
2589
2640
  const isBusy = status === "submitted" || isStreaming;
2590
2641
  const isEmpty = messages.length === 0;
2591
- useEffect7(() => {
2642
+ useEffect8(() => {
2592
2643
  if (!isBusy) {
2593
2644
  setStopRequested(false);
2594
2645
  }
@@ -2687,7 +2738,7 @@ function useTranscriptItems({ messages, visibleStart, streamingMessageId, option
2687
2738
  messages
2688
2739
  };
2689
2740
  const copyTimers = useRef7(/* @__PURE__ */ new Map());
2690
- useEffect7(() => () => {
2741
+ useEffect8(() => () => {
2691
2742
  for (const timer of copyTimers.current.values()) {
2692
2743
  clearTimeout(timer);
2693
2744
  }
@@ -3430,7 +3481,7 @@ function toItem(entry) {
3430
3481
  __name(toItem, "toItem");
3431
3482
 
3432
3483
  // src/composer/use-composer-autocomplete.ts
3433
- import { useCallback as useCallback7, useEffect as useEffect8, useId, useLayoutEffect, useMemo as useMemo4, useRef as useRef8, useState as useState9 } from "react";
3484
+ import { useCallback as useCallback7, useEffect as useEffect9, useId, useLayoutEffect, useMemo as useMemo5, useRef as useRef8, useState as useState9 } from "react";
3434
3485
  function useComposerAutocomplete(options) {
3435
3486
  const { value, sources, acceptOnTab = true } = options;
3436
3487
  const latest = useRef8(options);
@@ -3443,7 +3494,7 @@ function useComposerAutocomplete(options) {
3443
3494
  const [activeIndex, setActiveIndex] = useState9(0);
3444
3495
  const [dismissedIndex, setDismissedIndex] = useState9(null);
3445
3496
  const safeCaret = Math.min(caret, value.length);
3446
- const match = useMemo4(() => findActiveTrigger(value, safeCaret, sources), [
3497
+ const match = useMemo5(() => findActiveTrigger(value, safeCaret, sources), [
3447
3498
  value,
3448
3499
  safeCaret,
3449
3500
  sources
@@ -3458,7 +3509,7 @@ function useComposerAutocomplete(options) {
3458
3509
  const activeIndexRef = useRef8(activeIndex);
3459
3510
  activeIndexRef.current = activeIndex;
3460
3511
  const requestKey = isActive && match ? `${match.source.id}\0${match.query}` : null;
3461
- useEffect8(() => {
3512
+ useEffect9(() => {
3462
3513
  const current = matchRef.current;
3463
3514
  if (requestKey === null || current === null) {
3464
3515
  setItems([]);
@@ -3668,7 +3719,7 @@ function isPromise(value) {
3668
3719
  __name(isPromise, "isPromise");
3669
3720
 
3670
3721
  // src/presentation/use-tool-catalog.ts
3671
- import { useCallback as useCallback8, useEffect as useEffect9, useMemo as useMemo5, useState as useState10 } from "react";
3722
+ import { useCallback as useCallback8, useEffect as useEffect10, useMemo as useMemo6, useState as useState10 } from "react";
3672
3723
  var shared = /* @__PURE__ */ new WeakMap();
3673
3724
  function load(client, agent) {
3674
3725
  let byAgent = shared.get(client);
@@ -3696,7 +3747,7 @@ function useToolCatalog(options) {
3696
3747
  const [isLoading, setLoading] = useState10(enabled);
3697
3748
  const [error, setError] = useState10(null);
3698
3749
  const [generation, setGeneration] = useState10(0);
3699
- useEffect9(() => {
3750
+ useEffect10(() => {
3700
3751
  if (!enabled) {
3701
3752
  setLoading(false);
3702
3753
  return;
@@ -3729,7 +3780,7 @@ function useToolCatalog(options) {
3729
3780
  client,
3730
3781
  agent
3731
3782
  ]);
3732
- const catalog = useMemo5(() => toolCatalogFrom(entries), [
3783
+ const catalog = useMemo6(() => toolCatalogFrom(entries), [
3733
3784
  entries
3734
3785
  ]);
3735
3786
  return {
@@ -3743,7 +3794,7 @@ function useToolCatalog(options) {
3743
3794
  __name(useToolCatalog, "useToolCatalog");
3744
3795
 
3745
3796
  // src/approvals/countdown.ts
3746
- import { useEffect as useEffect10, useRef as useRef9, useState as useState11 } from "react";
3797
+ import { useEffect as useEffect11, useRef as useRef9, useState as useState11 } from "react";
3747
3798
  function approvalCountdown(expiresAt, now = Date.now()) {
3748
3799
  const deadline = expiresAt == null ? Number.NaN : Date.parse(expiresAt);
3749
3800
  if (!Number.isFinite(deadline)) {
@@ -3764,7 +3815,7 @@ function useApprovalCountdown(expiresAt, options = {}) {
3764
3815
  const nowRef = useRef9(options.now ?? Date.now);
3765
3816
  nowRef.current = options.now ?? Date.now;
3766
3817
  const [state, setState] = useState11(() => approvalCountdown(expiresAt, nowRef.current()));
3767
- useEffect10(() => {
3818
+ useEffect11(() => {
3768
3819
  const read = /* @__PURE__ */ __name(() => approvalCountdown(expiresAt, nowRef.current()), "read");
3769
3820
  const first = read();
3770
3821
  setState(first);
@@ -4006,7 +4057,7 @@ __name(sumUsage, "sumUsage");
4006
4057
 
4007
4058
  // src/use-agent-chat.ts
4008
4059
  import { useChat } from "@ai-sdk/react";
4009
- import { useCallback as useCallback9, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef10, useState as useState12 } from "react";
4060
+ import { useCallback as useCallback9, useEffect as useEffect12, useMemo as useMemo7, useRef as useRef10, useState as useState12 } from "react";
4010
4061
  function useAgentChat(options) {
4011
4062
  const latest = useRef10(options);
4012
4063
  latest.current = options;
@@ -4019,7 +4070,7 @@ function useAgentChat(options) {
4019
4070
  const [activeRunId, setActiveRunId] = useState12(null);
4020
4071
  const regenerateNext = useRef10(false);
4021
4072
  const createdThreadId = useRef10(void 0);
4022
- const client = useMemo6(() => {
4073
+ const client = useMemo7(() => {
4023
4074
  if (options.backend) return options.backend;
4024
4075
  if (options.client) return options.client;
4025
4076
  return new AgentClient({
@@ -4039,7 +4090,7 @@ function useAgentChat(options) {
4039
4090
  status: "live"
4040
4091
  });
4041
4092
  const resyncAfterSettle = useRef10(false);
4042
- useEffect11(() => {
4093
+ useEffect12(() => {
4043
4094
  if (!options.resume || options.threadId === void 0) return;
4044
4095
  let cancelled = false;
4045
4096
  const threadId = options.threadId;
@@ -4059,7 +4110,7 @@ function useAgentChat(options) {
4059
4110
  options.resume,
4060
4111
  options.threadId
4061
4112
  ]);
4062
- const transport = useMemo6(() => {
4113
+ const transport = useMemo7(() => {
4063
4114
  function onMeta(meta) {
4064
4115
  settlingRunIdRef.current = meta.runId;
4065
4116
  setRunId(meta.runId);
@@ -4180,6 +4231,8 @@ function useAgentChat(options) {
4180
4231
  transport
4181
4232
  ]);
4182
4233
  const sendMessage = useCallback9(async (...args) => {
4234
+ const blocked = latest.current.blocked;
4235
+ if (blocked != null) throw new QuotaBlockedError(blocked);
4183
4236
  if (isTurnInFlight()) return;
4184
4237
  turnInFlight.current = true;
4185
4238
  try {
@@ -4223,7 +4276,7 @@ function useAgentChat(options) {
4223
4276
  ]);
4224
4277
  backgroundRef.current = refreshBackground;
4225
4278
  const isWorking = backgroundRuns.some((run) => run.status === "running");
4226
- useEffect11(() => {
4279
+ useEffect12(() => {
4227
4280
  if (options.background !== true || options.threadId === void 0) {
4228
4281
  return;
4229
4282
  }
@@ -4233,7 +4286,7 @@ function useAgentChat(options) {
4233
4286
  options.threadId,
4234
4287
  refreshBackground
4235
4288
  ]);
4236
- useEffect11(() => {
4289
+ useEffect12(() => {
4237
4290
  const every = latest.current.backgroundPollMs ?? 5e3;
4238
4291
  if (latest.current.background !== true || !isWorking || every <= 0) {
4239
4292
  return;
@@ -4347,6 +4400,8 @@ function useAgentChat(options) {
4347
4400
  client
4348
4401
  ]);
4349
4402
  const regenerate = useCallback9(() => {
4403
+ const blocked = latest.current.blocked;
4404
+ if (blocked != null) throw new QuotaBlockedError(blocked);
4350
4405
  if (isTurnInFlight()) return;
4351
4406
  regenerateNext.current = true;
4352
4407
  turnInFlight.current = true;
@@ -4418,6 +4473,16 @@ function useAgentChat(options) {
4418
4473
  };
4419
4474
  }
4420
4475
  __name(useAgentChat, "useAgentChat");
4476
+ var QuotaBlockedError = class extends Error {
4477
+ static {
4478
+ __name(this, "QuotaBlockedError");
4479
+ }
4480
+ block;
4481
+ constructor(block) {
4482
+ super(block.reason ?? `The ${block.period === "day" ? "daily" : "monthly"} quota is used up`), this.block = block;
4483
+ this.name = "QuotaBlockedError";
4484
+ }
4485
+ };
4421
4486
  async function mergeHeaders(options) {
4422
4487
  const dynamic = await options.getHeaders?.() ?? {};
4423
4488
  return {
@@ -4436,6 +4501,7 @@ export {
4436
4501
  MessageItem,
4437
4502
  MessageItemView,
4438
4503
  MessageList,
4504
+ QuotaBlockedError,
4439
4505
  SPEECH_LANGUAGES,
4440
4506
  applyCompletion,
4441
4507
  approvalCountdown,
@@ -4477,6 +4543,7 @@ export {
4477
4543
  useElapsed,
4478
4544
  useMessageFeedback,
4479
4545
  useModels,
4546
+ useQuota,
4480
4547
  useSpeechRecognition,
4481
4548
  useStickToBottom,
4482
4549
  useThreads,