@stackfactor/agent-utils 1.7.0 → 1.8.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.
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/errorHandling.ts"],"names":[],"mappings":"AAGA,gEAAgE;AAChE,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8GD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,MAAM,GAAE,WAAgB;IAUpC;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ;IAKrC;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW;IAIzC;;;;OAIG;IACH,OAAO,IAAI,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAS1D,MAAM,IAAI,WAAW;IAIrB;;;;OAIG;IACH,WAAW,IAAI,KAAK;IAIpB;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,GAAE,GAAU,EAAE,KAAK,GAAE,QAAkB,EAAE,OAAO,GAAE,GAAQ,GAAG,IAAI;CAU7E;;IAkBC;;;;;;;;;OASG;wBACiB,MAAM,gBAAgB,MAAM,YAAW,GAAG;;;;;;IAU9D,6EAA6E;mBApOpD,GAAG,KAAG,WAAW;IAsO1C,0EAA0E;;IAE1E,gFAAgF;oBA9BzE,OAAO,YACL,GAAG,YACH,GAAG,KACX,QAAQ;IA6BT,wDAAwD;uBArPhC,GAAG,KAAG,IAAI,IAAI,MAAM;IAuP5C,kCAAkC;;;AA7BpC,wBA+BE"}
1
+ {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/errorHandling.ts"],"names":[],"mappings":"AAGA,gEAAgE;AAChE,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmHD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,MAAM,GAAE,WAAgB;IAUpC;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ;IAKrC;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW;IAIzC;;;;OAIG;IACH,OAAO,IAAI,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAS1D,MAAM,IAAI,WAAW;IAIrB;;;;OAIG;IACH,WAAW,IAAI,KAAK;IAIpB;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,GAAE,GAAU,EAAE,KAAK,GAAE,QAAkB,EAAE,OAAO,GAAE,GAAQ,GAAG,IAAI;CAU7E;;IAkBC;;;;;;;;;OASG;wBACiB,MAAM,gBAAgB,MAAM,YAAW,GAAG;;;;;;IAU9D,6EAA6E;mBAzOpD,GAAG,KAAG,WAAW;IA2O1C,0EAA0E;;IAE1E,gFAAgF;oBA9BzE,OAAO,YACL,GAAG,YACH,GAAG,KACX,QAAQ;IA6BT,wDAAwD;uBA1PhC,GAAG,KAAG,IAAI,IAAI,MAAM;IA4P5C,kCAAkC;;;AA7BpC,wBA+BE"}
@@ -87,11 +87,16 @@ const parseError = (error) => {
87
87
  // A JSON-encoded error string, or just a plain message.
88
88
  try {
89
89
  const parsed = JSON.parse(error);
90
- return {
91
- code: isHttpCode(parsed.code) ? parsed.code : undefined,
92
- message: parsed.message,
93
- integration: parsed.integration,
94
- };
90
+ // Only an object is an encoded error; "404" or "true" also parse as
91
+ // JSON but are just the message text.
92
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
93
+ return {
94
+ code: isHttpCode(parsed.code) ? parsed.code : undefined,
95
+ message: parsed.message,
96
+ integration: parsed.integration,
97
+ };
98
+ }
99
+ return { message: error };
95
100
  }
96
101
  catch {
97
102
  return { message: error };
@@ -6,6 +6,7 @@ import { serve, runOnce, isRunOnceExecution, EXECUTION_ENV } from "./serve.js";
6
6
  import { callAgent, checkAgent } from "./client.js";
7
7
  import * as runtimeContext from "./runtimeContext.js";
8
8
  import { recordUsage, USAGE_UNITS } from "./usage.js";
9
+ import stackfactorKnowledge from "./stackfactorKnowledge.js";
9
10
  export { constants };
10
11
  export { errorHandling, AppError };
11
12
  export type { ParsedError } from "./errorHandling.js";
@@ -20,4 +21,6 @@ export type { AgentExecuteRequest, CallAgentOptions, CheckAgentOptions, AgentHea
20
21
  export { runtimeContext };
21
22
  export { recordUsage, USAGE_UNITS };
22
23
  export type { UsageEntry, UsageUnit } from "./usage.js";
24
+ export { stackfactorKnowledge };
25
+ export type { GroundingPassage, KnowledgeChunk, KnowledgeSearch, KnowledgeSource, SkippedSource, StackFactorReference, } from "./stackfactorKnowledge.js";
23
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAEnC,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AAEpC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AACnC,OAAO,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,oBAAoB,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC;AAEnC,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,CAAC;AAErB,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AAEpC,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,EAAE,oBAAoB,EAAE,CAAC;AAEhC,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,2BAA2B,CAAC"}
package/dist/cjs/index.js CHANGED
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.USAGE_UNITS = exports.recordUsage = exports.runtimeContext = exports.checkAgent = exports.callAgent = exports.EXECUTION_ENV = exports.isRunOnceExecution = exports.runOnce = exports.serve = exports.logger = exports.langChain = exports.AppError = exports.errorHandling = exports.constants = void 0;
39
+ exports.stackfactorKnowledge = exports.USAGE_UNITS = exports.recordUsage = exports.runtimeContext = exports.checkAgent = exports.callAgent = exports.EXECUTION_ENV = exports.isRunOnceExecution = exports.runOnce = exports.serve = exports.logger = exports.langChain = exports.AppError = exports.errorHandling = exports.constants = void 0;
40
40
  const const_js_1 = __importDefault(require("./const.js"));
41
41
  exports.constants = const_js_1.default;
42
42
  const errorHandling_js_1 = __importStar(require("./errorHandling.js"));
@@ -59,3 +59,5 @@ exports.runtimeContext = runtimeContext;
59
59
  const usage_js_1 = require("./usage.js");
60
60
  Object.defineProperty(exports, "recordUsage", { enumerable: true, get: function () { return usage_js_1.recordUsage; } });
61
61
  Object.defineProperty(exports, "USAGE_UNITS", { enumerable: true, get: function () { return usage_js_1.USAGE_UNITS; } });
62
+ const stackfactorKnowledge_js_1 = __importDefault(require("./stackfactorKnowledge.js"));
63
+ exports.stackfactorKnowledge = stackfactorKnowledge_js_1.default;
@@ -62,7 +62,7 @@ declare const _default: {
62
62
  supportsNativeSchema: (modelName: string) => boolean;
63
63
  checkIfAIProviderConfigured: (config: any) => void;
64
64
  createAgent: (name: string, modelName: string, systemPrompt: string, tools: any[], responseFormat: any, config: any, usageTracker?: UsageTracker | null) => any;
65
- runAgent: (agent: any, prompt: string, config: any, onProgress?: Function | null, usageTracker?: UsageTracker | null) => Promise<any>;
65
+ runAgent: (agent: any, prompt: string, config: any, onProgress?: Function | null, usageTracker?: UsageTracker | null, progress?: number) => Promise<any>;
66
66
  runPromptWithModel: (modelName: string, config: any, prompt: any, onProgressReport: any, minPercent?: number, maxPercent?: number, expectsJsonResponse?: boolean, schema?: any, agentName?: string, tools?: any[], usageTracker?: UsageTracker | null) => Promise<any>;
67
67
  runPromptWithModelForImageGeneration: (modelName: string, config: any, prompt: string, options?: any, usageTracker?: UsageTracker | null) => Promise<any>;
68
68
  runPromptWithModelForVideoGeneration: (modelName: string, config: any, prompt: string, options?: any, usageTracker?: UsageTracker | null) => Promise<any>;
@@ -1 +1 @@
1
- {"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"AAoGA,KAAK,UAAU,GAAG;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAKtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD,CAAC;AAmiBF;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,QAAQ,GAAG,EACX,SAAQ,GAAU,KACjB,GAwHF,CAAC;;8CA4Z+C,OAAO,UAAU,GAAG,KAAG,OAAO;oCAWxC,GAAG,KAAG,OAAO;0CAgBtC,MAAM,cACN,GAAG,SACR,GAAG,KACT,MAAM;2CA0CqC,GAAG,UAAU,GAAG,KAAG,MAAM;sCAvvC9B,MAAM,KAAG,OAAO;0CA+FZ,GAAG,KAAG,IAAI;wBAusB/C,MAAM,aACD,MAAM,gBACH,MAAM,SACb,GAAG,EAAE,kBACI,GAAG,UACX,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,GAAG;sBAoCG,GAAG,UACF,MAAM,UACN,GAAG,eACC,QAAQ,GAAG,IAAI,iBACb,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;oCA6fF,MAAM,UACT,GAAG,UACH,GAAG,oBACO,GAAG,eACT,MAAM,eACN,MAAM,wBACG,OAAO,WACpB,GAAG,cACA,MAAM,UACV,GAAG,EAAE,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDA0sBF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDAmTF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;0CAv6C8B,GAAG,KAAG,MAAM;uCA3wB9C,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,YACP,GAAG,WACJ,GAAG,YACF,QAAQ,GAAG,QAAQ,KAC5B,IAAI;kCA5CI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,SACV,UAAU,GAAG,IAAI,YACd,GAAG,KACZ,IAAI;+CA0FI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,kBACD,MAAM,YACZ,GAAG,KACZ,IAAI;uCAoBI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,WACR,MAAM,YACL,GAAG,KACZ,IAAI;mCA4sBU,MAAM,mBACJ,MAAM,EAAE,KACxB,MAAM;;AA08CT,wBAkBE"}
1
+ {"version":3,"file":"langChain.d.ts","sourceRoot":"","sources":["../../src/langChain.ts"],"names":[],"mappings":"AAoGA,KAAK,UAAU,GAAG;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IAKtB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE;QAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD,CAAC;AA0iBF;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,eAAO,MAAM,WAAW,GACtB,WAAW,MAAM,EACjB,QAAQ,GAAG,EACX,SAAQ,GAAU,KACjB,GAwHF,CAAC;;8CAkb+C,OAAO,UAAU,GAAG,KAAG,OAAO;oCAWxC,GAAG,KAAG,OAAO;0CAgBtC,MAAM,cACN,GAAG,SACR,GAAG,KACT,MAAM;2CA0CqC,GAAG,UAAU,GAAG,KAAG,MAAM;sCApxC9B,MAAM,KAAG,OAAO;0CA+FZ,GAAG,KAAG,IAAI;wBA8sB/C,MAAM,aACD,MAAM,gBACH,MAAM,SACb,GAAG,EAAE,kBACI,GAAG,UACX,GAAG,iBACG,YAAY,GAAG,IAAI,KAChC,GAAG;sBAsCG,GAAG,UACF,MAAM,UACN,GAAG,eACC,QAAQ,GAAG,IAAI,iBACb,YAAY,GAAG,IAAI,aACvB,MAAM,KACf,OAAO,CAAC,GAAG,CAAC;oCAghBF,MAAM,UACT,GAAG,UACH,GAAG,oBACO,GAAG,eACT,MAAM,eACN,MAAM,wBACG,OAAO,WACpB,GAAG,cACA,MAAM,UACV,GAAG,EAAE,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDA2sBF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;sDAmTF,MAAM,UACT,GAAG,UACH,MAAM,YACL,GAAG,iBACE,YAAY,GAAG,IAAI,KAChC,OAAO,CAAC,GAAG,CAAC;0CAx6C8B,GAAG,KAAG,MAAM;uCAxyB9C,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,YACP,GAAG,WACJ,GAAG,YACF,QAAQ,GAAG,QAAQ,KAC5B,IAAI;kCA5CI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,SACV,UAAU,GAAG,IAAI,YACd,GAAG,KACZ,IAAI;+CA0FI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,kBACD,MAAM,YACZ,GAAG,KACZ,IAAI;uCAoBI,YAAY,GAAG,IAAI,GAAG,SAAS,aAC7B,MAAM,WACR,MAAM,YACL,GAAG,KACZ,IAAI;mCAyuBU,MAAM,mBACJ,MAAM,EAAE,KACxB,MAAM;;AA28CT,wBAkBE"}
@@ -333,8 +333,14 @@ const formatZodErrors = (zodError) => {
333
333
  const path = err.path.length > 0 ? err.path.join(".") : "root";
334
334
  // Provide more context based on error type
335
335
  switch (err.code) {
336
- case "invalid_type":
337
- return `Field "${path}": Expected ${err.expected}, but received ${err.received}`;
336
+ case "invalid_type": {
337
+ // zod v3 sets `received`; zod v4 names it only in the message
338
+ // ("Invalid input: expected string, received number").
339
+ const received = err.received ??
340
+ /received (\w+)/.exec(String(err.message ?? ""))?.[1] ??
341
+ "a different type";
342
+ return `Field "${path}": Expected ${err.expected}, but received ${received}`;
343
+ }
338
344
  case "invalid_literal":
339
345
  return `Field "${path}": Expected literal value ${JSON.stringify(err.expected)}, but received ${JSON.stringify(err.received)}`;
340
346
  case "unrecognized_keys":
@@ -771,19 +777,30 @@ const createAgent = (name, modelName, systemPrompt, tools = [], responseFormat,
771
777
  * @param onProgress - Optional callback invoked with progress event objects throughout
772
778
  * agent execution
773
779
  * @param usageTracker - Optional usage accumulator updated on successful completion
780
+ * @param progress - The percentage every progress event reports (the stage's
781
+ * current one; the agent loop has no percentage of its own). Defaults to 0.
774
782
  * @returns The raw response object returned by the agent's `invoke` method
775
783
  */
776
- const runAgent = async (agent, prompt, config, onProgress = null, usageTracker = null) => {
784
+ const runAgent = async (agent, prompt, config, onProgress = null, usageTracker = null, progress = 0) => {
777
785
  const startTime = Date.now();
786
+ // Every event carries `progress`: callers forward these to the platform's
787
+ // `{ progress, message }` progress bar, where a missing value would read as
788
+ // 0% and make the bar jump back during a tool call. The agent loop reports
789
+ // no percentage of its own, so the stage's current one is repeated.
778
790
  const callbacks = onProgress
779
791
  ? [
780
792
  {
781
- handleToolStart: (toolInfo) => {
782
- if (toolInfo.name)
793
+ // LangChain calls handleToolStart(serializedTool, input, runId,
794
+ // parentRunId, tags, metadata, runName): the serialized tool
795
+ // ({ lc, type, id }) has no name; the tool's name is runName.
796
+ handleToolStart: (toolInfo, _input, _runId, _parentRunId, _tags, _metadata, runName) => {
797
+ const name = runName || toolInfo?.name || toolInfo?.kwargs?.name;
798
+ if (name)
783
799
  onProgress({
784
800
  type: "tool_start",
785
- message: `Using "${toolInfo.name}" tool`,
786
- tool: toolInfo.name,
801
+ message: `Using "${name}" tool`,
802
+ tool: name,
803
+ progress,
787
804
  });
788
805
  },
789
806
  handleAgentAction: (action) => {
@@ -792,12 +809,14 @@ const runAgent = async (agent, prompt, config, onProgress = null, usageTracker =
792
809
  message: action.log || `Calling "${action.tool}" action`,
793
810
  tool: action.tool,
794
811
  input: action.toolInput,
812
+ progress,
795
813
  });
796
814
  },
797
815
  handleChainError: (err) => {
798
816
  onProgress({
799
817
  type: "error",
800
818
  message: `Error: ${err?.message || String(err)}`,
819
+ progress,
801
820
  });
802
821
  },
803
822
  },
@@ -1261,7 +1280,7 @@ const runPromptWithModel = async (modelName, config, prompt, onProgressReport, m
1261
1280
  let attempt = 0;
1262
1281
  for (;;) {
1263
1282
  // Run the agent with progress callback
1264
- const response = await runAgent(agent, activeUserPrompt, config, onProgressReport || null, usageTracker);
1283
+ const response = await runAgent(agent, activeUserPrompt, config, onProgressReport || null, usageTracker, minPercent);
1265
1284
  // Extract content from agent response
1266
1285
  const messages = response?.messages || [];
1267
1286
  if (messages.length === 0) {
@@ -0,0 +1,182 @@
1
+ /** What a STACKFACTOR reference to a knowledge base document carries (backend-core REFERENCE). */
2
+ export declare const STACKFACTOR_REFERENCE: Readonly<{
3
+ KIND: "STACKFACTOR";
4
+ TARGET_ELEMENT_TYPE: "KNOWLEDGE_BASE_DOCUMENT";
5
+ ORIGIN: "KB_EXTRACTION";
6
+ VISIBILITY: "EDIT";
7
+ }>;
8
+ /** How many documents one search may be kept to (the backend's bound); more are split. */
9
+ export declare const SEARCH_DOCUMENT_IDS_MAX = 500;
10
+ /** How long a query may be (the backend's bound); longer ones are cut. */
11
+ export declare const QUERY_MAX_LENGTH = 4000;
12
+ /** How many passages one search asks for when the caller does not say. */
13
+ export declare const DEFAULT_TOP_K = 8;
14
+ /** A chunk as the platform's search answers it (client-api `RetrievedChunk`). */
15
+ export interface KnowledgeChunk {
16
+ _id: string;
17
+ knowledgeBaseId?: string;
18
+ documentId: string;
19
+ documentName?: string | null;
20
+ sectionTitle?: string | null;
21
+ pageNumber?: number | null;
22
+ text?: string;
23
+ skills?: {
24
+ name: string | null;
25
+ microSkills?: string[];
26
+ }[];
27
+ score?: number | null;
28
+ [field: string]: unknown;
29
+ }
30
+ /** The platform's search, as client-api's `knowledgeBaseAgent.search` is called. */
31
+ export type KnowledgeSearch = (knowledgeBaseId: string, query: string, options: {
32
+ topK?: number;
33
+ documentIds?: string[];
34
+ }, token: string) => Promise<{
35
+ chunks: KnowledgeChunk[];
36
+ }>;
37
+ /** Where to search: a whole knowledge base, or only some of its documents. */
38
+ export interface KnowledgeSource {
39
+ knowledgeBaseId: string;
40
+ /** Only these documents; omitted, the whole knowledge base. */
41
+ documentIds?: string[];
42
+ }
43
+ /** A passage handed to the model, tagged so it can cite it. */
44
+ export interface GroundingPassage {
45
+ /** "k1", "k2"… in the order they rank. */
46
+ tag: string;
47
+ chunkId: string;
48
+ knowledgeBaseId: string;
49
+ documentId: string;
50
+ documentName: string | null;
51
+ sectionTitle: string | null;
52
+ pageNumber: number | null;
53
+ text: string;
54
+ /** The skills its passage teaches, as labelling named them. */
55
+ skills: {
56
+ name: string | null;
57
+ microSkills: string[];
58
+ }[];
59
+ score: number | null;
60
+ }
61
+ /** A knowledge base that could not be searched, and why. */
62
+ export interface SkippedSource {
63
+ knowledgeBaseId: string;
64
+ /** The HTTP status, when the platform answered one. */
65
+ status: number | null;
66
+ /** True when the person may not read it (or it is gone): expected, not a fault. */
67
+ noAccess: boolean;
68
+ message: string;
69
+ }
70
+ /** A STACKFACTOR reference to the knowledge base document a passage came from. */
71
+ export interface StackFactorReference {
72
+ kind: "STACKFACTOR";
73
+ title: string;
74
+ description: string | null;
75
+ target: {
76
+ elementType: "KNOWLEDGE_BASE_DOCUMENT";
77
+ elementId: string;
78
+ parentId: string;
79
+ };
80
+ knowledgeBase: {
81
+ knowledgeBaseId: string;
82
+ documentId: string;
83
+ chunkId: string;
84
+ sectionTitle: string | null;
85
+ };
86
+ origin: "KB_EXTRACTION";
87
+ visibility: "EDIT";
88
+ }
89
+ /**
90
+ * The knowledge bases, and the documents in them, that a list of references
91
+ * cites: its STACKFACTOR references to knowledge base documents, by their
92
+ * `knowledgeBase` ids, or by their `target` when only that is there. Any other
93
+ * reference is passed over. Each knowledge base once, its documents once each,
94
+ * in the order they first appear.
95
+ * @param references A skill's (or a microskill's) references
96
+ * @returns The sources to search
97
+ */
98
+ export declare const sourcesFromReferences: (references: unknown) => KnowledgeSource[];
99
+ /**
100
+ * The knowledge bases skill coverage found (client-api
101
+ * `knowledgeBase.getSkillCoverage`): every one the person can open that holds
102
+ * the skill, each searched whole.
103
+ * @param coverage The coverage answer, `{ knowledgeBases: [{ _id }] }`
104
+ * @returns The sources to search
105
+ */
106
+ export declare const sourcesFromCoverage: (coverage: unknown) => KnowledgeSource[];
107
+ /**
108
+ * Searches every source for every query, under the person's access, and hands
109
+ * back the passages found, best first, each once, tagged "k1", "k2"… for the
110
+ * model to cite. A source with documents is searched within them (in batches of
111
+ * SEARCH_DOCUMENT_IDS_MAX); one without, whole. A source the person may not
112
+ * read (401, 403, 404) is skipped: none of its passages are used and no more of
113
+ * its searches are made. A search that fails otherwise is reported and the
114
+ * passages its other searches found stand. Either way it is in `skipped`, once
115
+ * per knowledge base, and the passages of the others stand.
116
+ * @param options `sources`, `queries`, `search` (client-api
117
+ * `knowledgeBaseAgent.search`), `token` (the run's AGENT token), `topK`
118
+ * per search (default DEFAULT_TOP_K)
119
+ * @returns `{ passages, skipped }`
120
+ */
121
+ export declare const retrievePassages: (options: {
122
+ sources: KnowledgeSource[];
123
+ queries: string[];
124
+ search: KnowledgeSearch;
125
+ token: string;
126
+ topK?: number;
127
+ }) => Promise<{
128
+ passages: GroundingPassage[];
129
+ skipped: SkippedSource[];
130
+ }>;
131
+ /**
132
+ * The passages as a prompt shows them: tag, where each came from, and its text.
133
+ * @param passages From `retrievePassages`
134
+ * @returns `[{ tag, document, section, text }]`, for the model's input
135
+ */
136
+ export declare const passagesForPrompt: (passages: GroundingPassage[]) => {
137
+ tag: string;
138
+ document: string | null;
139
+ section: string | null;
140
+ text: string;
141
+ }[];
142
+ /**
143
+ * STACKFACTOR references for passages: one per passage, in their order, with no
144
+ * cap. With `tags`, only the passages the model cited by tag (any tag it made
145
+ * up is passed over); without, every passage.
146
+ * @param passages From `retrievePassages`
147
+ * @param tags The tags the model cited ("k3", "K3" and " k3 " alike)
148
+ * @returns The references, ready for a skill's, a microskill's or a question's `references`
149
+ */
150
+ export declare const referencesFor: (passages: GroundingPassage[], tags?: unknown[]) => StackFactorReference[];
151
+ declare const _default: {
152
+ DEFAULT_TOP_K: number;
153
+ QUERY_MAX_LENGTH: number;
154
+ SEARCH_DOCUMENT_IDS_MAX: number;
155
+ STACKFACTOR_REFERENCE: Readonly<{
156
+ KIND: "STACKFACTOR";
157
+ TARGET_ELEMENT_TYPE: "KNOWLEDGE_BASE_DOCUMENT";
158
+ ORIGIN: "KB_EXTRACTION";
159
+ VISIBILITY: "EDIT";
160
+ }>;
161
+ passagesForPrompt: (passages: GroundingPassage[]) => {
162
+ tag: string;
163
+ document: string | null;
164
+ section: string | null;
165
+ text: string;
166
+ }[];
167
+ referencesFor: (passages: GroundingPassage[], tags?: unknown[]) => StackFactorReference[];
168
+ retrievePassages: (options: {
169
+ sources: KnowledgeSource[];
170
+ queries: string[];
171
+ search: KnowledgeSearch;
172
+ token: string;
173
+ topK?: number;
174
+ }) => Promise<{
175
+ passages: GroundingPassage[];
176
+ skipped: SkippedSource[];
177
+ }>;
178
+ sourcesFromCoverage: (coverage: unknown) => KnowledgeSource[];
179
+ sourcesFromReferences: (references: unknown) => KnowledgeSource[];
180
+ };
181
+ export default _default;
182
+ //# sourceMappingURL=stackfactorKnowledge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackfactorKnowledge.d.ts","sourceRoot":"","sources":["../../src/stackfactorKnowledge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ //
3
+ // StackFactor knowledge — grounding generated content in the knowledge bases
4
+ //
5
+ // A generation agent grounded in StackFactor (the Additional Information data
6
+ // source "StackFactor", `dataSource: "RAG"`) writes from knowledge-base
7
+ // passages instead of a web search, and cites every passage it used as a
8
+ // STACKFACTOR reference. A later agent generating for the same skill (its
9
+ // assessments, its learning content) reads those references and searches the
10
+ // documents they cite. Designed with Candin, 2026-10-08:
11
+ //
12
+ // - which knowledge bases: every one the person can open that holds the
13
+ // skill (skill coverage), never a fixed number of them;
14
+ // - which references: one per passage used, with no cap per document or per
15
+ // microskill;
16
+ // - access: the platform's search judges the person the run acts for, so a
17
+ // run reads only what that person may open. A knowledge base the person
18
+ // cannot read is skipped and reported, never an error: the agent
19
+ // generates without it.
20
+ //
21
+ // A reference points at the content and never copies it: the passage is
22
+ // searched again, under the reader's own access, whenever it is used. It is
23
+ // EDIT-only (`visibility: "EDIT"`): the platform strips it from what is
24
+ // published, so a knowledge base's titles never reach a learner; agents read
25
+ // it from the draft.
26
+ //
27
+ // The search itself is the caller's (`search`: client-api
28
+ // `knowledgeBaseAgent.search`, 1.11 or later for `documentIds`), so this
29
+ // module needs no particular client-api.
30
+ //
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.referencesFor = exports.passagesForPrompt = exports.retrievePassages = exports.sourcesFromCoverage = exports.sourcesFromReferences = exports.DEFAULT_TOP_K = exports.QUERY_MAX_LENGTH = exports.SEARCH_DOCUMENT_IDS_MAX = exports.STACKFACTOR_REFERENCE = void 0;
33
+ /** What a STACKFACTOR reference to a knowledge base document carries (backend-core REFERENCE). */
34
+ exports.STACKFACTOR_REFERENCE = Object.freeze({
35
+ KIND: "STACKFACTOR",
36
+ TARGET_ELEMENT_TYPE: "KNOWLEDGE_BASE_DOCUMENT",
37
+ ORIGIN: "KB_EXTRACTION",
38
+ VISIBILITY: "EDIT",
39
+ });
40
+ /** How many documents one search may be kept to (the backend's bound); more are split. */
41
+ exports.SEARCH_DOCUMENT_IDS_MAX = 500;
42
+ /** How long a query may be (the backend's bound); longer ones are cut. */
43
+ exports.QUERY_MAX_LENGTH = 4000;
44
+ /** How many passages one search asks for when the caller does not say. */
45
+ exports.DEFAULT_TOP_K = 8;
46
+ /** How many searches run at once. */
47
+ const CONCURRENCY = 4;
48
+ /** Statuses that mean the person may not read the knowledge base, or it is gone. */
49
+ const NO_ACCESS = new Set([401, 403, 404]);
50
+ const text = (value) => (typeof value === "string" ? value.trim() : "");
51
+ const id = (value) => typeof value === "string" ? value.trim() : value != null && typeof value === "object" ? String(value) : "";
52
+ /**
53
+ * The knowledge bases, and the documents in them, that a list of references
54
+ * cites: its STACKFACTOR references to knowledge base documents, by their
55
+ * `knowledgeBase` ids, or by their `target` when only that is there. Any other
56
+ * reference is passed over. Each knowledge base once, its documents once each,
57
+ * in the order they first appear.
58
+ * @param references A skill's (or a microskill's) references
59
+ * @returns The sources to search
60
+ */
61
+ const sourcesFromReferences = (references) => {
62
+ const byBase = new Map();
63
+ for (const reference of Array.isArray(references) ? references : []) {
64
+ if (reference?.kind !== exports.STACKFACTOR_REFERENCE.KIND)
65
+ continue;
66
+ const target = reference.target ?? {};
67
+ const isDocumentTarget = target.elementType === exports.STACKFACTOR_REFERENCE.TARGET_ELEMENT_TYPE;
68
+ const knowledgeBaseId = id(reference.knowledgeBase?.knowledgeBaseId) || (isDocumentTarget ? id(target.parentId) : "");
69
+ const documentId = id(reference.knowledgeBase?.documentId) || (isDocumentTarget ? id(target.elementId) : "");
70
+ if (!knowledgeBaseId || !documentId)
71
+ continue;
72
+ const documents = byBase.get(knowledgeBaseId) ?? new Set();
73
+ documents.add(documentId);
74
+ byBase.set(knowledgeBaseId, documents);
75
+ }
76
+ return [...byBase.entries()].map(([knowledgeBaseId, documents]) => ({
77
+ knowledgeBaseId,
78
+ documentIds: [...documents],
79
+ }));
80
+ };
81
+ exports.sourcesFromReferences = sourcesFromReferences;
82
+ /**
83
+ * The knowledge bases skill coverage found (client-api
84
+ * `knowledgeBase.getSkillCoverage`): every one the person can open that holds
85
+ * the skill, each searched whole.
86
+ * @param coverage The coverage answer, `{ knowledgeBases: [{ _id }] }`
87
+ * @returns The sources to search
88
+ */
89
+ const sourcesFromCoverage = (coverage) => {
90
+ const bases = coverage?.knowledgeBases;
91
+ const seen = new Set();
92
+ const sources = [];
93
+ for (const base of Array.isArray(bases) ? bases : []) {
94
+ const knowledgeBaseId = id(base?._id);
95
+ if (!knowledgeBaseId || seen.has(knowledgeBaseId))
96
+ continue;
97
+ seen.add(knowledgeBaseId);
98
+ sources.push({ knowledgeBaseId });
99
+ }
100
+ return sources;
101
+ };
102
+ exports.sourcesFromCoverage = sourcesFromCoverage;
103
+ /** The documents of a source in batches the backend accepts; one batch of none for a whole knowledge base. */
104
+ const batchesOf = (source) => {
105
+ if (!Array.isArray(source.documentIds))
106
+ return [undefined];
107
+ const batches = [];
108
+ for (let at = 0; at < source.documentIds.length; at += exports.SEARCH_DOCUMENT_IDS_MAX) {
109
+ batches.push(source.documentIds.slice(at, at + exports.SEARCH_DOCUMENT_IDS_MAX));
110
+ }
111
+ return batches;
112
+ };
113
+ /** Runs `worker` over `items`, at most `limit` at a time. */
114
+ const inPool = async (items, limit, worker) => {
115
+ let next = 0;
116
+ const run = async () => {
117
+ while (next < items.length) {
118
+ const index = next++;
119
+ await worker(items[index]);
120
+ }
121
+ };
122
+ await Promise.all(Array.from({ length: Math.min(limit, items.length) }, run));
123
+ };
124
+ /** The status of a failed platform call, from an axios error or one shaped like it. */
125
+ const statusOf = (error) => {
126
+ const status = error?.response?.status ?? error?.status;
127
+ return typeof status === "number" ? status : null;
128
+ };
129
+ /**
130
+ * Searches every source for every query, under the person's access, and hands
131
+ * back the passages found, best first, each once, tagged "k1", "k2"… for the
132
+ * model to cite. A source with documents is searched within them (in batches of
133
+ * SEARCH_DOCUMENT_IDS_MAX); one without, whole. A source the person may not
134
+ * read (401, 403, 404) is skipped: none of its passages are used and no more of
135
+ * its searches are made. A search that fails otherwise is reported and the
136
+ * passages its other searches found stand. Either way it is in `skipped`, once
137
+ * per knowledge base, and the passages of the others stand.
138
+ * @param options `sources`, `queries`, `search` (client-api
139
+ * `knowledgeBaseAgent.search`), `token` (the run's AGENT token), `topK`
140
+ * per search (default DEFAULT_TOP_K)
141
+ * @returns `{ passages, skipped }`
142
+ */
143
+ const retrievePassages = async (options) => {
144
+ const queries = [
145
+ ...new Set((Array.isArray(options.queries) ? options.queries : [])
146
+ .map((query) => text(query).slice(0, exports.QUERY_MAX_LENGTH))
147
+ .filter(Boolean)),
148
+ ];
149
+ const sources = Array.isArray(options.sources) ? options.sources : [];
150
+ const topK = options.topK ?? exports.DEFAULT_TOP_K;
151
+ const searches = [];
152
+ for (const source of sources) {
153
+ for (const documentIds of batchesOf(source)) {
154
+ if (documentIds && documentIds.length === 0)
155
+ continue;
156
+ for (const query of queries) {
157
+ searches.push({ source, query, documentIds, order: searches.length });
158
+ }
159
+ }
160
+ }
161
+ const found = new Map();
162
+ const skipped = new Map();
163
+ await inPool(searches, CONCURRENCY, async ({ source, query, documentIds, order }) => {
164
+ if (skipped.get(source.knowledgeBaseId)?.noAccess)
165
+ return;
166
+ try {
167
+ const answer = await options.search(source.knowledgeBaseId, query, documentIds ? { topK, documentIds } : { topK }, options.token);
168
+ (Array.isArray(answer?.chunks) ? answer.chunks : []).forEach((chunk, rank) => {
169
+ const chunkId = id(chunk?._id);
170
+ if (!chunkId || !id(chunk?.documentId))
171
+ return;
172
+ const known = found.get(chunkId);
173
+ const better = !known || (chunk.score ?? 0) > (known.chunk.score ?? 0);
174
+ // Ties keep the first search's rank, so the order is the searches' own.
175
+ found.set(chunkId, {
176
+ chunk: better ? chunk : known.chunk,
177
+ knowledgeBaseId: source.knowledgeBaseId,
178
+ order: known ? Math.min(known.order, order * 1000 + rank) : order * 1000 + rank,
179
+ });
180
+ });
181
+ }
182
+ catch (error) {
183
+ const status = statusOf(error);
184
+ const noAccess = status !== null && NO_ACCESS.has(status);
185
+ // A refusal outranks a failure reported before it.
186
+ if (skipped.has(source.knowledgeBaseId) && !noAccess)
187
+ return;
188
+ skipped.set(source.knowledgeBaseId, {
189
+ knowledgeBaseId: source.knowledgeBaseId,
190
+ message: typeof error?.message === "string" ? error.message : String(error),
191
+ noAccess,
192
+ status,
193
+ });
194
+ }
195
+ });
196
+ const passages = [...found.entries()]
197
+ .filter(([, entry]) => !skipped.get(entry.knowledgeBaseId)?.noAccess)
198
+ .sort(([, a], [, b]) => (b.chunk.score ?? 0) - (a.chunk.score ?? 0) || a.order - b.order)
199
+ .map(([chunkId, { chunk, knowledgeBaseId }], index) => ({
200
+ chunkId,
201
+ documentId: id(chunk.documentId),
202
+ documentName: text(chunk.documentName) || null,
203
+ knowledgeBaseId: id(chunk.knowledgeBaseId) || knowledgeBaseId,
204
+ pageNumber: typeof chunk.pageNumber === "number" ? chunk.pageNumber : null,
205
+ score: typeof chunk.score === "number" ? chunk.score : null,
206
+ sectionTitle: text(chunk.sectionTitle) || null,
207
+ skills: (Array.isArray(chunk.skills) ? chunk.skills : []).map((skill) => ({
208
+ microSkills: (Array.isArray(skill?.microSkills) ? skill.microSkills : []).filter((name) => typeof name === "string"),
209
+ name: typeof skill?.name === "string" ? skill.name : null,
210
+ })),
211
+ tag: `k${index + 1}`,
212
+ text: typeof chunk.text === "string" ? chunk.text : "",
213
+ }));
214
+ return { passages, skipped: [...skipped.values()] };
215
+ };
216
+ exports.retrievePassages = retrievePassages;
217
+ /**
218
+ * The passages as a prompt shows them: tag, where each came from, and its text.
219
+ * @param passages From `retrievePassages`
220
+ * @returns `[{ tag, document, section, text }]`, for the model's input
221
+ */
222
+ const passagesForPrompt = (passages) => (Array.isArray(passages) ? passages : []).map((passage) => ({
223
+ document: passage.documentName,
224
+ section: passage.sectionTitle,
225
+ tag: passage.tag,
226
+ text: passage.text,
227
+ }));
228
+ exports.passagesForPrompt = passagesForPrompt;
229
+ /**
230
+ * STACKFACTOR references for passages: one per passage, in their order, with no
231
+ * cap. With `tags`, only the passages the model cited by tag (any tag it made
232
+ * up is passed over); without, every passage.
233
+ * @param passages From `retrievePassages`
234
+ * @param tags The tags the model cited ("k3", "K3" and " k3 " alike)
235
+ * @returns The references, ready for a skill's, a microskill's or a question's `references`
236
+ */
237
+ const referencesFor = (passages, tags) => {
238
+ const list = Array.isArray(passages) ? passages : [];
239
+ const cited = Array.isArray(tags)
240
+ ? new Set(tags.map((tag) => text(tag).toLowerCase()).filter(Boolean))
241
+ : null;
242
+ return list
243
+ .filter((passage) => !cited || cited.has(passage.tag.toLowerCase()))
244
+ .map((passage) => ({
245
+ description: passage.sectionTitle,
246
+ kind: exports.STACKFACTOR_REFERENCE.KIND,
247
+ knowledgeBase: {
248
+ chunkId: passage.chunkId,
249
+ documentId: passage.documentId,
250
+ knowledgeBaseId: passage.knowledgeBaseId,
251
+ sectionTitle: passage.sectionTitle,
252
+ },
253
+ origin: exports.STACKFACTOR_REFERENCE.ORIGIN,
254
+ target: {
255
+ elementId: passage.documentId,
256
+ elementType: exports.STACKFACTOR_REFERENCE.TARGET_ELEMENT_TYPE,
257
+ parentId: passage.knowledgeBaseId,
258
+ },
259
+ title: passage.documentName || passage.sectionTitle || "Knowledge base document",
260
+ visibility: exports.STACKFACTOR_REFERENCE.VISIBILITY,
261
+ }));
262
+ };
263
+ exports.referencesFor = referencesFor;
264
+ exports.default = {
265
+ DEFAULT_TOP_K: exports.DEFAULT_TOP_K,
266
+ QUERY_MAX_LENGTH: exports.QUERY_MAX_LENGTH,
267
+ SEARCH_DOCUMENT_IDS_MAX: exports.SEARCH_DOCUMENT_IDS_MAX,
268
+ STACKFACTOR_REFERENCE: exports.STACKFACTOR_REFERENCE,
269
+ passagesForPrompt: exports.passagesForPrompt,
270
+ referencesFor: exports.referencesFor,
271
+ retrievePassages: exports.retrievePassages,
272
+ sourcesFromCoverage: exports.sourcesFromCoverage,
273
+ sourcesFromReferences: exports.sourcesFromReferences,
274
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/errorHandling.ts"],"names":[],"mappings":"AAGA,gEAAgE;AAChE,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AA8GD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,MAAM,GAAE,WAAgB;IAUpC;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ;IAKrC;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW;IAIzC;;;;OAIG;IACH,OAAO,IAAI,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAS1D,MAAM,IAAI,WAAW;IAIrB;;;;OAIG;IACH,WAAW,IAAI,KAAK;IAIpB;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,GAAE,GAAU,EAAE,KAAK,GAAE,QAAkB,EAAE,OAAO,GAAE,GAAQ,GAAG,IAAI;CAU7E;;IAkBC;;;;;;;;;OASG;wBACiB,MAAM,gBAAgB,MAAM,YAAW,GAAG;;;;;;IAU9D,6EAA6E;mBApOpD,GAAG,KAAG,WAAW;IAsO1C,0EAA0E;;IAE1E,gFAAgF;oBA9BzE,OAAO,YACL,GAAG,YACH,GAAG,KACX,QAAQ;IA6BT,wDAAwD;uBArPhC,GAAG,KAAG,IAAI,IAAI,MAAM;IAuP5C,kCAAkC;;;AA7BpC,wBA+BE"}
1
+ {"version":3,"file":"errorHandling.d.ts","sourceRoot":"","sources":["../../src/errorHandling.ts"],"names":[],"mappings":"AAGA,gEAAgE;AAChE,KAAK,QAAQ,GACT,OAAO,GACP,MAAM,GACN,MAAM,GACN,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,CAAC;AAEZ;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmHD;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,0EAA0E;IAC1E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC;IACvB,qEAAqE;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;gBAElB,MAAM,GAAE,WAAgB;IAUpC;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ;IAKrC;;;OAGG;IACH,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW;IAIzC;;;;OAIG;IACH,OAAO,IAAI,WAAW,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAS1D,MAAM,IAAI,WAAW;IAIrB;;;;OAIG;IACH,WAAW,IAAI,KAAK;IAIpB;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,GAAE,GAAU,EAAE,KAAK,GAAE,QAAkB,EAAE,OAAO,GAAE,GAAQ,GAAG,IAAI;CAU7E;;IAkBC;;;;;;;;;OASG;wBACiB,MAAM,gBAAgB,MAAM,YAAW,GAAG;;;;;;IAU9D,6EAA6E;mBAzOpD,GAAG,KAAG,WAAW;IA2O1C,0EAA0E;;IAE1E,gFAAgF;oBA9BzE,OAAO,YACL,GAAG,YACH,GAAG,KACX,QAAQ;IA6BT,wDAAwD;uBA1PhC,GAAG,KAAG,IAAI,IAAI,MAAM;IA4P5C,kCAAkC;;;AA7BpC,wBA+BE"}