@juspay/neurolink 10.3.0 → 10.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.
Files changed (127) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/browser/neurolink.min.js +430 -417
  3. package/dist/cli/loop/optionsSchema.js +4 -0
  4. package/dist/constants/contextWindows.d.ts +24 -0
  5. package/dist/constants/contextWindows.js +50 -0
  6. package/dist/context/errorDetection.d.ts +6 -0
  7. package/dist/context/errorDetection.js +18 -0
  8. package/dist/context/stepBudgetGuard.d.ts +17 -3
  9. package/dist/context/stepBudgetGuard.js +53 -14
  10. package/dist/core/baseProvider.d.ts +12 -0
  11. package/dist/core/baseProvider.js +18 -0
  12. package/dist/core/modules/GenerationHandler.js +208 -42
  13. package/dist/core/modules/ToolsManager.d.ts +17 -0
  14. package/dist/core/modules/ToolsManager.js +99 -1
  15. package/dist/index.d.ts +1 -0
  16. package/dist/index.js +3 -0
  17. package/dist/knowledge/context.d.ts +18 -0
  18. package/dist/knowledge/context.js +91 -0
  19. package/dist/knowledge/defaults.d.ts +24 -0
  20. package/dist/knowledge/defaults.js +29 -0
  21. package/dist/knowledge/engine.d.ts +35 -0
  22. package/dist/knowledge/engine.js +179 -0
  23. package/dist/knowledge/index.d.ts +15 -0
  24. package/dist/knowledge/index.js +15 -0
  25. package/dist/knowledge/indexCache.d.ts +19 -0
  26. package/dist/knowledge/indexCache.js +109 -0
  27. package/dist/knowledge/knowledgeIndex.d.ts +41 -0
  28. package/dist/knowledge/knowledgeIndex.js +204 -0
  29. package/dist/knowledge/normalize.d.ts +32 -0
  30. package/dist/knowledge/normalize.js +74 -0
  31. package/dist/knowledge/resolve.d.ts +18 -0
  32. package/dist/knowledge/resolve.js +156 -0
  33. package/dist/knowledge/retrieval.d.ts +16 -0
  34. package/dist/knowledge/retrieval.js +221 -0
  35. package/dist/lib/constants/contextWindows.d.ts +24 -0
  36. package/dist/lib/constants/contextWindows.js +50 -0
  37. package/dist/lib/context/errorDetection.d.ts +6 -0
  38. package/dist/lib/context/errorDetection.js +18 -0
  39. package/dist/lib/context/stepBudgetGuard.d.ts +17 -3
  40. package/dist/lib/context/stepBudgetGuard.js +53 -14
  41. package/dist/lib/core/baseProvider.d.ts +12 -0
  42. package/dist/lib/core/baseProvider.js +18 -0
  43. package/dist/lib/core/modules/GenerationHandler.js +208 -42
  44. package/dist/lib/core/modules/ToolsManager.d.ts +17 -0
  45. package/dist/lib/core/modules/ToolsManager.js +99 -1
  46. package/dist/lib/files/fileTools.d.ts +1 -1
  47. package/dist/lib/index.d.ts +1 -0
  48. package/dist/lib/index.js +3 -0
  49. package/dist/lib/knowledge/context.d.ts +18 -0
  50. package/dist/lib/knowledge/context.js +92 -0
  51. package/dist/lib/knowledge/defaults.d.ts +24 -0
  52. package/dist/lib/knowledge/defaults.js +30 -0
  53. package/dist/lib/knowledge/engine.d.ts +35 -0
  54. package/dist/lib/knowledge/engine.js +180 -0
  55. package/dist/lib/knowledge/index.d.ts +15 -0
  56. package/dist/lib/knowledge/index.js +16 -0
  57. package/dist/lib/knowledge/indexCache.d.ts +19 -0
  58. package/dist/lib/knowledge/indexCache.js +110 -0
  59. package/dist/lib/knowledge/knowledgeIndex.d.ts +41 -0
  60. package/dist/lib/knowledge/knowledgeIndex.js +205 -0
  61. package/dist/lib/knowledge/normalize.d.ts +32 -0
  62. package/dist/lib/knowledge/normalize.js +75 -0
  63. package/dist/lib/knowledge/resolve.d.ts +18 -0
  64. package/dist/lib/knowledge/resolve.js +157 -0
  65. package/dist/lib/knowledge/retrieval.d.ts +16 -0
  66. package/dist/lib/knowledge/retrieval.js +222 -0
  67. package/dist/lib/mcp/toolDiscoveryService.js +59 -20
  68. package/dist/lib/neurolink.d.ts +14 -1
  69. package/dist/lib/neurolink.js +142 -12
  70. package/dist/lib/providers/litellm.d.ts +27 -19
  71. package/dist/lib/providers/litellm.js +171 -92
  72. package/dist/lib/providers/openaiChatCompletionsBase.d.ts +37 -1
  73. package/dist/lib/providers/openaiChatCompletionsBase.js +201 -33
  74. package/dist/lib/providers/openaiChatCompletionsClient.d.ts +23 -5
  75. package/dist/lib/providers/openaiChatCompletionsClient.js +94 -14
  76. package/dist/lib/proxy/proxyFetch.d.ts +17 -0
  77. package/dist/lib/proxy/proxyFetch.js +42 -4
  78. package/dist/lib/types/config.d.ts +12 -0
  79. package/dist/lib/types/conversation.d.ts +1 -1
  80. package/dist/lib/types/dynamic.d.ts +12 -0
  81. package/dist/lib/types/generate.d.ts +32 -2
  82. package/dist/lib/types/index.d.ts +1 -0
  83. package/dist/lib/types/index.js +1 -0
  84. package/dist/lib/types/knowledge.d.ts +342 -0
  85. package/dist/lib/types/knowledge.js +30 -0
  86. package/dist/lib/types/openaiCompatible.d.ts +2 -0
  87. package/dist/lib/types/providers.d.ts +9 -0
  88. package/dist/lib/types/stream.d.ts +14 -0
  89. package/dist/lib/utils/errorHandling.js +8 -2
  90. package/dist/lib/utils/schemaConversion.d.ts +16 -0
  91. package/dist/lib/utils/schemaConversion.js +165 -8
  92. package/dist/lib/utils/timeout.d.ts +22 -0
  93. package/dist/lib/utils/timeout.js +72 -12
  94. package/dist/lib/utils/tokenLimits.js +22 -0
  95. package/dist/lib/utils/toolCallRepair.d.ts +8 -0
  96. package/dist/lib/utils/toolCallRepair.js +4 -1
  97. package/dist/mcp/toolDiscoveryService.js +59 -20
  98. package/dist/neurolink.d.ts +14 -1
  99. package/dist/neurolink.js +142 -12
  100. package/dist/providers/litellm.d.ts +27 -19
  101. package/dist/providers/litellm.js +171 -92
  102. package/dist/providers/openaiChatCompletionsBase.d.ts +37 -1
  103. package/dist/providers/openaiChatCompletionsBase.js +201 -33
  104. package/dist/providers/openaiChatCompletionsClient.d.ts +23 -5
  105. package/dist/providers/openaiChatCompletionsClient.js +94 -14
  106. package/dist/proxy/proxyFetch.d.ts +17 -0
  107. package/dist/proxy/proxyFetch.js +42 -4
  108. package/dist/types/config.d.ts +12 -0
  109. package/dist/types/conversation.d.ts +1 -1
  110. package/dist/types/dynamic.d.ts +12 -0
  111. package/dist/types/generate.d.ts +32 -2
  112. package/dist/types/index.d.ts +1 -0
  113. package/dist/types/index.js +1 -0
  114. package/dist/types/knowledge.d.ts +342 -0
  115. package/dist/types/knowledge.js +29 -0
  116. package/dist/types/openaiCompatible.d.ts +2 -0
  117. package/dist/types/providers.d.ts +9 -0
  118. package/dist/types/stream.d.ts +14 -0
  119. package/dist/utils/errorHandling.js +8 -2
  120. package/dist/utils/schemaConversion.d.ts +16 -0
  121. package/dist/utils/schemaConversion.js +165 -8
  122. package/dist/utils/timeout.d.ts +22 -0
  123. package/dist/utils/timeout.js +72 -12
  124. package/dist/utils/tokenLimits.js +22 -0
  125. package/dist/utils/toolCallRepair.d.ts +8 -0
  126. package/dist/utils/toolCallRepair.js +4 -1
  127. package/package.json +4 -1
@@ -3,6 +3,23 @@
3
3
  * Supports HTTP/HTTPS, SOCKS4/5, authentication, and NO_PROXY bypass
4
4
  * Lightweight implementation extracted from research of major proxy packages
5
5
  */
6
+ /**
7
+ * Classify a fetch failure as a transient network error worth retrying.
8
+ *
9
+ * undici's `fetch()` wraps the real failure in `TypeError: fetch failed`
10
+ * with the actionable code (`ECONNRESET`, `UND_ERR_SOCKET`, ...) on
11
+ * `error.cause` — sometimes nested another level (e.g. SocketError inside
12
+ * a ConnectTimeoutError). Walk the cause chain so those are recognized;
13
+ * checking only the top-level error silently classified every undici
14
+ * connection death as non-retryable.
15
+ *
16
+ * Deliberately NOT retried: `UND_ERR_HEADERS_TIMEOUT` / `UND_ERR_BODY_TIMEOUT`
17
+ * — those already waited out undici's own long deadline (default 300s), and
18
+ * replaying them can triple a stall under the caller's wall-clock budget.
19
+ *
20
+ * Exported for direct coverage by the no-API test suite.
21
+ */
22
+ export declare function isTransientNetworkError(error: unknown): boolean;
6
23
  /**
7
24
  * Create a proxy-aware fetch function with enhanced capabilities
8
25
  * Supports HTTP/HTTPS, SOCKS4/5, authentication, and NO_PROXY bypass
@@ -79,6 +79,47 @@ function extractHostname(url) {
79
79
  return "[unknown]";
80
80
  }
81
81
  }
82
+ /** Error codes classified as transient (module-scope: the retry path is hot). */
83
+ const TRANSIENT_NETWORK_CODES = new Set([
84
+ "ECONNRESET",
85
+ "ETIMEDOUT",
86
+ "ECONNREFUSED",
87
+ "EPIPE",
88
+ "UND_ERR_SOCKET",
89
+ "UND_ERR_CONNECT_TIMEOUT",
90
+ ]);
91
+ /**
92
+ * Classify a fetch failure as a transient network error worth retrying.
93
+ *
94
+ * undici's `fetch()` wraps the real failure in `TypeError: fetch failed`
95
+ * with the actionable code (`ECONNRESET`, `UND_ERR_SOCKET`, ...) on
96
+ * `error.cause` — sometimes nested another level (e.g. SocketError inside
97
+ * a ConnectTimeoutError). Walk the cause chain so those are recognized;
98
+ * checking only the top-level error silently classified every undici
99
+ * connection death as non-retryable.
100
+ *
101
+ * Deliberately NOT retried: `UND_ERR_HEADERS_TIMEOUT` / `UND_ERR_BODY_TIMEOUT`
102
+ * — those already waited out undici's own long deadline (default 300s), and
103
+ * replaying them can triple a stall under the caller's wall-clock budget.
104
+ *
105
+ * Exported for direct coverage by the no-API test suite.
106
+ */
107
+ export function isTransientNetworkError(error) {
108
+ let current = error;
109
+ for (let depth = 0; depth < 5 && current; depth++) {
110
+ const err = current;
111
+ if (err.code && TRANSIENT_NETWORK_CODES.has(err.code)) {
112
+ return true;
113
+ }
114
+ if (err.message?.includes("socket hang up") ||
115
+ err.message?.includes("network socket disconnected") ||
116
+ err.message?.includes("other side closed")) {
117
+ return true;
118
+ }
119
+ current = err.cause;
120
+ }
121
+ return false;
122
+ }
82
123
  /**
83
124
  * Retry-aware fetch wrapper for transient network errors (ECONNRESET, ETIMEDOUT, socket hang up).
84
125
  * Protects all LLM API calls and token refreshes that go through createProxyFetch().
@@ -104,11 +145,8 @@ async function fetchWithRetry(url, init, maxRetries = 3, baseDelay = 500) {
104
145
  return response;
105
146
  }
106
147
  catch (error) {
148
+ const isRetryable = isTransientNetworkError(error);
107
149
  const err = error;
108
- const isRetryable = err?.code === "ECONNRESET" ||
109
- err?.code === "ETIMEDOUT" ||
110
- err?.message?.includes("socket hang up") ||
111
- err?.message?.includes("network socket disconnected");
112
150
  if (!isRetryable || attempt === maxRetries) {
113
151
  // Final failure — record on span and rethrow
114
152
  span.setAttribute("http.request.total_attempts", totalAttempts);
@@ -13,6 +13,7 @@ import type { ModelPoolConfig } from "./modelPool.js";
13
13
  import type { RequestRouter } from "./requestRouter.js";
14
14
  import type { ClassifierRouterConfig } from "./classifierRouter.js";
15
15
  import type { SkillsConfig } from "./skills.js";
16
+ import type { KnowledgeGroundingConfig } from "./knowledge.js";
16
17
  /**
17
18
  * Main NeuroLink configuration type
18
19
  */
@@ -130,6 +131,17 @@ export type NeurolinkConstructorConfig = {
130
131
  * Opt-in and fails open on read paths. See {@link SkillsConfig}.
131
132
  */
132
133
  skills?: SkillsConfig;
134
+ /**
135
+ * Knowledge grounding: lexical-first host-supplied knowledge retrieval. When
136
+ * enabled with at least one source, a deterministic in-memory retrieval runs
137
+ * before each generate()/stream() turn — independently of tool routing — and
138
+ * attaches a token-bounded, ephemeral knowledge block to the model call. No
139
+ * embeddings or vector store. Opt-in (`enabled: false` by default) and fails
140
+ * open: any retrieval failure leaves the turn ungrounded. Sources are fixed
141
+ * for the lifetime of the instance. See
142
+ * {@link KnowledgeGroundingConfig}.
143
+ */
144
+ knowledgeGrounding?: KnowledgeGroundingConfig;
133
145
  };
134
146
  /**
135
147
  * Configuration for MCP enhancement modules wired into generate()/stream() paths.
@@ -429,7 +429,7 @@ export type SessionMetadata = {
429
429
  * Report type for agentic loop reports
430
430
  * Identifies the platform or category of the report
431
431
  */
432
- export type AgenticLoopReportType = "META" | "GOOGLEADS" | "GOOGLEGA4" | "OTHER";
432
+ export type AgenticLoopReportType = "META" | "GOOGLEADS" | "GOOGLEGA4" | "SHOPIFY" | "BREEZE" | "OTHER";
433
433
  /**
434
434
  * Status of an agentic loop report
435
435
  */
@@ -7,6 +7,7 @@
7
7
  * @module types/dynamic
8
8
  */
9
9
  import type { AIProviderName } from "../constants/enums.js";
10
+ import type { KnowledgeRequestScope } from "./knowledge.js";
10
11
  /**
11
12
  * Context passed to context-aware dynamic argument functions.
12
13
  * `requestContext` is whatever the consumer passed as `dynamicContext` —
@@ -39,6 +40,17 @@ export type DynamicArgument<T> = T | (() => T) | (() => Promise<T>) | ((context:
39
40
  * instead of static values for context-aware resolution.
40
41
  */
41
42
  export type DynamicOptions = {
43
+ /**
44
+ * Opt this call into the knowledge grounding configured on the NeuroLink
45
+ * instance. This flag is intentionally static because grounding runs before
46
+ * dynamic arguments are resolved.
47
+ */
48
+ useKnowledgeGrounding?: boolean;
49
+ /**
50
+ * Enabled integrations used to scope knowledge retrieval for this turn.
51
+ * This scope is intentionally static for the same reason.
52
+ */
53
+ knowledgeContext?: KnowledgeRequestScope;
42
54
  model?: DynamicArgument<string>;
43
55
  provider?: DynamicArgument<AIProviderName | string>;
44
56
  temperature?: DynamicArgument<number>;
@@ -1,5 +1,6 @@
1
1
  import type { AIProviderName } from "../constants/enums.js";
2
2
  import type { RAGConfig } from "./rag.js";
3
+ import type { KnowledgeGroundingMetadata, KnowledgeRequestScope } from "./knowledge.js";
3
4
  import type { SkillsCallOptions } from "./skills.js";
4
5
  import type { AnalyticsData, TokenUsage } from "./analytics.js";
5
6
  import type { JsonValue } from "./common.js";
@@ -323,8 +324,15 @@ export type GenerateOptions = {
323
324
  * never the step-cap text. Unset = no turn-level deadline (the library
324
325
  * imposes no product policy).
325
326
  *
326
- * Enforced by the native Vertex loops (Gemini + Claude); AI-SDK-driven
327
- * providers currently ignore it.
327
+ * Enforced by the native Vertex loops (Gemini + Claude) AND the AI-SDK
328
+ * loop path (litellm and other OpenAI-compatible providers). On the AI-SDK
329
+ * path, an explicit `timeout` also engages the same wrap-up when
330
+ * `turnTimeoutMs` is unset. Once the wrap-up window begins (see
331
+ * `wrapupTimeLeadMs`), the loop forcibly sets `toolChoice: "none"` for the
332
+ * remaining steps — overriding any caller-supplied `toolChoice` or
333
+ * `prepareStep` tool selection — and appends an honest time message that a
334
+ * caller's `prepareStep` callback does not observe (it runs before the
335
+ * wrap-up nudge is applied). An honest partial beats a discarded turn.
328
336
  */
329
337
  turnTimeoutMs?: number;
330
338
  /**
@@ -340,6 +348,11 @@ export type GenerateOptions = {
340
348
  * next tool-result turn telling the model to consolidate what it has and
341
349
  * produce its final answer. Defaults to 120_000 when `turnTimeoutMs` is
342
350
  * set; ignored when it is not.
351
+ *
352
+ * On the AI-SDK loop path the lead is clamped to a quarter of the turn
353
+ * budget (so short budgets don't wrap up on step one) and wrap-up steps
354
+ * run with a forced `toolChoice: "none"` — see `turnTimeoutMs` for the
355
+ * exact override semantics.
343
356
  */
344
357
  wrapupTimeLeadMs?: number;
345
358
  /**
@@ -350,6 +363,8 @@ export type GenerateOptions = {
350
363
  toolTimeoutMs?: number;
351
364
  /** AbortSignal for external cancellation of the AI call */
352
365
  abortSignal?: AbortSignal;
366
+ /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
367
+ disableToolCallRepair?: boolean;
353
368
  /**
354
369
  * Disable tool execution (including built-in tools)
355
370
  *
@@ -531,6 +546,17 @@ export type GenerateOptions = {
531
546
  onError?: OnErrorCallback;
532
547
  /** Pre-validated user context for the request */
533
548
  requestContext?: Record<string, unknown>;
549
+ /**
550
+ * Opt this generation call into the knowledge grounding configured on the
551
+ * NeuroLink instance. Defaults to `false` when omitted.
552
+ */
553
+ useKnowledgeGrounding?: boolean;
554
+ /**
555
+ * Enabled integrations used to scope knowledge retrieval for this turn.
556
+ * Used only when `useKnowledgeGrounding` is true and knowledge grounding is
557
+ * enabled on the NeuroLink instance.
558
+ */
559
+ knowledgeContext?: KnowledgeRequestScope;
534
560
  /** Raw auth token — validated by configured auth provider */
535
561
  auth?: {
536
562
  token: string;
@@ -676,6 +702,8 @@ export type GenerateStopReason = "completed" | "step-cap" | "context-cap" | "tim
676
702
  */
677
703
  export type GenerateResult = {
678
704
  content: string;
705
+ /** Knowledge-grounding diagnostics for this turn (present only when grounding ran). */
706
+ knowledge?: KnowledgeGroundingMetadata;
679
707
  /**
680
708
  * Parsed structured object when a `schema` was requested. Populated from
681
709
  * AI-SDK experimental_output, or from text-mode coercion (balanced-scan +
@@ -1015,6 +1043,8 @@ export type TextGenerationOptions = {
1015
1043
  /** AbortSignal for external cancellation of the AI call */
1016
1044
  abortSignal?: AbortSignal;
1017
1045
  disableTools?: boolean;
1046
+ /** Disable the schema-driven tool call repair mechanism (BZ-665). Default: false (repair enabled). */
1047
+ disableToolCallRepair?: boolean;
1018
1048
  maxSteps?: number;
1019
1049
  /** Include only these tools by name (whitelist). If set, only matching tools are available. */
1020
1050
  toolFilter?: string[];
@@ -28,6 +28,7 @@ export * from "./generate.js";
28
28
  export * from "./grounding.js";
29
29
  export * from "./guardrails.js";
30
30
  export * from "./hitl.js";
31
+ export * from "./knowledge.js";
31
32
  export * from "./livekit.js";
32
33
  export * from "./mcp.js";
33
34
  export * from "./mcpOutput.js";
@@ -29,6 +29,7 @@ export * from "./generate.js";
29
29
  export * from "./grounding.js";
30
30
  export * from "./guardrails.js";
31
31
  export * from "./hitl.js";
32
+ export * from "./knowledge.js";
32
33
  export * from "./livekit.js";
33
34
  export * from "./mcp.js";
34
35
  export * from "./mcpOutput.js";
@@ -0,0 +1,342 @@
1
+ /**
2
+ * Knowledge grounding — lexical-first host-supplied knowledge retrieval.
3
+ *
4
+ * A host application owns a structured *knowledge registry*: versioned entries
5
+ * describing concepts, configuration, taxonomies, procedures, and operating
6
+ * rules. NeuroLink owns the
7
+ * generic engine that ingests that registry, builds an in-memory lexical
8
+ * index once per instance, and — independently of tool routing — retrieves a
9
+ * small, token-bounded set of relevant entries before each main model call.
10
+ * The selected entries are attached as *ephemeral context*: visible to the
11
+ * current generation call, never persisted into conversation memory.
12
+ *
13
+ * This is retrieval-augmented generation WITHOUT vector retrieval. The first
14
+ * release ranks with exact identifiers, reviewed aliases, metadata filters,
15
+ * and weighted field-aware BM25 only. No embedding model, embedding service,
16
+ * or vector store is initialized. An LLM reranker and semantic retrieval are
17
+ * deferred behind an explicit evaluation gate.
18
+ *
19
+ * Ownership boundary: NeuroLink defines the contracts below and the engine;
20
+ * it never contains host product content. The host supplies content and
21
+ * per-request scope. The engine stays provider-neutral.
22
+ *
23
+ * Type names are globally prefixed `Knowledge*` to satisfy the repo's
24
+ * unique-type-name rule and to avoid collision with the pre-existing
25
+ * web-search `grounding.ts` vocabulary (`EnhancedGroundingMetadata` et al.),
26
+ * which is a different concept (Google search grounding, not product
27
+ * knowledge).
28
+ */
29
+ /** What a knowledge entry primarily is. Drives context labelling, not ranking. */
30
+ export type KnowledgeEntryKind = "concept" | "text" | "configuration" | "tool" | "procedure" | "policy" | "troubleshooting";
31
+ /** Lifecycle state. Only `active` entries are retrievable by default. */
32
+ export type KnowledgeStatus = "draft" | "active" | "deprecated";
33
+ /**
34
+ * Retrieval mode. Only `"lexical"` is supported in the first release; the
35
+ * literal is a union of one to reserve a clean upgrade path to `"hybrid"` /
36
+ * `"vector"` without a breaking change.
37
+ */
38
+ export type KnowledgeRetrievalMode = "lexical";
39
+ /**
40
+ * Confidence class returned with every retrieval so the host prompt can
41
+ * instruct the model to qualify low-confidence answers rather than present
42
+ * them as authoritative.
43
+ */
44
+ export type KnowledgeRetrievalConfidence = "high" | "medium" | "low" | "none";
45
+ /** The five weighted text fields used by the field-aware lexical scorer. */
46
+ export type KnowledgeFieldName = "title" | "aliases" | "keywords" | "summary" | "body";
47
+ /**
48
+ * The record a host author writes. `id`, `title`, `summary`, `domain`, and
49
+ * `integrations` are required; every other field is optional and omitted
50
+ * optionals fall back to SDK defaults during normalization.
51
+ */
52
+ export type KnowledgeEntryInput = {
53
+ /** Stable unique id (e.g. "account.multi-step-flow"). Drives exact-match lookup and citations. */
54
+ id: string;
55
+ /** Human-readable name of the concept/setting. Highest-weighted search field. */
56
+ title: string;
57
+ /** One-line searchable description — the short answer when a full body is unnecessary. */
58
+ summary: string;
59
+ /** Primary grouping and the main retrieval filter (e.g. "account-settings"). */
60
+ domain: string;
61
+ /** Integration identifiers this entry applies to. Empty array = applies to all integrations. */
62
+ integrations: string[];
63
+ /** What the entry is (concept, configuration, procedure, …). Default "text". Labels context, not ranking. */
64
+ kind?: KnowledgeEntryKind;
65
+ /** Lifecycle state. Default "active"; only active entries are retrievable. */
66
+ status?: KnowledgeStatus;
67
+ /** Full explanatory content (Markdown). Use only when the summary is insufficient. */
68
+ body?: string;
69
+ /** Reviewed alternate phrasings or raw identifiers that resolve to exact and alias matches. */
70
+ aliases?: string[];
71
+ /** Extra search terms that aid recall but are not full aliases. */
72
+ keywords?: string[];
73
+ /** Ids of directly related entries, pulled in by bounded relationship expansion. */
74
+ relatedEntryIds?: string[];
75
+ /** Id of the parent entry when this is a subtype or child. */
76
+ parentEntryId?: string;
77
+ };
78
+ /**
79
+ * The complete, defaults-resolved record NeuroLink indexes and injects. Omitted
80
+ * optionals are materialized (arrays to `[]`, `body` to `""`, `kind` to "text",
81
+ * `status` to "active") so downstream code never re-checks the resolution chain.
82
+ * Field meanings mirror `KnowledgeEntryInput`.
83
+ */
84
+ export type NormalizedKnowledgeEntry = {
85
+ id: string;
86
+ title: string;
87
+ summary: string;
88
+ domain: string;
89
+ integrations: string[];
90
+ kind: KnowledgeEntryKind;
91
+ status: KnowledgeStatus;
92
+ body: string;
93
+ aliases: string[];
94
+ keywords: string[];
95
+ relatedEntryIds: string[];
96
+ parentEntryId?: string;
97
+ /** Content version from the source/manifest; appears in citations as [KB:id@version]. */
98
+ version: string;
99
+ };
100
+ /** One catalog inside a build manifest — a source id and its entries. */
101
+ export type KnowledgeManifestCatalog = {
102
+ id: string;
103
+ entries: KnowledgeEntryInput[];
104
+ };
105
+ /**
106
+ * The versioned build artifact a host emits at build time. NeuroLink can
107
+ * consume it directly (each catalog becomes a structured source) so hosts do
108
+ * not need to construct `KnowledgeSource[]` by hand.
109
+ */
110
+ export type KnowledgeManifest = {
111
+ schemaVersion: string;
112
+ contentVersion: string;
113
+ generatedAt: string;
114
+ catalogs: KnowledgeManifestCatalog[];
115
+ };
116
+ /**
117
+ * A configured knowledge source: inline structured entries passed to the
118
+ * engine. Markdown/provider source kinds were intentionally dropped for now;
119
+ * re-introduce this as a discriminated union (with a `type` tag) if another
120
+ * source kind is needed later.
121
+ */
122
+ export type KnowledgeSource = {
123
+ id: string;
124
+ version?: string;
125
+ entries: KnowledgeEntryInput[];
126
+ };
127
+ /**
128
+ * Relative weight applied to a lexical match in each field. Title/alias
129
+ * matches outrank body matches. Tunable through evaluation.
130
+ */
131
+ export type KnowledgeFieldWeights = {
132
+ title: number;
133
+ aliases: number;
134
+ keywords: number;
135
+ summary: number;
136
+ body: number;
137
+ };
138
+ /** Lexical retrieval tuning. All fields optional; the engine supplies defaults. */
139
+ export type KnowledgeRetrievalConfig = {
140
+ /** Retrieval mode. Default: "lexical". */
141
+ mode?: KnowledgeRetrievalMode;
142
+ /** How many scored candidates enter relationship expansion. Default: 24. */
143
+ candidateLimit?: number;
144
+ /** How many primary entries survive into the assembled context. Default: 8. */
145
+ resultLimit?: number;
146
+ /** Cap on relationship-expanded entries added after primary retrieval. Default: 4. */
147
+ relationLimit?: number;
148
+ /** Per-field BM25 weights. */
149
+ fieldWeights?: KnowledgeFieldWeights;
150
+ /** Additive boost for an exact entry-id / configuration-key match. Dominant. Default: 100. */
151
+ exactBoost?: number;
152
+ /** Additive boost for an exact reviewed-alias phrase match. Default: 60. */
153
+ aliasBoost?: number;
154
+ };
155
+ /** Ephemeral-context assembly limits. */
156
+ export type KnowledgeContextConfig = {
157
+ /** Hard token budget for the assembled grounding block. Default: 4000. */
158
+ maxTokens?: number;
159
+ /** Emit `[KB:<id>@<version>]` citations. Default: true. */
160
+ includeCitations?: boolean;
161
+ };
162
+ /**
163
+ * Constructor-level configuration for knowledge grounding. Sources are fixed
164
+ * for the lifetime of a NeuroLink instance so the index can be built once.
165
+ */
166
+ export type KnowledgeGroundingConfig = {
167
+ /** Master switch. Grounding runs only when true AND at least one source is loaded. */
168
+ enabled: boolean;
169
+ /**
170
+ * Knowledge sources used to build the instance's immutable in-memory index.
171
+ * Required alongside `enabled`; pass an empty array only when intentionally
172
+ * configuring no retrievable content.
173
+ */
174
+ sources: KnowledgeSource[];
175
+ /** Exclude these domains from retrieval. Empty/omitted means all domains are eligible. */
176
+ blockedDomains?: string[];
177
+ retrieval?: KnowledgeRetrievalConfig;
178
+ context?: KnowledgeContextConfig;
179
+ /** Hard ceiling for one grounding operation before it fails open. Default: 800ms. */
180
+ timeoutMs?: number;
181
+ };
182
+ /**
183
+ * Per-call scope the host attaches to `GenerateOptions` / `StreamOptions`.
184
+ * Supplies the enabled integrations for this turn only.
185
+ */
186
+ export type KnowledgeRequestScope = {
187
+ /** Installed/enabled integrations used to filter integration-specific entries. */
188
+ enabledIntegrations?: string[];
189
+ };
190
+ /** One bounded recent conversation turn used to contextualize the query. */
191
+ export type KnowledgeConversationTurn = {
192
+ role: "user" | "assistant";
193
+ text: string;
194
+ };
195
+ /**
196
+ * The fully-resolved retrieval request the engine builds internally from the
197
+ * user query, a bounded recent window, and host scope.
198
+ */
199
+ export type KnowledgeRetrievalRequest = {
200
+ query: string;
201
+ recentTurns: KnowledgeConversationTurn[];
202
+ enabledIntegrations: string[];
203
+ };
204
+ /**
205
+ * The internal search document built from a normalized entry. `exactKeys` and
206
+ * `fields` hold pre-tokenized normalized text. Internal to NeuroLink.
207
+ */
208
+ export type IndexedKnowledgeDocument = {
209
+ id: string;
210
+ /** Normalized whole-phrase keys for exact/alias resolution. */
211
+ exactKeys: string[];
212
+ /** Per-field normalized token arrays fed to the field-aware BM25 scorer. */
213
+ fields: {
214
+ title: string[];
215
+ aliases: string[];
216
+ keywords: string[];
217
+ summary: string[];
218
+ body: string[];
219
+ };
220
+ };
221
+ /** One lexical match with its per-field score breakdown, for tuning and traces. */
222
+ export type KnowledgeLexicalMatch = {
223
+ id: string;
224
+ score: number;
225
+ fieldScores: Partial<Record<KnowledgeFieldName, number>>;
226
+ };
227
+ /**
228
+ * Structural contract of the field-aware lexical index held in a snapshot. A
229
+ * concrete class in the knowledge runtime module satisfies this shape; typing
230
+ * it structurally keeps this types file free of runtime imports.
231
+ */
232
+ export type KnowledgeLexicalSearcher = {
233
+ search: (queryTokens: string[], topK: number, eligibleEntryIds?: ReadonlySet<string>) => KnowledgeLexicalMatch[];
234
+ };
235
+ /**
236
+ * Immutable, ready-to-query index built once at client construction. Sessions
237
+ * and turns search this snapshot; it is never mutated in place.
238
+ */
239
+ export type KnowledgeIndexSnapshot = {
240
+ entriesById: Map<string, NormalizedKnowledgeEntry>;
241
+ /** Normalized entry id or title phrase -> entry ids. */
242
+ exactIndex: Map<string, Set<string>>;
243
+ /** Normalized reviewed alias phrase -> entry ids. */
244
+ aliasIndex: Map<string, Set<string>>;
245
+ /** Entry id -> directly related entry ids, for bounded expansion. */
246
+ relationIndex: Map<string, string[]>;
247
+ /** Field-aware BM25 over all documents. */
248
+ lexical: KnowledgeLexicalSearcher;
249
+ entryCount: number;
250
+ };
251
+ /** A stable citation to a specific knowledge entry version. */
252
+ export type KnowledgeCitation = {
253
+ id: string;
254
+ version: string;
255
+ };
256
+ /**
257
+ * The result of one retrieval: the selected entries, the assembled ephemeral
258
+ * context string, a confidence class, and assembly diagnostics.
259
+ */
260
+ export type KnowledgeRetrievalResult = {
261
+ entries: NormalizedKnowledgeEntry[];
262
+ assembledContext: string;
263
+ confidence: KnowledgeRetrievalConfidence;
264
+ citations: KnowledgeCitation[];
265
+ /** Ids of the primary (non-expanded) entries, in final order. */
266
+ selectedEntryIds: string[];
267
+ /** Ids added by bounded relationship expansion. */
268
+ expandedEntryIds: string[];
269
+ /** Candidates scored before truncation to the result limit. */
270
+ candidateCount: number;
271
+ /** Estimated token size of `assembledContext`. */
272
+ contextTokens: number;
273
+ /** True when any entry body was truncated or entries were dropped for budget. */
274
+ truncated: boolean;
275
+ durationMs: number;
276
+ };
277
+ /**
278
+ * A block of context assembled for a single generation call without becoming
279
+ * durable conversation. The NeuroLink call boundary injects its content into
280
+ * the effective system prompt and never persists it as a user message.
281
+ */
282
+ export type EphemeralContext = {
283
+ content: string;
284
+ kind: "knowledge";
285
+ /** Host-supplied reviewed content is trusted reference data. */
286
+ trusted: boolean;
287
+ citations?: KnowledgeCitation[];
288
+ metadata?: Record<string, unknown>;
289
+ };
290
+ /**
291
+ * Aggregate, content-free diagnostics attached to a generation/stream result
292
+ * so the host can evaluate retrieval without the SDK exposing entry bodies.
293
+ */
294
+ export type KnowledgeGroundingMetadata = {
295
+ retrievalMode: KnowledgeRetrievalMode;
296
+ selectedIds: string[];
297
+ expandedIds: string[];
298
+ candidateCount: number;
299
+ contextTokens: number;
300
+ truncated: boolean;
301
+ durationMs: number;
302
+ confidence?: KnowledgeRetrievalConfidence;
303
+ /** Present when grounding failed open; names the failure class. */
304
+ failureReason?: string;
305
+ };
306
+ /** A single validation problem found while normalizing/indexing a source. */
307
+ export type KnowledgeValidationIssue = {
308
+ level: "error" | "warning";
309
+ code: string;
310
+ message: string;
311
+ entryId?: string;
312
+ sourceId?: string;
313
+ };
314
+ /** Outcome of validating a set of sources before indexing. */
315
+ export type KnowledgeValidationResult = {
316
+ ok: boolean;
317
+ issues: KnowledgeValidationIssue[];
318
+ };
319
+ /** Per-turn input to `KnowledgeGroundingEngine.ground()`. */
320
+ export type KnowledgeGroundingInput = {
321
+ query: string;
322
+ recentTurns?: KnowledgeConversationTurn[];
323
+ scope?: KnowledgeRequestScope;
324
+ };
325
+ /**
326
+ * The engine's per-turn output: the ephemeral context to inject (null on
327
+ * no-match, when disabled, or on fail-open), the aggregate metadata for the
328
+ * result, and the full retrieval for host diagnostics.
329
+ */
330
+ export type KnowledgeGroundingOutcome = {
331
+ ephemeralContext: EphemeralContext | null;
332
+ metadata: KnowledgeGroundingMetadata;
333
+ retrieval: KnowledgeRetrievalResult | null;
334
+ };
335
+ /** Snapshot of engine health for telemetry and host introspection. */
336
+ export type KnowledgeEngineStatus = {
337
+ enabled: boolean;
338
+ ready: boolean;
339
+ entryCount: number;
340
+ lastError: string | null;
341
+ validationIssues: KnowledgeValidationIssue[];
342
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Knowledge grounding — lexical-first host-supplied knowledge retrieval.
3
+ *
4
+ * A host application owns a structured *knowledge registry*: versioned entries
5
+ * describing concepts, configuration, taxonomies, procedures, and operating
6
+ * rules. NeuroLink owns the
7
+ * generic engine that ingests that registry, builds an in-memory lexical
8
+ * index once per instance, and — independently of tool routing — retrieves a
9
+ * small, token-bounded set of relevant entries before each main model call.
10
+ * The selected entries are attached as *ephemeral context*: visible to the
11
+ * current generation call, never persisted into conversation memory.
12
+ *
13
+ * This is retrieval-augmented generation WITHOUT vector retrieval. The first
14
+ * release ranks with exact identifiers, reviewed aliases, metadata filters,
15
+ * and weighted field-aware BM25 only. No embedding model, embedding service,
16
+ * or vector store is initialized. An LLM reranker and semantic retrieval are
17
+ * deferred behind an explicit evaluation gate.
18
+ *
19
+ * Ownership boundary: NeuroLink defines the contracts below and the engine;
20
+ * it never contains host product content. The host supplies content and
21
+ * per-request scope. The engine stays provider-neutral.
22
+ *
23
+ * Type names are globally prefixed `Knowledge*` to satisfy the repo's
24
+ * unique-type-name rule and to avoid collision with the pre-existing
25
+ * web-search `grounding.ts` vocabulary (`EnhancedGroundingMetadata` et al.),
26
+ * which is a different concept (Google search grounding, not product
27
+ * knowledge).
28
+ */
29
+ export {};
30
+ //# sourceMappingURL=knowledge.js.map
@@ -226,6 +226,8 @@ export type StreamLoopArgs = {
226
226
  openAITools: OpenAICompatChatTool[] | undefined;
227
227
  openAIToolChoice: OpenAICompatToolChoiceWire | undefined;
228
228
  toolsRecord: Record<string, Tool>;
229
+ /** Wire → registered tool-name map when sanitization was needed (see buildWireToolNameMaps). */
230
+ toolNameFromWire?: Map<string, string>;
229
231
  emitter: TypedEventEmitter<NeuroLinkEvents> | undefined;
230
232
  toolsUsed: string[];
231
233
  toolExecutionSummaries: ToolExecutionSummaryInternal[];
@@ -601,6 +601,15 @@ export type AIProvider = {
601
601
  * external AIProvider implementations — callers treat absence as `true`.
602
602
  */
603
603
  supportsTools?(): boolean;
604
+ /**
605
+ * Ensure runtime-discovered model limits (context window, output-token
606
+ * ceiling) are registered before budget math runs. Implemented by
607
+ * BaseProvider (default no-op); providers with a discovery source override
608
+ * it (LiteLLM `/model/info`). Must never reject — discovery failure
609
+ * degrades to static defaults. Optional for compile compatibility with
610
+ * external AIProvider implementations — callers treat absence as no-op.
611
+ */
612
+ ensureModelLimits?(): Promise<void>;
604
613
  };
605
614
  /**
606
615
  * Provider attempt result for iteration tracking (converted from interface)