@123toto/ai-app-assistant-server 0.2.0 → 0.2.1

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
@@ -44,6 +44,7 @@ import { createManagedAiAppAssistantServer } from "@123toto/ai-app-assistant-ser
44
44
 
45
45
  const aiAppAssistant = createManagedAiAppAssistantServer({
46
46
  configuration: {
47
+ enabled: process.env.AI_APP_ASSISTANT_LLM_ENABLED === "true",
47
48
  storage: { type: "redis", client: redis },
48
49
  encryptionKey: process.env.AI_APP_ASSISTANT_SECRET_ENCRYPTION_KEY!,
49
50
  defaultConfiguration: {
@@ -63,6 +64,9 @@ const aiAppAssistant = createManagedAiAppAssistantServer({
63
64
  await aiAppAssistant.initialize();
64
65
  ```
65
66
 
67
+ `enabled: false` disables every provider operation while keeping the host
68
+ application and the read-only administration endpoints available.
69
+
66
70
  Documents may also be loaded after application bootstrap with `aiAppAssistant.setDocuments(documents)`.
67
71
 
68
72
  ## Framework connectors
@@ -1,4 +1,4 @@
1
- import { M as ManagedAiAppAssistantServer } from './managed-server-CthTKEQ6.cjs';
1
+ import { M as ManagedAiAppAssistantServer } from './managed-server-CQb-RK-i.cjs';
2
2
  import './ai-sdk-qU3KgNu-.cjs';
3
3
  import 'ai';
4
4
  import '@123toto/ai-app-assistant-contracts';
package/dist/express.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { M as ManagedAiAppAssistantServer } from './managed-server-BGQ-1jkx.js';
1
+ import { M as ManagedAiAppAssistantServer } from './managed-server-CGmvVYsF.js';
2
2
  import './ai-sdk-qU3KgNu-.js';
3
3
  import 'ai';
4
4
  import '@123toto/ai-app-assistant-contracts';
package/dist/index.cjs CHANGED
@@ -1609,12 +1609,17 @@ var AiAppAssistantConfigurationManager = class {
1609
1609
  this.#repository = options.repository;
1610
1610
  this.#quotaStore = options.quotaStore ?? createMemoryAiAppAssistantQuotaStore();
1611
1611
  }
1612
+ /** Returns the current state of the host-controlled global kill switch. */
1613
+ isEnabled() {
1614
+ return typeof this.#options.enabled === "function" ? this.#options.enabled() : this.#options.enabled ?? true;
1615
+ }
1612
1616
  /** Returns the built-in provider catalogue; no credentials are exposed. */
1613
1617
  listProviders() {
1614
1618
  return listAiProviders();
1615
1619
  }
1616
1620
  /** Discovers models with an explicit key or the currently configured secret. */
1617
1621
  async listModels(input) {
1622
+ this.assertEnabled();
1618
1623
  const apiKey = await this.resolveApiKey(input.provider, input.apiKey);
1619
1624
  if (this.#options.listModels) {
1620
1625
  return this.#options.listModels({ ...input, ...apiKey ? { apiKey } : {} });
@@ -1640,7 +1645,10 @@ var AiAppAssistantConfigurationManager = class {
1640
1645
  let connected = event.connectionValidated;
1641
1646
  if (event.reloadRequired) {
1642
1647
  this.#recentConnectionValidation = void 0;
1643
- if (connected) {
1648
+ if (!this.isEnabled()) {
1649
+ connected = false;
1650
+ this.#runtimeConnection = { status: "disabled", checkedAt: this.now() };
1651
+ } else if (connected) {
1644
1652
  const configuration = await this.getRuntimeConfiguration();
1645
1653
  this.#runtimeConnection = configuration ? {
1646
1654
  status: "connected",
@@ -1670,6 +1678,7 @@ var AiAppAssistantConfigurationManager = class {
1670
1678
  }
1671
1679
  /** Tests credentials and briefly caches a successful result for the next save. */
1672
1680
  async testConnection(input) {
1681
+ this.assertEnabled();
1673
1682
  const apiKey = await this.resolveApiKey(input.provider, input.apiKey);
1674
1683
  const connection = this.#options.testConnection ? await this.#options.testConnection({ ...input, ...apiKey ? { apiKey } : {} }) : await testAiSdkConnection({
1675
1684
  model: `${input.provider}:${input.model}`,
@@ -1698,6 +1707,10 @@ var AiAppAssistantConfigurationManager = class {
1698
1707
  /** Checks the effective stored/deployment connection used by live questions. */
1699
1708
  async validateRuntimeConnection() {
1700
1709
  this.#lastReconnectAttempt = Date.now();
1710
+ if (!this.isEnabled()) {
1711
+ this.#runtimeConnection = { status: "disabled", checkedAt: this.now() };
1712
+ return false;
1713
+ }
1701
1714
  const configuration = await this.getRuntimeConfiguration();
1702
1715
  if (!configuration || configuration.provider !== "ollama" && !configuration.apiKey) {
1703
1716
  this.#runtimeConnection = {
@@ -1740,6 +1753,7 @@ var AiAppAssistantConfigurationManager = class {
1740
1753
  const initialActive = this.effectiveConfiguration(initial);
1741
1754
  const initialApiKey = input.apiKey ?? (initialActive?.provider === input.provider ? initialActive.apiKey : void 0) ?? this.resolveDefaultApiKey(input.provider);
1742
1755
  const initialConnectionChanged = connectionChanged(initialActive, input);
1756
+ if (!this.isEnabled() && initialConnectionChanged) throw disabled();
1743
1757
  let connection = initialConnectionChanged ? await this.validateConnectionForSave(input, initialApiKey) : this.lastKnownConnection(input.provider, input.model);
1744
1758
  if (initialConnectionChanged && !connection.success) {
1745
1759
  return { saved: false, connection, reloadRequired: false };
@@ -1968,6 +1982,7 @@ var AiAppAssistantConfigurationManager = class {
1968
1982
  }
1969
1983
  /** Combines configuration, provider health and application access rules. */
1970
1984
  async canUse(identity) {
1985
+ if (!this.isEnabled()) return false;
1971
1986
  const configuration = await this.getRuntimeConfiguration();
1972
1987
  if (!configuration || configuration.provider !== "ollama" && !configuration.apiKey) return false;
1973
1988
  if (!await this.ensureRuntimeConnection()) return false;
@@ -1986,6 +2001,7 @@ var AiAppAssistantConfigurationManager = class {
1986
2001
  }
1987
2002
  /** Enforces access and quota immediately before any model call. */
1988
2003
  async assertCanAsk(identity) {
2004
+ this.assertEnabled();
1989
2005
  if (!await this.canUse(identity)) {
1990
2006
  throw forbidden("AI assistant access is not enabled for this user");
1991
2007
  }
@@ -2001,6 +2017,7 @@ var AiAppAssistantConfigurationManager = class {
2001
2017
  }
2002
2018
  /** Retries a failed provider lazily, with a shared backoff across requests. */
2003
2019
  async ensureRuntimeConnection() {
2020
+ if (!this.isEnabled()) return false;
2004
2021
  if (this.#runtimeConnection.status === "connected") return true;
2005
2022
  const intervalMs = Math.max(1e3, this.#options.reconnectIntervalMs ?? 3e4);
2006
2023
  if (Date.now() - this.#lastReconnectAttempt < intervalMs) return false;
@@ -2108,6 +2125,9 @@ var AiAppAssistantConfigurationManager = class {
2108
2125
  now() {
2109
2126
  return (this.#options.now?.() ?? /* @__PURE__ */ new Date()).toISOString();
2110
2127
  }
2128
+ assertEnabled() {
2129
+ if (!this.isEnabled()) throw disabled();
2130
+ }
2111
2131
  async publishAndEmit(event) {
2112
2132
  await this.#options.synchronizer?.publish(event);
2113
2133
  await this.emit(event);
@@ -2231,6 +2251,13 @@ function configurationChanges(previous, input, allowModelChangesByOthers) {
2231
2251
  function forbidden(message) {
2232
2252
  return new AiAppAssistantManagementError(403, "forbidden", message);
2233
2253
  }
2254
+ function disabled() {
2255
+ return new AiAppAssistantManagementError(
2256
+ 503,
2257
+ "assistant_disabled",
2258
+ "AI assistant is disabled"
2259
+ );
2260
+ }
2234
2261
 
2235
2262
  // src/telemetry.ts
2236
2263
  function createMemoryAiAppAssistantTelemetryStore(options) {
@@ -2400,6 +2427,11 @@ function createManagedAiAppAssistantRuntime(options) {
2400
2427
  return reloadQueue;
2401
2428
  });
2402
2429
  const rebuild = async (event) => {
2430
+ if (!options.configuration.isEnabled()) {
2431
+ assistant = void 0;
2432
+ activeGenerator = void 0;
2433
+ return;
2434
+ }
2403
2435
  const connected = event.connectionValidated || await options.configuration.validateRuntimeConnection();
2404
2436
  const configuration = await options.configuration.getRuntimeConfiguration();
2405
2437
  if (!connected || !configuration) {