@xbbg/langgraph 1.2.7 → 1.3.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/dist/index.js CHANGED
@@ -65,6 +65,13 @@ var DEFAULT_MAX_BQL_QUERY_CHARS = 4e3;
65
65
  var DEFAULT_MAX_SEARCH_SPEC_CHARS = 1e3;
66
66
  var DEFAULT_MAX_STREAM_UPDATES = 10;
67
67
  var DEFAULT_MAX_STREAM_WAIT_MS = 15e3;
68
+ var DEFAULT_ENGINE_REQUEST_TIMEOUT_MS = 6e4;
69
+ function engineConfigWithDefaults(config) {
70
+ if (config?.requestTimeoutMs !== void 0) {
71
+ return config;
72
+ }
73
+ return { ...config, requestTimeoutMs: DEFAULT_ENGINE_REQUEST_TIMEOUT_MS };
74
+ }
68
75
  function positiveInteger(value, fallback, name) {
69
76
  if (value === void 0) {
70
77
  return fallback;
@@ -82,7 +89,7 @@ function normalizeBloombergToolsOptions(options = {}) {
82
89
  core: options.core,
83
90
  disabledTools: disabledToolSet(options.disabledTools),
84
91
  engine: options.engine,
85
- engineConfig: options.engineConfig,
92
+ engineConfig: engineConfigWithDefaults(options.engineConfig),
86
93
  maxBqlQueryChars: positiveInteger(
87
94
  options.maxBqlQueryChars,
88
95
  DEFAULT_MAX_BQL_QUERY_CHARS,
@@ -167,180 +174,6 @@ function createCoreResolver(options = {}) {
167
174
  options: normalized
168
175
  };
169
176
  }
170
- function inputJsonSchema(schema) {
171
- const jsonSchema = zodToJsonSchema.zodToJsonSchema(schema, {
172
- $refStrategy: "none",
173
- effectStrategy: "input",
174
- pipeStrategy: "input"
175
- });
176
- delete jsonSchema.$schema;
177
- delete jsonSchema.definitions;
178
- return jsonSchema;
179
- }
180
- function createBloombergStructuredTool(func, fields) {
181
- const providerToolDefinition = {
182
- type: "function",
183
- function: {
184
- description: fields.description,
185
- name: fields.name,
186
- parameters: inputJsonSchema(fields.schema)
187
- }
188
- };
189
- return tools.tool(
190
- func,
191
- {
192
- ...fields,
193
- extras: { providerToolDefinition }
194
- }
195
- );
196
- }
197
-
198
- // src/cdx-fields.ts
199
- var CDX_INFO_FIELDS = Object.freeze([
200
- "ROLLING_SERIES",
201
- "VERSION",
202
- "ON_THE_RUN_CURRENT_BD_INDICATOR",
203
- "CDS_FIRST_ACCRUAL_START_DATE",
204
- "NAME",
205
- "NUM_CURRENT_COMPANIES_CCY_TKR",
206
- "NUM_ORIG_COMPANIES_CRNCY_TKR",
207
- "PX_LAST"
208
- ]);
209
- var CDX_PRICING_FIELDS = Object.freeze([
210
- "PX_LAST",
211
- "PX_BID",
212
- "PX_ASK",
213
- "UPFRONT_LAST",
214
- "UPFRONT_BID",
215
- "UPFRONT_ASK",
216
- "CDS_FLAT_SPREAD",
217
- "UPFRONT_FEE",
218
- "PV_CDS_PREMIUM_LEG",
219
- "PV_CDS_DEFAULT_LEG"
220
- ]);
221
- var CDX_RISK_FIELDS = Object.freeze([
222
- "SW_CNV_BPV",
223
- "SW_EQV_BPV",
224
- "CDS_SPREAD_MID_MODIFIED_DURATION",
225
- "CDS_SPREAD_MID_CONVEXITY",
226
- "RECOVERY_RATE_SEN",
227
- "CDS_RECOVERY_RT"
228
- ]);
229
-
230
- // src/descriptions.ts
231
- var REQUIRED_TOOL_INSTRUCTIONS = [
232
- "# Bloomberg tool usage",
233
- "- Use these tools only for server-side Bloomberg data access through @xbbg/core. Never imply Bloomberg data was retrieved unless a tool call actually returned it.",
234
- "- Ask a clarifying question before calling a tool when any security identity, field mnemonic, date range, currency, periodicity, intraday interval, timezone, override, or universe is ambiguous.",
235
- "- Do not invent Bloomberg tickers, field mnemonics, overrides, or BQL functions. If the user gives a field description rather than a confident mnemonic, call xbbg_bflds first.",
236
- "",
237
- "## Security identifiers",
238
- "- Prefer fully qualified Bloomberg securities supplied by the user, such as <TICKER> <MARKET_SECTOR>, <INDEX_TICKER> <MARKET_SECTOR>, or <CREDIT_INDEX_TICKER> <MARKET_SECTOR>.",
239
- "- For raw security identifiers, request or pass Bloomberg identifier syntax directly: /isin/<ISIN> for ISINs or /cusip/<CUSIP> for CUSIPs.",
240
- "- Do not pass raw ISIN or CUSIP strings when the request is meant to identify a security. Do not use xbbg_bsrch as a replacement for a known ticker, ISIN, or CUSIP.",
241
- "- For dealer quote / BQR workflows, use xbbg_bqr with a fixed-income identifier plus a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>. For raw intraday ticks, use xbbg_bdtick.",
242
- "",
243
- "## Core request tools",
244
- "- xbbg_bdp: current or reference point-in-time fields. Use a small explicit securities list and a small explicit fields list. Use includeSecurityErrors only when the caller wants Bloomberg security errors in the response.",
245
- "- xbbg_bdh: historical daily or periodic time series. Always provide explicit start and end dates in YYYY-MM-DD or YYYYMMDD form. Ask before choosing periodicity, currency, fill behavior, adjustment overrides, or a wide output table.",
246
- "- xbbg_bds: Bloomberg bulk/table fields. Provide exactly one bulk field; do not use bds for ordinary multi-field reference data.",
247
- "- xbbg_bdib: intraday bars only. Provide one ticker, explicit ISO start/end datetimes with time components, a positive interval in minutes, and timezone context when datetimes are naive.",
248
- "- xbbg_bdtick: intraday tick data. Provide one ticker, explicit ISO start/end datetimes with time components, and explicit eventTypes unless the default event stream is intended. Use includeBrokerCodes or includeConditionCodes only when those columns are needed.",
249
- "- xbbg_bql: BQL expressions only when the user asks for BQL or the request is naturally expressed as a bounded BQL query. Keep queries short, explicit, and scoped to the requested universe.",
250
- "- xbbg_bsrch: Bloomberg search-grid or saved-search workflows only. Do not use it for ordinary security lookup.",
251
- "- xbbg_bqr: Bloomberg Quote Request / dealer quotes. Prefer fixed-income identifier inputs with a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>, explicit start/end datetimes with time components, and explicit event types.",
252
- "- xbbg_bflds: Bloomberg field metadata/search. Provide exactly one of fields or searchSpec; use searchSpec for natural-language field names and fields for known mnemonics.",
253
- "- xbbg_beqs: Bloomberg equity screening by named BEQS screen. Prefer this over hand-written BQL when the user names an existing Bloomberg screen.",
254
- "- xbbg_yas: fixed-income YAS recipe fields. Prefer this over manual YAS-style BDP requests when the user asks for yield, duration, spread, or price analytics.",
255
- "- xbbg_preferreds: preferred stock discovery from an equity ticker. Prefer this over xbbg_ext_bql_builder plus xbbg_bql when the user wants the actual preferreds result.",
256
- "- xbbg_corporate_bonds: bounded corporate bond universe query for a company ticker. Prefer this over generic BQL for company debt discovery.",
257
- "- xbbg_index_members: index constituents through the core index recipe. Prefer this over generic BDS/BQL members when the user asks for constituents.",
258
- "- xbbg_resolve_isins: resolves supplied ISIN strings to Bloomberg securities. Pass raw ISIN strings only for this recipe; otherwise use /isin/<ISIN> syntax with data tools.",
259
- "- xbbg_issuer_isins: issuer/bond ISIN workflow for supplied bond ISIN strings.",
260
- "- xbbg_etf_holdings: ETF holdings recipe for a single ETF ticker. Prefer this over generic BQL holdings when the user asks for ETF constituents.",
261
- "- xbbg_stream_snapshot: bounded live market-data observation from //blp/mktdata. Requires explicit maxUpdates and always terminates/unsubscribes.",
262
- "- xbbg_mktbar_snapshot: bounded live market-bar observation from //blp/mktbar for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
263
- "- xbbg_depth_snapshot: bounded market-depth observation from //blp/mktdepthdata for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
264
- "",
265
- "## BQL guidance",
266
- "- BQL is a complete Bloomberg Query Language expression sent as one query string; the tool does not assemble get/for/with clauses for you.",
267
- "- Basic shape: get(<FIELD_1>, <FIELD_2>) for(<UNIVERSE>). Use placeholders such as '<TICKER> <MARKET_SECTOR>', holdings('<ETF_TICKER> <MARKET_SECTOR>'), or members('<INDEX_TICKER> <MARKET_SECTOR>') until the user supplies real inputs.",
268
- "- Use BQL for universe-oriented analytics and screens only when the user provides a bounded universe, filters, and date range.",
269
- "- Prefer xbbg_ext_bql_builder instead of hand-writing BQL for supported workflows: preferred stocks, corporate bonds, and ETF holdings.",
270
- "- Do not use BQL just because the user asks for normal reference data; xbbg_bdp is simpler for current fields and xbbg_bdh is simpler for historical time series.",
271
- "",
272
- "## Output handling",
273
- "- Tool results use LangChain content_and_artifact output: content starts with a compact summary and then includes bounded model-readable JSON; artifact is the structured bounded envelope with tool, rowCount, truncated, and data for application code.",
274
- "- If a response is empty, truncated, or contains Bloomberg/security errors, say that directly. Do not fill gaps from memory or assumptions."
275
- ];
276
- var OPTIONAL_EXTENSION_INSTRUCTIONS = [
277
- "",
278
- "## Extension helper tools",
279
- "- xbbg_ext_ticker: ticker hygiene before live calls. parse_ticker splits a Bloomberg ticker, normalize_tickers trims/canonicalizes lists, filter_equity_tickers keeps equity-like tickers, is_specific_contract checks futures specificity, and validate_generic_ticker rejects malformed generic futures tickers.",
280
- "- xbbg_ext_futures: futures contract construction and selection. Use build_futures_ticker for root/month/year/asset assembly, get_futures_months for month-code lookup, generate_candidates for generic-to-specific candidates, contract_index for generic contract rank, filter_candidates_by_cycle for HMUZ/quarterly cycles, and filter_valid_contracts to keep contracts valid for a date.",
281
- "- xbbg_ext_cdx: CDX ticker workflow support. Use parse_cdx_ticker to understand a CDX ticker, previous_cdx_series to roll back a series, cdx_gen_to_specific to resolve a generic CDX to a target series, and cdx_info/cdx_pricing/cdx_risk for predefined BDP field bundles. cdx_pricing and cdx_risk accept recoveryRate, which becomes the CDS_RR override.",
282
- "- xbbg_ext_currency: currency-planning helpers. build_fx_pair constructs the Bloomberg FX pair and conversion factor, same_currency avoids unnecessary conversion, and currencies_needing_conversion identifies which currencies differ from a target before requesting converted values.",
283
- "- xbbg_ext_bql_builder: safe BQL generators for common xbbg workflows. Use build_preferreds_query for preferred-stock discovery from an equity, build_corporate_bonds_query for company bond universes with optional currency/active filters, and build_etf_holdings_query for ETF constituents. Prefer these builders over hand-writing those BQL shapes.",
284
- "- xbbg_ext_market_session: exchange calendar/timezone support. derive_sessions turns day session times into session blocks, infer_timezone maps country codes to timezones, session_times_to_utc converts local sessions to UTC, get_market_rule gets MIC/exchange rules, default_turnover_dates and default_bqr_datetimes provide bounded defaults, and get/list_exchange_override inspect configured exchange metadata.",
285
- "- xbbg_ext_yas_overrides: builds flat YAS override maps for fixed-income BDP requests when the lower-level BDP workflow is required. Prefer xbbg_yas for actual YAS recipe fields.",
286
- "- xbbg_ext_constants: static lookup/format helpers for date parsing/formatting, futures month code/name mappings, dividend type mappings, and known dividend/ETF output columns.",
287
- "- xbbg_ext_columns: post-processing helpers for Bloomberg-shaped tables. Use rename_dividend_columns, rename_etf_columns, or build_earning_header_rename when explaining or normalizing response column names after a request.",
288
- "- xbbg_ext_calculate: small numeric helper for Bloomberg workflows. calculate_level_percentages pairs observed values with levels; values and levels must have the same length."
289
- ];
290
- var OPTIONAL_LIMIT_INSTRUCTIONS = [
291
- "",
292
- "## Request limits and inputs",
293
- "- Keep Bloomberg requests bounded: explicit securities, explicit fields, explicit dates, limited rows, and no broad exploratory pulls unless the user narrows the universe.",
294
- "- Respect configured tool limits for securities, fields, rows, string size, BQL length, and search spec length. Ask the user to narrow the request rather than exceeding them.",
295
- "- Use flat primitive overrides and kwargs only: string, number, or boolean values. Do not send nested objects, arrays, or inferred defaults as overrides."
296
- ];
297
- var BLOOMBERG_TOOL_INSTRUCTIONS = [
298
- ...REQUIRED_TOOL_INSTRUCTIONS,
299
- ...OPTIONAL_EXTENSION_INSTRUCTIONS,
300
- ...OPTIONAL_LIMIT_INSTRUCTIONS
301
- ].join("\n");
302
- function getBloombergToolInstructions(options = {}) {
303
- const includeExtensionGuidance = options.includeExtensionGuidance ?? true;
304
- const includeLimitReminder = options.includeLimitReminder ?? true;
305
- const lines = [...REQUIRED_TOOL_INSTRUCTIONS];
306
- if (includeExtensionGuidance) {
307
- lines.push(...OPTIONAL_EXTENSION_INSTRUCTIONS);
308
- }
309
- if (includeLimitReminder) {
310
- lines.push(...OPTIONAL_LIMIT_INSTRUCTIONS);
311
- }
312
- return lines.join("\n");
313
- }
314
- var BDP_DESCRIPTION = 'Bloomberg reference data for current or point-in-time fields. Use for a small bounded list of fully qualified securities. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"].';
315
- var BDH_DESCRIPTION = 'Bloomberg historical time series. Requires explicit start and end dates; ask before using if the date range or periodicity is ambiguous. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"], start "<START_DATE>", end "<END_DATE>".';
316
- var BDS_DESCRIPTION = 'Bloomberg bulk/table reference data. Requires exactly one bulk field, not a field list. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<INDEX_TICKER> <MARKET_SECTOR>"], field "<BULK_FIELD>".';
317
- var BDIB_DESCRIPTION = 'Bloomberg intraday bars. Requires one ticker plus explicit ISO start/end datetimes with time components and a positive interval in minutes. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: ticker "<TICKER> <MARKET_SECTOR>", start "<START_DATETIME>", end "<END_DATETIME>", interval <MINUTES>.';
318
- var BDTICK_DESCRIPTION = 'Bloomberg intraday tick data. Requires one ticker plus explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"], and includeBrokerCodes/includeConditionCodes only when needed.';
319
- var BQL_DESCRIPTION = "Bloomberg Query Language expression sent as one complete query string. Use for bounded universe analytics with placeholder-shaped syntax such as get(<FIELD>) for('<TICKER> <MARKET_SECTOR>'), holdings('<ETF_TICKER> <MARKET_SECTOR>'), members('<INDEX_TICKER> <MARKET_SECTOR>'), filters with with(...), or dates=range(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.";
320
- var BSRCH_DESCRIPTION = 'Bloomberg search/grid request. Use for saved-search or ExcelGetGrid-style Bloomberg searches, not ordinary security lookup. Example searchSpec "<SEARCH_SPEC>".';
321
- var BQR_DESCRIPTION = 'Bloomberg Quote Request / dealer quotes. Use for fixed-income dealer quote ticks, preferably with an ISIN plus dealer source such as "/isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>"; requires explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"].';
322
- var BFLDS_DESCRIPTION = 'Bloomberg field metadata and field search. Use first when a field mnemonic is uncertain. Provide exactly one of fields or searchSpec. Example: fields ["<FIELD>"] or searchSpec "<FIELD_SEARCH_TEXT>".';
323
- var BEQS_DESCRIPTION = "Bloomberg equity screening by named BEQS screen. Use when the user names an existing Bloomberg screen and wants its bounded result set. Prefer this over hand-written BQL for saved Bloomberg screens.";
324
- var YAS_DESCRIPTION = "Bloomberg fixed-income YAS recipe fields for one or more bonds. Use for yield, duration, spread, benchmark, or price analytics; provide explicit fields and optional settlement/yield/price inputs.";
325
- var PREFERREDS_DESCRIPTION = "Preferred stock discovery for one equity ticker. Use when the user asks for preferred shares or preferred stock securities related to an issuer.";
326
- var CORPORATE_BONDS_DESCRIPTION = "Corporate bond universe query for one issuer/company ticker, with optional currency, active-only filter, and result fields. Prefer this over generic BQL for company debt discovery.";
327
- var INDEX_MEMBERS_DESCRIPTION = "Index constituent recipe for one Bloomberg index. Use for bounded member lists and optional historical/as-of constituent membership.";
328
- var RESOLVE_ISINS_DESCRIPTION = "Resolve raw ISIN strings to Bloomberg securities through the core ISIN recipe. Do not add /isin/ prefixes in this tool; pass the exact ISIN strings supplied by the user.";
329
- var ISSUER_ISINS_DESCRIPTION = "Issuer/bond ISIN workflow for supplied bond ISIN strings. Use for issuer-level ISIN discovery starting from known bond ISINs.";
330
- var ETF_HOLDINGS_DESCRIPTION = "ETF holdings recipe for one ETF ticker. Use when the user asks for ETF constituents or holdings and wants the bounded holdings result.";
331
- var STREAM_SNAPSHOT_DESCRIPTION = "Bounded live market-data snapshot from //blp/mktdata. Collects at most maxUpdates updates until timeout/done, then always unsubscribes; use for finite observations, not open subscriptions.";
332
- var MKTBAR_SNAPSHOT_DESCRIPTION = "Bounded live market-bar snapshot from //blp/mktbar for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
333
- var DEPTH_SNAPSHOT_DESCRIPTION = "Bounded live market-depth snapshot from //blp/mktdepthdata for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
334
- var EXT_TICKER_DESCRIPTION = "Ticker hygiene helpers: parse_ticker, normalize_tickers, filter_equity_tickers, is_specific_contract, and validate_generic_ticker.";
335
- var EXT_FUTURES_DESCRIPTION = "Futures helpers for contract construction and selection: build_futures_ticker, generate_candidates, contract_index, filter_candidates_by_cycle, filter_valid_contracts, and get_futures_months.";
336
- var EXT_CDX_DESCRIPTION = "CDX helpers for parsing, series rolling/resolution, and predefined info/pricing/risk BDP field bundles.";
337
- var EXT_CURRENCY_DESCRIPTION = "Currency planning helpers: build FX pairs, test same-currency requests, and find currencies needing conversion.";
338
- var EXT_BQL_BUILDER_DESCRIPTION = "BQL builders for preferred stocks, corporate bonds, and ETF holdings. Prefer to construct those bounded BQL shapes before xbbg_bql.";
339
- var EXT_MARKET_SESSION_DESCRIPTION = "Market session and timezone helpers for deriving sessions, UTC windows, market rules, exchange metadata, turnover defaults, and BQR datetime defaults.";
340
- var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed-income analytics fields.";
341
- var EXT_CONSTANTS_DESCRIPTION = "Static Bloomberg helper constants for date parsing/formatting, futures months, dividend types, and ETF/dividend columns.";
342
- var EXT_COLUMNS_DESCRIPTION = "Column rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.";
343
- var EXT_CALCULATE_DESCRIPTION = "Small numeric helper operations for Bloomberg workflows, including level percentage calculations.";
344
177
 
345
178
  // src/result-limits.ts
346
179
  var MAX_RESULT_DEPTH = 32;
@@ -383,7 +216,16 @@ function limitValue(value, maxRows, maxStringChars, state, depth = 0, seen = /*
383
216
  state.truncated = true;
384
217
  return "[Circular]";
385
218
  }
219
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
220
+ state.truncated = true;
221
+ return `[binary data: ${value.byteLength} bytes]`;
222
+ }
386
223
  if (!isPlainObject(value)) {
224
+ const toJSON = value.toJSON;
225
+ if (typeof toJSON === "function") {
226
+ seen.add(value);
227
+ return limitValue(toJSON.call(value), maxRows, maxStringChars, state, depth + 1, seen);
228
+ }
387
229
  return value;
388
230
  }
389
231
  seen.add(value);
@@ -462,8 +304,10 @@ function limitResult(value, maxRows, maxStringChars) {
462
304
  function summarizeEnvelope(envelope) {
463
305
  const rowText = envelope.rowCount === null ? "row count unknown" : `${envelope.rowCount} row${envelope.rowCount === 1 ? "" : "s"}`;
464
306
  const notes = [];
465
- if (envelope.rowCount === 0) {
466
- notes.push("empty result");
307
+ if (envelope.rowCount === 0 || envelope.data === null || envelope.data === void 0) {
308
+ notes.push(
309
+ "empty result; verify identifiers, fields, and date range before concluding no data exists"
310
+ );
467
311
  }
468
312
  if (envelope.truncated) {
469
313
  notes.push("artifact truncated to configured limits");
@@ -478,41 +322,236 @@ function resultJsonReplacer(_key, value) {
478
322
  if (typeof value === "bigint") {
479
323
  return value.toString();
480
324
  }
481
- return value;
482
- }
483
- function formatToolContent(envelope) {
484
- const payload = {
485
- tool: envelope.tool,
486
- rowCount: envelope.rowCount,
487
- truncated: envelope.truncated,
488
- data: envelope.data
489
- };
490
- return `${summarizeEnvelope(envelope)}
491
- ${JSON.stringify(payload, resultJsonReplacer)}`;
492
- }
493
- function createToolResult(tool2, value, maxRows, maxStringChars) {
494
- const limited = limitResult(value, maxRows, maxStringChars);
495
- const envelope = {
496
- tool: tool2,
497
- rowCount: limited.rowCount,
498
- truncated: limited.truncated,
499
- data: limited.value
500
- };
501
- return [formatToolContent(envelope), envelope];
502
- }
503
- function throwWithToolContext(tool2, error) {
504
- const prefix = `${tool2} failed`;
505
- if (error instanceof Error) {
506
- if (!error.message.startsWith(prefix)) {
507
- Object.defineProperty(error, "message", {
508
- configurable: true,
509
- value: `${prefix}: ${error.message}`
510
- });
511
- }
512
- throw error;
325
+ return value;
326
+ }
327
+ function formatToolContent(envelope) {
328
+ const payload = {
329
+ tool: envelope.tool,
330
+ rowCount: envelope.rowCount,
331
+ truncated: envelope.truncated,
332
+ data: envelope.data
333
+ };
334
+ return `${summarizeEnvelope(envelope)}
335
+ ${JSON.stringify(payload, resultJsonReplacer)}`;
336
+ }
337
+ function createToolResult(tool2, value, maxRows, maxStringChars) {
338
+ const limited = limitResult(value, maxRows, maxStringChars);
339
+ const envelope = {
340
+ tool: tool2,
341
+ rowCount: limited.rowCount,
342
+ truncated: limited.truncated,
343
+ data: limited.value
344
+ };
345
+ return [formatToolContent(envelope), envelope];
346
+ }
347
+ function throwWithToolContext(tool2, error) {
348
+ const prefix = `${tool2} failed`;
349
+ if (error instanceof Error) {
350
+ if (error.message.startsWith(prefix)) {
351
+ throw error;
352
+ }
353
+ const wrapped = new Error(`${prefix}: ${error.message}`, { cause: error });
354
+ wrapped.name = error.name;
355
+ throw wrapped;
356
+ }
357
+ throw new Error(`${prefix}: ${String(error)}`);
358
+ }
359
+
360
+ // src/langchain-tool.ts
361
+ function inputJsonSchema(schema) {
362
+ const jsonSchema = zodToJsonSchema.zodToJsonSchema(schema, {
363
+ $refStrategy: "none",
364
+ effectStrategy: "input",
365
+ pipeStrategy: "input"
366
+ });
367
+ delete jsonSchema.$schema;
368
+ delete jsonSchema.definitions;
369
+ return jsonSchema;
370
+ }
371
+ function toolParameterJsonSchema(toolInstance) {
372
+ const schema = toolInstance.schema;
373
+ if (schema !== null && typeof schema === "object" && !("safeParse" in schema)) {
374
+ return schema;
375
+ }
376
+ return inputJsonSchema(schema);
377
+ }
378
+ function createBloombergStructuredTool(func, fields) {
379
+ const providerToolDefinition = {
380
+ type: "function",
381
+ function: {
382
+ description: fields.description,
383
+ name: fields.name,
384
+ parameters: inputJsonSchema(fields.schema)
385
+ }
386
+ };
387
+ const guarded = async (input, config) => {
388
+ try {
389
+ config?.signal?.throwIfAborted();
390
+ } catch (error) {
391
+ throwWithToolContext(fields.name, error);
392
+ }
393
+ return await func(input, config);
394
+ };
395
+ return tools.tool(
396
+ guarded,
397
+ {
398
+ ...fields,
399
+ extras: { providerToolDefinition }
400
+ }
401
+ );
402
+ }
403
+
404
+ // src/cdx-fields.ts
405
+ var CDX_INFO_FIELDS = Object.freeze([
406
+ "ROLLING_SERIES",
407
+ "VERSION",
408
+ "ON_THE_RUN_CURRENT_BD_INDICATOR",
409
+ "CDS_FIRST_ACCRUAL_START_DATE",
410
+ "NAME",
411
+ "NUM_CURRENT_COMPANIES_CCY_TKR",
412
+ "NUM_ORIG_COMPANIES_CRNCY_TKR",
413
+ "PX_LAST"
414
+ ]);
415
+ var CDX_PRICING_FIELDS = Object.freeze([
416
+ "PX_LAST",
417
+ "PX_BID",
418
+ "PX_ASK",
419
+ "UPFRONT_LAST",
420
+ "UPFRONT_BID",
421
+ "UPFRONT_ASK",
422
+ "CDS_FLAT_SPREAD",
423
+ "UPFRONT_FEE",
424
+ "PV_CDS_PREMIUM_LEG",
425
+ "PV_CDS_DEFAULT_LEG"
426
+ ]);
427
+ var CDX_RISK_FIELDS = Object.freeze([
428
+ "SW_CNV_BPV",
429
+ "SW_EQV_BPV",
430
+ "CDS_SPREAD_MID_MODIFIED_DURATION",
431
+ "CDS_SPREAD_MID_CONVEXITY",
432
+ "RECOVERY_RATE_SEN",
433
+ "CDS_RECOVERY_RT"
434
+ ]);
435
+
436
+ // src/descriptions.ts
437
+ var REQUIRED_TOOL_INSTRUCTIONS = [
438
+ "# Bloomberg tool usage",
439
+ "- Use these tools only for server-side Bloomberg data access through @xbbg/core. Never imply Bloomberg data was retrieved unless a tool call actually returned it.",
440
+ "- Ask a clarifying question before calling a tool when any security identity, field mnemonic, date range, currency, periodicity, intraday interval, timezone, override, or universe is ambiguous.",
441
+ "- Do not invent Bloomberg tickers, field mnemonics, overrides, or BQL functions. If the user gives a field description rather than a confident mnemonic, call xbbg_bflds first.",
442
+ "- Issue one tool call per dataset and read any error before retrying; never probe parameter variants in parallel. Omit optional output-shape parameters such as format unless the user asked for a specific shape.",
443
+ "",
444
+ "## Security identifiers",
445
+ "- Pass each security in the form the user supplied it; never translate between identifier kinds on your own.",
446
+ "- User supplied a Bloomberg ticker: pass it through fully qualified as <TICKER> <MARKET_SECTOR>, for example <TICKER> <EXCHANGE> Equity, <INDEX_TICKER> Index, or <CCY_PAIR> Curncy.",
447
+ "- The market sector ending (Bloomberg yellow key) is part of the security string. The sectors are: Equity, Index, Curncy, Comdty, Corp, Govt, Muni, Mtge, M-Mkt, and Pfd. Equity securities carry an exchange or composite code before the sector (<TICKER> <EXCHANGE> Equity); preferred securities use the Pfd sector; corporate and government bonds use Corp and Govt. Request tools pass the security through to Bloomberg without validating the sector, so copy it exactly as the user supplied it.",
448
+ "- User supplied a raw ISIN or CUSIP: pass Bloomberg identifier syntax directly: /isin/<ISIN> or /cusip/<CUSIP>. Never pass the bare identifier without its prefix, except to xbbg_resolve_isins and xbbg_issuer_isins, which take raw ISIN strings.",
449
+ "- <TICKER> <MARKET_SECTOR> is a format template, not authorization to construct a ticker. Never invent, recall from memory, or guess the Bloomberg ticker behind an identifier the user gave; identifier syntax is already a complete, valid security input. Use xbbg_resolve_isins only when the user wants the resolved Bloomberg security itself.",
450
+ "- Recipe tools that take tickers (xbbg_preferreds, xbbg_corporate_bonds, xbbg_index_members, xbbg_etf_holdings) do not accept identifier syntax. When the user supplied an ISIN or CUSIP for those workflows, resolve it with xbbg_resolve_isins first and use the returned Bloomberg security; never guess the ticker.",
451
+ "- Do not use xbbg_bsrch as a replacement for a known ticker, ISIN, or CUSIP.",
452
+ "- For dealer quote / BQR workflows, use xbbg_bqr with a fixed-income identifier plus a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>. For raw intraday ticks, use xbbg_bdtick.",
453
+ "",
454
+ "## Core request tools",
455
+ "- xbbg_bdp: current or reference point-in-time fields. Use a small explicit securities list and a small explicit fields list. Use includeSecurityErrors only when the caller wants Bloomberg security errors in the response.",
456
+ "- xbbg_bdh: historical daily or periodic time series. Always provide explicit start and end dates in YYYY-MM-DD or YYYYMMDD form. Ask before choosing periodicity, currency, fill behavior, adjustment overrides, or a wide output table.",
457
+ "- xbbg_bds: Bloomberg bulk/table fields. Provide exactly one bulk field; do not use bds for ordinary multi-field reference data.",
458
+ "- xbbg_bdib: intraday bars only. Provide one ticker, explicit ISO start/end datetimes with time components, a positive interval in minutes, and timezone context when datetimes are naive.",
459
+ "- xbbg_bdtick: intraday tick data. Provide one ticker, explicit ISO start/end datetimes with time components, and explicit eventTypes unless the default event stream is intended. Use includeBrokerCodes or includeConditionCodes only when those columns are needed.",
460
+ "- xbbg_bql: BQL expressions only when the user asks for BQL or the request is naturally expressed as a bounded BQL query. Keep queries short, explicit, and scoped to the requested universe.",
461
+ "- xbbg_bsrch: Bloomberg search-grid or saved-search workflows only. Do not use it for ordinary security lookup.",
462
+ "- xbbg_bqr: Bloomberg Quote Request / dealer quotes. Prefer fixed-income identifier inputs with a dealer quote source such as /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>, explicit start/end datetimes with time components, and explicit event types.",
463
+ "- xbbg_bflds: Bloomberg field metadata/search. Provide exactly one of fields or searchSpec; use searchSpec for natural-language field names and fields for known mnemonics.",
464
+ "- xbbg_beqs: Bloomberg equity screening by named BEQS screen. Prefer this over hand-written BQL when the user names an existing Bloomberg screen.",
465
+ "- xbbg_yas: fixed-income YAS recipe fields. Prefer this over manual YAS-style BDP requests when the user asks for yield, duration, spread, or price analytics.",
466
+ "- xbbg_preferreds: preferred stock discovery from the issuer's common equity ticker, never a guessed preferred ('Pfd') ticker. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first. Prefer this over xbbg_ext_bql_builder plus xbbg_bql when the user wants the actual preferreds result.",
467
+ "- xbbg_corporate_bonds: bounded corporate bond universe query for a company ticker. Prefer this over generic BQL for company debt discovery.",
468
+ "- xbbg_index_members: index constituents through the core index recipe. Prefer this over generic BDS/BQL members when the user asks for constituents.",
469
+ "- xbbg_resolve_isins: resolves supplied ISIN strings to Bloomberg securities. Pass raw ISIN strings only for this recipe; otherwise use /isin/<ISIN> syntax with data tools.",
470
+ "- xbbg_issuer_isins: issuer/bond ISIN workflow for supplied bond ISIN strings.",
471
+ "- xbbg_etf_holdings: ETF holdings recipe for a single ETF ticker. Prefer this over generic BQL holdings when the user asks for ETF constituents.",
472
+ "- xbbg_stream_snapshot: bounded live market-data observation from //blp/mktdata. Requires explicit maxUpdates and always terminates/unsubscribes.",
473
+ "- xbbg_mktbar_snapshot: bounded live market-bar observation from //blp/mktbar for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
474
+ "- xbbg_depth_snapshot: bounded market-depth observation from //blp/mktdepthdata for one ticker. Requires explicit maxUpdates and always terminates/unsubscribes.",
475
+ "",
476
+ "## BQL guidance",
477
+ "- BQL is a complete Bloomberg Query Language expression sent as one query string; the tool does not assemble get/for/with clauses for you.",
478
+ "- Basic shape: get(<FIELD_1>, <FIELD_2>) for(<UNIVERSE>). Use placeholders such as '<TICKER> <MARKET_SECTOR>', holdings('<ETF_TICKER> <MARKET_SECTOR>'), or members('<INDEX_TICKER> <MARKET_SECTOR>') until the user supplies real inputs.",
479
+ "- Use BQL for universe-oriented analytics and screens only when the user provides a bounded universe, filters, and date range.",
480
+ "- Prefer xbbg_ext_bql_builder instead of hand-writing BQL for supported workflows: preferred stocks, corporate bonds, and ETF holdings.",
481
+ "- Do not use BQL just because the user asks for normal reference data; xbbg_bdp is simpler for current fields and xbbg_bdh is simpler for historical time series.",
482
+ "",
483
+ "## Output handling",
484
+ "- Tool results use LangChain content_and_artifact output: content starts with a compact summary and then includes bounded model-readable JSON; artifact is the structured bounded envelope with tool, rowCount, truncated, and data for application code.",
485
+ "- If a response is empty, truncated, or contains Bloomberg/security errors, say that directly. Do not fill gaps from memory or assumptions."
486
+ ];
487
+ var OPTIONAL_EXTENSION_INSTRUCTIONS = [
488
+ "",
489
+ "## Extension helper tools",
490
+ "- xbbg_ext_ticker: ticker hygiene before live calls. parse_ticker splits generic futures-style tickers only \u2014 asset endings Index, Curncy, Comdty, or Corp as <ROOT><N> <ASSET>, or <ROOT><N> <EXCHANGE> Equity \u2014 and rejects other market sectors (Pfd, Govt, Muni, Mtge, M-Mkt) and non-futures securities. normalize_tickers trims/canonicalizes lists, filter_equity_tickers keeps equity-like tickers, is_specific_contract checks futures specificity, and validate_generic_ticker rejects malformed generic futures tickers.",
491
+ "- xbbg_ext_futures: futures contract construction and selection. Use build_futures_ticker for root/month/year/asset assembly, get_futures_months for month-code lookup, generate_candidates for generic-to-specific candidates, contract_index for generic contract rank, filter_candidates_by_cycle for HMUZ/quarterly cycles, and filter_valid_contracts to keep contracts valid for a date.",
492
+ "- xbbg_ext_cdx: CDX ticker workflow support. Use parse_cdx_ticker to understand a CDX ticker, previous_cdx_series to roll back a series, cdx_gen_to_specific to resolve a generic CDX to a target series, and cdx_info/cdx_pricing/cdx_risk for predefined BDP field bundles. cdx_pricing and cdx_risk accept recoveryRate, which becomes the CDS_RR override.",
493
+ "- xbbg_ext_currency: currency-planning helpers. build_fx_pair constructs the Bloomberg FX pair and conversion factor, same_currency avoids unnecessary conversion, and currencies_needing_conversion identifies which currencies differ from a target before requesting converted values.",
494
+ "- xbbg_ext_bql_builder: safe BQL generators for common xbbg workflows. Use build_preferreds_query for preferred-stock discovery from an equity, build_corporate_bonds_query for company bond universes with optional currency/active filters, and build_etf_holdings_query for ETF constituents. Prefer these builders over hand-writing those BQL shapes.",
495
+ "- xbbg_ext_market_session: exchange calendar/timezone support. derive_sessions turns day session times into session blocks, infer_timezone maps country codes to timezones, session_times_to_utc converts local sessions to UTC, get_market_rule gets MIC/exchange rules, default_turnover_dates and default_bqr_datetimes provide bounded defaults, and get/list_exchange_override inspect configured exchange metadata.",
496
+ "- xbbg_ext_yas_overrides: builds flat YAS override maps for fixed-income BDP requests when the lower-level BDP workflow is required. Prefer xbbg_yas for actual YAS recipe fields.",
497
+ "- xbbg_ext_constants: static lookup/format helpers for date parsing/formatting, futures month code/name mappings, dividend type mappings, and known dividend/ETF output columns.",
498
+ "- xbbg_ext_columns: post-processing helpers for Bloomberg-shaped tables. Use rename_dividend_columns, rename_etf_columns, or build_earning_header_rename when explaining or normalizing response column names after a request.",
499
+ "- xbbg_ext_calculate: small numeric helper for Bloomberg workflows. calculate_level_percentages pairs observed values with levels; values and levels must have the same length."
500
+ ];
501
+ var OPTIONAL_LIMIT_INSTRUCTIONS = [
502
+ "",
503
+ "## Request limits and inputs",
504
+ "- Keep Bloomberg requests bounded: explicit securities, explicit fields, explicit dates, limited rows, and no broad exploratory pulls unless the user narrows the universe.",
505
+ "- Respect configured tool limits for securities, fields, rows, string size, BQL length, and search spec length. Ask the user to narrow the request rather than exceeding them.",
506
+ "- Use flat primitive overrides and kwargs only: string, number, or boolean values. Do not send nested objects, arrays, or inferred defaults as overrides."
507
+ ];
508
+ var BLOOMBERG_TOOL_INSTRUCTIONS = [
509
+ ...REQUIRED_TOOL_INSTRUCTIONS,
510
+ ...OPTIONAL_EXTENSION_INSTRUCTIONS,
511
+ ...OPTIONAL_LIMIT_INSTRUCTIONS
512
+ ].join("\n");
513
+ function getBloombergToolInstructions(options = {}) {
514
+ const includeExtensionGuidance = options.includeExtensionGuidance ?? true;
515
+ const includeLimitReminder = options.includeLimitReminder ?? true;
516
+ const lines = [...REQUIRED_TOOL_INSTRUCTIONS];
517
+ if (includeExtensionGuidance) {
518
+ lines.push(...OPTIONAL_EXTENSION_INSTRUCTIONS);
519
+ }
520
+ if (includeLimitReminder) {
521
+ lines.push(...OPTIONAL_LIMIT_INSTRUCTIONS);
513
522
  }
514
- throw new Error(`${prefix}: ${String(error)}`);
523
+ return lines.join("\n");
515
524
  }
525
+ var BDP_DESCRIPTION = 'Bloomberg reference data for current or point-in-time fields. Use for a small bounded list of fully qualified securities. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"].';
526
+ var BDH_DESCRIPTION = 'Bloomberg historical time series. Requires explicit start and end dates; ask before using if the date range or periodicity is ambiguous. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<TICKER> <MARKET_SECTOR>"], fields ["<FIELD>"], start "<START_DATE>", end "<END_DATE>".';
527
+ var BDS_DESCRIPTION = 'Bloomberg bulk/table reference data. Requires exactly one bulk field, not a field list. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: securities ["<INDEX_TICKER> <MARKET_SECTOR>"], field "<BULK_FIELD>".';
528
+ var BDIB_DESCRIPTION = 'Bloomberg intraday bars. Requires one ticker plus explicit ISO start/end datetimes with time components and a positive interval in minutes. Use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Example: ticker "<TICKER> <MARKET_SECTOR>", start "<START_DATETIME>", end "<END_DATETIME>", interval <MINUTES>.';
529
+ var BDTICK_DESCRIPTION = 'Bloomberg intraday tick data. Requires one ticker plus explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"], and includeBrokerCodes/includeConditionCodes only when needed.';
530
+ var BQL_DESCRIPTION = "Bloomberg Query Language expression sent as one complete query string. Use for bounded universe analytics with placeholder-shaped syntax such as get(<FIELD>) for('<TICKER> <MARKET_SECTOR>'), holdings('<ETF_TICKER> <MARKET_SECTOR>'), members('<INDEX_TICKER> <MARKET_SECTOR>'), filters with with(...), or dates=range(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.";
531
+ var BSRCH_DESCRIPTION = 'Bloomberg search/grid request. Use for saved-search or ExcelGetGrid-style Bloomberg searches, not ordinary security lookup. Example searchSpec "<SEARCH_SPEC>".';
532
+ var BQR_DESCRIPTION = 'Bloomberg Quote Request / dealer quotes. Use for fixed-income dealer quote ticks, preferably with an ISIN plus dealer source such as "/isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>"; requires explicit ISO start/end datetimes with time components. Set eventTypes explicitly, for example ["<EVENT_TYPE>"].';
533
+ var BFLDS_DESCRIPTION = 'Bloomberg field metadata and field search. Use first when a field mnemonic is uncertain. Provide exactly one of fields or searchSpec. Example: fields ["<FIELD>"] or searchSpec "<FIELD_SEARCH_TEXT>".';
534
+ var BEQS_DESCRIPTION = "Bloomberg equity screening by named BEQS screen. Use when the user names an existing Bloomberg screen and wants its bounded result set. Prefer this over hand-written BQL for saved Bloomberg screens.";
535
+ var YAS_DESCRIPTION = "Bloomberg fixed-income YAS recipe fields for one or more bonds. Use for yield, duration, spread, benchmark, or price analytics; provide explicit fields and optional settlement/yield/price inputs. Pass securities as supplied: '<TICKER> <MARKET_SECTOR>' or identifier syntax such as '/isin/<ISIN> <MARKET_SECTOR>'.";
536
+ var PREFERREDS_DESCRIPTION = "Preferred stock discovery for one issuer. Takes the issuer's common equity ticker such as '<TICKER> US Equity', never a preferred ('Pfd') ticker and never a guessed one. If the user supplied an ISIN or CUSIP, resolve it with xbbg_resolve_isins first.";
537
+ var CORPORATE_BONDS_DESCRIPTION = "Corporate bond universe query for one issuer/company equity ticker, with optional currency, active-only filter, and result fields. Prefer this over generic BQL for company debt discovery. If the user supplied an ISIN or CUSIP, resolve it with xbbg_resolve_isins first; never guess the ticker.";
538
+ var INDEX_MEMBERS_DESCRIPTION = "Index constituent recipe for one Bloomberg index ticker such as '<INDEX_TICKER> Index'. Use for bounded member lists and optional historical/as-of constituent membership; never guess index tickers.";
539
+ var RESOLVE_ISINS_DESCRIPTION = "Resolve raw ISIN strings to Bloomberg securities through the core ISIN recipe. Do not add /isin/ prefixes in this tool; pass the exact ISIN strings supplied by the user.";
540
+ var ISSUER_ISINS_DESCRIPTION = "Issuer/bond ISIN workflow for supplied bond ISIN strings. Use for issuer-level ISIN discovery starting from known bond ISINs.";
541
+ var ETF_HOLDINGS_DESCRIPTION = "ETF holdings recipe for one ETF ticker such as '<ETF_TICKER> <MARKET_SECTOR>'. Use when the user asks for ETF constituents or holdings and wants the bounded holdings result. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess the ticker.";
542
+ var STREAM_SNAPSHOT_DESCRIPTION = "Bounded live market-data snapshot from //blp/mktdata. Collects at most maxUpdates updates until timeout/done, then always unsubscribes; use for finite observations, not open subscriptions.";
543
+ var MKTBAR_SNAPSHOT_DESCRIPTION = "Bounded live market-bar snapshot from //blp/mktbar for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
544
+ var DEPTH_SNAPSHOT_DESCRIPTION = "Bounded live market-depth snapshot from //blp/mktdepthdata for one ticker. Collects at most maxUpdates updates until timeout/done, then always unsubscribes.";
545
+ var EXT_TICKER_DESCRIPTION = "Ticker hygiene helpers: parse_ticker (generic futures-style tickers ending in Index, Curncy, Comdty, or Corp, or <ROOT><N> <EXCHANGE> Equity; other market sectors are rejected), normalize_tickers, filter_equity_tickers, is_specific_contract, and validate_generic_ticker.";
546
+ var EXT_FUTURES_DESCRIPTION = "Futures helpers for contract construction and selection: build_futures_ticker, generate_candidates, contract_index, filter_candidates_by_cycle, filter_valid_contracts, and get_futures_months.";
547
+ var EXT_CDX_DESCRIPTION = "CDX helpers for parsing, series rolling/resolution, and predefined info/pricing/risk BDP field bundles.";
548
+ var EXT_CURRENCY_DESCRIPTION = "Currency planning helpers: build FX pairs, test same-currency requests, and find currencies needing conversion.";
549
+ var EXT_BQL_BUILDER_DESCRIPTION = "BQL builders for preferred stocks, corporate bonds, and ETF holdings. Prefer to construct those bounded BQL shapes before xbbg_bql.";
550
+ var EXT_MARKET_SESSION_DESCRIPTION = "Market session and timezone helpers for deriving sessions, UTC windows, market rules, exchange metadata, turnover defaults, and BQR datetime defaults.";
551
+ var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed-income analytics fields.";
552
+ var EXT_CONSTANTS_DESCRIPTION = "Static Bloomberg helper constants for date parsing/formatting, futures months, dividend types, and ETF/dividend columns.";
553
+ var EXT_COLUMNS_DESCRIPTION = "Column rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.";
554
+ var EXT_CALCULATE_DESCRIPTION = "Small numeric helper operations for Bloomberg workflows, including level percentage calculations.";
516
555
  var stringPairSchema = z__namespace.object({
517
556
  key: z__namespace.string().trim().min(1).describe("String pair key."),
518
557
  value: z__namespace.string().trim().min(1).describe("String pair value.")
@@ -534,7 +573,7 @@ function optionalString(options, description) {
534
573
  function tickerSchema(options) {
535
574
  const ticker = nonEmptyString(
536
575
  options,
537
- "One Bloomberg ticker for parse/contract validation operations."
576
+ "One generic futures-style Bloomberg ticker: <ROOT><N> ending in Index, Curncy, Comdty, or Corp, or <ROOT><N> <EXCHANGE> Equity. parse_ticker rejects other market sectors (Pfd, Govt, Muni, Mtge, M-Mkt) and non-futures securities."
538
577
  );
539
578
  const tickers = stringArray(
540
579
  options,
@@ -550,94 +589,151 @@ function tickerSchema(options) {
550
589
  ]);
551
590
  }
552
591
  function futuresSchema(options) {
553
- return z__namespace.object({
554
- asset: optionalString(options, "Bloomberg asset class suffix supplied by the user."),
555
- candidates: z__namespace.array(futuresCandidateSchema).min(1).max(options.maxFields).optional().describe("Candidate futures contracts."),
556
- contracts: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).optional().describe("Contract pairs for validity filtering."),
557
- count: z__namespace.number().int().positive().optional().describe("Maximum number of futures candidates to generate."),
558
- cycle: optionalString(options, "Futures cycle code to filter candidates by."),
559
- day: z__namespace.number().int().min(1).max(31).optional().describe("Day number for contract filtering."),
560
- freq: optionalString(options, "Futures frequency/cycle hint."),
561
- genTicker: optionalString(options, "Generic Bloomberg futures ticker."),
562
- month: z__namespace.number().int().min(1).max(12).optional().describe("Month number, 1-12."),
563
- monthCode: optionalString(options, "Bloomberg futures month code, for example H."),
564
- operation: z__namespace.enum([
565
- "build_futures_ticker",
566
- "generate_candidates",
567
- "contract_index",
568
- "filter_candidates_by_cycle",
569
- "filter_valid_contracts",
570
- "get_futures_months"
571
- ]).describe("Futures helper operation to run."),
572
- prefix: optionalString(options, "Futures ticker root prefix."),
573
- year: z__namespace.union([z__namespace.string().trim().min(1), z__namespace.number().int()]).optional().describe("Contract year.")
574
- });
592
+ const genTicker = nonEmptyString(
593
+ options,
594
+ "Generic Bloomberg futures ticker, for example ES1 Index."
595
+ );
596
+ const year = z__namespace.number().int().describe("Contract year, for example 2024.");
597
+ const month = z__namespace.number().int().min(1).max(12).describe("Month number, 1-12.");
598
+ const day = z__namespace.number().int().min(1).max(31).describe("Day number, 1-31.");
599
+ return z__namespace.discriminatedUnion("operation", [
600
+ z__namespace.object({
601
+ asset: nonEmptyString(
602
+ options,
603
+ "Bloomberg asset class suffix, for example Index or Comdty."
604
+ ),
605
+ monthCode: nonEmptyString(options, "Bloomberg futures month code, for example H."),
606
+ operation: z__namespace.literal("build_futures_ticker"),
607
+ prefix: nonEmptyString(options, "Futures ticker root prefix, for example ES."),
608
+ year: z__namespace.union([z__namespace.string().trim().min(1), z__namespace.number().int().transform(String)]).describe("Contract year, full or abbreviated, as a string or integer.")
609
+ }).strict(),
610
+ z__namespace.object({
611
+ count: z__namespace.number().int().positive().optional().describe("Maximum number of futures candidates to generate."),
612
+ day,
613
+ freq: optionalString(options, "Futures frequency/cycle hint."),
614
+ genTicker,
615
+ month,
616
+ operation: z__namespace.literal("generate_candidates"),
617
+ year
618
+ }).strict(),
619
+ z__namespace.object({ genTicker, operation: z__namespace.literal("contract_index") }).strict(),
620
+ z__namespace.object({
621
+ candidates: z__namespace.array(futuresCandidateSchema).min(1).max(options.maxFields).describe("Candidate futures contracts."),
622
+ cycle: nonEmptyString(options, "Futures cycle code to filter candidates by."),
623
+ operation: z__namespace.literal("filter_candidates_by_cycle")
624
+ }).strict(),
625
+ z__namespace.object({
626
+ contracts: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).describe("Contract pairs for validity filtering."),
627
+ day,
628
+ month,
629
+ operation: z__namespace.literal("filter_valid_contracts"),
630
+ year
631
+ }).strict(),
632
+ z__namespace.object({ operation: z__namespace.literal("get_futures_months") }).strict()
633
+ ]);
575
634
  }
576
635
  function cdxSchema(options) {
577
- return z__namespace.object({
578
- genTicker: optionalString(options, "Generic CDX ticker."),
579
- operation: z__namespace.enum([
580
- "parse_cdx_ticker",
581
- "previous_cdx_series",
582
- "cdx_gen_to_specific",
583
- "cdx_info",
584
- "cdx_pricing",
585
- "cdx_risk"
586
- ]).describe("CDX helper operation to run."),
587
- recoveryRate: z__namespace.number().optional().describe("Optional recovery rate override for pricing/risk lookups."),
588
- series: z__namespace.number().int().positive().optional().describe("Specific CDX series number."),
589
- ticker: optionalString(options, "CDX ticker.")
590
- });
636
+ const ticker = nonEmptyString(options, "CDX ticker, generic or specific.");
637
+ const recoveryRate = z__namespace.number().min(0).max(1).optional().describe("Decimal recovery rate override, e.g. 0.4 for 40%; sent as the CDS_RR override.");
638
+ return z__namespace.discriminatedUnion("operation", [
639
+ z__namespace.object({ operation: z__namespace.literal("parse_cdx_ticker"), ticker }).strict(),
640
+ z__namespace.object({ operation: z__namespace.literal("previous_cdx_series"), ticker }).strict(),
641
+ z__namespace.object({ operation: z__namespace.literal("cdx_info"), ticker }).strict(),
642
+ z__namespace.object({ operation: z__namespace.literal("cdx_pricing"), recoveryRate, ticker }).strict(),
643
+ z__namespace.object({ operation: z__namespace.literal("cdx_risk"), recoveryRate, ticker }).strict(),
644
+ z__namespace.object({
645
+ genTicker: nonEmptyString(
646
+ options,
647
+ "Generic CDX ticker, for example CDX IG CDSI GEN 5Y Corp."
648
+ ),
649
+ operation: z__namespace.literal("cdx_gen_to_specific"),
650
+ series: z__namespace.number().int().positive().describe("Specific CDX series number.")
651
+ }).strict()
652
+ ]);
591
653
  }
592
654
  function currencySchema(options) {
593
- return z__namespace.object({
594
- ccy1: optionalString(options, "First ISO currency code."),
595
- ccy2: optionalString(options, "Second ISO currency code."),
596
- currencies: stringArray(options, "ISO currency codes.").optional(),
597
- fromCcy: optionalString(options, "Source ISO currency code."),
598
- operation: z__namespace.enum(["build_fx_pair", "same_currency", "currencies_needing_conversion"]).describe("Currency helper operation to run."),
599
- target: optionalString(options, "Target ISO currency code."),
600
- toCcy: optionalString(options, "Destination ISO currency code.")
601
- });
655
+ return z__namespace.discriminatedUnion("operation", [
656
+ z__namespace.object({
657
+ fromCcy: nonEmptyString(options, "Source ISO currency code."),
658
+ operation: z__namespace.literal("build_fx_pair"),
659
+ toCcy: nonEmptyString(options, "Destination ISO currency code.")
660
+ }).strict(),
661
+ z__namespace.object({
662
+ ccy1: nonEmptyString(options, "First ISO currency code."),
663
+ ccy2: nonEmptyString(options, "Second ISO currency code."),
664
+ operation: z__namespace.literal("same_currency")
665
+ }).strict(),
666
+ z__namespace.object({
667
+ currencies: stringArray(options, "ISO currency codes to check."),
668
+ operation: z__namespace.literal("currencies_needing_conversion"),
669
+ target: nonEmptyString(options, "Target ISO currency code.")
670
+ }).strict()
671
+ ]);
602
672
  }
603
673
  function bqlBuilderSchema(options) {
604
- return z__namespace.object({
605
- activeOnly: z__namespace.boolean().optional().describe("Restrict corporate bond query to active bonds."),
606
- ccy: optionalString(options, "Currency filter for corporate bond query."),
607
- equityTicker: optionalString(options, "Equity ticker for preferreds query."),
608
- etfTicker: optionalString(options, "ETF ticker for holdings query."),
609
- extraFields: stringArray(options, "Extra BQL fields to include.").optional(),
610
- operation: z__namespace.enum(["build_preferreds_query", "build_corporate_bonds_query", "build_etf_holdings_query"]).describe("BQL builder operation to run."),
611
- ticker: optionalString(options, "Ticker for corporate bond query.")
612
- });
674
+ const extraFields = stringArray(options, "Extra BQL fields to include.").optional();
675
+ return z__namespace.discriminatedUnion("operation", [
676
+ z__namespace.object({
677
+ equityTicker: nonEmptyString(options, "Equity ticker for preferreds query."),
678
+ extraFields,
679
+ operation: z__namespace.literal("build_preferreds_query")
680
+ }).strict(),
681
+ z__namespace.object({
682
+ activeOnly: z__namespace.boolean().optional().describe("Restrict corporate bond query to active bonds."),
683
+ ccy: optionalString(options, "Currency filter for corporate bond query."),
684
+ extraFields,
685
+ operation: z__namespace.literal("build_corporate_bonds_query"),
686
+ ticker: nonEmptyString(options, "Ticker for corporate bond query.")
687
+ }).strict(),
688
+ z__namespace.object({
689
+ etfTicker: nonEmptyString(options, "ETF ticker for holdings query."),
690
+ extraFields,
691
+ operation: z__namespace.literal("build_etf_holdings_query")
692
+ }).strict()
693
+ ]);
613
694
  }
614
695
  function marketSessionSchema(options) {
615
- return z__namespace.object({
616
- countryIso: optionalString(options, "ISO country code for timezone inference."),
617
- date: optionalString(options, "Date for UTC session conversion, YYYY-MM-DD or YYYYMMDD."),
618
- dayEnd: optionalString(options, "Exchange day end time, for example 16:00."),
619
- dayStart: optionalString(options, "Exchange day start time, for example 09:30."),
620
- endDate: optionalString(options, "Optional end date."),
621
- endDatetime: optionalString(options, "Optional end datetime."),
622
- endTime: optionalString(options, "Session end time, for example 16:00."),
623
- exchCode: optionalString(options, "Bloomberg exchange code."),
624
- exchangeTz: optionalString(options, "IANA exchange timezone."),
625
- mic: optionalString(options, "Market Identifier Code."),
626
- operation: z__namespace.enum([
627
- "derive_sessions",
628
- "get_market_rule",
629
- "infer_timezone",
630
- "session_times_to_utc",
631
- "default_turnover_dates",
632
- "default_bqr_datetimes",
633
- "get_exchange_override",
634
- "list_exchange_overrides"
635
- ]).describe("Market session helper operation to run."),
636
- startDate: optionalString(options, "Optional start date."),
637
- startDatetime: optionalString(options, "Optional start datetime."),
638
- startTime: optionalString(options, "Session start time, for example 09:30."),
639
- ticker: optionalString(options, "Ticker for exchange override lookup.")
640
- });
696
+ const mic = optionalString(options, "Market Identifier Code, for example XNYS.");
697
+ const exchCode = optionalString(options, "Bloomberg exchange code.");
698
+ return z__namespace.discriminatedUnion("operation", [
699
+ z__namespace.object({
700
+ dayEnd: nonEmptyString(options, "Exchange day end time, for example 16:00."),
701
+ dayStart: nonEmptyString(options, "Exchange day start time, for example 09:30."),
702
+ exchCode,
703
+ mic,
704
+ operation: z__namespace.literal("derive_sessions")
705
+ }).strict(),
706
+ z__namespace.object({ exchCode, mic, operation: z__namespace.literal("get_market_rule") }).strict(),
707
+ z__namespace.object({
708
+ countryIso: nonEmptyString(options, "ISO country code for timezone inference."),
709
+ operation: z__namespace.literal("infer_timezone")
710
+ }).strict(),
711
+ z__namespace.object({
712
+ date: nonEmptyString(options, "Date for UTC session conversion, YYYY-MM-DD or YYYYMMDD."),
713
+ endTime: nonEmptyString(options, "Session end time, for example 16:00."),
714
+ exchangeTz: nonEmptyString(
715
+ options,
716
+ "IANA exchange timezone, for example America/New_York."
717
+ ),
718
+ operation: z__namespace.literal("session_times_to_utc"),
719
+ startTime: nonEmptyString(options, "Session start time, for example 09:30.")
720
+ }).strict(),
721
+ z__namespace.object({
722
+ endDate: optionalString(options, "Optional end date."),
723
+ operation: z__namespace.literal("default_turnover_dates"),
724
+ startDate: optionalString(options, "Optional start date.")
725
+ }).strict(),
726
+ z__namespace.object({
727
+ endDatetime: optionalString(options, "Optional end datetime."),
728
+ operation: z__namespace.literal("default_bqr_datetimes"),
729
+ startDatetime: optionalString(options, "Optional start datetime.")
730
+ }).strict(),
731
+ z__namespace.object({
732
+ operation: z__namespace.literal("get_exchange_override"),
733
+ ticker: nonEmptyString(options, "Ticker for exchange override lookup.")
734
+ }).strict(),
735
+ z__namespace.object({ operation: z__namespace.literal("list_exchange_overrides") }).strict()
736
+ ]);
641
737
  }
642
738
  function yasOverridesSchema(options) {
643
739
  return z__namespace.object({
@@ -647,94 +743,67 @@ function yasOverridesSchema(options) {
647
743
  spread: z__namespace.number().optional().describe("YAS spread override."),
648
744
  yieldType: z__namespace.number().int().optional().describe("YAS yield type override."),
649
745
  yieldVal: z__namespace.number().optional().describe("YAS yield value override.")
650
- });
746
+ }).strict();
651
747
  }
652
748
  function constantsSchema(options) {
653
- return z__namespace.object({
654
- code: optionalString(options, "Month code."),
655
- dateStr: optionalString(options, "Date string to parse."),
656
- day: z__namespace.number().int().min(1).max(31).optional().describe("Day number."),
657
- dvdType: optionalString(options, "Dividend type code or label."),
658
- fmt: optionalString(options, "Date output format."),
659
- month: z__namespace.number().int().min(1).max(12).optional().describe("Month number."),
660
- monthName: optionalString(options, "Month name."),
661
- operation: z__namespace.enum([
662
- "parse_date",
663
- "fmt_date",
664
- "get_month_code",
665
- "get_month_name",
666
- "get_futures_months",
667
- "get_dvd_type",
668
- "get_dvd_types",
669
- "get_dvd_cols",
670
- "get_etf_cols"
671
- ]).describe("Constants helper operation to run."),
672
- year: z__namespace.number().int().min(1).optional().describe("Year number.")
673
- });
749
+ return z__namespace.discriminatedUnion("operation", [
750
+ z__namespace.object({
751
+ dateStr: nonEmptyString(options, "Date string to parse."),
752
+ operation: z__namespace.literal("parse_date")
753
+ }).strict(),
754
+ z__namespace.object({
755
+ day: z__namespace.number().int().min(1).max(31).describe("Day number, 1-31."),
756
+ fmt: optionalString(options, "Date output format."),
757
+ month: z__namespace.number().int().min(1).max(12).describe("Month number, 1-12."),
758
+ operation: z__namespace.literal("fmt_date"),
759
+ year: z__namespace.number().int().min(1).describe("Year number.")
760
+ }).strict(),
761
+ z__namespace.object({
762
+ monthName: nonEmptyString(options, "Month name, for example March."),
763
+ operation: z__namespace.literal("get_month_code")
764
+ }).strict(),
765
+ z__namespace.object({
766
+ code: nonEmptyString(options, "Month code, for example H."),
767
+ operation: z__namespace.literal("get_month_name")
768
+ }).strict(),
769
+ z__namespace.object({
770
+ dvdType: nonEmptyString(options, "Dividend type code or label."),
771
+ operation: z__namespace.literal("get_dvd_type")
772
+ }).strict(),
773
+ z__namespace.object({ operation: z__namespace.literal("get_futures_months") }).strict(),
774
+ z__namespace.object({ operation: z__namespace.literal("get_dvd_types") }).strict(),
775
+ z__namespace.object({ operation: z__namespace.literal("get_dvd_cols") }).strict(),
776
+ z__namespace.object({ operation: z__namespace.literal("get_etf_cols") }).strict()
777
+ ]);
674
778
  }
675
779
  function columnsSchema(options) {
676
- return z__namespace.object({
677
- columns: stringArray(options, "Column names to rename.").optional(),
678
- dataColumns: stringArray(options, "Earnings data column names.").optional(),
679
- headerRow: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).optional().describe("Earnings header row key/value pairs."),
680
- operation: z__namespace.enum(["rename_dividend_columns", "rename_etf_columns", "build_earning_header_rename"]).describe("Column helper operation to run.")
681
- });
780
+ const columns = stringArray(options, "Column names to rename.");
781
+ return z__namespace.discriminatedUnion("operation", [
782
+ z__namespace.object({ columns, operation: z__namespace.literal("rename_dividend_columns") }).strict(),
783
+ z__namespace.object({ columns, operation: z__namespace.literal("rename_etf_columns") }).strict(),
784
+ z__namespace.object({
785
+ dataColumns: stringArray(options, "Earnings data column names."),
786
+ headerRow: z__namespace.array(stringPairSchema).min(1).max(options.maxFields).describe("Earnings header row key/value pairs."),
787
+ operation: z__namespace.literal("build_earning_header_rename")
788
+ }).strict()
789
+ ]);
682
790
  }
683
791
  function calculateSchema(options) {
684
792
  return z__namespace.object({
685
793
  levels: z__namespace.array(z__namespace.number().nullable()).min(1).max(options.maxFields).describe("Reference level values."),
686
794
  operation: z__namespace.literal("calculate_level_percentages").describe("Numeric helper operation to run."),
687
795
  values: z__namespace.array(z__namespace.number().nullable()).min(1).max(options.maxFields).describe("Observed values.")
796
+ }).strict().superRefine((input, ctx) => {
797
+ if (input.values.length !== input.levels.length) {
798
+ ctx.addIssue({
799
+ code: z__namespace.ZodIssueCode.custom,
800
+ message: "values and levels must have the same length"
801
+ });
802
+ }
688
803
  });
689
804
  }
690
805
 
691
806
  // src/ext-tools.ts
692
- function asRecord(value) {
693
- return value;
694
- }
695
- function requireString(toolName, input, field) {
696
- const value = input[field];
697
- if (typeof value !== "string" || value.trim().length === 0) {
698
- throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string`);
699
- }
700
- return value.trim();
701
- }
702
- function requireNumber(toolName, input, field) {
703
- const value = input[field];
704
- if (typeof value !== "number" || !Number.isFinite(value)) {
705
- throw new TypeError(`${toolName}: ${field} is required and must be a finite number`);
706
- }
707
- return value;
708
- }
709
- function requireInteger(toolName, input, field) {
710
- const value = requireNumber(toolName, input, field);
711
- if (!Number.isInteger(value)) {
712
- throw new TypeError(`${toolName}: ${field} must be an integer`);
713
- }
714
- return value;
715
- }
716
- function requireYearString(toolName, input, field) {
717
- const value = input[field];
718
- if (typeof value === "number" && Number.isInteger(value)) {
719
- return String(value);
720
- }
721
- if (typeof value === "string" && value.trim().length > 0) {
722
- return value.trim();
723
- }
724
- throw new TypeError(`${toolName}: ${field} is required and must be a year string or integer`);
725
- }
726
- function requireStringArray(toolName, input, field) {
727
- const value = input[field];
728
- if (!Array.isArray(value) || value.length === 0) {
729
- throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string array`);
730
- }
731
- return value.map((entry) => {
732
- if (typeof entry !== "string" || entry.trim().length === 0) {
733
- throw new TypeError(`${toolName}: ${field} entries must be non-empty strings`);
734
- }
735
- return entry.trim();
736
- });
737
- }
738
807
  function resultString(resolver, name, value) {
739
808
  return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
740
809
  }
@@ -762,37 +831,18 @@ function extTickerWithResolver(resolver) {
762
831
  async (input) => {
763
832
  try {
764
833
  const core = await resolver.getCore();
765
- const args = asRecord(input);
766
834
  switch (input.operation) {
767
835
  case "parse_ticker":
768
- return resultString(
769
- resolver,
770
- name,
771
- core.ext.parseTicker(requireString(name, args, "ticker"))
772
- );
836
+ return resultString(resolver, name, core.ext.parseTicker(input.ticker));
773
837
  case "normalize_tickers":
774
- return resultString(
775
- resolver,
776
- name,
777
- core.ext.normalizeTickers(requireStringArray(name, args, "tickers"))
778
- );
838
+ return resultString(resolver, name, core.ext.normalizeTickers(input.tickers));
779
839
  case "filter_equity_tickers":
780
- return resultString(
781
- resolver,
782
- name,
783
- core.ext.filterEquityTickers(requireStringArray(name, args, "tickers"))
784
- );
840
+ return resultString(resolver, name, core.ext.filterEquityTickers(input.tickers));
785
841
  case "is_specific_contract":
786
- return resultString(
787
- resolver,
788
- name,
789
- core.ext.isSpecificContract(requireString(name, args, "ticker"))
790
- );
791
- case "validate_generic_ticker": {
792
- const ticker = requireString(name, args, "ticker");
793
- core.ext.validateGenericTicker(ticker);
794
- return resultString(resolver, name, { ticker, valid: true });
795
- }
842
+ return resultString(resolver, name, core.ext.isSpecificContract(input.ticker));
843
+ case "validate_generic_ticker":
844
+ core.ext.validateGenericTicker(input.ticker);
845
+ return resultString(resolver, name, { ticker: input.ticker, valid: true });
796
846
  }
797
847
  } catch (error) {
798
848
  throwWithToolContext(name, error);
@@ -812,63 +862,39 @@ function extFuturesWithResolver(resolver) {
812
862
  async (input) => {
813
863
  try {
814
864
  const core = await resolver.getCore();
815
- const args = asRecord(input);
816
865
  switch (input.operation) {
817
866
  case "build_futures_ticker":
818
867
  return resultString(
819
868
  resolver,
820
869
  name,
821
- core.ext.buildFuturesTicker(
822
- requireString(name, args, "prefix"),
823
- requireString(name, args, "monthCode"),
824
- requireYearString(name, args, "year"),
825
- requireString(name, args, "asset")
826
- )
870
+ core.ext.buildFuturesTicker(input.prefix, input.monthCode, input.year, input.asset)
827
871
  );
828
872
  case "generate_candidates":
829
873
  return resultString(
830
874
  resolver,
831
875
  name,
832
876
  core.ext.generateFuturesCandidates(
833
- requireString(name, args, "genTicker"),
834
- requireInteger(name, args, "year"),
835
- requireInteger(name, args, "month"),
836
- requireInteger(name, args, "day"),
877
+ input.genTicker,
878
+ input.year,
879
+ input.month,
880
+ input.day,
837
881
  input.freq,
838
882
  input.count
839
883
  )
840
884
  );
841
885
  case "contract_index":
842
- return resultString(
843
- resolver,
844
- name,
845
- core.ext.contractIndex(requireString(name, args, "genTicker"))
846
- );
886
+ return resultString(resolver, name, core.ext.contractIndex(input.genTicker));
847
887
  case "filter_candidates_by_cycle":
848
- if (input.candidates === void 0) {
849
- throw new TypeError(`${name}: candidates is required`);
850
- }
851
888
  return resultString(
852
889
  resolver,
853
890
  name,
854
- core.ext.filterCandidatesByCycle(
855
- input.candidates,
856
- requireString(name, args, "cycle")
857
- )
891
+ core.ext.filterCandidatesByCycle(input.candidates, input.cycle)
858
892
  );
859
893
  case "filter_valid_contracts":
860
- if (input.contracts === void 0) {
861
- throw new TypeError(`${name}: contracts is required`);
862
- }
863
894
  return resultString(
864
895
  resolver,
865
896
  name,
866
- core.ext.filterValidContracts(
867
- input.contracts,
868
- requireInteger(name, args, "year"),
869
- requireInteger(name, args, "month"),
870
- requireInteger(name, args, "day")
871
- )
897
+ core.ext.filterValidContracts(input.contracts, input.year, input.month, input.day)
872
898
  );
873
899
  case "get_futures_months":
874
900
  return resultString(resolver, name, core.ext.getFuturesMonths());
@@ -888,41 +914,31 @@ function extFuturesWithResolver(resolver) {
888
914
  function extCdxWithResolver(resolver) {
889
915
  const name = "xbbg_ext_cdx";
890
916
  return createBloombergStructuredTool(
891
- async (input) => {
917
+ async (input, config) => {
892
918
  try {
893
- const args = asRecord(input);
919
+ config?.signal?.throwIfAborted();
894
920
  if (input.operation === "cdx_info" || input.operation === "cdx_pricing" || input.operation === "cdx_risk") {
895
921
  const engine = await resolver.getEngine();
896
- const ticker = requireString(name, args, "ticker");
897
922
  const fields = input.operation === "cdx_info" ? CDX_INFO_FIELDS : input.operation === "cdx_pricing" ? CDX_PRICING_FIELDS : CDX_RISK_FIELDS;
898
- const result = await engine.bdp([ticker], fields, {
923
+ const result = await engine.bdp([input.ticker], fields, {
899
924
  backend: "json",
900
- overrides: recoveryOverrides(input.recoveryRate)
925
+ overrides: recoveryOverrides(
926
+ input.operation === "cdx_pricing" || input.operation === "cdx_risk" ? input.recoveryRate : void 0
927
+ )
901
928
  });
902
929
  return resultString(resolver, name, result);
903
930
  }
904
931
  const core = await resolver.getCore();
905
932
  switch (input.operation) {
906
933
  case "parse_cdx_ticker":
907
- return resultString(
908
- resolver,
909
- name,
910
- core.ext.parseCdxTicker(requireString(name, args, "ticker"))
911
- );
934
+ return resultString(resolver, name, core.ext.parseCdxTicker(input.ticker));
912
935
  case "previous_cdx_series":
913
- return resultString(
914
- resolver,
915
- name,
916
- core.ext.previousCdxSeries(requireString(name, args, "ticker"))
917
- );
936
+ return resultString(resolver, name, core.ext.previousCdxSeries(input.ticker));
918
937
  case "cdx_gen_to_specific":
919
938
  return resultString(
920
939
  resolver,
921
940
  name,
922
- core.ext.cdxGenToSpecific(
923
- requireString(name, args, "genTicker"),
924
- requireInteger(name, args, "series")
925
- )
941
+ core.ext.cdxGenToSpecific(input.genTicker, input.series)
926
942
  );
927
943
  }
928
944
  } catch (error) {
@@ -943,34 +959,16 @@ function extCurrencyWithResolver(resolver) {
943
959
  async (input) => {
944
960
  try {
945
961
  const core = await resolver.getCore();
946
- const args = asRecord(input);
947
962
  switch (input.operation) {
948
963
  case "build_fx_pair":
949
- return resultString(
950
- resolver,
951
- name,
952
- core.ext.buildFxPair(
953
- requireString(name, args, "fromCcy"),
954
- requireString(name, args, "toCcy")
955
- )
956
- );
964
+ return resultString(resolver, name, core.ext.buildFxPair(input.fromCcy, input.toCcy));
957
965
  case "same_currency":
958
- return resultString(
959
- resolver,
960
- name,
961
- core.ext.sameCurrency(
962
- requireString(name, args, "ccy1"),
963
- requireString(name, args, "ccy2")
964
- )
965
- );
966
+ return resultString(resolver, name, core.ext.sameCurrency(input.ccy1, input.ccy2));
966
967
  case "currencies_needing_conversion":
967
968
  return resultString(
968
969
  resolver,
969
970
  name,
970
- core.ext.currenciesNeedingConversion(
971
- requireStringArray(name, args, "currencies"),
972
- requireString(name, args, "target")
973
- )
971
+ core.ext.currenciesNeedingConversion(input.currencies, input.target)
974
972
  );
975
973
  }
976
974
  } catch (error) {
@@ -991,23 +989,19 @@ function extBqlBuilderWithResolver(resolver) {
991
989
  async (input) => {
992
990
  try {
993
991
  const core = await resolver.getCore();
994
- const args = asRecord(input);
995
992
  switch (input.operation) {
996
993
  case "build_preferreds_query":
997
994
  return resultString(
998
995
  resolver,
999
996
  name,
1000
- core.ext.buildPreferredsQuery(
1001
- requireString(name, args, "equityTicker"),
1002
- input.extraFields
1003
- )
997
+ core.ext.buildPreferredsQuery(input.equityTicker, input.extraFields)
1004
998
  );
1005
999
  case "build_corporate_bonds_query":
1006
1000
  return resultString(
1007
1001
  resolver,
1008
1002
  name,
1009
1003
  core.ext.buildCorporateBondsQuery(
1010
- requireString(name, args, "ticker"),
1004
+ input.ticker,
1011
1005
  input.ccy,
1012
1006
  input.extraFields,
1013
1007
  input.activeOnly
@@ -1017,10 +1011,7 @@ function extBqlBuilderWithResolver(resolver) {
1017
1011
  return resultString(
1018
1012
  resolver,
1019
1013
  name,
1020
- core.ext.buildEtfHoldingsQuery(
1021
- requireString(name, args, "etfTicker"),
1022
- input.extraFields
1023
- )
1014
+ core.ext.buildEtfHoldingsQuery(input.etfTicker, input.extraFields)
1024
1015
  );
1025
1016
  }
1026
1017
  } catch (error) {
@@ -1041,36 +1032,26 @@ function extMarketSessionWithResolver(resolver) {
1041
1032
  async (input) => {
1042
1033
  try {
1043
1034
  const core = await resolver.getCore();
1044
- const args = asRecord(input);
1045
1035
  switch (input.operation) {
1046
1036
  case "derive_sessions":
1047
1037
  return resultString(
1048
1038
  resolver,
1049
1039
  name,
1050
- core.ext.deriveSessions(
1051
- requireString(name, args, "dayStart"),
1052
- requireString(name, args, "dayEnd"),
1053
- input.mic,
1054
- input.exchCode
1055
- )
1040
+ core.ext.deriveSessions(input.dayStart, input.dayEnd, input.mic, input.exchCode)
1056
1041
  );
1057
1042
  case "get_market_rule":
1058
1043
  return resultString(resolver, name, core.ext.getMarketRule(input.mic, input.exchCode));
1059
1044
  case "infer_timezone":
1060
- return resultString(
1061
- resolver,
1062
- name,
1063
- core.ext.inferTimezone(requireString(name, args, "countryIso"))
1064
- );
1045
+ return resultString(resolver, name, core.ext.inferTimezone(input.countryIso));
1065
1046
  case "session_times_to_utc":
1066
1047
  return resultString(
1067
1048
  resolver,
1068
1049
  name,
1069
1050
  core.ext.sessionTimesToUtc(
1070
- requireString(name, args, "startTime"),
1071
- requireString(name, args, "endTime"),
1072
- requireString(name, args, "exchangeTz"),
1073
- requireString(name, args, "date")
1051
+ input.startTime,
1052
+ input.endTime,
1053
+ input.exchangeTz,
1054
+ input.date
1074
1055
  )
1075
1056
  );
1076
1057
  case "default_turnover_dates":
@@ -1086,11 +1067,7 @@ function extMarketSessionWithResolver(resolver) {
1086
1067
  core.ext.defaultBqrDatetimes(input.startDatetime, input.endDatetime)
1087
1068
  );
1088
1069
  case "get_exchange_override":
1089
- return resultString(
1090
- resolver,
1091
- name,
1092
- core.ext.getExchangeOverride(requireString(name, args, "ticker"))
1093
- );
1070
+ return resultString(resolver, name, core.ext.getExchangeOverride(input.ticker));
1094
1071
  case "list_exchange_overrides":
1095
1072
  return resultString(resolver, name, core.ext.listExchangeOverrides());
1096
1073
  }
@@ -1142,45 +1119,23 @@ function extConstantsWithResolver(resolver) {
1142
1119
  async (input) => {
1143
1120
  try {
1144
1121
  const core = await resolver.getCore();
1145
- const args = asRecord(input);
1146
1122
  switch (input.operation) {
1147
1123
  case "parse_date":
1148
- return resultString(
1149
- resolver,
1150
- name,
1151
- core.ext.parseDate(requireString(name, args, "dateStr"))
1152
- );
1124
+ return resultString(resolver, name, core.ext.parseDate(input.dateStr));
1153
1125
  case "fmt_date":
1154
1126
  return resultString(
1155
1127
  resolver,
1156
1128
  name,
1157
- core.ext.fmtDate(
1158
- requireInteger(name, args, "year"),
1159
- requireInteger(name, args, "month"),
1160
- requireInteger(name, args, "day"),
1161
- input.fmt
1162
- )
1129
+ core.ext.fmtDate(input.year, input.month, input.day, input.fmt)
1163
1130
  );
1164
1131
  case "get_month_code":
1165
- return resultString(
1166
- resolver,
1167
- name,
1168
- core.ext.getMonthCode(requireString(name, args, "monthName"))
1169
- );
1132
+ return resultString(resolver, name, core.ext.getMonthCode(input.monthName));
1170
1133
  case "get_month_name":
1171
- return resultString(
1172
- resolver,
1173
- name,
1174
- core.ext.getMonthName(requireString(name, args, "code"))
1175
- );
1134
+ return resultString(resolver, name, core.ext.getMonthName(input.code));
1176
1135
  case "get_futures_months":
1177
1136
  return resultString(resolver, name, core.ext.getFuturesMonths());
1178
1137
  case "get_dvd_type":
1179
- return resultString(
1180
- resolver,
1181
- name,
1182
- core.ext.getDvdType(requireString(name, args, "dvdType"))
1183
- );
1138
+ return resultString(resolver, name, core.ext.getDvdType(input.dvdType));
1184
1139
  case "get_dvd_types":
1185
1140
  return resultString(resolver, name, core.ext.getDvdTypes());
1186
1141
  case "get_dvd_cols":
@@ -1206,31 +1161,16 @@ function extColumnsWithResolver(resolver) {
1206
1161
  async (input) => {
1207
1162
  try {
1208
1163
  const core = await resolver.getCore();
1209
- const args = asRecord(input);
1210
1164
  switch (input.operation) {
1211
1165
  case "rename_dividend_columns":
1212
- return resultString(
1213
- resolver,
1214
- name,
1215
- core.ext.renameDividendColumns(requireStringArray(name, args, "columns"))
1216
- );
1166
+ return resultString(resolver, name, core.ext.renameDividendColumns(input.columns));
1217
1167
  case "rename_etf_columns":
1218
- return resultString(
1219
- resolver,
1220
- name,
1221
- core.ext.renameEtfColumns(requireStringArray(name, args, "columns"))
1222
- );
1168
+ return resultString(resolver, name, core.ext.renameEtfColumns(input.columns));
1223
1169
  case "build_earning_header_rename":
1224
- if (input.headerRow === void 0) {
1225
- throw new TypeError(`${name}: headerRow is required`);
1226
- }
1227
1170
  return resultString(
1228
1171
  resolver,
1229
1172
  name,
1230
- core.ext.buildEarningHeaderRename(
1231
- input.headerRow,
1232
- requireStringArray(name, args, "dataColumns")
1233
- )
1173
+ core.ext.buildEarningHeaderRename(input.headerRow, input.dataColumns)
1234
1174
  );
1235
1175
  }
1236
1176
  } catch (error) {
@@ -1250,9 +1190,6 @@ function extCalculateWithResolver(resolver) {
1250
1190
  return createBloombergStructuredTool(
1251
1191
  async (input) => {
1252
1192
  try {
1253
- if (input.values.length !== input.levels.length) {
1254
- throw new TypeError(`${name}: values and levels must have the same length`);
1255
- }
1256
1193
  const core = await resolver.getCore();
1257
1194
  return resultString(
1258
1195
  resolver,
@@ -1321,6 +1258,9 @@ var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/u;
1321
1258
  var BBG_DATE_RE = /^\d{8}$/u;
1322
1259
  var AMBIGUOUS_DATE_RE = /^\d{1,2}[-/]\d{1,2}[-/]\d{2,4}([T \D]|$)/u;
1323
1260
  var ISO_DATE_TIME_RE = /^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?$/u;
1261
+ var MIN_NUMERIC_BBG_DATE = 19000101;
1262
+ var MAX_NUMERIC_BBG_DATE = 29991231;
1263
+ var MIN_EPOCH_MS = 1e11;
1324
1264
  var primitiveSchema = z__namespace.union([
1325
1265
  z__namespace.string().transform((value) => value.trim()),
1326
1266
  z__namespace.number(),
@@ -1335,18 +1275,30 @@ function dateFromParts(year, month, day) {
1335
1275
  return formatted;
1336
1276
  }
1337
1277
  function dateToBbg(value) {
1338
- const date2 = value instanceof Date ? value : new Date(value);
1339
- if (Number.isNaN(date2.getTime())) {
1278
+ const date = value instanceof Date ? value : new Date(value);
1279
+ if (Number.isNaN(date.getTime())) {
1340
1280
  throw new TypeError("Invalid date value; expected YYYY-MM-DD, YYYYMMDD, Date, or epoch ms");
1341
1281
  }
1342
- const year = String(date2.getUTCFullYear()).padStart(4, "0");
1343
- const month = String(date2.getUTCMonth() + 1).padStart(2, "0");
1344
- const day = String(date2.getUTCDate()).padStart(2, "0");
1282
+ const year = String(date.getUTCFullYear()).padStart(4, "0");
1283
+ const month = String(date.getUTCMonth() + 1).padStart(2, "0");
1284
+ const day = String(date.getUTCDate()).padStart(2, "0");
1345
1285
  return `${year}${month}${day}`;
1346
1286
  }
1287
+ function numericDateToBbg(value, unit) {
1288
+ if (Number.isFinite(value) && value >= MIN_EPOCH_MS) {
1289
+ return new Date(value);
1290
+ }
1291
+ throw new TypeError(
1292
+ `Ambiguous numeric ${unit} ${String(value)}; use "YYYY-MM-DD" text or epoch milliseconds`
1293
+ );
1294
+ }
1347
1295
  function normalizeDate(value) {
1348
- if (value instanceof Date || typeof value === "number") {
1349
- return dateToBbg(value);
1296
+ if (typeof value === "number") {
1297
+ if (Number.isInteger(value) && value >= MIN_NUMERIC_BBG_DATE && value <= MAX_NUMERIC_BBG_DATE) {
1298
+ const text2 = String(value);
1299
+ return dateFromParts(text2.slice(0, 4), text2.slice(4, 6), text2.slice(6, 8));
1300
+ }
1301
+ return dateToBbg(numericDateToBbg(value, "date"));
1350
1302
  }
1351
1303
  const text = value.trim();
1352
1304
  if (text.length === 0) {
@@ -1364,12 +1316,13 @@ function normalizeDate(value) {
1364
1316
  throw new TypeError(`Invalid date ${JSON.stringify(text)}; use YYYY-MM-DD or YYYYMMDD`);
1365
1317
  }
1366
1318
  function normalizeDateTime(value) {
1367
- if (value instanceof Date || typeof value === "number") {
1368
- const date2 = value instanceof Date ? value : new Date(value);
1369
- if (Number.isNaN(date2.getTime())) {
1370
- throw new TypeError("Invalid datetime value; expected ISO 8601 datetime, Date, or epoch ms");
1319
+ if (typeof value === "number") {
1320
+ if (Number.isInteger(value) && value >= MIN_NUMERIC_BBG_DATE && value <= MAX_NUMERIC_BBG_DATE) {
1321
+ throw new TypeError(
1322
+ `Invalid numeric datetime ${String(value)}; include an explicit time component such as "2024-01-02T09:30:00"`
1323
+ );
1371
1324
  }
1372
- return date2.toISOString();
1325
+ return numericDateToBbg(value, "datetime").toISOString();
1373
1326
  }
1374
1327
  const text = value.trim();
1375
1328
  if (text.length === 0) {
@@ -1399,8 +1352,15 @@ function nonEmptyString2(tool2, field, maxChars, example) {
1399
1352
  function stringArray2(tool2, field, maxItems, maxChars, example) {
1400
1353
  return z__namespace.array(nonEmptyString2(tool2, field, maxChars, example)).min(1, `${tool2}: ${field} must contain at least one non-empty string. Example: ${example}`).max(maxItems, `${tool2}: ${field} can contain at most ${maxItems} values`);
1401
1354
  }
1355
+ function normalizationIssue(context, tool2, field, error) {
1356
+ context.addIssue({
1357
+ code: "custom",
1358
+ message: `${tool2}: ${field}: ${error instanceof Error ? error.message : String(error)}`
1359
+ });
1360
+ return z__namespace.NEVER;
1361
+ }
1402
1362
  function primitiveMap(tool2, field) {
1403
- return z__namespace.record(z__namespace.string().min(1), primitiveSchema).optional().transform((value) => {
1363
+ return z__namespace.record(z__namespace.string().min(1), primitiveSchema).optional().transform((value, context) => {
1404
1364
  if (value === void 0) {
1405
1365
  return void 0;
1406
1366
  }
@@ -1408,10 +1368,15 @@ function primitiveMap(tool2, field) {
1408
1368
  for (const [key, entry] of Object.entries(value)) {
1409
1369
  const normalizedKey = key.trim();
1410
1370
  if (normalizedKey.length === 0) {
1411
- throw new TypeError(`${tool2}: ${field} contains an empty key`);
1371
+ return normalizationIssue(context, tool2, field, new TypeError("contains an empty key"));
1412
1372
  }
1413
1373
  if (typeof entry === "string" && entry.length === 0) {
1414
- throw new TypeError(`${tool2}: ${field}.${normalizedKey} must not be an empty string`);
1374
+ return normalizationIssue(
1375
+ context,
1376
+ tool2,
1377
+ field,
1378
+ new TypeError(`${normalizedKey} must not be an empty string`)
1379
+ );
1415
1380
  }
1416
1381
  normalized[normalizedKey] = entry;
1417
1382
  }
@@ -1419,12 +1384,18 @@ function primitiveMap(tool2, field) {
1419
1384
  });
1420
1385
  }
1421
1386
  function dateField(tool2, field) {
1422
- return z__namespace.union([z__namespace.string(), z__namespace.date(), z__namespace.number()]).transform((value) => normalizeDate(value)).describe(
1387
+ return z__namespace.union([z__namespace.string(), z__namespace.number()]).transform((value, context) => {
1388
+ try {
1389
+ return normalizeDate(value);
1390
+ } catch (error) {
1391
+ return normalizationIssue(context, tool2, field, error);
1392
+ }
1393
+ }).describe(
1423
1394
  `${field} date. Use YYYY-MM-DD or Bloomberg-native YYYYMMDD, never ambiguous MM/DD/YYYY.`
1424
1395
  );
1425
1396
  }
1426
1397
  function dateTimeField(tool2, field) {
1427
- return z__namespace.union([z__namespace.string(), z__namespace.date(), z__namespace.number()]).superRefine((value, context) => {
1398
+ return z__namespace.union([z__namespace.string(), z__namespace.number()]).superRefine((value, context) => {
1428
1399
  if (typeof value !== "string") {
1429
1400
  return;
1430
1401
  }
@@ -1435,7 +1406,13 @@ function dateTimeField(tool2, field) {
1435
1406
  message: `${tool2}: ${field} datetime requires an explicit time component; use ISO 8601 such as YYYY-MM-DDT09:30:00`
1436
1407
  });
1437
1408
  }
1438
- }).transform((value) => normalizeDateTime(value)).describe(`${field} datetime. Use ISO 8601 with an explicit time component.`);
1409
+ }).transform((value, context) => {
1410
+ try {
1411
+ return normalizeDateTime(value);
1412
+ } catch (error) {
1413
+ return normalizationIssue(context, tool2, field, error);
1414
+ }
1415
+ }).describe(`${field} datetime. Use ISO 8601 with an explicit time component.`);
1439
1416
  }
1440
1417
  function referenceFormat(tool2) {
1441
1418
  return z__namespace.enum(REFERENCE_FORMATS, {
@@ -1478,7 +1455,7 @@ function createBdpSchema(options) {
1478
1455
  options.maxStringChars,
1479
1456
  '["<TICKER> <MARKET_SECTOR>"]'
1480
1457
  ).describe(
1481
- "Fully qualified Bloomberg securities supplied by the user; use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs. Do not invent tickers."
1458
+ "Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
1482
1459
  ),
1483
1460
  validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
1484
1461
  });
@@ -1510,7 +1487,7 @@ function createBdhSchema(options) {
1510
1487
  options.maxStringChars,
1511
1488
  '["<TICKER> <MARKET_SECTOR>"]'
1512
1489
  ).describe(
1513
- "Fully qualified Bloomberg securities supplied by the user; use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs."
1490
+ "Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
1514
1491
  ),
1515
1492
  start: dateField(tool2, "start").describe("Required start date. Use YYYY-MM-DD or YYYYMMDD."),
1516
1493
  validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
@@ -1530,7 +1507,6 @@ function createBdsSchema(options) {
1530
1507
  field: nonEmptyString2(tool2, "field", options.maxStringChars, "<BULK_FIELD>").describe(
1531
1508
  "Exactly one Bloomberg bulk/table field supplied by the user."
1532
1509
  ),
1533
- format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
1534
1510
  kwargs: primitiveMap(tool2, "kwargs").describe(
1535
1511
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1536
1512
  ),
@@ -1544,7 +1520,7 @@ function createBdsSchema(options) {
1544
1520
  options.maxStringChars,
1545
1521
  '["<INDEX_TICKER> <MARKET_SECTOR>"]'
1546
1522
  ).describe(
1547
- "Fully qualified Bloomberg securities supplied by the user; use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs."
1523
+ "Securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' for Bloomberg tickers, '/isin/<ISIN>' for raw ISINs, '/cusip/<CUSIP>' for raw CUSIPs. Never invent, guess, or convert identifiers into tickers."
1548
1524
  ),
1549
1525
  validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
1550
1526
  });
@@ -1571,7 +1547,7 @@ function createBdibSchema(options) {
1571
1547
  options.maxStringChars,
1572
1548
  "<TICKER> <MARKET_SECTOR>"
1573
1549
  ).describe(
1574
- "One fully qualified Bloomberg security supplied by the user; use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs."
1550
+ "One security exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent, guess, or convert identifiers into tickers."
1575
1551
  )
1576
1552
  });
1577
1553
  }
@@ -1610,14 +1586,13 @@ function createBdtickSchema(options) {
1610
1586
  options.maxStringChars,
1611
1587
  "<TICKER> <MARKET_SECTOR>"
1612
1588
  ).describe(
1613
- "One fully qualified Bloomberg security supplied by the user; use /isin/<ISIN> for ISINs and /cusip/<CUSIP> for CUSIPs."
1589
+ "One security exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent, guess, or convert identifiers into tickers."
1614
1590
  )
1615
1591
  });
1616
1592
  }
1617
1593
  function createBqlSchema(options) {
1618
1594
  const tool2 = "xbbg_bql";
1619
1595
  return z__namespace.object({
1620
- format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
1621
1596
  kwargs: primitiveMap(tool2, "kwargs").describe(
1622
1597
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1623
1598
  ),
@@ -1656,7 +1631,6 @@ function createBqrSchema(options) {
1656
1631
  function createBsrchSchema(options) {
1657
1632
  const tool2 = "xbbg_bsrch";
1658
1633
  return z__namespace.object({
1659
- format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
1660
1634
  kwargs: primitiveMap(tool2, "kwargs").describe(
1661
1635
  "Search-grid kwargs as flat string/number/boolean values only."
1662
1636
  ),
@@ -1679,7 +1653,6 @@ function createBfldsSchema(options) {
1679
1653
  fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe(
1680
1654
  "Specific field mnemonics to inspect. Provide either fields or searchSpec, not both."
1681
1655
  ),
1682
- format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
1683
1656
  kwargs: primitiveMap(tool2, "kwargs").describe(
1684
1657
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1685
1658
  ),
@@ -1707,7 +1680,6 @@ function createBeqsSchema(options) {
1707
1680
  const tool2 = "xbbg_beqs";
1708
1681
  return z__namespace.object({
1709
1682
  asof: dateField(tool2, "asof").optional().describe("Optional as-of date for the screen."),
1710
- format: referenceFormat(tool2).describe("JSON output shape. Usually omit."),
1711
1683
  group: nonEmptyString2(tool2, "group", options.maxStringChars, "<BEQS_GROUP>").optional().describe("Bloomberg BEQS group when required by the screen."),
1712
1684
  kwargs: primitiveMap(tool2, "kwargs").describe(
1713
1685
  "Advanced BEQS request kwargs as flat string/number/boolean values only."
@@ -1741,7 +1713,9 @@ function createYasSchema(options) {
1741
1713
  options.maxSecurities,
1742
1714
  options.maxStringChars,
1743
1715
  '["/isin/<ISIN> <MARKET_SECTOR>"]'
1744
- ).describe("Fully qualified fixed-income Bloomberg securities supplied by the user."),
1716
+ ).describe(
1717
+ "Fixed-income securities exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>' or identifier syntax such as '/isin/<ISIN> <MARKET_SECTOR>'. Never invent or guess tickers."
1718
+ ),
1745
1719
  yieldType: z__namespace.number().int().optional().describe("Optional YAS yield type."),
1746
1720
  yieldVal: z__namespace.number().optional().describe("Optional YAS yield value input.")
1747
1721
  });
@@ -1754,7 +1728,9 @@ function createPreferredsSchema(options) {
1754
1728
  "equityTicker",
1755
1729
  options.maxStringChars,
1756
1730
  "<ISSUER_TICKER> <MARKET_SECTOR>"
1757
- ).describe("One fully qualified issuer equity ticker supplied by the user."),
1731
+ ).describe(
1732
+ "The issuer's common equity ticker as '<TICKER> <MARKET_SECTOR>', never a preferred ('Pfd') ticker and never a guessed one. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first."
1733
+ ),
1758
1734
  fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the preferreds recipe result.")
1759
1735
  });
1760
1736
  }
@@ -1769,7 +1745,9 @@ function createCorporateBondsSchema(options) {
1769
1745
  "ticker",
1770
1746
  options.maxStringChars,
1771
1747
  "<ISSUER_TICKER> <MARKET_SECTOR>"
1772
- ).describe("One fully qualified issuer/company ticker supplied by the user.")
1748
+ ).describe(
1749
+ "The issuer/company equity ticker as '<TICKER> <MARKET_SECTOR>' supplied by the user. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess tickers."
1750
+ )
1773
1751
  });
1774
1752
  }
1775
1753
  function createIndexMembersSchema(options) {
@@ -1782,7 +1760,9 @@ function createIndexMembersSchema(options) {
1782
1760
  "index",
1783
1761
  options.maxStringChars,
1784
1762
  "<INDEX_TICKER> <MARKET_SECTOR>"
1785
- ).describe("One fully qualified Bloomberg index ticker supplied by the user.")
1763
+ ).describe(
1764
+ "One Bloomberg index ticker as '<INDEX_TICKER> <MARKET_SECTOR>' supplied by the user; never guess index tickers."
1765
+ )
1786
1766
  });
1787
1767
  }
1788
1768
  function createResolveIsinsSchema(options) {
@@ -1817,7 +1797,9 @@ function createEtfHoldingsSchema(options) {
1817
1797
  "etfTicker",
1818
1798
  options.maxStringChars,
1819
1799
  "<ETF_TICKER> <MARKET_SECTOR>"
1820
- ).describe("One fully qualified Bloomberg ETF ticker supplied by the user."),
1800
+ ).describe(
1801
+ "One Bloomberg ETF ticker as '<ETF_TICKER> <MARKET_SECTOR>' supplied by the user. Resolve a supplied ISIN/CUSIP with xbbg_resolve_isins first; never guess tickers."
1802
+ ),
1821
1803
  fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the ETF holdings recipe result.")
1822
1804
  });
1823
1805
  }
@@ -1826,7 +1808,7 @@ function snapshotControlFields(tool2, options) {
1826
1808
  allFields: z__namespace.boolean().optional().describe("Request all Bloomberg fields when supported."),
1827
1809
  conflate: z__namespace.boolean().optional().describe("Enable Bloomberg conflated streaming when supported."),
1828
1810
  drain: z__namespace.boolean().optional().describe(
1829
- "Pass drain=true to unsubscribe. Defaults to false; collected output remains bounded."
1811
+ "Flush buffered backlog while closing the subscription. The subscription always closes; collected output stays bounded either way. Defaults to false."
1830
1812
  ),
1831
1813
  flushThreshold: z__namespace.number().int().positive().optional().describe("Optional stream flush threshold."),
1832
1814
  maxUpdates: z__namespace.number().int(`${tool2}: maxUpdates must be a positive integer.`).positive(`${tool2}: maxUpdates must be greater than zero.`).max(
@@ -1861,7 +1843,9 @@ function createStreamSnapshotSchema(options) {
1861
1843
  options.maxSecurities,
1862
1844
  options.maxStringChars,
1863
1845
  '["<TICKER> <MARKET_SECTOR>"]'
1864
- ).describe("Fully qualified Bloomberg securities supplied by the user to observe."),
1846
+ ).describe(
1847
+ "Securities to observe, exactly as the user supplied them: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
1848
+ ),
1865
1849
  ...snapshotControlFields(tool2, options)
1866
1850
  });
1867
1851
  }
@@ -1874,7 +1858,9 @@ function createMktbarSnapshotSchema(options) {
1874
1858
  "ticker",
1875
1859
  options.maxStringChars,
1876
1860
  "<TICKER> <MARKET_SECTOR>"
1877
- ).describe("One fully qualified Bloomberg security supplied by the user to observe."),
1861
+ ).describe(
1862
+ "One security to observe, exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
1863
+ ),
1878
1864
  ...snapshotControlFields(tool2, options)
1879
1865
  });
1880
1866
  }
@@ -1887,7 +1873,9 @@ function createDepthSnapshotSchema(options) {
1887
1873
  "ticker",
1888
1874
  options.maxStringChars,
1889
1875
  "<TICKER> <MARKET_SECTOR>"
1890
- ).describe("One fully qualified Bloomberg security supplied by the user to observe."),
1876
+ ).describe(
1877
+ "One security to observe, exactly as the user supplied it: '<TICKER> <MARKET_SECTOR>', '/isin/<ISIN>', or '/cusip/<CUSIP>'. Never invent or guess tickers."
1878
+ ),
1891
1879
  ...snapshotControlFields(tool2, options)
1892
1880
  });
1893
1881
  }
@@ -1897,17 +1885,24 @@ function resultString2(resolver, name, value) {
1897
1885
  return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
1898
1886
  }
1899
1887
  var STREAM_TIMEOUT = /* @__PURE__ */ Symbol("stream_timeout");
1888
+ var STREAM_ABORTED = /* @__PURE__ */ Symbol("stream_aborted");
1889
+ function abortError(signal) {
1890
+ const reason = signal?.reason;
1891
+ return reason instanceof Error ? reason : new Error("Tool call aborted");
1892
+ }
1900
1893
  function streamOptions(input) {
1901
1894
  return {
1902
1895
  allFields: input.allFields,
1903
1896
  conflate: input.conflate,
1904
- fields: input.fields,
1905
1897
  flushThreshold: input.flushThreshold,
1906
1898
  options: input.options,
1907
1899
  overflowPolicy: input.overflowPolicy,
1908
1900
  streamCapacity: input.streamCapacity
1909
1901
  };
1910
1902
  }
1903
+ function singleTickerStreamOptions(input) {
1904
+ return { ...streamOptions(input), fields: input.fields };
1905
+ }
1911
1906
  function isRecord(value) {
1912
1907
  return typeof value === "object" && value !== null;
1913
1908
  }
@@ -1963,42 +1958,55 @@ function normalizeStreamUpdate(value) {
1963
1958
  const rows = rowsFromArrowTable(value);
1964
1959
  return rows === void 0 ? jsonCompatible(value) : rows.map(jsonCompatible);
1965
1960
  }
1966
- async function nextWithinTimeout(iterator, deadlineMs) {
1961
+ async function nextWithinTimeout(iterator, deadlineMs, signal) {
1962
+ if (signal?.aborted === true) {
1963
+ return STREAM_ABORTED;
1964
+ }
1967
1965
  const remainingMs = deadlineMs - Date.now();
1968
1966
  if (remainingMs <= 0) {
1969
1967
  return STREAM_TIMEOUT;
1970
1968
  }
1971
1969
  const nextPromise = iterator.next();
1972
1970
  let timer;
1973
- const timeoutPromise = new Promise((resolve) => {
1974
- timer = setTimeout(() => resolve(STREAM_TIMEOUT), remainingMs);
1975
- });
1976
- const result = await Promise.race([nextPromise, timeoutPromise]);
1971
+ let onAbort;
1972
+ const racers = [
1973
+ nextPromise,
1974
+ new Promise((resolve) => {
1975
+ timer = setTimeout(() => resolve(STREAM_TIMEOUT), remainingMs);
1976
+ })
1977
+ ];
1978
+ if (signal !== void 0) {
1979
+ racers.push(
1980
+ new Promise((resolve) => {
1981
+ onAbort = () => resolve(STREAM_ABORTED);
1982
+ signal.addEventListener("abort", onAbort, { once: true });
1983
+ })
1984
+ );
1985
+ }
1986
+ const result = await Promise.race(racers);
1977
1987
  if (timer !== void 0) {
1978
1988
  clearTimeout(timer);
1979
1989
  }
1980
- if (result === STREAM_TIMEOUT) {
1990
+ if (signal !== void 0 && onAbort !== void 0) {
1991
+ signal.removeEventListener("abort", onAbort);
1992
+ }
1993
+ if (result === STREAM_TIMEOUT || result === STREAM_ABORTED) {
1981
1994
  void nextPromise.catch(() => void 0);
1982
1995
  }
1983
1996
  return result;
1984
1997
  }
1985
- async function unsubscribeSnapshot(subscription, drain, priorError) {
1986
- try {
1987
- await subscription.unsubscribe(drain);
1988
- } catch (error) {
1989
- if (priorError === void 0) {
1990
- throw error;
1991
- }
1992
- }
1993
- }
1994
- async function collectSnapshot(subscription, input) {
1998
+ async function collectSnapshot(subscription, input, signal) {
1995
1999
  const updates = [];
1996
2000
  const deadlineMs = Date.now() + input.timeoutMs;
1997
2001
  let reason = "max_updates";
2002
+ let failed = false;
1998
2003
  let caught;
1999
2004
  try {
2000
2005
  while (updates.length < input.maxUpdates) {
2001
- const next = await nextWithinTimeout(subscription, deadlineMs);
2006
+ const next = await nextWithinTimeout(subscription, deadlineMs, signal);
2007
+ if (next === STREAM_ABORTED) {
2008
+ throw abortError(signal);
2009
+ }
2002
2010
  if (next === STREAM_TIMEOUT) {
2003
2011
  reason = "timeout";
2004
2012
  break;
@@ -2009,26 +2017,34 @@ async function collectSnapshot(subscription, input) {
2009
2017
  }
2010
2018
  updates.push(normalizeStreamUpdate(next.value));
2011
2019
  }
2012
- return {
2013
- maxUpdates: input.maxUpdates,
2014
- reason,
2015
- timeoutMs: input.timeoutMs,
2016
- updateCount: updates.length,
2017
- updates
2018
- };
2019
2020
  } catch (error) {
2021
+ failed = true;
2020
2022
  caught = error;
2021
- throw error;
2022
- } finally {
2023
- await unsubscribeSnapshot(subscription, input.drain === true, caught);
2024
2023
  }
2024
+ const drain = input.drain === true && signal?.aborted !== true;
2025
+ let unsubscribeError;
2026
+ try {
2027
+ await subscription.unsubscribe(drain);
2028
+ } catch (error) {
2029
+ if (!failed) {
2030
+ unsubscribeError = error instanceof Error ? error.message : String(error);
2031
+ }
2032
+ }
2033
+ if (failed) {
2034
+ throw caught;
2035
+ }
2036
+ return {
2037
+ maxUpdates: input.maxUpdates,
2038
+ reason,
2039
+ timeoutMs: input.timeoutMs,
2040
+ updateCount: updates.length,
2041
+ updates,
2042
+ ...unsubscribeError === void 0 ? {} : { unsubscribeError }
2043
+ };
2025
2044
  }
2026
2045
  function validationSetting(resolver, value) {
2027
2046
  return value ?? resolver.options.validateFields;
2028
2047
  }
2029
- function enabledTool(resolver, name, creator) {
2030
- return isToolDisabled(resolver.options, name) ? [] : [creator(resolver)];
2031
- }
2032
2048
  function bdpWithResolver(resolver) {
2033
2049
  const name = "xbbg_bdp";
2034
2050
  return createBloombergStructuredTool(
@@ -2092,7 +2108,6 @@ function bdsWithResolver(resolver) {
2092
2108
  const engine = await resolver.getEngine();
2093
2109
  const result = await engine.bds(input.securities, [input.field], {
2094
2110
  backend: "json",
2095
- format: input.format,
2096
2111
  kwargs: input.kwargs,
2097
2112
  overrides: input.overrides,
2098
2113
  validateFields: validationSetting(resolver, input.validateFields)
@@ -2182,7 +2197,6 @@ function bqlWithResolver(resolver) {
2182
2197
  const engine = await resolver.getEngine();
2183
2198
  const result = await engine.bql(input.query, {
2184
2199
  backend: "json",
2185
- format: input.format,
2186
2200
  kwargs: input.kwargs
2187
2201
  });
2188
2202
  return resultString2(resolver, name, result);
@@ -2206,7 +2220,6 @@ function bsrchWithResolver(resolver) {
2206
2220
  const engine = await resolver.getEngine();
2207
2221
  const result = await engine.bsrch(input.searchSpec, {
2208
2222
  backend: "json",
2209
- format: input.format,
2210
2223
  kwargs: input.kwargs,
2211
2224
  overrides: input.overrides
2212
2225
  });
@@ -2258,7 +2271,6 @@ function bfldsWithResolver(resolver) {
2258
2271
  const result = await engine.bflds({
2259
2272
  backend: "json",
2260
2273
  fields: input.fields,
2261
- format: input.format,
2262
2274
  kwargs: input.kwargs,
2263
2275
  searchSpec: input.searchSpec
2264
2276
  });
@@ -2284,7 +2296,6 @@ function beqsWithResolver(resolver) {
2284
2296
  const result = await engine.beqs(input.screen, {
2285
2297
  asof: input.asof,
2286
2298
  backend: "json",
2287
- format: input.format,
2288
2299
  group: input.group,
2289
2300
  kwargs: input.kwargs,
2290
2301
  overrides: input.overrides,
@@ -2469,11 +2480,13 @@ function etfHoldingsWithResolver(resolver) {
2469
2480
  function streamSnapshotWithResolver(resolver) {
2470
2481
  const name = "xbbg_stream_snapshot";
2471
2482
  return createBloombergStructuredTool(
2472
- async (input) => {
2483
+ async (input, config) => {
2484
+ const signal = config?.signal;
2473
2485
  try {
2474
2486
  const engine = await resolver.getEngine();
2487
+ signal?.throwIfAborted();
2475
2488
  const subscription = await engine.stream(input.tickers, input.fields, streamOptions(input));
2476
- const result = await collectSnapshot(subscription, input);
2489
+ const result = await collectSnapshot(subscription, input, signal);
2477
2490
  return resultString2(resolver, name, result);
2478
2491
  } catch (error) {
2479
2492
  throwWithToolContext(name, error);
@@ -2490,11 +2503,13 @@ function streamSnapshotWithResolver(resolver) {
2490
2503
  function mktbarSnapshotWithResolver(resolver) {
2491
2504
  const name = "xbbg_mktbar_snapshot";
2492
2505
  return createBloombergStructuredTool(
2493
- async (input) => {
2506
+ async (input, config) => {
2507
+ const signal = config?.signal;
2494
2508
  try {
2495
2509
  const engine = await resolver.getEngine();
2496
- const subscription = await engine.mktbar(input.ticker, streamOptions(input));
2497
- const result = await collectSnapshot(subscription, input);
2510
+ signal?.throwIfAborted();
2511
+ const subscription = await engine.mktbar(input.ticker, singleTickerStreamOptions(input));
2512
+ const result = await collectSnapshot(subscription, input, signal);
2498
2513
  return resultString2(resolver, name, result);
2499
2514
  } catch (error) {
2500
2515
  throwWithToolContext(name, error);
@@ -2511,11 +2526,13 @@ function mktbarSnapshotWithResolver(resolver) {
2511
2526
  function depthSnapshotWithResolver(resolver) {
2512
2527
  const name = "xbbg_depth_snapshot";
2513
2528
  return createBloombergStructuredTool(
2514
- async (input) => {
2529
+ async (input, config) => {
2530
+ const signal = config?.signal;
2515
2531
  try {
2516
2532
  const engine = await resolver.getEngine();
2517
- const subscription = await engine.depth(input.ticker, streamOptions(input));
2518
- const result = await collectSnapshot(subscription, input);
2533
+ signal?.throwIfAborted();
2534
+ const subscription = await engine.depth(input.ticker, singleTickerStreamOptions(input));
2535
+ const result = await collectSnapshot(subscription, input, signal);
2519
2536
  return resultString2(resolver, name, result);
2520
2537
  } catch (error) {
2521
2538
  throwWithToolContext(name, error);
@@ -2589,29 +2606,32 @@ function createMktbarSnapshotTool(options = {}) {
2589
2606
  function createDepthSnapshotTool(options = {}) {
2590
2607
  return depthSnapshotWithResolver(createCoreResolver(options));
2591
2608
  }
2609
+ var CORE_TOOL_DEFINITIONS = Object.freeze([
2610
+ { create: bdpWithResolver, name: "xbbg_bdp" },
2611
+ { create: bdhWithResolver, name: "xbbg_bdh" },
2612
+ { create: bdsWithResolver, name: "xbbg_bds" },
2613
+ { create: bdibWithResolver, name: "xbbg_bdib" },
2614
+ { create: bdtickWithResolver, name: "xbbg_bdtick" },
2615
+ { create: bqlWithResolver, name: "xbbg_bql" },
2616
+ { create: bsrchWithResolver, name: "xbbg_bsrch" },
2617
+ { create: bqrWithResolver, name: "xbbg_bqr" },
2618
+ { create: bfldsWithResolver, name: "xbbg_bflds" },
2619
+ { create: beqsWithResolver, name: "xbbg_beqs" },
2620
+ { create: yasWithResolver, name: "xbbg_yas" },
2621
+ { create: preferredsWithResolver, name: "xbbg_preferreds" },
2622
+ { create: corporateBondsWithResolver, name: "xbbg_corporate_bonds" },
2623
+ { create: indexMembersWithResolver, name: "xbbg_index_members" },
2624
+ { create: resolveIsinsWithResolver, name: "xbbg_resolve_isins" },
2625
+ { create: issuerIsinsWithResolver, name: "xbbg_issuer_isins" },
2626
+ { create: etfHoldingsWithResolver, name: "xbbg_etf_holdings" },
2627
+ { create: streamSnapshotWithResolver, name: "xbbg_stream_snapshot" },
2628
+ { create: mktbarSnapshotWithResolver, name: "xbbg_mktbar_snapshot" },
2629
+ { create: depthSnapshotWithResolver, name: "xbbg_depth_snapshot" }
2630
+ ]);
2592
2631
  function createBloombergToolsForResolver(resolver) {
2593
- return [
2594
- ...enabledTool(resolver, "xbbg_bdp", bdpWithResolver),
2595
- ...enabledTool(resolver, "xbbg_bdh", bdhWithResolver),
2596
- ...enabledTool(resolver, "xbbg_bds", bdsWithResolver),
2597
- ...enabledTool(resolver, "xbbg_bdib", bdibWithResolver),
2598
- ...enabledTool(resolver, "xbbg_bdtick", bdtickWithResolver),
2599
- ...enabledTool(resolver, "xbbg_bql", bqlWithResolver),
2600
- ...enabledTool(resolver, "xbbg_bsrch", bsrchWithResolver),
2601
- ...enabledTool(resolver, "xbbg_bqr", bqrWithResolver),
2602
- ...enabledTool(resolver, "xbbg_bflds", bfldsWithResolver),
2603
- ...enabledTool(resolver, "xbbg_beqs", beqsWithResolver),
2604
- ...enabledTool(resolver, "xbbg_yas", yasWithResolver),
2605
- ...enabledTool(resolver, "xbbg_preferreds", preferredsWithResolver),
2606
- ...enabledTool(resolver, "xbbg_corporate_bonds", corporateBondsWithResolver),
2607
- ...enabledTool(resolver, "xbbg_index_members", indexMembersWithResolver),
2608
- ...enabledTool(resolver, "xbbg_resolve_isins", resolveIsinsWithResolver),
2609
- ...enabledTool(resolver, "xbbg_issuer_isins", issuerIsinsWithResolver),
2610
- ...enabledTool(resolver, "xbbg_etf_holdings", etfHoldingsWithResolver),
2611
- ...enabledTool(resolver, "xbbg_stream_snapshot", streamSnapshotWithResolver),
2612
- ...enabledTool(resolver, "xbbg_mktbar_snapshot", mktbarSnapshotWithResolver),
2613
- ...enabledTool(resolver, "xbbg_depth_snapshot", depthSnapshotWithResolver)
2614
- ];
2632
+ return CORE_TOOL_DEFINITIONS.filter(
2633
+ (definition) => !isToolDisabled(resolver.options, definition.name)
2634
+ ).map((definition) => definition.create(resolver));
2615
2635
  }
2616
2636
  function createBloombergTools(options = {}) {
2617
2637
  return createBloombergToolsForResolver(createCoreResolver(options));
@@ -2629,6 +2649,7 @@ function createAllBloombergTools(options = {}) {
2629
2649
  exports.BLOOMBERG_EXT_TOOL_NAMES = BLOOMBERG_EXT_TOOL_NAMES;
2630
2650
  exports.BLOOMBERG_TOOL_INSTRUCTIONS = BLOOMBERG_TOOL_INSTRUCTIONS;
2631
2651
  exports.BLOOMBERG_TOOL_NAMES = BLOOMBERG_TOOL_NAMES;
2652
+ exports.DEFAULT_ENGINE_REQUEST_TIMEOUT_MS = DEFAULT_ENGINE_REQUEST_TIMEOUT_MS;
2632
2653
  exports.createAllBloombergTools = createAllBloombergTools;
2633
2654
  exports.createBdhTool = createBdhTool;
2634
2655
  exports.createBdibTool = createBdibTool;
@@ -2663,5 +2684,6 @@ exports.createResolveIsinsTool = createResolveIsinsTool;
2663
2684
  exports.createStreamSnapshotTool = createStreamSnapshotTool;
2664
2685
  exports.createYasTool = createYasTool;
2665
2686
  exports.getBloombergToolInstructions = getBloombergToolInstructions;
2687
+ exports.toolParameterJsonSchema = toolParameterJsonSchema;
2666
2688
  //# sourceMappingURL=index.js.map
2667
2689
  //# sourceMappingURL=index.js.map