@lenne.tech/ng-base 22.0.0 → 22.0.2

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
@@ -193,9 +193,9 @@ Screenshots need the optional peer `modern-screenshot`; without it the screensho
193
193
  Off in production, decided at runtime per stage: the browser reads `NG_PUBLIC_APP_ENV` from the runtime config, the
194
194
  endpoint from the environment. Without `NG_PUBLIC_APP_ENV` both fail closed (browser part only in dev mode, endpoint
195
195
  `404`; set `NG_PUBLIC_APP_ENV=local` locally). `enabled` overrides on both sides; while off no capture hook is installed.
196
- Per stage without a rebuild: `NG_PUBLIC_LT_BUG_ENABLED`, `NG_PUBLIC_LT_BUG_AUTO_SHOW`, `NG_PUBLIC_LT_BUG_AUTO_OPEN_ON_ERROR`,
197
- `NG_PUBLIC_LT_BUG_ENABLE_SCREENSHOT`, `NG_PUBLIC_LT_BUG_POSITION`, `NG_PUBLIC_LT_BUG_BUTTON_COLOR`, `NG_PUBLIC_LT_BUG_BUTTON_TEXT`
198
- (browser part; the endpoint keeps its own `enabled` option).
196
+ Per stage without a rebuild: `NG_PUBLIC_LT_BUG_ENABLED` switches both sides (browser part and endpoint, before the
197
+ `enabled` option); `NG_PUBLIC_LT_BUG_AUTO_SHOW`, `NG_PUBLIC_LT_BUG_AUTO_OPEN_ON_ERROR`, `NG_PUBLIC_LT_BUG_ENABLE_SCREENSHOT`,
198
+ `NG_PUBLIC_LT_BUG_POSITION`, `NG_PUBLIC_LT_BUG_BUTTON_COLOR` and `NG_PUBLIC_LT_BUG_BUTTON_TEXT` are browser-only.
199
199
 
200
200
  Redaction before sending (and again on the server before Linear): `Authorization`, `Cookie`, `Set-Cookie`,
201
201
  `X-System-Setup-Token` and similar headers become `[redacted]`; bodies of `/iam/`, `/system-setup/` and other auth
@@ -488,13 +488,17 @@ var LtAiPromptsService = class LtAiPromptsService {
488
488
  calls = new LtAiCallState();
489
489
  list = signal([], ...ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []);
490
490
  loadSequence = 0;
491
+ includeDisabled = false;
491
492
  error = this.calls.error;
492
493
  loading = this.calls.loading;
493
494
  prompts = this.list.asReadonly();
494
- async load() {
495
+ enabledPrompts = computed(() => this.list().filter((prompt) => prompt.enabled !== false), ...ngDevMode ? [{ debugName: "enabledPrompts" }] : /* istanbul ignore next */ []);
496
+ async load(options = {}) {
495
497
  const sequence = ++this.loadSequence;
498
+ this.includeDisabled = options.includeDisabled === true;
499
+ const path = this.includeDisabled ? "/prompts?includeDisabled=true" : "/prompts";
496
500
  try {
497
- const prompts = await this.calls.run(() => this.http.request("GET", "/prompts"));
501
+ const prompts = await this.calls.run(() => this.http.request("GET", path));
498
502
  if (sequence === this.loadSequence) this.list.set(prompts ?? []);
499
503
  } catch {
500
504
  if (sequence === this.loadSequence) this.list.set([]);
@@ -512,7 +516,7 @@ var LtAiPromptsService = class LtAiPromptsService {
512
516
  async mutate(call) {
513
517
  return this.calls.run(async () => {
514
518
  const result = await call();
515
- await this.load();
519
+ await this.load({ includeDisabled: this.includeDisabled });
516
520
  return result;
517
521
  });
518
522
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lenne.tech-ng-base-ai.mjs","names":[],"sources":["../../../projects/ng-base/ai/src/lib/ai-options.ts","../../../projects/ng-base/ai/src/lib/ai-http.ts","../../../projects/ng-base/ai/src/lib/ai-call-state.ts","../../../projects/ng-base/ai/src/lib/ai-chat.ts","../../../projects/ng-base/ai/src/lib/ai-admin-service.ts","../../../projects/ng-base/ai/src/lib/ai-connections-service.ts","../../../projects/ng-base/ai/src/lib/ai-placeholders-service.ts","../../../projects/ng-base/ai/src/lib/ai-prompts-service.ts","../../../projects/ng-base/ai/src/lib/ai-service.ts","../../../projects/ng-base/ai/src/lib/ai-settings-service.ts","../../../projects/ng-base/ai/src/lib/ai-status-service.ts","../../../projects/ng-base/ai/src/lib/ai-usage-service.ts"],"sourcesContent":["import { inject, InjectionToken, makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { LT_RUNTIME_CONFIG, mergeLtFeatureOptions } from '@lenne.tech/ng-base';\n\n/** Options of `provideLtAi()`; runtime override `NG_PUBLIC_LT_AI_BASE_PATH`. */\nexport interface LtAiOptions {\n /** REST base of the nest-server AI controller (default `/ai`). */\n basePath?: string;\n}\n\nconst LT_AI_INPUT_OPTIONS = new InjectionToken<LtAiOptions>('LT_AI_INPUT_OPTIONS', { factory: () => ({}) });\n\n/** Resolved AI options. */\nexport const LT_AI_OPTIONS = new InjectionToken<Required<LtAiOptions>>('LT_AI_OPTIONS', {\n factory: () => mergeLtFeatureOptions<Required<LtAiOptions>>({ basePath: '/ai' }, inject(LT_AI_INPUT_OPTIONS), inject(LT_RUNTIME_CONFIG, { optional: true })?.lt.ai),\n});\n\n/** AI providers (base path). The AI services work without it with the defaults. */\nexport function provideLtAi(options: LtAiOptions = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: LT_AI_INPUT_OPTIONS, useValue: options }]);\n}\n","import { inject, Service } from '@angular/core';\nimport { LT_FETCH, LtApiUrlService } from '@lenne.tech/ng-base';\n\nimport { LT_AI_OPTIONS } from './ai-options';\nimport type { LtAiStreamEvent } from './ai-types';\n\n/** Maximum length of one SSE line (1 MiB); longer lines abort the stream. */\nexport const LT_AI_SSE_MAX_LINE = 1024 * 1024;\n\n/** HTTP helpers of the AI services (counterpart of `buildLtAiUrl` / `ltAiRequest`). All calls use the auth-aware `LT_FETCH`. */\n@Service()\nexport class LtAiHttpService {\n private readonly api = inject(LtApiUrlService);\n private readonly fetch = inject(LT_FETCH);\n private readonly options = inject(LT_AI_OPTIONS);\n\n /** AI base path (`/ai`). */\n basePath(): string {\n return this.options.basePath;\n }\n\n /** `<api><basePath><path>`. */\n buildUrl(path: string): string {\n return this.api.buildUrl(`${this.options.basePath}${path.startsWith('/') ? path : `/${path}`}`);\n }\n\n /** JSON request (`Accept: application/json`); throws {@link ltAiResponseError} on non-2xx; 204 → `undefined`. */\n async request<T>(method: 'DELETE' | 'GET' | 'POST' | 'PUT', path: string, body?: unknown, options: { signal?: AbortSignal } = {}): Promise<T> {\n const init: RequestInit = { headers: { accept: 'application/json' }, method, signal: options.signal };\n if (body !== undefined) {\n init.body = JSON.stringify(body);\n init.headers = { ...(init.headers as Record<string, string>), 'content-type': 'application/json' };\n }\n const response = await this.fetch(this.buildUrl(path), init);\n if (!response.ok) {\n throw await ltAiResponseError(response);\n }\n if (response.status === 204) {\n return undefined as T;\n }\n const text = await response.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** Raw request for streaming (`POST /ai/stream`). */\n stream(path: string, body: unknown, options: { signal?: AbortSignal } = {}): Promise<Response> {\n return this.fetch(this.buildUrl(path), {\n body: JSON.stringify(body),\n headers: { accept: 'text/event-stream', 'content-type': 'application/json' },\n method: 'POST',\n signal: options.signal,\n });\n }\n}\n\n/** Build an `Error & { status }` from an error response (`message`/`error`, arrays joined, capped at 1 KiB). */\nexport async function ltAiResponseError(response: Response): Promise<Error & { status: number }> {\n let message = `${response.status} ${response.statusText}`.trim();\n try {\n const body = (await response.json()) as { error?: unknown; message?: unknown } | null;\n const raw = body?.message ?? body?.error;\n if (Array.isArray(raw)) {\n message = raw.map(String).join(', ');\n } else if (typeof raw === 'string' && raw) {\n message = raw;\n }\n } catch {\n // keep the status line\n }\n const error = new Error(message.slice(0, 1024)) as Error & { status: number };\n error.status = response.status;\n return error;\n}\n\n/**\n * Parse an SSE response body (`data: {json}` lines) and call `onEvent` per event. Handles chunks split mid-line,\n * ignores non-`data:` lines, `[DONE]` and malformed JSON, throws on lines over 1 MiB; aborting cancels the reader.\n *\n * `options.signal` stops parsing without cancelling the underlying fetch (component-destroy races): the reader is\n * cancelled, also while it waits for the next chunk, and the function resolves without delivering further events.\n * An error thrown by `onEvent` propagates (and cancels the reader); only unparsable payloads are skipped.\n */\nexport async function parseLtAiSseStream(response: Response, onEvent: (event: LtAiStreamEvent) => void, options: { signal?: AbortSignal } = {}): Promise<void> {\n const body = response.body;\n if (!body) {\n throw new Error('AI stream response has no body');\n }\n const signal = options.signal;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let finished = false;\n\n const cancel = (): void => {\n reader.cancel().catch(() => undefined);\n };\n const tooLong = (): Error => new Error('AI stream line exceeds maximum allowed size');\n const handleLine = (line: string): void => {\n if (line.length > LT_AI_SSE_MAX_LINE) {\n throw tooLong();\n }\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) {\n return;\n }\n const payload = trimmed.slice(5).trim();\n if (!payload || payload === '[DONE]') {\n return;\n }\n let event: LtAiStreamEvent;\n try {\n event = JSON.parse(payload) as LtAiStreamEvent;\n } catch {\n return; // a malformed event line is skipped\n }\n onEvent(event);\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n try {\n if (signal?.aborted) {\n return;\n }\n for (;;) {\n const { done, value } = await reader.read();\n if (signal?.aborted) {\n return;\n }\n if (done) {\n break;\n }\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n handleLine(line);\n if (signal?.aborted) {\n return;\n }\n }\n if (buffer.length > LT_AI_SSE_MAX_LINE) {\n throw tooLong();\n }\n }\n buffer += decoder.decode();\n finished = true;\n if (buffer) {\n handleLine(buffer);\n }\n } finally {\n signal?.removeEventListener('abort', cancel);\n if (!finished) {\n cancel();\n }\n reader.releaseLock();\n }\n}\n","import { computed, signal } from '@angular/core';\n\nimport { ltAiResponseError, parseLtAiSseStream, type LtAiHttpService } from './ai-http';\nimport type { LtAiPromptRunInput, LtAiResponse, LtAiStreamHandlers } from './ai-types';\n\n/**\n * Loading/error state shared by the AI services (internal, not part of the public API).\n *\n * `loading` counts the calls in flight, so two overlapping calls of a root service do not switch the flag off while\n * one of them still runs. `error` holds the message of the latest failed call and is cleared when a call starts.\n */\nexport class LtAiCallState {\n private readonly pending = signal(0);\n private readonly lastError = signal<null | string>(null);\n\n /** `true` while at least one call runs. */\n readonly loading = computed(() => this.pending() > 0);\n /** Message of the latest failed call. */\n readonly error = this.lastError.asReadonly();\n\n /** Run `call`; on failure store the message and rethrow. */\n async run<T>(call: () => Promise<T>): Promise<T> {\n this.pending.update((count) => count + 1);\n this.lastError.set(null);\n try {\n return await call();\n } catch (error) {\n this.lastError.set(ltAiErrorMessage(error));\n throw error;\n } finally {\n this.pending.update((count) => Math.max(0, count - 1));\n }\n }\n\n /** Run `call`; on failure store the message and resolve with `undefined` instead of throwing. */\n async runQuietly<T>(call: () => Promise<T>): Promise<T | undefined> {\n try {\n return await this.run(call);\n } catch {\n return undefined;\n }\n }\n\n /** Set the error message directly (stream `error` events). */\n setError(message: null | string): void {\n this.lastError.set(message);\n }\n}\n\n/** Message of a thrown value. */\nexport function ltAiErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Whether `error` is the result of an abort (`AbortController.abort()` without a custom reason). */\nexport function isLtAiAbortError(error: unknown): boolean {\n return (error as { name?: unknown } | null)?.name === 'AbortError';\n}\n\n/**\n * `POST /ai/stream` and dispatch the SSE events to `handlers` (internal; used by `LtAiService` and `injectLtAiChat`).\n *\n * Resolves with the `final` response, or `undefined` when the backend closes the stream without one. A non-2xx answer\n * rejects with {@link ltAiResponseError}; an abort through `options.signal` rejects with the abort reason\n * (an `AbortError` for a plain `abort()`), also when the parser stopped cleanly.\n */\nexport async function runLtAiStream(\n http: LtAiHttpService,\n input: LtAiPromptRunInput,\n handlers: LtAiStreamHandlers | undefined,\n options: { signal?: AbortSignal } = {},\n): Promise<LtAiResponse | undefined> {\n const response = await http.stream('/stream', input, options);\n if (!response.ok) {\n throw await ltAiResponseError(response);\n }\n let final: LtAiResponse | undefined;\n await parseLtAiSseStream(\n response,\n (event) => {\n handlers?.onEvent?.(event);\n switch (event.type) {\n case 'action':\n handlers?.onAction?.(event.action);\n break;\n case 'error':\n handlers?.onError?.(event.message);\n break;\n case 'final':\n final = event.response;\n handlers?.onFinal?.(event.response);\n break;\n case 'token':\n handlers?.onToken?.(event.token);\n break;\n }\n },\n options,\n );\n if (options.signal?.aborted) {\n throw abortReason(options.signal);\n }\n return final;\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n const reason: unknown = signal.reason;\n if (reason instanceof Error || (typeof DOMException !== 'undefined' && reason instanceof DOMException)) {\n return reason;\n }\n const error = new Error('The operation was aborted.');\n error.name = 'AbortError';\n return error;\n}\n","import { assertInInjectionContext, computed, DestroyRef, inject, isSignal, linkedSignal, signal } from '@angular/core';\n\nimport { isLtAiAbortError, ltAiErrorMessage, runLtAiStream } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiBudgetSummary, LtAiChatOptions, LtAiChatState, LtAiMessage, LtAiPromptRunInput, LtAiResponse } from './ai-types';\n\n/** A chat session created by {@link injectLtAiChat}. */\nexport type LtAiChat = LtAiChatState;\n\n/**\n * Create a chat session (counterpart of `useLtAiChat()`), bound to the current injection context: a running stream is\n * stopped on destroy. Streams by default; `send` is ignored while a turn runs; `confirm()` re-sends the last prompt with\n * `confirm: true`; abort is not an error; `maxMessages` trims the oldest messages.\n *\n * Every chat has its own state (messages, conversation, budget, streaming); it does not share `LtAiService`'s signals.\n * A stream `error` event marks the assistant turn as failed and sets `error`, like a failed request.\n *\n * @example\n * protected readonly chat = injectLtAiChat({ connectionId: this.connectionId, metadata: () => ({ url: location.href }) });\n */\nexport function injectLtAiChat(options: LtAiChatOptions = {}): LtAiChat {\n assertInInjectionContext(injectLtAiChat);\n const http = inject(LtAiHttpService);\n\n const messages = signal<LtAiMessage[]>([]);\n // Follows a signal option (a new conversation selected outside) and keeps the id the server assigns.\n const conversationId = linkedSignal<string | undefined>(() => (isSignal(options.conversationId) ? options.conversationId() : options.conversationId));\n const budget = signal<LtAiBudgetSummary | null>(null);\n const contextWindow = signal<{ total: number; used: number } | null>(null);\n const error = signal<null | string>(null);\n const streaming = signal(false);\n let busy = false;\n let turnSequence = 0;\n let controller: AbortController | undefined;\n let lastPrompt = '';\n\n const requiresConfirmation = computed(() => {\n const list = messages();\n const last = list[list.length - 1];\n return !!last && last.role === 'assistant' && !!last.requiresConfirmation;\n });\n\n function resolveConnectionId(): string | undefined {\n const value = options.connectionId;\n return (isSignal(value) ? value() : value) || undefined;\n }\n\n function push(message: LtAiMessage): void {\n messages.update((list) => {\n const next = [...list, message];\n return options.maxMessages && options.maxMessages > 0 && next.length > options.maxMessages ? next.slice(next.length - options.maxMessages) : next;\n });\n }\n\n function buildInput(prompt: string, confirm: boolean): LtAiPromptRunInput {\n const input: LtAiPromptRunInput = {\n connectionId: resolveConnectionId(),\n conversationId: conversationId(),\n metadata: options.metadata?.(),\n mode: isSignal(options.mode) ? options.mode() : options.mode,\n prompt,\n };\n if (confirm) {\n input.confirm = true;\n }\n return input;\n }\n\n /** Run one assistant turn, streaming into a new message. */\n async function runTurn(input: LtAiPromptRunInput): Promise<void> {\n const turn = ++turnSequence;\n const isCurrent = (): boolean => turn === turnSequence;\n error.set(null);\n let assistant: LtAiMessage = { content: '', createdAt: new Date().toISOString(), pending: true, role: 'assistant' };\n push(assistant);\n // Messages are immutable: every change replaces the element, a cleared or trimmed turn is no longer found.\n const patch = (changes: Partial<LtAiMessage>): void => {\n const previous = assistant;\n assistant = { ...previous, ...changes };\n const next = assistant;\n messages.update((list) => (list.includes(previous) ? list.map((message) => (message === previous ? next : message)) : list));\n };\n const applyFinal = (response: LtAiResponse): void => {\n patch({\n actions: response.actions,\n budget: response.budget,\n content: response.text || assistant.content,\n denied: response.denied,\n pending: false,\n pendingActions: response.pendingActions,\n requiresConfirmation: response.requiresConfirmation,\n });\n if (!isCurrent()) {\n return;\n }\n if (response.budget) {\n budget.set(response.budget);\n }\n if (response.contextWindow) {\n contextWindow.set(response.contextWindow);\n }\n if (response.conversationId) {\n conversationId.set(response.conversationId);\n }\n };\n const fail = (message: string): void => {\n patch({ content: assistant.content || message, error: true, pending: false });\n if (isCurrent()) {\n error.set(message);\n }\n };\n\n const abort = new AbortController();\n controller = abort;\n busy = true;\n const stream = options.stream !== false;\n streaming.set(stream);\n try {\n if (stream) {\n let streamError: string | undefined;\n // applyFinal runs from onFinal, so budget/contextWindow/conversationId update the moment the event arrives.\n await runLtAiStream(\n http,\n input,\n {\n onError: (message) => (streamError = message),\n onFinal: applyFinal,\n onToken: (token) => patch({ content: assistant.content + token }),\n },\n { signal: abort.signal },\n );\n if (streamError !== undefined) {\n fail(streamError);\n } else if (assistant.pending) {\n patch({ pending: false });\n }\n } else {\n applyFinal(await http.request<LtAiResponse>('POST', '/prompt', input, { signal: abort.signal }));\n }\n } catch (caught) {\n // A user-initiated stop() is no error: keep the streamed content and show no message.\n if (isLtAiAbortError(caught)) {\n patch({ pending: false });\n } else {\n fail(ltAiErrorMessage(caught));\n }\n } finally {\n if (isCurrent()) {\n controller = undefined;\n busy = false;\n streaming.set(false);\n }\n }\n }\n\n /** Send a new user message and stream the assistant's answer; ignored while a turn runs or for blank input. */\n async function send(content: string): Promise<void> {\n const text = content.trim();\n if (!text || busy) {\n return;\n }\n lastPrompt = text;\n push({ content: text, createdAt: new Date().toISOString(), role: 'user' });\n await runTurn(buildInput(text, false));\n }\n\n /** Confirm the last turn that requires confirmation (re-runs its prompt with `confirm: true`). */\n async function confirm(): Promise<void> {\n if (!requiresConfirmation() || !lastPrompt || busy) {\n return;\n }\n await runTurn(buildInput(lastPrompt, true));\n }\n\n /** Abort the running turn; its streamed content stays. */\n function stop(): void {\n controller?.abort();\n controller = undefined;\n if (busy) {\n // Detach the aborted turn, so a new send() is possible right away and the old turn cannot reset the state.\n turnSequence++;\n busy = false;\n streaming.set(false);\n }\n }\n\n /** Clear the local history and abort a running turn (the server-side conversation stays). */\n function clear(): void {\n stop();\n messages.set([]);\n budget.set(null);\n contextWindow.set(null);\n error.set(null);\n lastPrompt = '';\n }\n\n inject(DestroyRef).onDestroy(() => stop());\n\n return {\n budget: budget.asReadonly(),\n clear,\n confirm,\n contextWindow: contextWindow.asReadonly(),\n conversationId: conversationId.asReadonly(),\n error: error.asReadonly(),\n messages: messages.asReadonly(),\n requiresConfirmation,\n send,\n stop,\n streaming: streaming.asReadonly(),\n };\n}\n","import { inject, Service } from '@angular/core';\n\nimport { LtAiHttpService } from './ai-http';\nimport type {\n LtAiAdminState,\n LtAiBudgetLimit,\n LtAiConnection,\n LtAiConnectionInput,\n LtAiConnectionPreference,\n LtAiEffectiveSlot,\n LtAiInteraction,\n LtAiPromptHint,\n LtAiPromptHintInput,\n LtAiSlot,\n LtAiSlotInput,\n} from './ai-types';\n\n/**\n * Admin AI endpoints, headless on purpose: every method returns the raw response, no shared loading/error state.\n * ADMIN is enforced server-side (`@Restricted(ADMIN)`). Ids are `encodeURIComponent`-ed.\n */\n@Service()\nexport class LtAiAdminService implements LtAiAdminState {\n private readonly http = inject(LtAiHttpService);\n\n listConnections = () => this.http.request<LtAiConnection[]>('GET', '/connections');\n createConnection = (input: LtAiConnectionInput) => this.http.request<LtAiConnection>('POST', '/connections', input);\n getConnection = (id: string) => this.http.request<LtAiConnection>('GET', `/connections/${encodeURIComponent(id)}`);\n updateConnection = (id: string, input: LtAiConnectionInput) => this.http.request<LtAiConnection>('PUT', `/connections/${encodeURIComponent(id)}`, input);\n deleteConnection = (id: string) => this.http.request<LtAiConnection>('DELETE', `/connections/${encodeURIComponent(id)}`);\n detectCapabilities = (id: string) => this.http.request<LtAiConnection>('POST', `/connections/${encodeURIComponent(id)}/detect-capabilities`);\n listPreferences = () => this.http.request<LtAiConnectionPreference[]>('GET', '/connections/preferences');\n setPreference = (input: LtAiConnectionPreference) => this.http.request<LtAiConnectionPreference>('POST', '/connections/preferences', input);\n deletePreference = (id: string) => this.http.request<LtAiConnectionPreference>('DELETE', `/connections/preferences/${encodeURIComponent(id)}`);\n listBudgetLimits = () => this.http.request<LtAiBudgetLimit[]>('GET', '/budget-limits');\n createBudgetLimit = (input: LtAiBudgetLimit) => this.http.request<LtAiBudgetLimit>('POST', '/budget-limits', input);\n updateBudgetLimit = (id: string, input: LtAiBudgetLimit) => this.http.request<LtAiBudgetLimit>('PUT', `/budget-limits/${encodeURIComponent(id)}`, input);\n deleteBudgetLimit = (id: string) => this.http.request<LtAiBudgetLimit>('DELETE', `/budget-limits/${encodeURIComponent(id)}`);\n listSlots = () => this.http.request<LtAiSlot[]>('GET', '/slots');\n listEffectiveSlots = () => this.http.request<LtAiEffectiveSlot[]>('GET', '/slots/effective');\n createSlot = (input: LtAiSlotInput) => this.http.request<LtAiSlot>('POST', '/slots', input);\n updateSlot = (id: string, input: LtAiSlotInput) => this.http.request<LtAiSlot>('PUT', `/slots/${encodeURIComponent(id)}`, input);\n deleteSlot = (id: string) => this.http.request<LtAiSlot>('DELETE', `/slots/${encodeURIComponent(id)}`);\n resetSlot = (id: string) => this.http.request<boolean>('POST', `/slots/${encodeURIComponent(id)}/reset`);\n listPromptHints = () => this.http.request<LtAiPromptHint[]>('GET', '/prompt-hints');\n createPromptHint = (input: LtAiPromptHintInput) => this.http.request<LtAiPromptHint>('POST', '/prompt-hints', input);\n updatePromptHint = (id: string, input: LtAiPromptHintInput) => this.http.request<LtAiPromptHint>('PUT', `/prompt-hints/${encodeURIComponent(id)}`, input);\n deletePromptHint = (id: string) => this.http.request<LtAiPromptHint>('DELETE', `/prompt-hints/${encodeURIComponent(id)}`);\n listInteractions = () => this.http.request<LtAiInteraction[]>('GET', '/interactions');\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiAvailableConnection, LtAiConnectionsState } from './ai-types';\n\n/**\n * Connections the user may pick (`GET /ai/connections/available`, `POST /ai/connections/select`), the counterpart\n * of `useLtAiConnections()`. `selected` is the connection flagged `selected`; `locked` is true when a mandatory layer\n * applies (any connection flagged `locked`), then the picker should be read-only.\n */\n@Service()\nexport class LtAiConnectionsService implements LtAiConnectionsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiAvailableConnection[]>([]);\n\n readonly connections = this.list.asReadonly();\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly locked = computed(() => this.list().some((connection) => connection.locked));\n readonly selected = computed(() => this.list().find((connection) => connection.selected));\n\n /** Load the available connections; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.list.set((await this.http.request<LtAiAvailableConnection[]>('GET', '/connections/available')) ?? []);\n });\n }\n\n /** Make `connectionId` the user's default; adopts the list the server answers with. Throws (and sets `error`) when refused. */\n async select(connectionId: string): Promise<void> {\n await this.calls.run(async () => {\n this.list.set((await this.http.request<LtAiAvailableConnection[]>('POST', '/connections/select', { connectionId })) ?? []);\n });\n }\n}\n","import { inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPlaceholder, LtAiPlaceholdersState } from './ai-types';\n\n/**\n * Runtime placeholder registry for prompts (`GET /ai/placeholders`), the counterpart of `useLtAiPlaceholders()`, so\n * slot/prompt editors can list the supported `{{placeholders}}` without hard-coding them.\n */\n@Service()\nexport class LtAiPlaceholdersService implements LtAiPlaceholdersState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiPlaceholder[]>([]);\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly placeholders = this.list.asReadonly();\n\n /** Load the registry; a failure sets `error`, empties the list and does not throw. */\n async load(): Promise<void> {\n try {\n await this.calls.run(async () => {\n this.list.set((await this.http.request<LtAiPlaceholder[]>('GET', '/placeholders')) ?? []);\n });\n } catch {\n this.list.set([]);\n }\n }\n}\n","import { inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPrompt, LtAiPromptInput, LtAiPromptsState } from './ai-types';\n\n/**\n * Saved prompts (\"Vorlagen\") of the user and the tenant (`GET/POST /ai/prompts`, `PUT/DELETE /ai/prompts/:id`), the\n * counterpart of `useLtAiPrompts()`. `load()` returns what the user may see (own + tenant), filtered by the server.\n * The list reloads after each mutation; ids are `encodeURIComponent`-ed.\n */\n@Service()\nexport class LtAiPromptsService implements LtAiPromptsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiPrompt[]>([]);\n private loadSequence = 0;\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly prompts = this.list.asReadonly();\n\n /** Load the visible prompts; a failure sets `error`, empties the list and does not throw. Only the latest load is applied. */\n async load(): Promise<void> {\n const sequence = ++this.loadSequence;\n try {\n const prompts = await this.calls.run(() => this.http.request<LtAiPrompt[]>('GET', '/prompts'));\n if (sequence === this.loadSequence) {\n this.list.set(prompts ?? []);\n }\n } catch {\n if (sequence === this.loadSequence) {\n this.list.set([]);\n }\n }\n }\n\n /** Create a prompt and reload the list; throws (and sets `error`) when refused. */\n async create(input: LtAiPromptInput): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('POST', '/prompts', input));\n }\n\n /** Update a prompt and reload the list; throws (and sets `error`) when refused. */\n async update(id: string, input: LtAiPromptInput): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('PUT', `/prompts/${encodeURIComponent(id)}`, input));\n }\n\n /** Delete a prompt and reload the list; throws (and sets `error`) when refused. */\n async remove(id: string): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('DELETE', `/prompts/${encodeURIComponent(id)}`));\n }\n\n private async mutate(call: () => Promise<LtAiPrompt>): Promise<LtAiPrompt> {\n return this.calls.run(async () => {\n const result = await call();\n await this.load();\n return result;\n });\n }\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { isLtAiAbortError, LtAiCallState, ltAiErrorMessage, runLtAiStream } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPromptRunInput, LtAiResponse, LtAiState, LtAiStreamHandlers } from './ai-types';\n\n/**\n * Prompt runs (`POST /ai/prompt`) and the SSE stream (`POST /ai/stream`, events token/action/error/final), the\n * counterpart of `useLtAi()`. Headless: pair it with an own UI or use {@link injectLtAiChat}.\n *\n * Root service: `loading` and `streaming` stay `true` while any call of the kind runs, `error` holds the latest\n * failure (an abort is not one).\n */\n@Service()\nexport class LtAiService implements LtAiState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly streams = signal(0);\n\n /** Message of the latest failed run or stream `error` event. */\n readonly error = this.calls.error;\n /** `true` while a `prompt()` runs. */\n readonly loading = this.calls.loading;\n /** `true` while a `promptStream()` runs. */\n readonly streaming = computed(() => this.streams() > 0);\n\n /** Run a prompt and return the full structured response; rejects (and sets `error`) on a non-2xx answer. */\n async prompt(input: LtAiPromptRunInput): Promise<LtAiResponse> {\n return this.calls.run(() => this.http.request<LtAiResponse>('POST', '/prompt', input));\n }\n\n /**\n * Run a prompt and stream the answer; resolves with the final response, or `undefined` when the backend closes the\n * stream without a `final` event. A stream `error` event sets `error` and calls `handlers.onError` without\n * rejecting. Aborting through `options.signal` rejects with an `AbortError` and leaves `error` untouched.\n *\n * Meant for the browser: during SSR the render waits until the stream ends.\n */\n async promptStream(input: LtAiPromptRunInput, handlers?: LtAiStreamHandlers, options: { signal?: AbortSignal } = {}): Promise<LtAiResponse | undefined> {\n this.streams.update((count) => count + 1);\n this.calls.setError(null);\n try {\n return await runLtAiStream(\n this.http,\n input,\n {\n ...handlers,\n onError: (message) => {\n this.calls.setError(message);\n handlers?.onError?.(message);\n },\n },\n options,\n );\n } catch (error) {\n if (!isLtAiAbortError(error)) {\n this.calls.setError(ltAiErrorMessage(error));\n }\n throw error;\n } finally {\n this.streams.update((count) => Math.max(0, count - 1));\n }\n }\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiSettings, LtAiSettingsInput, LtAiSettingsState } from './ai-types';\n\n/**\n * The user's own AI settings (`GET/PUT /ai/settings`, nest-server >= 12.3.0), the counterpart of `useLtAiSettings()`.\n *\n * The answer is always the setting as it takes effect and is adopted as is. When the server fixes it\n * (`ai.mcp.confirmation.enforced`), `enforced` is true, the switch should be shown disabled, and `update()` is refused\n * with 403 `#LTNS_0609` (the previous value stays).\n */\n@Service()\nexport class LtAiSettingsService implements LtAiSettingsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly current = signal<LtAiSettings | null>(null);\n\n readonly enforced = computed(() => this.current()?.mcpConfirmationEnforced === true);\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly settings = this.current.asReadonly();\n\n /** Load the settings; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.current.set((await this.http.request<LtAiSettings>('GET', '/settings')) ?? null);\n });\n }\n\n /** Store the user's choice and adopt the server's answer; throws (and sets `error`) when refused. */\n async update(input: LtAiSettingsInput): Promise<void> {\n await this.calls.run(async () => {\n this.current.set((await this.http.request<LtAiSettings>('PUT', '/settings', input)) ?? null);\n });\n }\n}\n","import { isPlatformServer } from '@angular/common';\nimport { computed, inject, makeStateKey, PendingTasks, PLATFORM_ID, Service, signal, TransferState } from '@angular/core';\n\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiStatus, LtAiStatusState } from './ai-types';\n\n/** `TransferState` key under which the server hands the AI status to the browser. */\nexport const LT_AI_STATUS_STATE_KEY = makeStateKey<LtAiStatus>('lt-ai-status');\n\n/** Upper bound of the status request, so a hanging API cannot stall every server render. */\nexport const LT_AI_STATUS_TIMEOUT_MS = 5000;\n\nconst INITIAL_STATUS: LtAiStatus = { enabled: false, error: null, loaded: false, mcp: false };\n\n/**\n * Whether the API's AI module is on (`GET /ai/status`, no credentials, 5 s timeout), the counterpart of\n * `useLtAiStatus()`. nest-server answers 200 `{ mcp }` while the module is on and 404 while it is off.\n *\n * One request per app: concurrent `load()` calls share it, a loaded status is not asked again unless `force` is set.\n * On the server the render waits for the answer and the status travels to the browser via `TransferState`, so the\n * browser adopts it without a second request. Sent without credentials: the endpoint is public and the auth-aware\n * fetch would start its 401 handling for nothing.\n *\n * Fails closed: anything but a well-formed 200 leaves `enabled` false. A 404 is an answer (\"AI is off\") and sets no\n * `error`; a network error, a timeout, any other status or a malformed body sets a fixed `error` text, never the raw\n * error message (on the server that may carry the private API URL incl. credentials and ends up in the HTML).\n */\n@Service()\nexport class LtAiStatusService implements LtAiStatusState {\n private readonly http = inject(LtAiHttpService);\n private readonly transferState = inject(TransferState);\n private readonly pendingTasks = inject(PendingTasks);\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n private readonly state = signal<LtAiStatus>(this.readTransferred());\n private inflight: Promise<void> | null = null;\n\n readonly enabled = computed(() => this.state().enabled);\n readonly error = computed(() => this.state().error);\n readonly loaded = computed(() => this.state().loaded);\n readonly mcp = computed(() => this.state().mcp);\n\n /** Read the status once per app start; `force` asks again. Never throws. */\n load(options: { force?: boolean } = {}): Promise<void> {\n if (this.state().loaded && !options.force) {\n return Promise.resolve();\n }\n if (this.inflight) {\n return this.inflight;\n }\n const done = this.isServer ? this.pendingTasks.add() : undefined;\n const request = this.fetchStatus()\n .then((status) => {\n this.state.set(status);\n if (this.isServer) {\n this.transferState.set(LT_AI_STATUS_STATE_KEY, status);\n }\n })\n .finally(() => {\n this.inflight = null;\n done?.();\n });\n this.inflight = request;\n return request;\n }\n\n private async fetchStatus(): Promise<LtAiStatus> {\n const failed = (error: string): LtAiStatus => ({ enabled: false, error, loaded: true, mcp: false });\n let response: Response;\n try {\n response = await fetch(this.http.buildUrl('/status'), {\n credentials: 'omit',\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(LT_AI_STATUS_TIMEOUT_MS),\n });\n } catch (error) {\n return failed((error as { name?: unknown } | null)?.name === 'TimeoutError' ? 'AI status request timed out' : 'AI status request failed');\n }\n if (response.status === 404) {\n return { enabled: false, error: null, loaded: true, mcp: false };\n }\n if (!response.ok) {\n return failed(`HTTP ${response.status}`);\n }\n try {\n const body = (await response.json()) as { mcp?: unknown } | null;\n if (typeof body?.mcp === 'boolean') {\n return { enabled: true, error: null, loaded: true, mcp: body.mcp };\n }\n } catch {\n // not JSON, e.g. an HTML page from a misrouted proxy\n }\n return failed('Unexpected AI status response');\n }\n\n private readTransferred(): LtAiStatus {\n const transferred = this.transferState.get<LtAiStatus | null>(LT_AI_STATUS_STATE_KEY, null);\n if (!transferred || transferred.loaded !== true) {\n return INITIAL_STATUS;\n }\n return {\n enabled: transferred.enabled === true,\n error: typeof transferred.error === 'string' ? transferred.error : null,\n loaded: true,\n mcp: transferred.enabled === true && transferred.mcp === true,\n };\n }\n}\n","import { inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiUsageInfo, LtAiUsageState } from './ai-types';\n\n/**\n * Token/prompt usage and budget of user and tenant (`GET /ai/usage`), the counterpart of `useLtAiUsage()`. The compact\n * per-response budget is on every prompt response (see `injectLtAiChat().budget`); this loads the full breakdown.\n */\n@Service()\nexport class LtAiUsageService implements LtAiUsageState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly current = signal<LtAiUsageInfo | null>(null);\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly usage = this.current.asReadonly();\n\n /** Load the usage; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.current.set((await this.http.request<LtAiUsageInfo>('GET', '/usage')) ?? null);\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"lenne.tech-ng-base-ai.mjs","names":[],"sources":["../../../projects/ng-base/ai/src/lib/ai-options.ts","../../../projects/ng-base/ai/src/lib/ai-http.ts","../../../projects/ng-base/ai/src/lib/ai-call-state.ts","../../../projects/ng-base/ai/src/lib/ai-chat.ts","../../../projects/ng-base/ai/src/lib/ai-admin-service.ts","../../../projects/ng-base/ai/src/lib/ai-connections-service.ts","../../../projects/ng-base/ai/src/lib/ai-placeholders-service.ts","../../../projects/ng-base/ai/src/lib/ai-prompts-service.ts","../../../projects/ng-base/ai/src/lib/ai-service.ts","../../../projects/ng-base/ai/src/lib/ai-settings-service.ts","../../../projects/ng-base/ai/src/lib/ai-status-service.ts","../../../projects/ng-base/ai/src/lib/ai-usage-service.ts"],"sourcesContent":["import { inject, InjectionToken, makeEnvironmentProviders, type EnvironmentProviders } from '@angular/core';\nimport { LT_RUNTIME_CONFIG, mergeLtFeatureOptions } from '@lenne.tech/ng-base';\n\n/** Options of `provideLtAi()`; runtime override `NG_PUBLIC_LT_AI_BASE_PATH`. */\nexport interface LtAiOptions {\n /** REST base of the nest-server AI controller (default `/ai`). */\n basePath?: string;\n}\n\nconst LT_AI_INPUT_OPTIONS = new InjectionToken<LtAiOptions>('LT_AI_INPUT_OPTIONS', { factory: () => ({}) });\n\n/** Resolved AI options. */\nexport const LT_AI_OPTIONS = new InjectionToken<Required<LtAiOptions>>('LT_AI_OPTIONS', {\n factory: () => mergeLtFeatureOptions<Required<LtAiOptions>>({ basePath: '/ai' }, inject(LT_AI_INPUT_OPTIONS), inject(LT_RUNTIME_CONFIG, { optional: true })?.lt.ai),\n});\n\n/** AI providers (base path). The AI services work without it with the defaults. */\nexport function provideLtAi(options: LtAiOptions = {}): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: LT_AI_INPUT_OPTIONS, useValue: options }]);\n}\n","import { inject, Service } from '@angular/core';\nimport { LT_FETCH, LtApiUrlService } from '@lenne.tech/ng-base';\n\nimport { LT_AI_OPTIONS } from './ai-options';\nimport type { LtAiStreamEvent } from './ai-types';\n\n/** Maximum length of one SSE line (1 MiB); longer lines abort the stream. */\nexport const LT_AI_SSE_MAX_LINE = 1024 * 1024;\n\n/** HTTP helpers of the AI services (counterpart of `buildLtAiUrl` / `ltAiRequest`). All calls use the auth-aware `LT_FETCH`. */\n@Service()\nexport class LtAiHttpService {\n private readonly api = inject(LtApiUrlService);\n private readonly fetch = inject(LT_FETCH);\n private readonly options = inject(LT_AI_OPTIONS);\n\n /** AI base path (`/ai`). */\n basePath(): string {\n return this.options.basePath;\n }\n\n /** `<api><basePath><path>`. */\n buildUrl(path: string): string {\n return this.api.buildUrl(`${this.options.basePath}${path.startsWith('/') ? path : `/${path}`}`);\n }\n\n /** JSON request (`Accept: application/json`); throws {@link ltAiResponseError} on non-2xx; 204 → `undefined`. */\n async request<T>(method: 'DELETE' | 'GET' | 'POST' | 'PUT', path: string, body?: unknown, options: { signal?: AbortSignal } = {}): Promise<T> {\n const init: RequestInit = { headers: { accept: 'application/json' }, method, signal: options.signal };\n if (body !== undefined) {\n init.body = JSON.stringify(body);\n init.headers = { ...(init.headers as Record<string, string>), 'content-type': 'application/json' };\n }\n const response = await this.fetch(this.buildUrl(path), init);\n if (!response.ok) {\n throw await ltAiResponseError(response);\n }\n if (response.status === 204) {\n return undefined as T;\n }\n const text = await response.text();\n return (text ? JSON.parse(text) : undefined) as T;\n }\n\n /** Raw request for streaming (`POST /ai/stream`). */\n stream(path: string, body: unknown, options: { signal?: AbortSignal } = {}): Promise<Response> {\n return this.fetch(this.buildUrl(path), {\n body: JSON.stringify(body),\n headers: { accept: 'text/event-stream', 'content-type': 'application/json' },\n method: 'POST',\n signal: options.signal,\n });\n }\n}\n\n/** Build an `Error & { status }` from an error response (`message`/`error`, arrays joined, capped at 1 KiB). */\nexport async function ltAiResponseError(response: Response): Promise<Error & { status: number }> {\n let message = `${response.status} ${response.statusText}`.trim();\n try {\n const body = (await response.json()) as { error?: unknown; message?: unknown } | null;\n const raw = body?.message ?? body?.error;\n if (Array.isArray(raw)) {\n message = raw.map(String).join(', ');\n } else if (typeof raw === 'string' && raw) {\n message = raw;\n }\n } catch {\n // keep the status line\n }\n const error = new Error(message.slice(0, 1024)) as Error & { status: number };\n error.status = response.status;\n return error;\n}\n\n/**\n * Parse an SSE response body (`data: {json}` lines) and call `onEvent` per event. Handles chunks split mid-line,\n * ignores non-`data:` lines, `[DONE]` and malformed JSON, throws on lines over 1 MiB; aborting cancels the reader.\n *\n * `options.signal` stops parsing without cancelling the underlying fetch (component-destroy races): the reader is\n * cancelled, also while it waits for the next chunk, and the function resolves without delivering further events.\n * An error thrown by `onEvent` propagates (and cancels the reader); only unparsable payloads are skipped.\n */\nexport async function parseLtAiSseStream(response: Response, onEvent: (event: LtAiStreamEvent) => void, options: { signal?: AbortSignal } = {}): Promise<void> {\n const body = response.body;\n if (!body) {\n throw new Error('AI stream response has no body');\n }\n const signal = options.signal;\n const reader = body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n let finished = false;\n\n const cancel = (): void => {\n reader.cancel().catch(() => undefined);\n };\n const tooLong = (): Error => new Error('AI stream line exceeds maximum allowed size');\n const handleLine = (line: string): void => {\n if (line.length > LT_AI_SSE_MAX_LINE) {\n throw tooLong();\n }\n const trimmed = line.trim();\n if (!trimmed.startsWith('data:')) {\n return;\n }\n const payload = trimmed.slice(5).trim();\n if (!payload || payload === '[DONE]') {\n return;\n }\n let event: LtAiStreamEvent;\n try {\n event = JSON.parse(payload) as LtAiStreamEvent;\n } catch {\n return; // a malformed event line is skipped\n }\n onEvent(event);\n };\n\n signal?.addEventListener('abort', cancel, { once: true });\n try {\n if (signal?.aborted) {\n return;\n }\n for (;;) {\n const { done, value } = await reader.read();\n if (signal?.aborted) {\n return;\n }\n if (done) {\n break;\n }\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n buffer = lines.pop() ?? '';\n for (const line of lines) {\n handleLine(line);\n if (signal?.aborted) {\n return;\n }\n }\n if (buffer.length > LT_AI_SSE_MAX_LINE) {\n throw tooLong();\n }\n }\n buffer += decoder.decode();\n finished = true;\n if (buffer) {\n handleLine(buffer);\n }\n } finally {\n signal?.removeEventListener('abort', cancel);\n if (!finished) {\n cancel();\n }\n reader.releaseLock();\n }\n}\n","import { computed, signal } from '@angular/core';\n\nimport { ltAiResponseError, parseLtAiSseStream, type LtAiHttpService } from './ai-http';\nimport type { LtAiPromptRunInput, LtAiResponse, LtAiStreamHandlers } from './ai-types';\n\n/**\n * Loading/error state shared by the AI services (internal, not part of the public API).\n *\n * `loading` counts the calls in flight, so two overlapping calls of a root service do not switch the flag off while\n * one of them still runs. `error` holds the message of the latest failed call and is cleared when a call starts.\n */\nexport class LtAiCallState {\n private readonly pending = signal(0);\n private readonly lastError = signal<null | string>(null);\n\n /** `true` while at least one call runs. */\n readonly loading = computed(() => this.pending() > 0);\n /** Message of the latest failed call. */\n readonly error = this.lastError.asReadonly();\n\n /** Run `call`; on failure store the message and rethrow. */\n async run<T>(call: () => Promise<T>): Promise<T> {\n this.pending.update((count) => count + 1);\n this.lastError.set(null);\n try {\n return await call();\n } catch (error) {\n this.lastError.set(ltAiErrorMessage(error));\n throw error;\n } finally {\n this.pending.update((count) => Math.max(0, count - 1));\n }\n }\n\n /** Run `call`; on failure store the message and resolve with `undefined` instead of throwing. */\n async runQuietly<T>(call: () => Promise<T>): Promise<T | undefined> {\n try {\n return await this.run(call);\n } catch {\n return undefined;\n }\n }\n\n /** Set the error message directly (stream `error` events). */\n setError(message: null | string): void {\n this.lastError.set(message);\n }\n}\n\n/** Message of a thrown value. */\nexport function ltAiErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Whether `error` is the result of an abort (`AbortController.abort()` without a custom reason). */\nexport function isLtAiAbortError(error: unknown): boolean {\n return (error as { name?: unknown } | null)?.name === 'AbortError';\n}\n\n/**\n * `POST /ai/stream` and dispatch the SSE events to `handlers` (internal; used by `LtAiService` and `injectLtAiChat`).\n *\n * Resolves with the `final` response, or `undefined` when the backend closes the stream without one. A non-2xx answer\n * rejects with {@link ltAiResponseError}; an abort through `options.signal` rejects with the abort reason\n * (an `AbortError` for a plain `abort()`), also when the parser stopped cleanly.\n */\nexport async function runLtAiStream(\n http: LtAiHttpService,\n input: LtAiPromptRunInput,\n handlers: LtAiStreamHandlers | undefined,\n options: { signal?: AbortSignal } = {},\n): Promise<LtAiResponse | undefined> {\n const response = await http.stream('/stream', input, options);\n if (!response.ok) {\n throw await ltAiResponseError(response);\n }\n let final: LtAiResponse | undefined;\n await parseLtAiSseStream(\n response,\n (event) => {\n handlers?.onEvent?.(event);\n switch (event.type) {\n case 'action':\n handlers?.onAction?.(event.action);\n break;\n case 'error':\n handlers?.onError?.(event.message);\n break;\n case 'final':\n final = event.response;\n handlers?.onFinal?.(event.response);\n break;\n case 'token':\n handlers?.onToken?.(event.token);\n break;\n }\n },\n options,\n );\n if (options.signal?.aborted) {\n throw abortReason(options.signal);\n }\n return final;\n}\n\nfunction abortReason(signal: AbortSignal): unknown {\n const reason: unknown = signal.reason;\n if (reason instanceof Error || (typeof DOMException !== 'undefined' && reason instanceof DOMException)) {\n return reason;\n }\n const error = new Error('The operation was aborted.');\n error.name = 'AbortError';\n return error;\n}\n","import { assertInInjectionContext, computed, DestroyRef, inject, isSignal, linkedSignal, signal } from '@angular/core';\n\nimport { isLtAiAbortError, ltAiErrorMessage, runLtAiStream } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiBudgetSummary, LtAiChatOptions, LtAiChatState, LtAiMessage, LtAiPromptRunInput, LtAiResponse } from './ai-types';\n\n/** A chat session created by {@link injectLtAiChat}. */\nexport type LtAiChat = LtAiChatState;\n\n/**\n * Create a chat session (counterpart of `useLtAiChat()`), bound to the current injection context: a running stream is\n * stopped on destroy. Streams by default; `send` is ignored while a turn runs; `confirm()` re-sends the last prompt with\n * `confirm: true`; abort is not an error; `maxMessages` trims the oldest messages.\n *\n * Every chat has its own state (messages, conversation, budget, streaming); it does not share `LtAiService`'s signals.\n * A stream `error` event marks the assistant turn as failed and sets `error`, like a failed request.\n *\n * @example\n * protected readonly chat = injectLtAiChat({ connectionId: this.connectionId, metadata: () => ({ url: location.href }) });\n */\nexport function injectLtAiChat(options: LtAiChatOptions = {}): LtAiChat {\n assertInInjectionContext(injectLtAiChat);\n const http = inject(LtAiHttpService);\n\n const messages = signal<LtAiMessage[]>([]);\n // Follows a signal option (a new conversation selected outside) and keeps the id the server assigns.\n const conversationId = linkedSignal<string | undefined>(() => (isSignal(options.conversationId) ? options.conversationId() : options.conversationId));\n const budget = signal<LtAiBudgetSummary | null>(null);\n const contextWindow = signal<{ total: number; used: number } | null>(null);\n const error = signal<null | string>(null);\n const streaming = signal(false);\n let busy = false;\n let turnSequence = 0;\n let controller: AbortController | undefined;\n let lastPrompt = '';\n\n const requiresConfirmation = computed(() => {\n const list = messages();\n const last = list[list.length - 1];\n return !!last && last.role === 'assistant' && !!last.requiresConfirmation;\n });\n\n function resolveConnectionId(): string | undefined {\n const value = options.connectionId;\n return (isSignal(value) ? value() : value) || undefined;\n }\n\n function push(message: LtAiMessage): void {\n messages.update((list) => {\n const next = [...list, message];\n return options.maxMessages && options.maxMessages > 0 && next.length > options.maxMessages ? next.slice(next.length - options.maxMessages) : next;\n });\n }\n\n function buildInput(prompt: string, confirm: boolean): LtAiPromptRunInput {\n const input: LtAiPromptRunInput = {\n connectionId: resolveConnectionId(),\n conversationId: conversationId(),\n metadata: options.metadata?.(),\n mode: isSignal(options.mode) ? options.mode() : options.mode,\n prompt,\n };\n if (confirm) {\n input.confirm = true;\n }\n return input;\n }\n\n /** Run one assistant turn, streaming into a new message. */\n async function runTurn(input: LtAiPromptRunInput): Promise<void> {\n const turn = ++turnSequence;\n const isCurrent = (): boolean => turn === turnSequence;\n error.set(null);\n let assistant: LtAiMessage = { content: '', createdAt: new Date().toISOString(), pending: true, role: 'assistant' };\n push(assistant);\n // Messages are immutable: every change replaces the element, a cleared or trimmed turn is no longer found.\n const patch = (changes: Partial<LtAiMessage>): void => {\n const previous = assistant;\n assistant = { ...previous, ...changes };\n const next = assistant;\n messages.update((list) => (list.includes(previous) ? list.map((message) => (message === previous ? next : message)) : list));\n };\n const applyFinal = (response: LtAiResponse): void => {\n patch({\n actions: response.actions,\n budget: response.budget,\n content: response.text || assistant.content,\n denied: response.denied,\n pending: false,\n pendingActions: response.pendingActions,\n requiresConfirmation: response.requiresConfirmation,\n });\n if (!isCurrent()) {\n return;\n }\n if (response.budget) {\n budget.set(response.budget);\n }\n if (response.contextWindow) {\n contextWindow.set(response.contextWindow);\n }\n if (response.conversationId) {\n conversationId.set(response.conversationId);\n }\n };\n const fail = (message: string): void => {\n patch({ content: assistant.content || message, error: true, pending: false });\n if (isCurrent()) {\n error.set(message);\n }\n };\n\n const abort = new AbortController();\n controller = abort;\n busy = true;\n const stream = options.stream !== false;\n streaming.set(stream);\n try {\n if (stream) {\n let streamError: string | undefined;\n // applyFinal runs from onFinal, so budget/contextWindow/conversationId update the moment the event arrives.\n await runLtAiStream(\n http,\n input,\n {\n onError: (message) => (streamError = message),\n onFinal: applyFinal,\n onToken: (token) => patch({ content: assistant.content + token }),\n },\n { signal: abort.signal },\n );\n if (streamError !== undefined) {\n fail(streamError);\n } else if (assistant.pending) {\n patch({ pending: false });\n }\n } else {\n applyFinal(await http.request<LtAiResponse>('POST', '/prompt', input, { signal: abort.signal }));\n }\n } catch (caught) {\n // A user-initiated stop() is no error: keep the streamed content and show no message.\n if (isLtAiAbortError(caught)) {\n patch({ pending: false });\n } else {\n fail(ltAiErrorMessage(caught));\n }\n } finally {\n if (isCurrent()) {\n controller = undefined;\n busy = false;\n streaming.set(false);\n }\n }\n }\n\n /** Send a new user message and stream the assistant's answer; ignored while a turn runs or for blank input. */\n async function send(content: string): Promise<void> {\n const text = content.trim();\n if (!text || busy) {\n return;\n }\n lastPrompt = text;\n push({ content: text, createdAt: new Date().toISOString(), role: 'user' });\n await runTurn(buildInput(text, false));\n }\n\n /** Confirm the last turn that requires confirmation (re-runs its prompt with `confirm: true`). */\n async function confirm(): Promise<void> {\n if (!requiresConfirmation() || !lastPrompt || busy) {\n return;\n }\n await runTurn(buildInput(lastPrompt, true));\n }\n\n /** Abort the running turn; its streamed content stays. */\n function stop(): void {\n controller?.abort();\n controller = undefined;\n if (busy) {\n // Detach the aborted turn, so a new send() is possible right away and the old turn cannot reset the state.\n turnSequence++;\n busy = false;\n streaming.set(false);\n }\n }\n\n /** Clear the local history and abort a running turn (the server-side conversation stays). */\n function clear(): void {\n stop();\n messages.set([]);\n budget.set(null);\n contextWindow.set(null);\n error.set(null);\n lastPrompt = '';\n }\n\n inject(DestroyRef).onDestroy(() => stop());\n\n return {\n budget: budget.asReadonly(),\n clear,\n confirm,\n contextWindow: contextWindow.asReadonly(),\n conversationId: conversationId.asReadonly(),\n error: error.asReadonly(),\n messages: messages.asReadonly(),\n requiresConfirmation,\n send,\n stop,\n streaming: streaming.asReadonly(),\n };\n}\n","import { inject, Service } from '@angular/core';\n\nimport { LtAiHttpService } from './ai-http';\nimport type {\n LtAiAdminState,\n LtAiBudgetLimit,\n LtAiConnection,\n LtAiConnectionInput,\n LtAiConnectionPreference,\n LtAiEffectiveSlot,\n LtAiInteraction,\n LtAiPromptHint,\n LtAiPromptHintInput,\n LtAiSlot,\n LtAiSlotInput,\n} from './ai-types';\n\n/**\n * Admin AI endpoints, headless on purpose: every method returns the raw response, no shared loading/error state.\n * ADMIN is enforced server-side (`@Restricted(ADMIN)`). Ids are `encodeURIComponent`-ed.\n */\n@Service()\nexport class LtAiAdminService implements LtAiAdminState {\n private readonly http = inject(LtAiHttpService);\n\n listConnections = () => this.http.request<LtAiConnection[]>('GET', '/connections');\n createConnection = (input: LtAiConnectionInput) => this.http.request<LtAiConnection>('POST', '/connections', input);\n getConnection = (id: string) => this.http.request<LtAiConnection>('GET', `/connections/${encodeURIComponent(id)}`);\n updateConnection = (id: string, input: LtAiConnectionInput) => this.http.request<LtAiConnection>('PUT', `/connections/${encodeURIComponent(id)}`, input);\n deleteConnection = (id: string) => this.http.request<LtAiConnection>('DELETE', `/connections/${encodeURIComponent(id)}`);\n detectCapabilities = (id: string) => this.http.request<LtAiConnection>('POST', `/connections/${encodeURIComponent(id)}/detect-capabilities`);\n listPreferences = () => this.http.request<LtAiConnectionPreference[]>('GET', '/connections/preferences');\n setPreference = (input: LtAiConnectionPreference) => this.http.request<LtAiConnectionPreference>('POST', '/connections/preferences', input);\n deletePreference = (id: string) => this.http.request<LtAiConnectionPreference>('DELETE', `/connections/preferences/${encodeURIComponent(id)}`);\n listBudgetLimits = () => this.http.request<LtAiBudgetLimit[]>('GET', '/budget-limits');\n createBudgetLimit = (input: LtAiBudgetLimit) => this.http.request<LtAiBudgetLimit>('POST', '/budget-limits', input);\n updateBudgetLimit = (id: string, input: LtAiBudgetLimit) => this.http.request<LtAiBudgetLimit>('PUT', `/budget-limits/${encodeURIComponent(id)}`, input);\n deleteBudgetLimit = (id: string) => this.http.request<LtAiBudgetLimit>('DELETE', `/budget-limits/${encodeURIComponent(id)}`);\n listSlots = () => this.http.request<LtAiSlot[]>('GET', '/slots');\n listEffectiveSlots = () => this.http.request<LtAiEffectiveSlot[]>('GET', '/slots/effective');\n createSlot = (input: LtAiSlotInput) => this.http.request<LtAiSlot>('POST', '/slots', input);\n updateSlot = (id: string, input: LtAiSlotInput) => this.http.request<LtAiSlot>('PUT', `/slots/${encodeURIComponent(id)}`, input);\n deleteSlot = (id: string) => this.http.request<LtAiSlot>('DELETE', `/slots/${encodeURIComponent(id)}`);\n resetSlot = (id: string) => this.http.request<boolean>('POST', `/slots/${encodeURIComponent(id)}/reset`);\n listPromptHints = () => this.http.request<LtAiPromptHint[]>('GET', '/prompt-hints');\n createPromptHint = (input: LtAiPromptHintInput) => this.http.request<LtAiPromptHint>('POST', '/prompt-hints', input);\n updatePromptHint = (id: string, input: LtAiPromptHintInput) => this.http.request<LtAiPromptHint>('PUT', `/prompt-hints/${encodeURIComponent(id)}`, input);\n deletePromptHint = (id: string) => this.http.request<LtAiPromptHint>('DELETE', `/prompt-hints/${encodeURIComponent(id)}`);\n listInteractions = () => this.http.request<LtAiInteraction[]>('GET', '/interactions');\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiAvailableConnection, LtAiConnectionsState } from './ai-types';\n\n/**\n * Connections the user may pick (`GET /ai/connections/available`, `POST /ai/connections/select`), the counterpart\n * of `useLtAiConnections()`. `selected` is the connection flagged `selected`; `locked` is true when a mandatory layer\n * applies (any connection flagged `locked`), then the picker should be read-only.\n */\n@Service()\nexport class LtAiConnectionsService implements LtAiConnectionsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiAvailableConnection[]>([]);\n\n readonly connections = this.list.asReadonly();\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly locked = computed(() => this.list().some((connection) => connection.locked));\n readonly selected = computed(() => this.list().find((connection) => connection.selected));\n\n /** Load the available connections; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.list.set((await this.http.request<LtAiAvailableConnection[]>('GET', '/connections/available')) ?? []);\n });\n }\n\n /** Make `connectionId` the user's default; adopts the list the server answers with. Throws (and sets `error`) when refused. */\n async select(connectionId: string): Promise<void> {\n await this.calls.run(async () => {\n this.list.set((await this.http.request<LtAiAvailableConnection[]>('POST', '/connections/select', { connectionId })) ?? []);\n });\n }\n}\n","import { inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPlaceholder, LtAiPlaceholdersState } from './ai-types';\n\n/**\n * Runtime placeholder registry for prompts (`GET /ai/placeholders`), the counterpart of `useLtAiPlaceholders()`, so\n * slot/prompt editors can list the supported `{{placeholders}}` without hard-coding them.\n */\n@Service()\nexport class LtAiPlaceholdersService implements LtAiPlaceholdersState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiPlaceholder[]>([]);\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly placeholders = this.list.asReadonly();\n\n /** Load the registry; a failure sets `error`, empties the list and does not throw. */\n async load(): Promise<void> {\n try {\n await this.calls.run(async () => {\n this.list.set((await this.http.request<LtAiPlaceholder[]>('GET', '/placeholders')) ?? []);\n });\n } catch {\n this.list.set([]);\n }\n }\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPrompt, LtAiPromptInput, LtAiPromptsLoadOptions, LtAiPromptsState } from './ai-types';\n\n/**\n * Saved prompts (\"Vorlagen\") of the user and the tenant (`GET/POST /ai/prompts`, `PUT/DELETE /ai/prompts/:id`), the\n * counterpart of `useLtAiPrompts()`. `load()` returns what the user may see (own + tenant), filtered by the server;\n * `load({ includeDisabled: true })` adds the disabled ones for the management page (`GET /ai/prompts?includeDisabled=true`,\n * nest-server 12.7.0; older servers ignore the parameter). The list reloads after each mutation in the mode of the last\n * load; ids are `encodeURIComponent`-ed. The service is a root singleton, so a chat picker should read\n * {@link enabledPrompts}, which stays correct while a management page holds the list with disabled prompts.\n */\n@Service()\nexport class LtAiPromptsService implements LtAiPromptsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly list = signal<LtAiPrompt[]>([]);\n private loadSequence = 0;\n private includeDisabled = false;\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly prompts = this.list.asReadonly();\n /** The prompts a chat may offer: `prompts` without the disabled ones (`enabled: false`). */\n readonly enabledPrompts = computed(() => this.list().filter((prompt) => prompt.enabled !== false));\n\n /**\n * Load the visible prompts (with `includeDisabled` also the disabled ones); a failure sets `error`, empties the list\n * and does not throw. Only the latest load is applied.\n */\n async load(options: LtAiPromptsLoadOptions = {}): Promise<void> {\n const sequence = ++this.loadSequence;\n this.includeDisabled = options.includeDisabled === true;\n const path = this.includeDisabled ? '/prompts?includeDisabled=true' : '/prompts';\n try {\n const prompts = await this.calls.run(() => this.http.request<LtAiPrompt[]>('GET', path));\n if (sequence === this.loadSequence) {\n this.list.set(prompts ?? []);\n }\n } catch {\n if (sequence === this.loadSequence) {\n this.list.set([]);\n }\n }\n }\n\n /** Create a prompt and reload the list; throws (and sets `error`) when refused. */\n async create(input: LtAiPromptInput): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('POST', '/prompts', input));\n }\n\n /** Update a prompt and reload the list; throws (and sets `error`) when refused. */\n async update(id: string, input: LtAiPromptInput): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('PUT', `/prompts/${encodeURIComponent(id)}`, input));\n }\n\n /** Delete a prompt and reload the list; throws (and sets `error`) when refused. */\n async remove(id: string): Promise<LtAiPrompt> {\n return this.mutate(() => this.http.request<LtAiPrompt>('DELETE', `/prompts/${encodeURIComponent(id)}`));\n }\n\n private async mutate(call: () => Promise<LtAiPrompt>): Promise<LtAiPrompt> {\n return this.calls.run(async () => {\n const result = await call();\n await this.load({ includeDisabled: this.includeDisabled });\n return result;\n });\n }\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { isLtAiAbortError, LtAiCallState, ltAiErrorMessage, runLtAiStream } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiPromptRunInput, LtAiResponse, LtAiState, LtAiStreamHandlers } from './ai-types';\n\n/**\n * Prompt runs (`POST /ai/prompt`) and the SSE stream (`POST /ai/stream`, events token/action/error/final), the\n * counterpart of `useLtAi()`. Headless: pair it with an own UI or use {@link injectLtAiChat}.\n *\n * Root service: `loading` and `streaming` stay `true` while any call of the kind runs, `error` holds the latest\n * failure (an abort is not one).\n */\n@Service()\nexport class LtAiService implements LtAiState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly streams = signal(0);\n\n /** Message of the latest failed run or stream `error` event. */\n readonly error = this.calls.error;\n /** `true` while a `prompt()` runs. */\n readonly loading = this.calls.loading;\n /** `true` while a `promptStream()` runs. */\n readonly streaming = computed(() => this.streams() > 0);\n\n /** Run a prompt and return the full structured response; rejects (and sets `error`) on a non-2xx answer. */\n async prompt(input: LtAiPromptRunInput): Promise<LtAiResponse> {\n return this.calls.run(() => this.http.request<LtAiResponse>('POST', '/prompt', input));\n }\n\n /**\n * Run a prompt and stream the answer; resolves with the final response, or `undefined` when the backend closes the\n * stream without a `final` event. A stream `error` event sets `error` and calls `handlers.onError` without\n * rejecting. Aborting through `options.signal` rejects with an `AbortError` and leaves `error` untouched.\n *\n * Meant for the browser: during SSR the render waits until the stream ends.\n */\n async promptStream(input: LtAiPromptRunInput, handlers?: LtAiStreamHandlers, options: { signal?: AbortSignal } = {}): Promise<LtAiResponse | undefined> {\n this.streams.update((count) => count + 1);\n this.calls.setError(null);\n try {\n return await runLtAiStream(\n this.http,\n input,\n {\n ...handlers,\n onError: (message) => {\n this.calls.setError(message);\n handlers?.onError?.(message);\n },\n },\n options,\n );\n } catch (error) {\n if (!isLtAiAbortError(error)) {\n this.calls.setError(ltAiErrorMessage(error));\n }\n throw error;\n } finally {\n this.streams.update((count) => Math.max(0, count - 1));\n }\n }\n}\n","import { computed, inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiSettings, LtAiSettingsInput, LtAiSettingsState } from './ai-types';\n\n/**\n * The user's own AI settings (`GET/PUT /ai/settings`, nest-server >= 12.3.0), the counterpart of `useLtAiSettings()`.\n *\n * The answer is always the setting as it takes effect and is adopted as is. When the server fixes it\n * (`ai.mcp.confirmation.enforced`), `enforced` is true, the switch should be shown disabled, and `update()` is refused\n * with 403 `#LTNS_0609` (the previous value stays).\n */\n@Service()\nexport class LtAiSettingsService implements LtAiSettingsState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly current = signal<LtAiSettings | null>(null);\n\n readonly enforced = computed(() => this.current()?.mcpConfirmationEnforced === true);\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly settings = this.current.asReadonly();\n\n /** Load the settings; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.current.set((await this.http.request<LtAiSettings>('GET', '/settings')) ?? null);\n });\n }\n\n /** Store the user's choice and adopt the server's answer; throws (and sets `error`) when refused. */\n async update(input: LtAiSettingsInput): Promise<void> {\n await this.calls.run(async () => {\n this.current.set((await this.http.request<LtAiSettings>('PUT', '/settings', input)) ?? null);\n });\n }\n}\n","import { isPlatformServer } from '@angular/common';\nimport { computed, inject, makeStateKey, PendingTasks, PLATFORM_ID, Service, signal, TransferState } from '@angular/core';\n\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiStatus, LtAiStatusState } from './ai-types';\n\n/** `TransferState` key under which the server hands the AI status to the browser. */\nexport const LT_AI_STATUS_STATE_KEY = makeStateKey<LtAiStatus>('lt-ai-status');\n\n/** Upper bound of the status request, so a hanging API cannot stall every server render. */\nexport const LT_AI_STATUS_TIMEOUT_MS = 5000;\n\nconst INITIAL_STATUS: LtAiStatus = { enabled: false, error: null, loaded: false, mcp: false };\n\n/**\n * Whether the API's AI module is on (`GET /ai/status`, no credentials, 5 s timeout), the counterpart of\n * `useLtAiStatus()`. nest-server answers 200 `{ mcp }` while the module is on and 404 while it is off.\n *\n * One request per app: concurrent `load()` calls share it, a loaded status is not asked again unless `force` is set.\n * On the server the render waits for the answer and the status travels to the browser via `TransferState`, so the\n * browser adopts it without a second request. Sent without credentials: the endpoint is public and the auth-aware\n * fetch would start its 401 handling for nothing.\n *\n * Fails closed: anything but a well-formed 200 leaves `enabled` false. A 404 is an answer (\"AI is off\") and sets no\n * `error`; a network error, a timeout, any other status or a malformed body sets a fixed `error` text, never the raw\n * error message (on the server that may carry the private API URL incl. credentials and ends up in the HTML).\n */\n@Service()\nexport class LtAiStatusService implements LtAiStatusState {\n private readonly http = inject(LtAiHttpService);\n private readonly transferState = inject(TransferState);\n private readonly pendingTasks = inject(PendingTasks);\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n private readonly state = signal<LtAiStatus>(this.readTransferred());\n private inflight: Promise<void> | null = null;\n\n readonly enabled = computed(() => this.state().enabled);\n readonly error = computed(() => this.state().error);\n readonly loaded = computed(() => this.state().loaded);\n readonly mcp = computed(() => this.state().mcp);\n\n /** Read the status once per app start; `force` asks again. Never throws. */\n load(options: { force?: boolean } = {}): Promise<void> {\n if (this.state().loaded && !options.force) {\n return Promise.resolve();\n }\n if (this.inflight) {\n return this.inflight;\n }\n const done = this.isServer ? this.pendingTasks.add() : undefined;\n const request = this.fetchStatus()\n .then((status) => {\n this.state.set(status);\n if (this.isServer) {\n this.transferState.set(LT_AI_STATUS_STATE_KEY, status);\n }\n })\n .finally(() => {\n this.inflight = null;\n done?.();\n });\n this.inflight = request;\n return request;\n }\n\n private async fetchStatus(): Promise<LtAiStatus> {\n const failed = (error: string): LtAiStatus => ({ enabled: false, error, loaded: true, mcp: false });\n let response: Response;\n try {\n response = await fetch(this.http.buildUrl('/status'), {\n credentials: 'omit',\n headers: { accept: 'application/json' },\n signal: AbortSignal.timeout(LT_AI_STATUS_TIMEOUT_MS),\n });\n } catch (error) {\n return failed((error as { name?: unknown } | null)?.name === 'TimeoutError' ? 'AI status request timed out' : 'AI status request failed');\n }\n if (response.status === 404) {\n return { enabled: false, error: null, loaded: true, mcp: false };\n }\n if (!response.ok) {\n return failed(`HTTP ${response.status}`);\n }\n try {\n const body = (await response.json()) as { mcp?: unknown } | null;\n if (typeof body?.mcp === 'boolean') {\n return { enabled: true, error: null, loaded: true, mcp: body.mcp };\n }\n } catch {\n // not JSON, e.g. an HTML page from a misrouted proxy\n }\n return failed('Unexpected AI status response');\n }\n\n private readTransferred(): LtAiStatus {\n const transferred = this.transferState.get<LtAiStatus | null>(LT_AI_STATUS_STATE_KEY, null);\n if (!transferred || transferred.loaded !== true) {\n return INITIAL_STATUS;\n }\n return {\n enabled: transferred.enabled === true,\n error: typeof transferred.error === 'string' ? transferred.error : null,\n loaded: true,\n mcp: transferred.enabled === true && transferred.mcp === true,\n };\n }\n}\n","import { inject, Service, signal } from '@angular/core';\n\nimport { LtAiCallState } from './ai-call-state';\nimport { LtAiHttpService } from './ai-http';\nimport type { LtAiUsageInfo, LtAiUsageState } from './ai-types';\n\n/**\n * Token/prompt usage and budget of user and tenant (`GET /ai/usage`), the counterpart of `useLtAiUsage()`. The compact\n * per-response budget is on every prompt response (see `injectLtAiChat().budget`); this loads the full breakdown.\n */\n@Service()\nexport class LtAiUsageService implements LtAiUsageState {\n private readonly http = inject(LtAiHttpService);\n private readonly calls = new LtAiCallState();\n private readonly current = signal<LtAiUsageInfo | null>(null);\n\n readonly error = this.calls.error;\n readonly loading = this.calls.loading;\n readonly usage = this.current.asReadonly();\n\n /** Load the usage; a failure sets `error` and does not throw. */\n async load(): Promise<void> {\n await this.calls.runQuietly(async () => {\n this.current.set((await this.http.request<LtAiUsageInfo>('GET', '/usage')) ?? null);\n });\n }\n}\n"],"mappings":"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"}
@@ -106,7 +106,13 @@ var LtAuthStateService = class LtAuthStateService {
106
106
  let invalid = false;
107
107
  for (const raw of this.cookies.getAll(this.cookieNames.token)) {
108
108
  const token = parseToken(raw);
109
- if (isLtJwtShaped(token)) return token;
109
+ if (isLtJwtShaped(token)) {
110
+ if (raw !== token) {
111
+ this.deleteEverywhere(this.cookieNames.token);
112
+ this.cookies.set(this.cookieNames.token, token, { maxAge: LT_AUTH_COOKIE_MAX_AGE });
113
+ }
114
+ return token;
115
+ }
110
116
  invalid ||= !!token;
111
117
  }
112
118
  if (invalid) this.deleteEverywhere(this.cookieNames.token);
@@ -123,7 +129,7 @@ var LtAuthStateService = class LtAuthStateService {
123
129
  console.warn("[@lenne.tech/ng-base] Refused to store a token that is not a JWT as JWT.");
124
130
  return false;
125
131
  }
126
- this.cookies.set(this.cookieNames.token, JSON.stringify(token), { maxAge: LT_AUTH_COOKIE_MAX_AGE });
132
+ this.cookies.set(this.cookieNames.token, token, { maxAge: LT_AUTH_COOKIE_MAX_AGE });
127
133
  return true;
128
134
  }
129
135
  purgeInvalidJwt() {