@umituz/web-ai 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -90,6 +90,12 @@ The pieces a backend-proxy chat stack needs, all persistence-free:
90
90
  - `buildUsageDailySeries` / `usageWindowTotals` / `usageTrendOf` /
91
91
  `errorRatePct` — turn sparse SQL day aggregates into zero-filled usage
92
92
  series and dashboard math.
93
+ - `deriveConversationTitle(content, { fallback, maxChars })` — first-line
94
+ title derivation for new conversations (Markdown prefix strip, collapse,
95
+ truncate).
96
+ - `planStuckRecovery(task, now)` / `STUCK_TASK_THRESHOLD_MS` — recovery
97
+ decision for queue rows found stale in `running`; sits next to
98
+ `canStartTask` / `planTaskFailure`.
93
99
 
94
100
  ## Client-side chat over your own backend
95
101
 
@@ -322,6 +322,31 @@ function aiErrorStatus(code) {
322
322
  return AI_ERROR_STATUS[code];
323
323
  }
324
324
 
325
+ // src/core/errors/ai-failure.ts
326
+ var TYPE_TO_CODE = {
327
+ ["INVALID_API_KEY" /* INVALID_API_KEY */]: "invalid_key",
328
+ ["MISSING_CONFIG" /* MISSING_CONFIG */]: "missing_key",
329
+ ["NETWORK_ERROR" /* NETWORK_ERROR */]: "network",
330
+ ["ABORT_ERROR" /* ABORT_ERROR */]: "timeout",
331
+ ["RATE_LIMIT_ERROR" /* RATE_LIMIT_ERROR */]: "rate_limited",
332
+ ["SERVER_ERROR" /* SERVER_ERROR */]: "upstream_error",
333
+ ["CLIENT_ERROR" /* CLIENT_ERROR */]: "invalid_request",
334
+ ["UNKNOWN_ERROR" /* UNKNOWN_ERROR */]: "upstream_error"
335
+ };
336
+ function aiFailureOf(error) {
337
+ if (error instanceof AiError) {
338
+ return { code: error.code, status: AI_ERROR_STATUS[error.code], message: error.userMessage };
339
+ }
340
+ if (error instanceof AIError) {
341
+ const code = TYPE_TO_CODE[error.type];
342
+ return { code, status: AI_ERROR_STATUS[code], message: CODE_MESSAGES[code] };
343
+ }
344
+ if (error instanceof Error && error.name === "AbortError") {
345
+ return { code: "timeout", status: AI_ERROR_STATUS.timeout, message: CODE_MESSAGES.timeout };
346
+ }
347
+ return { code: "upstream_error", status: AI_ERROR_STATUS.upstream_error, message: CODE_MESSAGES.upstream_error };
348
+ }
349
+
325
350
  // src/core/executor/retry-executor.strategy.ts
326
351
  var RetryExecutor = class {
327
352
  constructor(retryManager2, options) {
@@ -935,6 +960,24 @@ function deriveConversationTitle(content, options = {}) {
935
960
  return cleaned.length > maxChars ? `${cleaned.slice(0, maxChars).trimEnd()}\u2026` : cleaned;
936
961
  }
937
962
 
963
+ // src/core/utils/allowance-window.ts
964
+ var DEFAULT_ALLOWANCE_WINDOW_MS = 36e5;
965
+ function createAllowanceWindow(options) {
966
+ const windowMs = options.windowMs ?? DEFAULT_ALLOWANCE_WINDOW_MS;
967
+ const buckets = /* @__PURE__ */ new Map();
968
+ return {
969
+ allow(key, now = Date.now()) {
970
+ const bucket = buckets.get(key);
971
+ if (bucket === void 0 || now - bucket.windowStart >= windowMs) {
972
+ buckets.set(key, { windowStart: now, count: 1 });
973
+ return true;
974
+ }
975
+ bucket.count += 1;
976
+ return bucket.count <= options.limit;
977
+ }
978
+ };
979
+ }
980
+
938
981
  // src/core/constants/protocol.constants.ts
939
982
  var SSE_PREFIX = "data: ";
940
983
  var SSE_DONE_MARKER = "[DONE]";
@@ -2108,6 +2151,7 @@ exports.CODE_MESSAGES = CODE_MESSAGES;
2108
2151
  exports.CacheManager = CacheManager;
2109
2152
  exports.CompositeExecutor = CompositeExecutor;
2110
2153
  exports.DEFAULT_AI_IDENTITY = DEFAULT_AI_IDENTITY;
2154
+ exports.DEFAULT_ALLOWANCE_WINDOW_MS = DEFAULT_ALLOWANCE_WINDOW_MS;
2111
2155
  exports.DEFAULT_API_KEY_RULE = DEFAULT_API_KEY_RULE;
2112
2156
  exports.DEFAULT_EMBED_BATCH_SIZE = DEFAULT_EMBED_BATCH_SIZE;
2113
2157
  exports.DEFAULT_ERROR_CLASSIFICATION_RULE = DEFAULT_ERROR_CLASSIFICATION_RULE;
@@ -2160,6 +2204,7 @@ exports.USER_FRIENDLY_ERROR_MESSAGES = USER_FRIENDLY_ERROR_MESSAGES;
2160
2204
  exports.accumulateReport = accumulateReport;
2161
2205
  exports.aiErrorMessage = aiErrorMessage;
2162
2206
  exports.aiErrorStatus = aiErrorStatus;
2207
+ exports.aiFailureOf = aiFailureOf;
2163
2208
  exports.asObjectArray = asObjectArray;
2164
2209
  exports.asRecord = asRecord;
2165
2210
  exports.asStringArray = asStringArray;
@@ -2185,6 +2230,7 @@ exports.classifyHttpStatus = classifyHttpStatus;
2185
2230
  exports.computeCostMicros = computeCostMicros;
2186
2231
  exports.cosineSimilarity = cosineSimilarity;
2187
2232
  exports.countChanges = countChanges;
2233
+ exports.createAllowanceWindow = createAllowanceWindow;
2188
2234
  exports.createRemoteChatClient = createRemoteChatClient;
2189
2235
  exports.createSseResponse = createSseResponse;
2190
2236
  exports.debounce = debounce;