@xbbg/langgraph 1.2.6 → 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
@@ -1,7 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var tools = require('@langchain/core/tools');
4
- var z2 = require('zod');
4
+ var zodToJsonSchema = require('zod-to-json-schema');
5
+ var z = require('zod/v3');
5
6
 
6
7
  function _interopNamespace(e) {
7
8
  if (e && e.__esModule) return e;
@@ -21,7 +22,7 @@ function _interopNamespace(e) {
21
22
  return Object.freeze(n);
22
23
  }
23
24
 
24
- var z2__namespace = /*#__PURE__*/_interopNamespace(z2);
25
+ var z__namespace = /*#__PURE__*/_interopNamespace(z);
25
26
 
26
27
  // src/options.ts
27
28
  var BLOOMBERG_TOOL_NAMES = [
@@ -64,6 +65,13 @@ var DEFAULT_MAX_BQL_QUERY_CHARS = 4e3;
64
65
  var DEFAULT_MAX_SEARCH_SPEC_CHARS = 1e3;
65
66
  var DEFAULT_MAX_STREAM_UPDATES = 10;
66
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
+ }
67
75
  function positiveInteger(value, fallback, name) {
68
76
  if (value === void 0) {
69
77
  return fallback;
@@ -81,7 +89,7 @@ function normalizeBloombergToolsOptions(options = {}) {
81
89
  core: options.core,
82
90
  disabledTools: disabledToolSet(options.disabledTools),
83
91
  engine: options.engine,
84
- engineConfig: options.engineConfig,
92
+ engineConfig: engineConfigWithDefaults(options.engineConfig),
85
93
  maxBqlQueryChars: positiveInteger(
86
94
  options.maxBqlQueryChars,
87
95
  DEFAULT_MAX_BQL_QUERY_CHARS,
@@ -125,22 +133,40 @@ function createCoreResolver(options = {}) {
125
133
  const normalized = normalizeBloombergToolsOptions(options);
126
134
  let corePromise;
127
135
  let enginePromise;
136
+ async function cacheCoreImport() {
137
+ const promise = importCore();
138
+ corePromise = promise;
139
+ promise.catch(() => {
140
+ if (corePromise === promise) {
141
+ corePromise = void 0;
142
+ }
143
+ });
144
+ return await promise;
145
+ }
146
+ async function cacheEngineConnect() {
147
+ const promise = (async () => {
148
+ const core = await getCore();
149
+ return await core.connect(normalized.engineConfig);
150
+ })();
151
+ enginePromise = promise;
152
+ promise.catch(() => {
153
+ if (enginePromise === promise) {
154
+ enginePromise = void 0;
155
+ }
156
+ });
157
+ return await promise;
158
+ }
128
159
  async function getCore() {
129
160
  if (normalized.core !== void 0) {
130
161
  return normalized.core;
131
162
  }
132
- corePromise ??= importCore();
133
- return await corePromise;
163
+ return await (corePromise ?? cacheCoreImport());
134
164
  }
135
165
  async function getEngine() {
136
166
  if (normalized.engine !== void 0) {
137
167
  return normalized.engine;
138
168
  }
139
- enginePromise ??= (async () => {
140
- const core = await getCore();
141
- return await core.connect(normalized.engineConfig);
142
- })();
143
- return await enginePromise;
169
+ return await (enginePromise ?? cacheEngineConnect());
144
170
  }
145
171
  return {
146
172
  getCore,
@@ -149,6 +175,232 @@ function createCoreResolver(options = {}) {
149
175
  };
150
176
  }
151
177
 
178
+ // src/result-limits.ts
179
+ var MAX_RESULT_DEPTH = 32;
180
+ function isPlainObject(value) {
181
+ const prototype = Object.getPrototypeOf(value);
182
+ return prototype === Object.prototype || prototype === null;
183
+ }
184
+ function truncateString(value, maxStringChars, state) {
185
+ if (value.length <= maxStringChars) {
186
+ return value;
187
+ }
188
+ state.truncated = true;
189
+ return `${value.slice(0, maxStringChars)}\u2026[truncated ${value.length - maxStringChars} chars]`;
190
+ }
191
+ function limitValue(value, maxRows, maxStringChars, state, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
192
+ if (typeof value === "string") {
193
+ return truncateString(value, maxStringChars, state);
194
+ }
195
+ if (value instanceof Date) {
196
+ return value.toISOString();
197
+ }
198
+ if (depth > MAX_RESULT_DEPTH) {
199
+ state.truncated = true;
200
+ return "[Max result depth exceeded]";
201
+ }
202
+ if (Array.isArray(value)) {
203
+ if (seen.has(value)) {
204
+ state.truncated = true;
205
+ return "[Circular]";
206
+ }
207
+ seen.add(value);
208
+ const capped = value.length > maxRows ? value.slice(0, maxRows) : value;
209
+ if (capped.length !== value.length) {
210
+ state.truncated = true;
211
+ }
212
+ return capped.map((item) => limitValue(item, maxRows, maxStringChars, state, depth + 1, seen));
213
+ }
214
+ if (typeof value === "object" && value !== null) {
215
+ if (seen.has(value)) {
216
+ state.truncated = true;
217
+ return "[Circular]";
218
+ }
219
+ if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {
220
+ state.truncated = true;
221
+ return `[binary data: ${value.byteLength} bytes]`;
222
+ }
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
+ }
229
+ return value;
230
+ }
231
+ seen.add(value);
232
+ const output = {};
233
+ for (const [key, entry] of Object.entries(value)) {
234
+ output[key] = limitValue(entry, maxRows, maxStringChars, state, depth + 1, seen);
235
+ }
236
+ return output;
237
+ }
238
+ return value;
239
+ }
240
+ function rowCountOf(value) {
241
+ if (Array.isArray(value)) {
242
+ return value.length;
243
+ }
244
+ if (typeof value !== "object" || value === null) {
245
+ return null;
246
+ }
247
+ const record2 = value;
248
+ const rowCount = record2.rowCount;
249
+ if (typeof rowCount === "number" && Number.isInteger(rowCount) && rowCount >= 0) {
250
+ return rowCount;
251
+ }
252
+ const updateCount = record2.updateCount;
253
+ if (typeof updateCount === "number" && Number.isInteger(updateCount) && updateCount >= 0) {
254
+ return updateCount;
255
+ }
256
+ return null;
257
+ }
258
+ var ERROR_SHAPE_KEYS = /* @__PURE__ */ new Set([
259
+ "error",
260
+ "errors",
261
+ "fielderrors",
262
+ "fieldexception",
263
+ "fieldexceptions",
264
+ "responseerror",
265
+ "securityerror"
266
+ ]);
267
+ function hasErrorShape(value) {
268
+ const pending = [value];
269
+ const seen = /* @__PURE__ */ new WeakSet();
270
+ while (pending.length > 0) {
271
+ const entry = pending.pop();
272
+ if (typeof entry !== "object" || entry === null) {
273
+ continue;
274
+ }
275
+ if (seen.has(entry)) {
276
+ continue;
277
+ }
278
+ seen.add(entry);
279
+ if (Array.isArray(entry)) {
280
+ for (const child of entry) {
281
+ pending.push(child);
282
+ }
283
+ continue;
284
+ }
285
+ for (const [key, child] of Object.entries(entry)) {
286
+ if (ERROR_SHAPE_KEYS.has(key.toLowerCase()) && child !== void 0) {
287
+ return true;
288
+ }
289
+ pending.push(child);
290
+ }
291
+ }
292
+ return false;
293
+ }
294
+ function limitResult(value, maxRows, maxStringChars) {
295
+ const state = { truncated: false };
296
+ const rowCount = rowCountOf(value);
297
+ const limitedValue = limitValue(value, maxRows, maxStringChars, state);
298
+ return {
299
+ rowCount,
300
+ truncated: state.truncated,
301
+ value: limitedValue
302
+ };
303
+ }
304
+ function summarizeEnvelope(envelope) {
305
+ const rowText = envelope.rowCount === null ? "row count unknown" : `${envelope.rowCount} row${envelope.rowCount === 1 ? "" : "s"}`;
306
+ const notes = [];
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
+ );
311
+ }
312
+ if (envelope.truncated) {
313
+ notes.push("artifact truncated to configured limits");
314
+ }
315
+ if (hasErrorShape(envelope.data)) {
316
+ notes.push("inspect result payload for Bloomberg error details");
317
+ }
318
+ const noteText = notes.length === 0 ? "" : `; ${notes.join("; ")}`;
319
+ return `${envelope.tool}: ${rowText}; truncated=${String(envelope.truncated)}${noteText}`;
320
+ }
321
+ function resultJsonReplacer(_key, value) {
322
+ if (typeof value === "bigint") {
323
+ return value.toString();
324
+ }
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
+
152
404
  // src/cdx-fields.ts
153
405
  var CDX_INFO_FIELDS = Object.freeze([
154
406
  "ROLLING_SERIES",
@@ -187,29 +439,34 @@ var REQUIRED_TOOL_INSTRUCTIONS = [
187
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.",
188
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.",
189
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.",
190
443
  "",
191
444
  "## Security identifiers",
192
- "- Prefer fully qualified Bloomberg securities such as AAPL US Equity, SPX Index, or CDX IG CDSI GEN 5Y Corp when the user provides them.",
193
- "- For raw security identifiers, request or pass Bloomberg identifier syntax directly: /isin/{isin} for ISINs, for example /isin/US0378331005; /cusip/{cusip} for CUSIPs, for example /cusip/037833100.",
194
- "- 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.",
195
- "- For dealer quote / BQR workflows, use xbbg_bqr with a fixed-income identifier plus a dealer quote source such as /isin/US037833FB15@MSG1 Corp. For raw intraday ticks, use xbbg_bdtick.",
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.",
196
453
  "",
197
454
  "## Core request tools",
198
- "- xbbg_bdp: current or reference point-in-time fields, e.g. PX_LAST, NAME, CUR_MKT_CAP. 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.",
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.",
199
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.",
200
- "- xbbg_bds: Bloomberg bulk/table fields such as index members. Provide exactly one bulk field; do not use bds for ordinary multi-field reference data.",
201
- "- xbbg_bdib: intraday bars only. Provide one ticker, explicit ISO start/end datetimes, a positive interval in minutes, and timezone context when datetimes are naive. TRADE is the usual event type unless the user asks otherwise.",
202
- "- xbbg_bdtick: intraday tick data. Provide one ticker, explicit ISO start/end datetimes, and explicit eventTypes when not asking for TRADE ticks. Use includeBrokerCodes or includeConditionCodes only when those columns are needed.",
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.",
203
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.",
204
- "- xbbg_bsrch: Bloomberg search-grid or saved-search workflows only, such as ExcelGetGrid-style searches. Do not use it for ordinary security lookup.",
205
- "- xbbg_bqr: Bloomberg Quote Request / dealer quotes. Prefer fixed-income ISIN inputs with a dealer quote source such as /isin/US037833FB15@MSG1 Corp, explicit start/end datetimes, and BID/ASK event types. includeBrokerCodes defaults to true.",
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.",
206
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.",
207
464
  "- xbbg_beqs: Bloomberg equity screening by named BEQS screen. Prefer this over hand-written BQL when the user names an existing Bloomberg screen.",
208
- "- xbbg_yas: fixed-income YAS recipe fields such as YAS_BOND_YLD, YAS_MOD_DUR, YAS_ZSPREAD, or YAS_BOND_PX. Prefer this over manual YAS_BOND_* BDP requests when the user asks for YAS yield, duration, spread, or price analytics.",
209
- "- 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.",
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.",
210
467
  "- xbbg_corporate_bonds: bounded corporate bond universe query for a company ticker. Prefer this over generic BQL for company debt discovery.",
211
468
  "- xbbg_index_members: index constituents through the core index recipe. Prefer this over generic BDS/BQL members when the user asks for constituents.",
212
- "- 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.",
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.",
213
470
  "- xbbg_issuer_isins: issuer/bond ISIN workflow for supplied bond ISIN strings.",
214
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.",
215
472
  "- xbbg_stream_snapshot: bounded live market-data observation from //blp/mktdata. Requires explicit maxUpdates and always terminates/unsubscribes.",
@@ -218,19 +475,19 @@ var REQUIRED_TOOL_INSTRUCTIONS = [
218
475
  "",
219
476
  "## BQL guidance",
220
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.",
221
- "- Basic shape: get(field1, field2) for(universe). Examples: get(px_last) for('AAPL US Equity') and get(px_last, volume) for(['IBM US Equity', 'AAPL US Equity']).",
222
- "- Use BQL for universe-oriented analytics and screens such as holdings('SPY US Equity'), members('SPX Index'), debt universes, filters with with(...), and date ranges such as with(dates=range(-5d, 0d)).",
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.",
223
480
  "- Prefer xbbg_ext_bql_builder instead of hand-writing BQL for supported workflows: preferred stocks, corporate bonds, and ETF holdings.",
224
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.",
225
482
  "",
226
483
  "## Output handling",
227
- "- Tool results use LangChain content_and_artifact output: content is a compact summary, artifact is a bounded envelope with tool, rowCount, truncated, and data. Inspect the artifact before summarizing.",
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.",
228
485
  "- If a response is empty, truncated, or contains Bloomberg/security errors, say that directly. Do not fill gaps from memory or assumptions."
229
486
  ];
230
487
  var OPTIONAL_EXTENSION_INSTRUCTIONS = [
231
488
  "",
232
489
  "## Extension helper tools",
233
- "- 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.",
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.",
234
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.",
235
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.",
236
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.",
@@ -265,387 +522,288 @@ function getBloombergToolInstructions(options = {}) {
265
522
  }
266
523
  return lines.join("\n");
267
524
  }
268
- var BDP_DESCRIPTION = 'Bloomberg reference data for current or point-in-time fields such as PX_LAST, NAME, or CUR_MKT_CAP. Use for a small bounded list of fully qualified securities. Use /isin/{isin} for ISINs and /cusip/{cusip} for CUSIPs. Example: securities ["AAPL US Equity"], fields ["PX_LAST"].';
269
- 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 ["AAPL US Equity"], fields ["PX_LAST"], start "2024-01-01", end "2024-01-31".';
270
- var BDS_DESCRIPTION = 'Bloomberg bulk/table reference data such as index members. Requires exactly one bulk field, not a field list. Use /isin/{isin} for ISINs and /cusip/{cusip} for CUSIPs. Example: securities ["SPX Index"], field "INDX_MEMBERS".';
271
- var BDIB_DESCRIPTION = 'Bloomberg intraday bars. Requires one ticker plus explicit ISO start/end datetimes and a positive interval in minutes. Use /isin/{isin} for ISINs and /cusip/{cusip} for CUSIPs. Example: ticker "AAPL US Equity", start "2024-01-31T09:30:00-05:00", end "2024-01-31T16:00:00-05:00", interval 5.';
272
- var BDTICK_DESCRIPTION = 'Bloomberg intraday tick data. Requires one ticker plus explicit ISO start/end datetimes. Defaults eventTypes to ["TRADE"]; use ["BID", "ASK"] for quote ticks and includeBrokerCodes/includeConditionCodes only when needed.';
273
- var BQL_DESCRIPTION = "Bloomberg Query Language expression sent as one complete query string. Use for bounded universe analytics such as get(px_last) for('AAPL US Equity'), get(px_last, volume) for(['IBM US Equity', 'AAPL US Equity']), holdings('SPY US Equity'), members('SPX Index'), filters with with(...), or dates=range(...). Prefer xbbg_bdp/xbbg_bdh for simple reference or historical requests.";
274
- var BSRCH_DESCRIPTION = 'Bloomberg search/grid request. Use for saved-search or ExcelGetGrid-style Bloomberg searches, not ordinary security lookup. Example searchSpec "COMDTY:NG".';
275
- 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/US037833FB15@MSG1 Corp"; requires explicit ISO start/end datetimes. Defaults eventTypes to ["BID", "ASK"] and includeBrokerCodes to true.';
276
- 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 ["PX_LAST"] or searchSpec "last price".';
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>".';
277
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.";
278
- var YAS_DESCRIPTION = "Bloomberg fixed-income YAS recipe fields for one or more bonds. Use for YAS yield, duration, spread, benchmark, or price analytics; provide explicit fields and optional settlement/yield/price inputs.";
279
- 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.";
280
- 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.";
281
- var INDEX_MEMBERS_DESCRIPTION = "Index constituent recipe for one Bloomberg index. Use for bounded member lists and optional historical/as-of constituent membership.";
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.";
282
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.";
283
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.";
284
- 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.";
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.";
285
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.";
286
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.";
287
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.";
288
- var EXT_TICKER_DESCRIPTION = "Ticker hygiene helpers: parse_ticker, normalize_tickers, filter_equity_tickers, is_specific_contract, and validate_generic_ticker.";
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.";
289
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.";
290
547
  var EXT_CDX_DESCRIPTION = "CDX helpers for parsing, series rolling/resolution, and predefined info/pricing/risk BDP field bundles.";
291
548
  var EXT_CURRENCY_DESCRIPTION = "Currency planning helpers: build FX pairs, test same-currency requests, and find currencies needing conversion.";
292
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.";
293
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.";
294
- var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed income fields such as YAS_BOND_YLD, YAS_MOD_DUR, YAS_ZSPREAD, or YAS_BOND_PX.";
551
+ var EXT_YAS_OVERRIDES_DESCRIPTION = "Build flat Bloomberg YAS override maps for fixed-income analytics fields.";
295
552
  var EXT_CONSTANTS_DESCRIPTION = "Static Bloomberg helper constants for date parsing/formatting, futures months, dividend types, and ETF/dividend columns.";
296
553
  var EXT_COLUMNS_DESCRIPTION = "Column rename helpers for dividend, ETF, and earnings-shaped Bloomberg responses.";
297
554
  var EXT_CALCULATE_DESCRIPTION = "Small numeric helper operations for Bloomberg workflows, including level percentage calculations.";
298
-
299
- // src/result-limits.ts
300
- var MAX_RESULT_DEPTH = 32;
301
- function isPlainObject(value) {
302
- const prototype = Object.getPrototypeOf(value);
303
- return prototype === Object.prototype || prototype === null;
304
- }
305
- function truncateString(value, maxStringChars, state) {
306
- if (value.length <= maxStringChars) {
307
- return value;
308
- }
309
- state.truncated = true;
310
- return `${value.slice(0, maxStringChars)}\u2026[truncated ${value.length - maxStringChars} chars]`;
311
- }
312
- function limitValue(value, maxRows, maxStringChars, state, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
313
- if (typeof value === "string") {
314
- return truncateString(value, maxStringChars, state);
315
- }
316
- if (value instanceof Date) {
317
- return value.toISOString();
318
- }
319
- if (depth > MAX_RESULT_DEPTH) {
320
- state.truncated = true;
321
- return "[Max result depth exceeded]";
322
- }
323
- if (Array.isArray(value)) {
324
- if (seen.has(value)) {
325
- state.truncated = true;
326
- return "[Circular]";
327
- }
328
- seen.add(value);
329
- const capped = value.length > maxRows ? value.slice(0, maxRows) : value;
330
- if (capped.length !== value.length) {
331
- state.truncated = true;
332
- }
333
- return capped.map((item) => limitValue(item, maxRows, maxStringChars, state, depth + 1, seen));
334
- }
335
- if (typeof value === "object" && value !== null) {
336
- if (seen.has(value)) {
337
- state.truncated = true;
338
- return "[Circular]";
339
- }
340
- if (!isPlainObject(value)) {
341
- return value;
342
- }
343
- seen.add(value);
344
- const output = {};
345
- for (const [key, entry] of Object.entries(value)) {
346
- output[key] = limitValue(entry, maxRows, maxStringChars, state, depth + 1, seen);
347
- }
348
- return output;
349
- }
350
- return value;
351
- }
352
- function rowCountOf(value) {
353
- if (Array.isArray(value)) {
354
- return value.length;
355
- }
356
- if (typeof value !== "object" || value === null) {
357
- return null;
358
- }
359
- const record2 = value;
360
- const rowCount = record2.rowCount;
361
- if (typeof rowCount === "number" && Number.isInteger(rowCount) && rowCount >= 0) {
362
- return rowCount;
363
- }
364
- const updateCount = record2.updateCount;
365
- if (typeof updateCount === "number" && Number.isInteger(updateCount) && updateCount >= 0) {
366
- return updateCount;
367
- }
368
- return null;
369
- }
370
- function hasErrorShape(value) {
371
- if (typeof value !== "object" || value === null) {
372
- return false;
373
- }
374
- const record2 = value;
375
- return record2.error !== void 0 || record2.errors !== void 0 || record2.securityError !== void 0;
376
- }
377
- function limitResult(value, maxRows, maxStringChars) {
378
- const state = { truncated: false };
379
- const rowCount = rowCountOf(value);
380
- const limitedValue = limitValue(value, maxRows, maxStringChars, state);
381
- return {
382
- rowCount,
383
- truncated: state.truncated,
384
- value: limitedValue
385
- };
386
- }
387
- function summarizeEnvelope(envelope) {
388
- const rowText = envelope.rowCount === null ? "row count unknown" : `${envelope.rowCount} row${envelope.rowCount === 1 ? "" : "s"}`;
389
- const notes = [];
390
- if (envelope.rowCount === 0) {
391
- notes.push("empty result");
392
- }
393
- if (envelope.truncated) {
394
- notes.push("artifact truncated to configured limits");
395
- }
396
- if (hasErrorShape(envelope.data)) {
397
- notes.push("inspect artifact for Bloomberg error details");
398
- }
399
- const noteText = notes.length === 0 ? "" : `; ${notes.join("; ")}`;
400
- return `${envelope.tool}: ${rowText}; truncated=${String(envelope.truncated)}${noteText}`;
401
- }
402
- function createToolResult(tool3, value, maxRows, maxStringChars) {
403
- const limited = limitResult(value, maxRows, maxStringChars);
404
- const envelope = {
405
- tool: tool3,
406
- rowCount: limited.rowCount,
407
- truncated: limited.truncated,
408
- data: limited.value
409
- };
410
- return [summarizeEnvelope(envelope), envelope];
411
- }
412
- function throwWithToolContext(tool3, error) {
413
- const prefix = `${tool3} failed`;
414
- if (error instanceof Error) {
415
- if (!error.message.startsWith(prefix)) {
416
- Object.defineProperty(error, "message", {
417
- configurable: true,
418
- value: `${prefix}: ${error.message}`
419
- });
420
- }
421
- throw error;
422
- }
423
- throw new Error(`${prefix}: ${String(error)}`);
424
- }
425
- var stringPairSchema = z2__namespace.object({
426
- key: z2__namespace.string().trim().min(1).describe("String pair key."),
427
- value: z2__namespace.string().trim().min(1).describe("String pair value.")
555
+ var stringPairSchema = z__namespace.object({
556
+ key: z__namespace.string().trim().min(1).describe("String pair key."),
557
+ value: z__namespace.string().trim().min(1).describe("String pair value.")
428
558
  });
429
- var futuresCandidateSchema = z2__namespace.object({
430
- month: z2__namespace.number().int().min(1).max(12).describe("Contract month number, 1-12."),
431
- ticker: z2__namespace.string().trim().min(1).describe("Specific Bloomberg futures ticker."),
432
- year: z2__namespace.number().int().min(1900).describe("Contract year.")
559
+ var futuresCandidateSchema = z__namespace.object({
560
+ month: z__namespace.number().int().min(1).max(12).describe("Contract month number, 1-12."),
561
+ ticker: z__namespace.string().trim().min(1).describe("Specific Bloomberg futures ticker."),
562
+ year: z__namespace.number().int().min(1900).describe("Contract year.")
433
563
  });
434
564
  function nonEmptyString(options, description) {
435
- return z2__namespace.string().trim().pipe(z2__namespace.string().min(1).max(options.maxStringChars).describe(description));
565
+ return z__namespace.string().trim().pipe(z__namespace.string().min(1).max(options.maxStringChars).describe(description));
436
566
  }
437
567
  function stringArray(options, description, maxItems = options.maxFields) {
438
- return z2__namespace.array(nonEmptyString(options, description)).min(1).max(maxItems).describe(description);
568
+ return z__namespace.array(nonEmptyString(options, description)).min(1).max(maxItems).describe(description);
439
569
  }
440
570
  function optionalString(options, description) {
441
571
  return nonEmptyString(options, description).optional();
442
572
  }
443
573
  function tickerSchema(options) {
444
- return z2__namespace.object({
445
- operation: z2__namespace.enum([
446
- "parse_ticker",
447
- "normalize_tickers",
448
- "filter_equity_tickers",
449
- "is_specific_contract",
450
- "validate_generic_ticker"
451
- ]).describe("Ticker helper operation to run."),
452
- ticker: optionalString(
453
- options,
454
- "One Bloomberg ticker for parse/contract validation operations."
455
- ),
456
- tickers: stringArray(
457
- options,
458
- "Bloomberg tickers to normalize or filter.",
459
- options.maxSecurities
460
- ).optional()
461
- });
574
+ const ticker = nonEmptyString(
575
+ options,
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."
577
+ );
578
+ const tickers = stringArray(
579
+ options,
580
+ "Bloomberg tickers to normalize or filter.",
581
+ options.maxSecurities
582
+ );
583
+ return z__namespace.discriminatedUnion("operation", [
584
+ z__namespace.object({ operation: z__namespace.literal("parse_ticker"), ticker }).strict(),
585
+ z__namespace.object({ operation: z__namespace.literal("is_specific_contract"), ticker }).strict(),
586
+ z__namespace.object({ operation: z__namespace.literal("validate_generic_ticker"), ticker }).strict(),
587
+ z__namespace.object({ operation: z__namespace.literal("normalize_tickers"), tickers }).strict(),
588
+ z__namespace.object({ operation: z__namespace.literal("filter_equity_tickers"), tickers }).strict()
589
+ ]);
462
590
  }
463
591
  function futuresSchema(options) {
464
- return z2__namespace.object({
465
- asset: optionalString(options, "Bloomberg asset class suffix, for example Comdty."),
466
- candidates: z2__namespace.array(futuresCandidateSchema).min(1).max(options.maxFields).optional().describe("Candidate futures contracts."),
467
- contracts: z2__namespace.array(stringPairSchema).min(1).max(options.maxFields).optional().describe("Contract pairs for validity filtering."),
468
- count: z2__namespace.number().int().positive().optional().describe("Maximum number of futures candidates to generate."),
469
- cycle: optionalString(options, "Futures cycle code to filter candidates by."),
470
- day: z2__namespace.number().int().min(1).max(31).optional().describe("Day number for contract filtering."),
471
- freq: optionalString(options, "Futures frequency/cycle hint."),
472
- genTicker: optionalString(options, "Generic Bloomberg futures ticker."),
473
- month: z2__namespace.number().int().min(1).max(12).optional().describe("Month number, 1-12."),
474
- monthCode: optionalString(options, "Bloomberg futures month code, for example H."),
475
- operation: z2__namespace.enum([
476
- "build_futures_ticker",
477
- "generate_candidates",
478
- "contract_index",
479
- "filter_candidates_by_cycle",
480
- "filter_valid_contracts",
481
- "get_futures_months"
482
- ]).describe("Futures helper operation to run."),
483
- prefix: optionalString(options, "Futures ticker root prefix."),
484
- year: z2__namespace.union([z2__namespace.string().trim().min(1), z2__namespace.number().int()]).optional().describe("Contract year.")
485
- });
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
+ ]);
486
634
  }
487
635
  function cdxSchema(options) {
488
- return z2__namespace.object({
489
- genTicker: optionalString(options, "Generic CDX ticker."),
490
- operation: z2__namespace.enum([
491
- "parse_cdx_ticker",
492
- "previous_cdx_series",
493
- "cdx_gen_to_specific",
494
- "cdx_info",
495
- "cdx_pricing",
496
- "cdx_risk"
497
- ]).describe("CDX helper operation to run."),
498
- recoveryRate: z2__namespace.number().optional().describe("Optional recovery rate override for pricing/risk lookups."),
499
- series: z2__namespace.number().int().positive().optional().describe("Specific CDX series number."),
500
- ticker: optionalString(options, "CDX ticker.")
501
- });
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
+ ]);
502
653
  }
503
654
  function currencySchema(options) {
504
- return z2__namespace.object({
505
- ccy1: optionalString(options, "First ISO currency code."),
506
- ccy2: optionalString(options, "Second ISO currency code."),
507
- currencies: stringArray(options, "ISO currency codes.").optional(),
508
- fromCcy: optionalString(options, "Source ISO currency code."),
509
- operation: z2__namespace.enum(["build_fx_pair", "same_currency", "currencies_needing_conversion"]).describe("Currency helper operation to run."),
510
- target: optionalString(options, "Target ISO currency code."),
511
- toCcy: optionalString(options, "Destination ISO currency code.")
512
- });
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
+ ]);
513
672
  }
514
673
  function bqlBuilderSchema(options) {
515
- return z2__namespace.object({
516
- activeOnly: z2__namespace.boolean().optional().describe("Restrict corporate bond query to active bonds."),
517
- ccy: optionalString(options, "Currency filter for corporate bond query."),
518
- equityTicker: optionalString(options, "Equity ticker for preferreds query."),
519
- etfTicker: optionalString(options, "ETF ticker for holdings query."),
520
- extraFields: stringArray(options, "Extra BQL fields to include.").optional(),
521
- operation: z2__namespace.enum(["build_preferreds_query", "build_corporate_bonds_query", "build_etf_holdings_query"]).describe("BQL builder operation to run."),
522
- ticker: optionalString(options, "Ticker for corporate bond query.")
523
- });
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
+ ]);
524
694
  }
525
695
  function marketSessionSchema(options) {
526
- return z2__namespace.object({
527
- countryIso: optionalString(options, "ISO country code for timezone inference."),
528
- date: optionalString(options, "Date for UTC session conversion, YYYY-MM-DD or YYYYMMDD."),
529
- dayEnd: optionalString(options, "Exchange day end time, for example 16:00."),
530
- dayStart: optionalString(options, "Exchange day start time, for example 09:30."),
531
- endDate: optionalString(options, "Optional end date."),
532
- endDatetime: optionalString(options, "Optional end datetime."),
533
- endTime: optionalString(options, "Session end time, for example 16:00."),
534
- exchCode: optionalString(options, "Bloomberg exchange code."),
535
- exchangeTz: optionalString(options, "IANA exchange timezone."),
536
- mic: optionalString(options, "Market Identifier Code."),
537
- operation: z2__namespace.enum([
538
- "derive_sessions",
539
- "get_market_rule",
540
- "infer_timezone",
541
- "session_times_to_utc",
542
- "default_turnover_dates",
543
- "default_bqr_datetimes",
544
- "get_exchange_override",
545
- "list_exchange_overrides"
546
- ]).describe("Market session helper operation to run."),
547
- startDate: optionalString(options, "Optional start date."),
548
- startDatetime: optionalString(options, "Optional start datetime."),
549
- startTime: optionalString(options, "Session start time, for example 09:30."),
550
- ticker: optionalString(options, "Ticker for exchange override lookup.")
551
- });
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
+ ]);
552
737
  }
553
738
  function yasOverridesSchema(options) {
554
- return z2__namespace.object({
739
+ return z__namespace.object({
555
740
  benchmark: optionalString(options, "Optional YAS benchmark."),
556
- price: z2__namespace.number().optional().describe("YAS price override."),
741
+ price: z__namespace.number().optional().describe("YAS price override."),
557
742
  settleDt: optionalString(options, "YAS settlement date."),
558
- spread: z2__namespace.number().optional().describe("YAS spread override."),
559
- yieldType: z2__namespace.number().int().optional().describe("YAS yield type override."),
560
- yieldVal: z2__namespace.number().optional().describe("YAS yield value override.")
561
- });
743
+ spread: z__namespace.number().optional().describe("YAS spread override."),
744
+ yieldType: z__namespace.number().int().optional().describe("YAS yield type override."),
745
+ yieldVal: z__namespace.number().optional().describe("YAS yield value override.")
746
+ }).strict();
562
747
  }
563
748
  function constantsSchema(options) {
564
- return z2__namespace.object({
565
- code: optionalString(options, "Month code."),
566
- dateStr: optionalString(options, "Date string to parse."),
567
- day: z2__namespace.number().int().min(1).max(31).optional().describe("Day number."),
568
- dvdType: optionalString(options, "Dividend type code or label."),
569
- fmt: optionalString(options, "Date output format."),
570
- month: z2__namespace.number().int().min(1).max(12).optional().describe("Month number."),
571
- monthName: optionalString(options, "Month name."),
572
- operation: z2__namespace.enum([
573
- "parse_date",
574
- "fmt_date",
575
- "get_month_code",
576
- "get_month_name",
577
- "get_futures_months",
578
- "get_dvd_type",
579
- "get_dvd_types",
580
- "get_dvd_cols",
581
- "get_etf_cols"
582
- ]).describe("Constants helper operation to run."),
583
- year: z2__namespace.number().int().min(1).optional().describe("Year number.")
584
- });
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
+ ]);
585
778
  }
586
779
  function columnsSchema(options) {
587
- return z2__namespace.object({
588
- columns: stringArray(options, "Column names to rename.").optional(),
589
- dataColumns: stringArray(options, "Earnings data column names.").optional(),
590
- headerRow: z2__namespace.array(stringPairSchema).min(1).max(options.maxFields).optional().describe("Earnings header row key/value pairs."),
591
- operation: z2__namespace.enum(["rename_dividend_columns", "rename_etf_columns", "build_earning_header_rename"]).describe("Column helper operation to run.")
592
- });
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
+ ]);
593
790
  }
594
791
  function calculateSchema(options) {
595
- return z2__namespace.object({
596
- levels: z2__namespace.array(z2__namespace.number().nullable()).min(1).max(options.maxFields).describe("Reference level values."),
597
- operation: z2__namespace.literal("calculate_level_percentages").describe("Numeric helper operation to run."),
598
- values: z2__namespace.array(z2__namespace.number().nullable()).min(1).max(options.maxFields).describe("Observed values.")
792
+ return z__namespace.object({
793
+ levels: z__namespace.array(z__namespace.number().nullable()).min(1).max(options.maxFields).describe("Reference level values."),
794
+ operation: z__namespace.literal("calculate_level_percentages").describe("Numeric helper operation to run."),
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
+ }
599
803
  });
600
804
  }
601
805
 
602
806
  // src/ext-tools.ts
603
- function asRecord(value) {
604
- return value;
605
- }
606
- function requireString(toolName, input, field) {
607
- const value = input[field];
608
- if (typeof value !== "string" || value.trim().length === 0) {
609
- throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string`);
610
- }
611
- return value.trim();
612
- }
613
- function requireNumber(toolName, input, field) {
614
- const value = input[field];
615
- if (typeof value !== "number" || !Number.isFinite(value)) {
616
- throw new TypeError(`${toolName}: ${field} is required and must be a finite number`);
617
- }
618
- return value;
619
- }
620
- function requireInteger(toolName, input, field) {
621
- const value = requireNumber(toolName, input, field);
622
- if (!Number.isInteger(value)) {
623
- throw new TypeError(`${toolName}: ${field} must be an integer`);
624
- }
625
- return value;
626
- }
627
- function requireYearString(toolName, input, field) {
628
- const value = input[field];
629
- if (typeof value === "number" && Number.isInteger(value)) {
630
- return String(value);
631
- }
632
- if (typeof value === "string" && value.trim().length > 0) {
633
- return value.trim();
634
- }
635
- throw new TypeError(`${toolName}: ${field} is required and must be a year string or integer`);
636
- }
637
- function requireStringArray(toolName, input, field) {
638
- const value = input[field];
639
- if (!Array.isArray(value) || value.length === 0) {
640
- throw new TypeError(`${toolName}: ${field} is required and must be a non-empty string array`);
641
- }
642
- return value.map((entry) => {
643
- if (typeof entry !== "string" || entry.trim().length === 0) {
644
- throw new TypeError(`${toolName}: ${field} entries must be non-empty strings`);
645
- }
646
- return entry.trim();
647
- });
648
- }
649
807
  function resultString(resolver, name, value) {
650
808
  return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
651
809
  }
@@ -669,41 +827,22 @@ var BLOOMBERG_EXT_TOOL_NAMES = Object.freeze(
669
827
  );
670
828
  function extTickerWithResolver(resolver) {
671
829
  const name = "xbbg_ext_ticker";
672
- return tools.tool(
830
+ return createBloombergStructuredTool(
673
831
  async (input) => {
674
832
  try {
675
833
  const core = await resolver.getCore();
676
- const args = asRecord(input);
677
834
  switch (input.operation) {
678
835
  case "parse_ticker":
679
- return resultString(
680
- resolver,
681
- name,
682
- core.ext.parseTicker(requireString(name, args, "ticker"))
683
- );
836
+ return resultString(resolver, name, core.ext.parseTicker(input.ticker));
684
837
  case "normalize_tickers":
685
- return resultString(
686
- resolver,
687
- name,
688
- core.ext.normalizeTickers(requireStringArray(name, args, "tickers"))
689
- );
838
+ return resultString(resolver, name, core.ext.normalizeTickers(input.tickers));
690
839
  case "filter_equity_tickers":
691
- return resultString(
692
- resolver,
693
- name,
694
- core.ext.filterEquityTickers(requireStringArray(name, args, "tickers"))
695
- );
840
+ return resultString(resolver, name, core.ext.filterEquityTickers(input.tickers));
696
841
  case "is_specific_contract":
697
- return resultString(
698
- resolver,
699
- name,
700
- core.ext.isSpecificContract(requireString(name, args, "ticker"))
701
- );
702
- case "validate_generic_ticker": {
703
- const ticker = requireString(name, args, "ticker");
704
- core.ext.validateGenericTicker(ticker);
705
- return resultString(resolver, name, { ticker, valid: true });
706
- }
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 });
707
846
  }
708
847
  } catch (error) {
709
848
  throwWithToolContext(name, error);
@@ -719,67 +858,43 @@ function extTickerWithResolver(resolver) {
719
858
  }
720
859
  function extFuturesWithResolver(resolver) {
721
860
  const name = "xbbg_ext_futures";
722
- return tools.tool(
861
+ return createBloombergStructuredTool(
723
862
  async (input) => {
724
863
  try {
725
864
  const core = await resolver.getCore();
726
- const args = asRecord(input);
727
865
  switch (input.operation) {
728
866
  case "build_futures_ticker":
729
867
  return resultString(
730
868
  resolver,
731
869
  name,
732
- core.ext.buildFuturesTicker(
733
- requireString(name, args, "prefix"),
734
- requireString(name, args, "monthCode"),
735
- requireYearString(name, args, "year"),
736
- requireString(name, args, "asset")
737
- )
870
+ core.ext.buildFuturesTicker(input.prefix, input.monthCode, input.year, input.asset)
738
871
  );
739
872
  case "generate_candidates":
740
873
  return resultString(
741
874
  resolver,
742
875
  name,
743
876
  core.ext.generateFuturesCandidates(
744
- requireString(name, args, "genTicker"),
745
- requireInteger(name, args, "year"),
746
- requireInteger(name, args, "month"),
747
- requireInteger(name, args, "day"),
877
+ input.genTicker,
878
+ input.year,
879
+ input.month,
880
+ input.day,
748
881
  input.freq,
749
882
  input.count
750
883
  )
751
884
  );
752
885
  case "contract_index":
753
- return resultString(
754
- resolver,
755
- name,
756
- core.ext.contractIndex(requireString(name, args, "genTicker"))
757
- );
886
+ return resultString(resolver, name, core.ext.contractIndex(input.genTicker));
758
887
  case "filter_candidates_by_cycle":
759
- if (input.candidates === void 0) {
760
- throw new TypeError(`${name}: candidates is required`);
761
- }
762
888
  return resultString(
763
889
  resolver,
764
890
  name,
765
- core.ext.filterCandidatesByCycle(
766
- input.candidates,
767
- requireString(name, args, "cycle")
768
- )
891
+ core.ext.filterCandidatesByCycle(input.candidates, input.cycle)
769
892
  );
770
893
  case "filter_valid_contracts":
771
- if (input.contracts === void 0) {
772
- throw new TypeError(`${name}: contracts is required`);
773
- }
774
894
  return resultString(
775
895
  resolver,
776
896
  name,
777
- core.ext.filterValidContracts(
778
- input.contracts,
779
- requireInteger(name, args, "year"),
780
- requireInteger(name, args, "month"),
781
- requireInteger(name, args, "day")
782
- )
897
+ core.ext.filterValidContracts(input.contracts, input.year, input.month, input.day)
783
898
  );
784
899
  case "get_futures_months":
785
900
  return resultString(resolver, name, core.ext.getFuturesMonths());
@@ -798,42 +913,32 @@ function extFuturesWithResolver(resolver) {
798
913
  }
799
914
  function extCdxWithResolver(resolver) {
800
915
  const name = "xbbg_ext_cdx";
801
- return tools.tool(
802
- async (input) => {
916
+ return createBloombergStructuredTool(
917
+ async (input, config) => {
803
918
  try {
804
- const args = asRecord(input);
919
+ config?.signal?.throwIfAborted();
805
920
  if (input.operation === "cdx_info" || input.operation === "cdx_pricing" || input.operation === "cdx_risk") {
806
921
  const engine = await resolver.getEngine();
807
- const ticker = requireString(name, args, "ticker");
808
922
  const fields = input.operation === "cdx_info" ? CDX_INFO_FIELDS : input.operation === "cdx_pricing" ? CDX_PRICING_FIELDS : CDX_RISK_FIELDS;
809
- const result = await engine.bdp([ticker], fields, {
923
+ const result = await engine.bdp([input.ticker], fields, {
810
924
  backend: "json",
811
- overrides: recoveryOverrides(input.recoveryRate)
925
+ overrides: recoveryOverrides(
926
+ input.operation === "cdx_pricing" || input.operation === "cdx_risk" ? input.recoveryRate : void 0
927
+ )
812
928
  });
813
929
  return resultString(resolver, name, result);
814
930
  }
815
931
  const core = await resolver.getCore();
816
932
  switch (input.operation) {
817
933
  case "parse_cdx_ticker":
818
- return resultString(
819
- resolver,
820
- name,
821
- core.ext.parseCdxTicker(requireString(name, args, "ticker"))
822
- );
934
+ return resultString(resolver, name, core.ext.parseCdxTicker(input.ticker));
823
935
  case "previous_cdx_series":
824
- return resultString(
825
- resolver,
826
- name,
827
- core.ext.previousCdxSeries(requireString(name, args, "ticker"))
828
- );
936
+ return resultString(resolver, name, core.ext.previousCdxSeries(input.ticker));
829
937
  case "cdx_gen_to_specific":
830
938
  return resultString(
831
939
  resolver,
832
940
  name,
833
- core.ext.cdxGenToSpecific(
834
- requireString(name, args, "genTicker"),
835
- requireInteger(name, args, "series")
836
- )
941
+ core.ext.cdxGenToSpecific(input.genTicker, input.series)
837
942
  );
838
943
  }
839
944
  } catch (error) {
@@ -850,38 +955,20 @@ function extCdxWithResolver(resolver) {
850
955
  }
851
956
  function extCurrencyWithResolver(resolver) {
852
957
  const name = "xbbg_ext_currency";
853
- return tools.tool(
958
+ return createBloombergStructuredTool(
854
959
  async (input) => {
855
960
  try {
856
961
  const core = await resolver.getCore();
857
- const args = asRecord(input);
858
962
  switch (input.operation) {
859
963
  case "build_fx_pair":
860
- return resultString(
861
- resolver,
862
- name,
863
- core.ext.buildFxPair(
864
- requireString(name, args, "fromCcy"),
865
- requireString(name, args, "toCcy")
866
- )
867
- );
964
+ return resultString(resolver, name, core.ext.buildFxPair(input.fromCcy, input.toCcy));
868
965
  case "same_currency":
869
- return resultString(
870
- resolver,
871
- name,
872
- core.ext.sameCurrency(
873
- requireString(name, args, "ccy1"),
874
- requireString(name, args, "ccy2")
875
- )
876
- );
966
+ return resultString(resolver, name, core.ext.sameCurrency(input.ccy1, input.ccy2));
877
967
  case "currencies_needing_conversion":
878
968
  return resultString(
879
969
  resolver,
880
970
  name,
881
- core.ext.currenciesNeedingConversion(
882
- requireStringArray(name, args, "currencies"),
883
- requireString(name, args, "target")
884
- )
971
+ core.ext.currenciesNeedingConversion(input.currencies, input.target)
885
972
  );
886
973
  }
887
974
  } catch (error) {
@@ -898,27 +985,23 @@ function extCurrencyWithResolver(resolver) {
898
985
  }
899
986
  function extBqlBuilderWithResolver(resolver) {
900
987
  const name = "xbbg_ext_bql_builder";
901
- return tools.tool(
988
+ return createBloombergStructuredTool(
902
989
  async (input) => {
903
990
  try {
904
991
  const core = await resolver.getCore();
905
- const args = asRecord(input);
906
992
  switch (input.operation) {
907
993
  case "build_preferreds_query":
908
994
  return resultString(
909
995
  resolver,
910
996
  name,
911
- core.ext.buildPreferredsQuery(
912
- requireString(name, args, "equityTicker"),
913
- input.extraFields
914
- )
997
+ core.ext.buildPreferredsQuery(input.equityTicker, input.extraFields)
915
998
  );
916
999
  case "build_corporate_bonds_query":
917
1000
  return resultString(
918
1001
  resolver,
919
1002
  name,
920
1003
  core.ext.buildCorporateBondsQuery(
921
- requireString(name, args, "ticker"),
1004
+ input.ticker,
922
1005
  input.ccy,
923
1006
  input.extraFields,
924
1007
  input.activeOnly
@@ -928,10 +1011,7 @@ function extBqlBuilderWithResolver(resolver) {
928
1011
  return resultString(
929
1012
  resolver,
930
1013
  name,
931
- core.ext.buildEtfHoldingsQuery(
932
- requireString(name, args, "etfTicker"),
933
- input.extraFields
934
- )
1014
+ core.ext.buildEtfHoldingsQuery(input.etfTicker, input.extraFields)
935
1015
  );
936
1016
  }
937
1017
  } catch (error) {
@@ -948,40 +1028,30 @@ function extBqlBuilderWithResolver(resolver) {
948
1028
  }
949
1029
  function extMarketSessionWithResolver(resolver) {
950
1030
  const name = "xbbg_ext_market_session";
951
- return tools.tool(
1031
+ return createBloombergStructuredTool(
952
1032
  async (input) => {
953
1033
  try {
954
1034
  const core = await resolver.getCore();
955
- const args = asRecord(input);
956
1035
  switch (input.operation) {
957
1036
  case "derive_sessions":
958
1037
  return resultString(
959
1038
  resolver,
960
1039
  name,
961
- core.ext.deriveSessions(
962
- requireString(name, args, "dayStart"),
963
- requireString(name, args, "dayEnd"),
964
- input.mic,
965
- input.exchCode
966
- )
1040
+ core.ext.deriveSessions(input.dayStart, input.dayEnd, input.mic, input.exchCode)
967
1041
  );
968
1042
  case "get_market_rule":
969
1043
  return resultString(resolver, name, core.ext.getMarketRule(input.mic, input.exchCode));
970
1044
  case "infer_timezone":
971
- return resultString(
972
- resolver,
973
- name,
974
- core.ext.inferTimezone(requireString(name, args, "countryIso"))
975
- );
1045
+ return resultString(resolver, name, core.ext.inferTimezone(input.countryIso));
976
1046
  case "session_times_to_utc":
977
1047
  return resultString(
978
1048
  resolver,
979
1049
  name,
980
1050
  core.ext.sessionTimesToUtc(
981
- requireString(name, args, "startTime"),
982
- requireString(name, args, "endTime"),
983
- requireString(name, args, "exchangeTz"),
984
- requireString(name, args, "date")
1051
+ input.startTime,
1052
+ input.endTime,
1053
+ input.exchangeTz,
1054
+ input.date
985
1055
  )
986
1056
  );
987
1057
  case "default_turnover_dates":
@@ -997,11 +1067,7 @@ function extMarketSessionWithResolver(resolver) {
997
1067
  core.ext.defaultBqrDatetimes(input.startDatetime, input.endDatetime)
998
1068
  );
999
1069
  case "get_exchange_override":
1000
- return resultString(
1001
- resolver,
1002
- name,
1003
- core.ext.getExchangeOverride(requireString(name, args, "ticker"))
1004
- );
1070
+ return resultString(resolver, name, core.ext.getExchangeOverride(input.ticker));
1005
1071
  case "list_exchange_overrides":
1006
1072
  return resultString(resolver, name, core.ext.listExchangeOverrides());
1007
1073
  }
@@ -1019,7 +1085,7 @@ function extMarketSessionWithResolver(resolver) {
1019
1085
  }
1020
1086
  function extYasOverridesWithResolver(resolver) {
1021
1087
  const name = "xbbg_ext_yas_overrides";
1022
- return tools.tool(
1088
+ return createBloombergStructuredTool(
1023
1089
  async (input) => {
1024
1090
  try {
1025
1091
  const core = await resolver.getCore();
@@ -1049,49 +1115,27 @@ function extYasOverridesWithResolver(resolver) {
1049
1115
  }
1050
1116
  function extConstantsWithResolver(resolver) {
1051
1117
  const name = "xbbg_ext_constants";
1052
- return tools.tool(
1118
+ return createBloombergStructuredTool(
1053
1119
  async (input) => {
1054
1120
  try {
1055
1121
  const core = await resolver.getCore();
1056
- const args = asRecord(input);
1057
1122
  switch (input.operation) {
1058
1123
  case "parse_date":
1059
- return resultString(
1060
- resolver,
1061
- name,
1062
- core.ext.parseDate(requireString(name, args, "dateStr"))
1063
- );
1124
+ return resultString(resolver, name, core.ext.parseDate(input.dateStr));
1064
1125
  case "fmt_date":
1065
1126
  return resultString(
1066
1127
  resolver,
1067
1128
  name,
1068
- core.ext.fmtDate(
1069
- requireInteger(name, args, "year"),
1070
- requireInteger(name, args, "month"),
1071
- requireInteger(name, args, "day"),
1072
- input.fmt
1073
- )
1129
+ core.ext.fmtDate(input.year, input.month, input.day, input.fmt)
1074
1130
  );
1075
1131
  case "get_month_code":
1076
- return resultString(
1077
- resolver,
1078
- name,
1079
- core.ext.getMonthCode(requireString(name, args, "monthName"))
1080
- );
1132
+ return resultString(resolver, name, core.ext.getMonthCode(input.monthName));
1081
1133
  case "get_month_name":
1082
- return resultString(
1083
- resolver,
1084
- name,
1085
- core.ext.getMonthName(requireString(name, args, "code"))
1086
- );
1134
+ return resultString(resolver, name, core.ext.getMonthName(input.code));
1087
1135
  case "get_futures_months":
1088
1136
  return resultString(resolver, name, core.ext.getFuturesMonths());
1089
1137
  case "get_dvd_type":
1090
- return resultString(
1091
- resolver,
1092
- name,
1093
- core.ext.getDvdType(requireString(name, args, "dvdType"))
1094
- );
1138
+ return resultString(resolver, name, core.ext.getDvdType(input.dvdType));
1095
1139
  case "get_dvd_types":
1096
1140
  return resultString(resolver, name, core.ext.getDvdTypes());
1097
1141
  case "get_dvd_cols":
@@ -1113,35 +1157,20 @@ function extConstantsWithResolver(resolver) {
1113
1157
  }
1114
1158
  function extColumnsWithResolver(resolver) {
1115
1159
  const name = "xbbg_ext_columns";
1116
- return tools.tool(
1160
+ return createBloombergStructuredTool(
1117
1161
  async (input) => {
1118
1162
  try {
1119
1163
  const core = await resolver.getCore();
1120
- const args = asRecord(input);
1121
1164
  switch (input.operation) {
1122
1165
  case "rename_dividend_columns":
1123
- return resultString(
1124
- resolver,
1125
- name,
1126
- core.ext.renameDividendColumns(requireStringArray(name, args, "columns"))
1127
- );
1166
+ return resultString(resolver, name, core.ext.renameDividendColumns(input.columns));
1128
1167
  case "rename_etf_columns":
1129
- return resultString(
1130
- resolver,
1131
- name,
1132
- core.ext.renameEtfColumns(requireStringArray(name, args, "columns"))
1133
- );
1168
+ return resultString(resolver, name, core.ext.renameEtfColumns(input.columns));
1134
1169
  case "build_earning_header_rename":
1135
- if (input.headerRow === void 0) {
1136
- throw new TypeError(`${name}: headerRow is required`);
1137
- }
1138
1170
  return resultString(
1139
1171
  resolver,
1140
1172
  name,
1141
- core.ext.buildEarningHeaderRename(
1142
- input.headerRow,
1143
- requireStringArray(name, args, "dataColumns")
1144
- )
1173
+ core.ext.buildEarningHeaderRename(input.headerRow, input.dataColumns)
1145
1174
  );
1146
1175
  }
1147
1176
  } catch (error) {
@@ -1158,12 +1187,9 @@ function extColumnsWithResolver(resolver) {
1158
1187
  }
1159
1188
  function extCalculateWithResolver(resolver) {
1160
1189
  const name = "xbbg_ext_calculate";
1161
- return tools.tool(
1190
+ return createBloombergStructuredTool(
1162
1191
  async (input) => {
1163
1192
  try {
1164
- if (input.values.length !== input.levels.length) {
1165
- throw new TypeError(`${name}: values and levels must have the same length`);
1166
- }
1167
1193
  const core = await resolver.getCore();
1168
1194
  return resultString(
1169
1195
  resolver,
@@ -1231,11 +1257,14 @@ var HISTORICAL_FORMATS = [
1231
1257
  var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/u;
1232
1258
  var BBG_DATE_RE = /^\d{8}$/u;
1233
1259
  var AMBIGUOUS_DATE_RE = /^\d{1,2}[-/]\d{1,2}[-/]\d{2,4}([T \D]|$)/u;
1234
- 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;
1235
- var primitiveSchema = z2__namespace.union([
1236
- z2__namespace.string().transform((value) => value.trim()),
1237
- z2__namespace.number(),
1238
- z2__namespace.boolean()
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;
1264
+ var primitiveSchema = z__namespace.union([
1265
+ z__namespace.string().transform((value) => value.trim()),
1266
+ z__namespace.number(),
1267
+ z__namespace.boolean()
1239
1268
  ]);
1240
1269
  function dateFromParts(year, month, day) {
1241
1270
  const formatted = `${year}${month}${day}`;
@@ -1246,18 +1275,30 @@ function dateFromParts(year, month, day) {
1246
1275
  return formatted;
1247
1276
  }
1248
1277
  function dateToBbg(value) {
1249
- const date2 = value instanceof Date ? value : new Date(value);
1250
- if (Number.isNaN(date2.getTime())) {
1278
+ const date = value instanceof Date ? value : new Date(value);
1279
+ if (Number.isNaN(date.getTime())) {
1251
1280
  throw new TypeError("Invalid date value; expected YYYY-MM-DD, YYYYMMDD, Date, or epoch ms");
1252
1281
  }
1253
- const year = String(date2.getUTCFullYear()).padStart(4, "0");
1254
- const month = String(date2.getUTCMonth() + 1).padStart(2, "0");
1255
- 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");
1256
1285
  return `${year}${month}${day}`;
1257
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
+ }
1258
1295
  function normalizeDate(value) {
1259
- if (value instanceof Date || typeof value === "number") {
1260
- 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"));
1261
1302
  }
1262
1303
  const text = value.trim();
1263
1304
  if (text.length === 0) {
@@ -1275,12 +1316,13 @@ function normalizeDate(value) {
1275
1316
  throw new TypeError(`Invalid date ${JSON.stringify(text)}; use YYYY-MM-DD or YYYYMMDD`);
1276
1317
  }
1277
1318
  function normalizeDateTime(value) {
1278
- if (value instanceof Date || typeof value === "number") {
1279
- const date2 = value instanceof Date ? value : new Date(value);
1280
- if (Number.isNaN(date2.getTime())) {
1281
- 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
+ );
1282
1324
  }
1283
- return date2.toISOString();
1325
+ return numericDateToBbg(value, "datetime").toISOString();
1284
1326
  }
1285
1327
  const text = value.trim();
1286
1328
  if (text.length === 0) {
@@ -1289,27 +1331,36 @@ function normalizeDateTime(value) {
1289
1331
  if (AMBIGUOUS_DATE_RE.test(text)) {
1290
1332
  throw new TypeError(`Ambiguous datetime ${JSON.stringify(text)}; use ISO 8601`);
1291
1333
  }
1292
- if (BBG_DATE_RE.test(text)) {
1293
- return `${text.slice(0, 4)}-${text.slice(4, 6)}-${text.slice(6, 8)}T00:00:00`;
1334
+ if (BBG_DATE_RE.test(text) || ISO_DATE_RE.test(text)) {
1335
+ throw new TypeError(
1336
+ `Invalid datetime ${JSON.stringify(text)}; include an explicit time component such as YYYY-MM-DDT09:30:00`
1337
+ );
1294
1338
  }
1295
1339
  if (!ISO_DATE_TIME_RE.test(text)) {
1296
1340
  throw new TypeError(`Invalid datetime ${JSON.stringify(text)}; use ISO 8601`);
1297
1341
  }
1298
1342
  return text.replace(" ", "T");
1299
1343
  }
1300
- function nonEmptyString2(tool3, field, maxChars, example) {
1301
- return z2__namespace.string().transform((value) => value.trim()).pipe(
1302
- z2__namespace.string().min(1, `${tool3}: ${field} must be a non-empty string. Example: ${example}`).max(
1344
+ function nonEmptyString2(tool2, field, maxChars, example) {
1345
+ return z__namespace.string().transform((value) => value.trim()).pipe(
1346
+ z__namespace.string().min(1, `${tool2}: ${field} must be a non-empty string. Example: ${example}`).max(
1303
1347
  maxChars,
1304
- `${tool3}: ${field} is too long; expected at most ${maxChars} characters. Example: ${example}`
1348
+ `${tool2}: ${field} is too long; expected at most ${maxChars} characters. Example: ${example}`
1305
1349
  )
1306
1350
  );
1307
1351
  }
1308
- function stringArray2(tool3, field, maxItems, maxChars, example) {
1309
- return z2__namespace.array(nonEmptyString2(tool3, field, maxChars, example)).min(1, `${tool3}: ${field} must contain at least one non-empty string. Example: ${example}`).max(maxItems, `${tool3}: ${field} can contain at most ${maxItems} values`);
1352
+ function stringArray2(tool2, field, maxItems, maxChars, example) {
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`);
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;
1310
1361
  }
1311
- function primitiveMap(tool3, field) {
1312
- return z2__namespace.record(z2__namespace.string().min(1), primitiveSchema).optional().transform((value) => {
1362
+ function primitiveMap(tool2, field) {
1363
+ return z__namespace.record(z__namespace.string().min(1), primitiveSchema).optional().transform((value, context) => {
1313
1364
  if (value === void 0) {
1314
1365
  return void 0;
1315
1366
  }
@@ -1317,169 +1368,203 @@ function primitiveMap(tool3, field) {
1317
1368
  for (const [key, entry] of Object.entries(value)) {
1318
1369
  const normalizedKey = key.trim();
1319
1370
  if (normalizedKey.length === 0) {
1320
- throw new TypeError(`${tool3}: ${field} contains an empty key`);
1371
+ return normalizationIssue(context, tool2, field, new TypeError("contains an empty key"));
1321
1372
  }
1322
1373
  if (typeof entry === "string" && entry.length === 0) {
1323
- throw new TypeError(`${tool3}: ${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
+ );
1324
1380
  }
1325
1381
  normalized[normalizedKey] = entry;
1326
1382
  }
1327
1383
  return normalized;
1328
1384
  });
1329
1385
  }
1330
- function dateField(tool3, field) {
1331
- return z2__namespace.union([z2__namespace.string(), z2__namespace.date(), z2__namespace.number()]).transform((value) => normalizeDate(value)).describe(
1386
+ function dateField(tool2, field) {
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(
1332
1394
  `${field} date. Use YYYY-MM-DD or Bloomberg-native YYYYMMDD, never ambiguous MM/DD/YYYY.`
1333
1395
  );
1334
1396
  }
1335
- function dateTimeField(tool3, field) {
1336
- return z2__namespace.union([z2__namespace.string(), z2__namespace.date(), z2__namespace.number()]).transform((value) => normalizeDateTime(value)).describe(`${field} datetime. Use ISO 8601, for example 2024-01-31T09:30:00-05:00.`);
1397
+ function dateTimeField(tool2, field) {
1398
+ return z__namespace.union([z__namespace.string(), z__namespace.number()]).superRefine((value, context) => {
1399
+ if (typeof value !== "string") {
1400
+ return;
1401
+ }
1402
+ const text = value.trim();
1403
+ if (BBG_DATE_RE.test(text) || ISO_DATE_RE.test(text)) {
1404
+ context.addIssue({
1405
+ code: "custom",
1406
+ message: `${tool2}: ${field} datetime requires an explicit time component; use ISO 8601 such as YYYY-MM-DDT09:30:00`
1407
+ });
1408
+ }
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.`);
1337
1416
  }
1338
- function referenceFormat(tool3) {
1339
- return z2__namespace.enum(REFERENCE_FORMATS, {
1340
- error: `${tool3}: format must be one of ${REFERENCE_FORMATS.join(", ")}`
1417
+ function referenceFormat(tool2) {
1418
+ return z__namespace.enum(REFERENCE_FORMATS, {
1419
+ errorMap: () => ({
1420
+ message: `${tool2}: format must be one of ${REFERENCE_FORMATS.join(", ")}`
1421
+ })
1341
1422
  }).optional();
1342
1423
  }
1343
- function historicalFormat(tool3) {
1344
- return z2__namespace.enum(HISTORICAL_FORMATS, {
1345
- error: `${tool3}: format must be one of ${HISTORICAL_FORMATS.join(", ")}`
1424
+ function historicalFormat(tool2) {
1425
+ return z__namespace.enum(HISTORICAL_FORMATS, {
1426
+ errorMap: () => ({
1427
+ message: `${tool2}: format must be one of ${HISTORICAL_FORMATS.join(", ")}`
1428
+ })
1346
1429
  }).optional();
1347
1430
  }
1348
1431
  function createBdpSchema(options) {
1349
- const tool3 = "xbbg_bdp";
1350
- return z2__namespace.object({
1432
+ const tool2 = "xbbg_bdp";
1433
+ return z__namespace.object({
1351
1434
  fields: stringArray2(
1352
- tool3,
1435
+ tool2,
1353
1436
  "fields",
1354
1437
  options.maxFields,
1355
1438
  options.maxStringChars,
1356
- '["PX_LAST"]'
1357
- ).describe(
1358
- 'Bloomberg field mnemonics to retrieve, for example ["PX_LAST", "NAME"]. Use xbbg_bflds first if uncertain.'
1359
- ),
1360
- format: referenceFormat(tool3).describe(
1439
+ '["<FIELD>"]'
1440
+ ).describe("Bloomberg field mnemonics to retrieve. Use xbbg_bflds first if uncertain."),
1441
+ format: referenceFormat(tool2).describe(
1361
1442
  "JSON output shape. Usually omit; use long_typed if downstream needs Bloomberg value types."
1362
1443
  ),
1363
- includeSecurityErrors: z2__namespace.boolean().optional().describe("Include Bloomberg security errors in the response when supported."),
1364
- kwargs: primitiveMap(tool3, "kwargs").describe(
1444
+ includeSecurityErrors: z__namespace.boolean().optional().describe("Include Bloomberg security errors in the response when supported."),
1445
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1365
1446
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1366
1447
  ),
1367
- overrides: primitiveMap(tool3, "overrides").describe(
1448
+ overrides: primitiveMap(tool2, "overrides").describe(
1368
1449
  "Bloomberg field overrides as flat string/number/boolean values only."
1369
1450
  ),
1370
1451
  securities: stringArray2(
1371
- tool3,
1452
+ tool2,
1372
1453
  "securities",
1373
1454
  options.maxSecurities,
1374
1455
  options.maxStringChars,
1375
- '["AAPL US Equity"]'
1456
+ '["<TICKER> <MARKET_SECTOR>"]'
1376
1457
  ).describe(
1377
- 'Fully qualified Bloomberg securities, for example ["AAPL US Equity"]; 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."
1378
1459
  ),
1379
- validateFields: z2__namespace.boolean().optional().describe("Override field validation for this request.")
1460
+ validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
1380
1461
  });
1381
1462
  }
1382
1463
  function createBdhSchema(options) {
1383
- const tool3 = "xbbg_bdh";
1384
- return z2__namespace.object({
1385
- end: dateField(tool3, "end").describe("Required end date. Use YYYY-MM-DD or YYYYMMDD."),
1464
+ const tool2 = "xbbg_bdh";
1465
+ return z__namespace.object({
1466
+ end: dateField(tool2, "end").describe("Required end date. Use YYYY-MM-DD or YYYYMMDD."),
1386
1467
  fields: stringArray2(
1387
- tool3,
1468
+ tool2,
1388
1469
  "fields",
1389
1470
  options.maxFields,
1390
1471
  options.maxStringChars,
1391
- '["PX_LAST"]'
1392
- ).describe('Bloomberg historical field mnemonics, for example ["PX_LAST"].'),
1393
- format: historicalFormat(tool3).describe(
1472
+ '["<FIELD>"]'
1473
+ ).describe("Bloomberg historical field mnemonics supplied by the user."),
1474
+ format: historicalFormat(tool2).describe(
1394
1475
  "Historical JSON output shape. Use wide only when the user asks for a table by date."
1395
1476
  ),
1396
- kwargs: primitiveMap(tool3, "kwargs").describe(
1477
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1397
1478
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1398
1479
  ),
1399
- overrides: primitiveMap(tool3, "overrides").describe(
1480
+ overrides: primitiveMap(tool2, "overrides").describe(
1400
1481
  "Bloomberg overrides as flat string/number/boolean values only."
1401
1482
  ),
1402
1483
  securities: stringArray2(
1403
- tool3,
1484
+ tool2,
1404
1485
  "securities",
1405
1486
  options.maxSecurities,
1406
1487
  options.maxStringChars,
1407
- '["AAPL US Equity"]'
1488
+ '["<TICKER> <MARKET_SECTOR>"]'
1408
1489
  ).describe(
1409
- 'Fully qualified Bloomberg securities, for example ["AAPL US Equity"]; 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."
1410
1491
  ),
1411
- start: dateField(tool3, "start").describe("Required start date. Use YYYY-MM-DD or YYYYMMDD."),
1412
- validateFields: z2__namespace.boolean().optional().describe("Override field validation for this request.")
1492
+ start: dateField(tool2, "start").describe("Required start date. Use YYYY-MM-DD or YYYYMMDD."),
1493
+ validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
1413
1494
  }).superRefine((value, ctx) => {
1414
1495
  if (value.start > value.end) {
1415
1496
  ctx.addIssue({
1416
1497
  code: "custom",
1417
- message: `${tool3}: start must be on or before end. Example: start "2024-01-01", end "2024-01-31"`,
1498
+ message: `${tool2}: start must be on or before end. Use an explicit start/end date range.`,
1418
1499
  path: ["start"]
1419
1500
  });
1420
1501
  }
1421
1502
  });
1422
1503
  }
1423
1504
  function createBdsSchema(options) {
1424
- const tool3 = "xbbg_bds";
1425
- return z2__namespace.object({
1426
- field: nonEmptyString2(tool3, "field", options.maxStringChars, "INDX_MEMBERS").describe(
1427
- "Exactly one Bloomberg bulk/table field, for example INDX_MEMBERS."
1505
+ const tool2 = "xbbg_bds";
1506
+ return z__namespace.object({
1507
+ field: nonEmptyString2(tool2, "field", options.maxStringChars, "<BULK_FIELD>").describe(
1508
+ "Exactly one Bloomberg bulk/table field supplied by the user."
1428
1509
  ),
1429
- format: referenceFormat(tool3).describe("JSON output shape. Usually omit."),
1430
- kwargs: primitiveMap(tool3, "kwargs").describe(
1510
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1431
1511
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1432
1512
  ),
1433
- overrides: primitiveMap(tool3, "overrides").describe(
1513
+ overrides: primitiveMap(tool2, "overrides").describe(
1434
1514
  "Bloomberg overrides as flat string/number/boolean values only."
1435
1515
  ),
1436
1516
  securities: stringArray2(
1437
- tool3,
1517
+ tool2,
1438
1518
  "securities",
1439
1519
  options.maxSecurities,
1440
1520
  options.maxStringChars,
1441
- '["SPX Index"]'
1521
+ '["<INDEX_TICKER> <MARKET_SECTOR>"]'
1442
1522
  ).describe(
1443
- 'Fully qualified Bloomberg securities, for example ["SPX Index"]; 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."
1444
1524
  ),
1445
- validateFields: z2__namespace.boolean().optional().describe("Override field validation for this request.")
1525
+ validateFields: z__namespace.boolean().optional().describe("Override field validation for this request.")
1446
1526
  });
1447
1527
  }
1448
1528
  function createBdibSchema(options) {
1449
- const tool3 = "xbbg_bdib";
1450
- return z2__namespace.object({
1451
- end: dateTimeField(tool3, "end").describe(
1529
+ const tool2 = "xbbg_bdib";
1530
+ return z__namespace.object({
1531
+ end: dateTimeField(tool2, "end").describe(
1452
1532
  "Required intraday end datetime. Use ISO 8601 with timezone when possible."
1453
1533
  ),
1454
- eventType: nonEmptyString2(tool3, "eventType", options.maxStringChars, "TRADE").optional().describe("Bloomberg event type. Usually TRADE."),
1455
- interval: z2__namespace.number().int(`${tool3}: interval must be a positive integer number of minutes. Example: 5`).positive(`${tool3}: interval must be greater than zero. Example: 5`).describe("Bar interval in minutes. Must be a positive integer."),
1456
- kwargs: primitiveMap(tool3, "kwargs").describe(
1534
+ eventType: nonEmptyString2(tool2, "eventType", options.maxStringChars, "<EVENT_TYPE>").optional().describe("Bloomberg event type supplied by the user."),
1535
+ interval: z__namespace.number().int(`${tool2}: interval must be a positive integer number of minutes. Example: 5`).positive(`${tool2}: interval must be greater than zero. Example: 5`).describe("Bar interval in minutes. Must be a positive integer."),
1536
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1457
1537
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1458
1538
  ),
1459
- outputTz: nonEmptyString2(tool3, "outputTz", options.maxStringChars, "America/New_York").optional().describe("Optional output timezone, for example America/New_York."),
1460
- requestTz: nonEmptyString2(tool3, "requestTz", options.maxStringChars, "America/New_York").optional().describe("Timezone for naive start/end datetimes, for example America/New_York."),
1461
- start: dateTimeField(tool3, "start").describe(
1539
+ outputTz: nonEmptyString2(tool2, "outputTz", options.maxStringChars, "<TIMEZONE>").optional().describe("Optional output timezone."),
1540
+ requestTz: nonEmptyString2(tool2, "requestTz", options.maxStringChars, "<TIMEZONE>").optional().describe("Timezone for naive start/end datetimes."),
1541
+ start: dateTimeField(tool2, "start").describe(
1462
1542
  "Required intraday start datetime. Use ISO 8601 with timezone when possible."
1463
1543
  ),
1464
- ticker: nonEmptyString2(tool3, "ticker", options.maxStringChars, "AAPL US Equity").describe(
1465
- "One fully qualified Bloomberg security, for example AAPL US Equity; use /isin/{isin} for ISINs and /cusip/{cusip} for CUSIPs."
1544
+ ticker: nonEmptyString2(
1545
+ tool2,
1546
+ "ticker",
1547
+ options.maxStringChars,
1548
+ "<TICKER> <MARKET_SECTOR>"
1549
+ ).describe(
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."
1466
1551
  )
1467
1552
  });
1468
1553
  }
1469
1554
  function createBdtickSchema(options) {
1470
- const tool3 = "xbbg_bdtick";
1471
- const includeFlag = z2__namespace.boolean().optional().describe("Optional IntradayTickRequest include flag.");
1472
- return z2__namespace.object({
1473
- end: dateTimeField(tool3, "end").describe(
1555
+ const tool2 = "xbbg_bdtick";
1556
+ const includeFlag = z__namespace.boolean().optional().describe("Optional IntradayTickRequest include flag.");
1557
+ return z__namespace.object({
1558
+ end: dateTimeField(tool2, "end").describe(
1474
1559
  "Required intraday tick end datetime. Use ISO 8601 with timezone when possible."
1475
1560
  ),
1476
1561
  eventTypes: stringArray2(
1477
- tool3,
1562
+ tool2,
1478
1563
  "eventTypes",
1479
1564
  options.maxFields,
1480
1565
  options.maxStringChars,
1481
- '["TRADE"]'
1482
- ).optional().describe('Bloomberg tick event types, for example ["TRADE"] or ["BID", "ASK"].'),
1566
+ '["<EVENT_TYPE>"]'
1567
+ ).optional().describe('Bloomberg tick event types, for example ["<EVENT_TYPE>"].'),
1483
1568
  includeBicMicCodes: includeFlag,
1484
1569
  includeBloombergStandardConditionCodes: includeFlag,
1485
1570
  includeBrokerCodes: includeFlag,
@@ -1487,94 +1572,96 @@ function createBdtickSchema(options) {
1487
1572
  includeExchangeCodes: includeFlag,
1488
1573
  includeNonPlottableEvents: includeFlag,
1489
1574
  includeRpsCodes: includeFlag,
1490
- kwargs: primitiveMap(tool3, "kwargs").describe(
1575
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1491
1576
  "Advanced IntradayTickRequest kwargs as flat string/number/boolean values only."
1492
1577
  ),
1493
- outputTz: nonEmptyString2(tool3, "outputTz", options.maxStringChars, "America/New_York").optional().describe("Optional output timezone, for example America/New_York."),
1494
- requestTz: nonEmptyString2(tool3, "requestTz", options.maxStringChars, "America/New_York").optional().describe("Timezone for naive start/end datetimes, for example America/New_York."),
1495
- start: dateTimeField(tool3, "start").describe(
1578
+ outputTz: nonEmptyString2(tool2, "outputTz", options.maxStringChars, "<TIMEZONE>").optional().describe("Optional output timezone."),
1579
+ requestTz: nonEmptyString2(tool2, "requestTz", options.maxStringChars, "<TIMEZONE>").optional().describe("Timezone for naive start/end datetimes."),
1580
+ start: dateTimeField(tool2, "start").describe(
1496
1581
  "Required intraday tick start datetime. Use ISO 8601 with timezone when possible."
1497
1582
  ),
1498
- ticker: nonEmptyString2(tool3, "ticker", options.maxStringChars, "AAPL US Equity").describe(
1499
- "One fully qualified Bloomberg security, for example AAPL US Equity; use /isin/{isin} for ISINs and /cusip/{cusip} for CUSIPs."
1583
+ ticker: nonEmptyString2(
1584
+ tool2,
1585
+ "ticker",
1586
+ options.maxStringChars,
1587
+ "<TICKER> <MARKET_SECTOR>"
1588
+ ).describe(
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."
1500
1590
  )
1501
1591
  });
1502
1592
  }
1503
1593
  function createBqlSchema(options) {
1504
- const tool3 = "xbbg_bql";
1505
- return z2__namespace.object({
1506
- format: referenceFormat(tool3).describe("JSON output shape. Usually omit."),
1507
- kwargs: primitiveMap(tool3, "kwargs").describe(
1594
+ const tool2 = "xbbg_bql";
1595
+ return z__namespace.object({
1596
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1508
1597
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1509
1598
  ),
1510
- query: nonEmptyString2(
1511
- tool3,
1512
- "query",
1513
- options.maxBqlQueryChars,
1514
- "get(px_last) for('AAPL US Equity')"
1515
- ).describe(
1516
- "Complete BQL expression string. Use get(...) for(...) with an explicit bounded universe; prefer BDP/BDH for simple reference or historical requests."
1599
+ query: nonEmptyString2(tool2, "query", options.maxBqlQueryChars, "<BQL_QUERY>").describe(
1600
+ "Complete BQL expression string with an explicit bounded universe; prefer BDP/BDH for simple reference or historical requests."
1517
1601
  )
1518
1602
  });
1519
1603
  }
1520
1604
  function createBqrSchema(options) {
1521
- const tool3 = "xbbg_bqr";
1522
- return z2__namespace.object({
1523
- end: dateTimeField(tool3, "end").describe(
1605
+ const tool2 = "xbbg_bqr";
1606
+ return z__namespace.object({
1607
+ end: dateTimeField(tool2, "end").describe(
1524
1608
  "Required BQR end datetime. Use ISO 8601 with timezone when possible."
1525
1609
  ),
1526
1610
  eventTypes: stringArray2(
1527
- tool3,
1611
+ tool2,
1528
1612
  "eventTypes",
1529
1613
  options.maxFields,
1530
1614
  options.maxStringChars,
1531
- '["BID", "ASK"]'
1532
- ).optional().describe('BQR event types. Usually ["BID", "ASK"].'),
1533
- includeBrokerCodes: z2__namespace.boolean().optional().describe("Include broker/dealer attribution columns. Defaults to true in @xbbg/core."),
1534
- start: dateTimeField(tool3, "start").describe(
1615
+ '["<EVENT_TYPE>"]'
1616
+ ).optional().describe('BQR event types, for example ["<EVENT_TYPE>"].'),
1617
+ includeBrokerCodes: z__namespace.boolean().optional().describe("Include broker/dealer attribution columns. Defaults to true in @xbbg/core."),
1618
+ start: dateTimeField(tool2, "start").describe(
1535
1619
  "Required BQR start datetime. Use ISO 8601 with timezone when possible."
1536
1620
  ),
1537
1621
  ticker: nonEmptyString2(
1538
- tool3,
1622
+ tool2,
1539
1623
  "ticker",
1540
1624
  options.maxStringChars,
1541
- "/isin/US037833FB15@MSG1 Corp"
1625
+ "/isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>"
1542
1626
  ).describe(
1543
- "Fixed-income ticker or identifier with dealer quote source, for example /isin/US037833FB15@MSG1 Corp."
1627
+ "Fixed-income ticker or identifier with dealer quote source, for example /isin/<ISIN>@<QUOTE_SOURCE> <MARKET_SECTOR>."
1544
1628
  )
1545
1629
  });
1546
1630
  }
1547
1631
  function createBsrchSchema(options) {
1548
- const tool3 = "xbbg_bsrch";
1549
- return z2__namespace.object({
1550
- format: referenceFormat(tool3).describe("JSON output shape. Usually omit."),
1551
- kwargs: primitiveMap(tool3, "kwargs").describe(
1632
+ const tool2 = "xbbg_bsrch";
1633
+ return z__namespace.object({
1634
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1552
1635
  "Search-grid kwargs as flat string/number/boolean values only."
1553
1636
  ),
1554
- overrides: primitiveMap(tool3, "overrides").describe(
1637
+ overrides: primitiveMap(tool2, "overrides").describe(
1555
1638
  "Search-grid overrides as flat string/number/boolean values only."
1556
1639
  ),
1557
1640
  searchSpec: nonEmptyString2(
1558
- tool3,
1641
+ tool2,
1559
1642
  "searchSpec",
1560
1643
  options.maxSearchSpecChars,
1561
- "COMDTY:NG"
1644
+ "<SEARCH_SPEC>"
1562
1645
  ).describe(
1563
1646
  "Bloomberg search/grid domain or saved-search spec. Not for normal security lookup."
1564
1647
  )
1565
1648
  });
1566
1649
  }
1567
1650
  function createBfldsSchema(options) {
1568
- const tool3 = "xbbg_bflds";
1569
- return z2__namespace.object({
1570
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["PX_LAST"]').optional().describe(
1571
- 'Specific field mnemonics to inspect, for example ["PX_LAST"]. Provide either fields or searchSpec, not both.'
1651
+ const tool2 = "xbbg_bflds";
1652
+ return z__namespace.object({
1653
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe(
1654
+ "Specific field mnemonics to inspect. Provide either fields or searchSpec, not both."
1572
1655
  ),
1573
- format: referenceFormat(tool3).describe("JSON output shape. Usually omit."),
1574
- kwargs: primitiveMap(tool3, "kwargs").describe(
1656
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1575
1657
  "Advanced Bloomberg request kwargs as flat string/number/boolean values only."
1576
1658
  ),
1577
- searchSpec: nonEmptyString2(tool3, "searchSpec", options.maxSearchSpecChars, "last price").optional().describe(
1659
+ searchSpec: nonEmptyString2(
1660
+ tool2,
1661
+ "searchSpec",
1662
+ options.maxSearchSpecChars,
1663
+ "<FIELD_SEARCH_TEXT>"
1664
+ ).optional().describe(
1578
1665
  "Field search text when the field mnemonic is unknown. Provide either searchSpec or fields, not both."
1579
1666
  )
1580
1667
  }).superRefine((value, ctx) => {
@@ -1583,188 +1670,213 @@ function createBfldsSchema(options) {
1583
1670
  if (hasFields === hasSearchSpec) {
1584
1671
  ctx.addIssue({
1585
1672
  code: "custom",
1586
- message: `${tool3}: provide exactly one of fields or searchSpec. Example: {"fields":["PX_LAST"]}`,
1673
+ message: `${tool2}: provide exactly one of fields or searchSpec. Example: {"fields":["<FIELD>"]}`,
1587
1674
  path: ["fields"]
1588
1675
  });
1589
1676
  }
1590
1677
  });
1591
1678
  }
1592
1679
  function createBeqsSchema(options) {
1593
- const tool3 = "xbbg_beqs";
1594
- return z2__namespace.object({
1595
- asof: dateField(tool3, "asof").optional().describe("Optional as-of date for the screen."),
1596
- format: referenceFormat(tool3).describe("JSON output shape. Usually omit."),
1597
- group: nonEmptyString2(tool3, "group", options.maxStringChars, "General").optional().describe("Bloomberg BEQS group. Defaults to General in @xbbg/core."),
1598
- kwargs: primitiveMap(tool3, "kwargs").describe(
1680
+ const tool2 = "xbbg_beqs";
1681
+ return z__namespace.object({
1682
+ asof: dateField(tool2, "asof").optional().describe("Optional as-of date for the screen."),
1683
+ group: nonEmptyString2(tool2, "group", options.maxStringChars, "<BEQS_GROUP>").optional().describe("Bloomberg BEQS group when required by the screen."),
1684
+ kwargs: primitiveMap(tool2, "kwargs").describe(
1599
1685
  "Advanced BEQS request kwargs as flat string/number/boolean values only."
1600
1686
  ),
1601
- overrides: primitiveMap(tool3, "overrides").describe(
1687
+ overrides: primitiveMap(tool2, "overrides").describe(
1602
1688
  "BEQS overrides as flat string/number/boolean values only."
1603
1689
  ),
1604
- screen: nonEmptyString2(
1605
- tool3,
1606
- "screen",
1607
- options.maxStringChars,
1608
- "Core Capital Goods Makers"
1609
- ).describe("Existing Bloomberg BEQS screen name."),
1610
- screenType: nonEmptyString2(tool3, "screenType", options.maxStringChars, "PRIVATE").optional().describe("Bloomberg BEQS screen type. Defaults to PRIVATE in @xbbg/core.")
1690
+ screen: nonEmptyString2(tool2, "screen", options.maxStringChars, "<BEQS_SCREEN>").describe(
1691
+ "Existing Bloomberg BEQS screen name supplied by the user."
1692
+ ),
1693
+ screenType: nonEmptyString2(tool2, "screenType", options.maxStringChars, "<SCREEN_TYPE>").optional().describe("Bloomberg BEQS screen type when required by the screen.")
1611
1694
  });
1612
1695
  }
1613
1696
  function createYasSchema(options) {
1614
- const tool3 = "xbbg_yas";
1615
- return z2__namespace.object({
1616
- benchmark: nonEmptyString2(tool3, "benchmark", options.maxStringChars, "USGG10YR Index").optional().describe("Optional YAS benchmark."),
1697
+ const tool2 = "xbbg_yas";
1698
+ return z__namespace.object({
1699
+ benchmark: nonEmptyString2(tool2, "benchmark", options.maxStringChars, "<BENCHMARK_TICKER>").optional().describe("Optional YAS benchmark supplied by the user."),
1617
1700
  fields: stringArray2(
1618
- tool3,
1701
+ tool2,
1619
1702
  "fields",
1620
1703
  options.maxFields,
1621
1704
  options.maxStringChars,
1622
- '["YAS_BOND_YLD"]'
1623
- ).describe('YAS field mnemonics, for example ["YAS_BOND_YLD", "YAS_MOD_DUR"].'),
1624
- price: z2__namespace.number().optional().describe("Optional YAS price input."),
1625
- settleDt: dateField(tool3, "settleDt").optional().describe("Optional YAS settlement date."),
1626
- spread: z2__namespace.number().optional().describe("Optional YAS spread input."),
1705
+ '["<YAS_FIELD>"]'
1706
+ ).describe("YAS field mnemonics supplied by the user."),
1707
+ price: z__namespace.number().optional().describe("Optional YAS price input."),
1708
+ settleDt: dateField(tool2, "settleDt").optional().describe("Optional YAS settlement date."),
1709
+ spread: z__namespace.number().optional().describe("Optional YAS spread input."),
1627
1710
  tickers: stringArray2(
1628
- tool3,
1711
+ tool2,
1629
1712
  "tickers",
1630
1713
  options.maxSecurities,
1631
1714
  options.maxStringChars,
1632
- '["/isin/US037833FB15 Corp"]'
1715
+ '["/isin/<ISIN> <MARKET_SECTOR>"]'
1633
1716
  ).describe(
1634
- 'Fully qualified fixed-income Bloomberg securities, for example ["/isin/US037833FB15 Corp"].'
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."
1635
1718
  ),
1636
- yieldType: z2__namespace.number().int().optional().describe("Optional YAS yield type."),
1637
- yieldVal: z2__namespace.number().optional().describe("Optional YAS yield value input.")
1719
+ yieldType: z__namespace.number().int().optional().describe("Optional YAS yield type."),
1720
+ yieldVal: z__namespace.number().optional().describe("Optional YAS yield value input.")
1638
1721
  });
1639
1722
  }
1640
1723
  function createPreferredsSchema(options) {
1641
- const tool3 = "xbbg_preferreds";
1642
- return z2__namespace.object({
1724
+ const tool2 = "xbbg_preferreds";
1725
+ return z__namespace.object({
1643
1726
  equityTicker: nonEmptyString2(
1644
- tool3,
1727
+ tool2,
1645
1728
  "equityTicker",
1646
1729
  options.maxStringChars,
1647
- "AAPL US Equity"
1648
- ).describe("One fully qualified issuer equity ticker."),
1649
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["id"]').optional().describe("Optional fields to include in the preferreds recipe result.")
1730
+ "<ISSUER_TICKER> <MARKET_SECTOR>"
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
+ ),
1734
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the preferreds recipe result.")
1650
1735
  });
1651
1736
  }
1652
1737
  function createCorporateBondsSchema(options) {
1653
- const tool3 = "xbbg_corporate_bonds";
1654
- return z2__namespace.object({
1655
- activeOnly: z2__namespace.boolean().optional().describe("Restrict to active bonds. Defaults to true in @xbbg/core."),
1656
- ccy: nonEmptyString2(tool3, "ccy", options.maxStringChars, "USD").optional().describe("Optional currency filter."),
1657
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["id"]').optional().describe("Optional fields to include in the corporate bond result."),
1658
- ticker: nonEmptyString2(tool3, "ticker", options.maxStringChars, "AAPL US Equity").describe(
1659
- "One fully qualified issuer/company ticker."
1738
+ const tool2 = "xbbg_corporate_bonds";
1739
+ return z__namespace.object({
1740
+ activeOnly: z__namespace.boolean().optional().describe("Restrict to active bonds. Defaults to true in @xbbg/core."),
1741
+ ccy: nonEmptyString2(tool2, "ccy", options.maxStringChars, "<CCY>").optional().describe("Optional currency filter supplied by the user."),
1742
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the corporate bond result."),
1743
+ ticker: nonEmptyString2(
1744
+ tool2,
1745
+ "ticker",
1746
+ options.maxStringChars,
1747
+ "<ISSUER_TICKER> <MARKET_SECTOR>"
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."
1660
1750
  )
1661
1751
  });
1662
1752
  }
1663
1753
  function createIndexMembersSchema(options) {
1664
- const tool3 = "xbbg_index_members";
1665
- return z2__namespace.object({
1666
- asof: dateField(tool3, "asof").optional().describe("Optional index membership as-of date."),
1667
- field: z2__namespace.enum(["INDX_MWEIGHT", "INDX_MEMBERS", "INDX_MEMBERS3"]).optional().describe("Bloomberg index members field. Omit for @xbbg/core default."),
1668
- index: nonEmptyString2(tool3, "index", options.maxStringChars, "SPX Index").describe(
1669
- "One fully qualified Bloomberg index ticker."
1754
+ const tool2 = "xbbg_index_members";
1755
+ return z__namespace.object({
1756
+ asof: dateField(tool2, "asof").optional().describe("Optional index membership as-of date."),
1757
+ field: z__namespace.enum(["INDX_MWEIGHT", "INDX_MEMBERS", "INDX_MEMBERS3"]).optional().describe("Bloomberg index members field. Omit for @xbbg/core default."),
1758
+ index: nonEmptyString2(
1759
+ tool2,
1760
+ "index",
1761
+ options.maxStringChars,
1762
+ "<INDEX_TICKER> <MARKET_SECTOR>"
1763
+ ).describe(
1764
+ "One Bloomberg index ticker as '<INDEX_TICKER> <MARKET_SECTOR>' supplied by the user; never guess index tickers."
1670
1765
  )
1671
1766
  });
1672
1767
  }
1673
1768
  function createResolveIsinsSchema(options) {
1674
- const tool3 = "xbbg_resolve_isins";
1675
- return z2__namespace.object({
1769
+ const tool2 = "xbbg_resolve_isins";
1770
+ return z__namespace.object({
1676
1771
  isins: stringArray2(
1677
- tool3,
1772
+ tool2,
1678
1773
  "isins",
1679
1774
  options.maxSecurities,
1680
1775
  options.maxStringChars,
1681
- '["US0378331005"]'
1776
+ '["<ISIN>"]'
1682
1777
  ).describe("Raw ISIN strings to resolve. Do not add /isin/ prefixes for this recipe.")
1683
1778
  });
1684
1779
  }
1685
1780
  function createIssuerIsinsSchema(options) {
1686
- const tool3 = "xbbg_issuer_isins";
1687
- return z2__namespace.object({
1781
+ const tool2 = "xbbg_issuer_isins";
1782
+ return z__namespace.object({
1688
1783
  bondIsins: stringArray2(
1689
- tool3,
1784
+ tool2,
1690
1785
  "bondIsins",
1691
1786
  options.maxSecurities,
1692
1787
  options.maxStringChars,
1693
- '["US037833FB15"]'
1788
+ '["<BOND_ISIN>"]'
1694
1789
  ).describe("Raw bond ISIN strings for issuer-level ISIN discovery.")
1695
1790
  });
1696
1791
  }
1697
1792
  function createEtfHoldingsSchema(options) {
1698
- const tool3 = "xbbg_etf_holdings";
1699
- return z2__namespace.object({
1700
- etfTicker: nonEmptyString2(tool3, "etfTicker", options.maxStringChars, "SPY US Equity").describe(
1701
- "One fully qualified Bloomberg ETF ticker."
1793
+ const tool2 = "xbbg_etf_holdings";
1794
+ return z__namespace.object({
1795
+ etfTicker: nonEmptyString2(
1796
+ tool2,
1797
+ "etfTicker",
1798
+ options.maxStringChars,
1799
+ "<ETF_TICKER> <MARKET_SECTOR>"
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."
1702
1802
  ),
1703
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["id"]').optional().describe("Optional fields to include in the ETF holdings recipe result.")
1803
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional fields to include in the ETF holdings recipe result.")
1704
1804
  });
1705
1805
  }
1706
- function snapshotControlFields(tool3, options) {
1806
+ function snapshotControlFields(tool2, options) {
1707
1807
  return {
1708
- allFields: z2__namespace.boolean().optional().describe("Request all Bloomberg fields when supported."),
1709
- conflate: z2__namespace.boolean().optional().describe("Enable Bloomberg conflated streaming when supported."),
1710
- drain: z2__namespace.boolean().optional().describe(
1711
- "Pass drain=true to unsubscribe. Defaults to false; collected output remains bounded."
1808
+ allFields: z__namespace.boolean().optional().describe("Request all Bloomberg fields when supported."),
1809
+ conflate: z__namespace.boolean().optional().describe("Enable Bloomberg conflated streaming when supported."),
1810
+ drain: z__namespace.boolean().optional().describe(
1811
+ "Flush buffered backlog while closing the subscription. The subscription always closes; collected output stays bounded either way. Defaults to false."
1712
1812
  ),
1713
- flushThreshold: z2__namespace.number().int().positive().optional().describe("Optional stream flush threshold."),
1714
- maxUpdates: z2__namespace.number().int(`${tool3}: maxUpdates must be a positive integer.`).positive(`${tool3}: maxUpdates must be greater than zero.`).max(
1813
+ flushThreshold: z__namespace.number().int().positive().optional().describe("Optional stream flush threshold."),
1814
+ maxUpdates: z__namespace.number().int(`${tool2}: maxUpdates must be a positive integer.`).positive(`${tool2}: maxUpdates must be greater than zero.`).max(
1715
1815
  options.maxStreamUpdates,
1716
- `${tool3}: maxUpdates can be at most ${options.maxStreamUpdates}.`
1816
+ `${tool2}: maxUpdates can be at most ${options.maxStreamUpdates}.`
1717
1817
  ).describe("Required maximum number of updates to collect before unsubscribing."),
1718
1818
  options: stringArray2(
1719
- tool3,
1819
+ tool2,
1720
1820
  "options",
1721
1821
  options.maxFields,
1722
1822
  options.maxStringChars,
1723
1823
  '["interval=5"]'
1724
1824
  ).optional().describe("Advanced Bloomberg subscription options."),
1725
- overflowPolicy: nonEmptyString2(tool3, "overflowPolicy", options.maxStringChars, "drop_oldest").optional().describe("Optional stream overflow policy."),
1726
- streamCapacity: z2__namespace.number().int().positive().optional().describe("Optional stream capacity."),
1727
- timeoutMs: z2__namespace.number().int().positive().max(options.maxStreamWaitMs, `${tool3}: timeoutMs can be at most ${options.maxStreamWaitMs}.`).optional().default(options.maxStreamWaitMs).describe("Maximum total wait in milliseconds before unsubscribing.")
1825
+ overflowPolicy: nonEmptyString2(tool2, "overflowPolicy", options.maxStringChars, "drop_oldest").optional().describe("Optional stream overflow policy."),
1826
+ streamCapacity: z__namespace.number().int().positive().optional().describe("Optional stream capacity."),
1827
+ timeoutMs: z__namespace.number().int().positive().max(options.maxStreamWaitMs, `${tool2}: timeoutMs can be at most ${options.maxStreamWaitMs}.`).optional().default(options.maxStreamWaitMs).describe("Maximum total wait in milliseconds before unsubscribing.")
1728
1828
  };
1729
1829
  }
1730
1830
  function createStreamSnapshotSchema(options) {
1731
- const tool3 = "xbbg_stream_snapshot";
1732
- return z2__namespace.object({
1831
+ const tool2 = "xbbg_stream_snapshot";
1832
+ return z__namespace.object({
1733
1833
  fields: stringArray2(
1734
- tool3,
1834
+ tool2,
1735
1835
  "fields",
1736
1836
  options.maxFields,
1737
1837
  options.maxStringChars,
1738
- '["LAST_PRICE"]'
1838
+ '["<FIELD>"]'
1739
1839
  ).describe("Bloomberg market-data fields to observe."),
1740
1840
  tickers: stringArray2(
1741
- tool3,
1841
+ tool2,
1742
1842
  "tickers",
1743
1843
  options.maxSecurities,
1744
1844
  options.maxStringChars,
1745
- '["AAPL US Equity"]'
1746
- ).describe("Fully qualified Bloomberg securities to observe."),
1747
- ...snapshotControlFields(tool3, options)
1845
+ '["<TICKER> <MARKET_SECTOR>"]'
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
+ ),
1849
+ ...snapshotControlFields(tool2, options)
1748
1850
  });
1749
1851
  }
1750
1852
  function createMktbarSnapshotSchema(options) {
1751
- const tool3 = "xbbg_mktbar_snapshot";
1752
- return z2__namespace.object({
1753
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["LAST_PRICE"]').optional().describe("Optional market-bar fields. Omit for Bloomberg defaults."),
1754
- ticker: nonEmptyString2(tool3, "ticker", options.maxStringChars, "AAPL US Equity").describe(
1755
- "One fully qualified Bloomberg security to observe."
1853
+ const tool2 = "xbbg_mktbar_snapshot";
1854
+ return z__namespace.object({
1855
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional market-bar fields. Omit for Bloomberg defaults."),
1856
+ ticker: nonEmptyString2(
1857
+ tool2,
1858
+ "ticker",
1859
+ options.maxStringChars,
1860
+ "<TICKER> <MARKET_SECTOR>"
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."
1756
1863
  ),
1757
- ...snapshotControlFields(tool3, options)
1864
+ ...snapshotControlFields(tool2, options)
1758
1865
  });
1759
1866
  }
1760
1867
  function createDepthSnapshotSchema(options) {
1761
- const tool3 = "xbbg_depth_snapshot";
1762
- return z2__namespace.object({
1763
- fields: stringArray2(tool3, "fields", options.maxFields, options.maxStringChars, '["BID"]').optional().describe("Optional market-depth fields. Omit for Bloomberg defaults."),
1764
- ticker: nonEmptyString2(tool3, "ticker", options.maxStringChars, "AAPL US Equity").describe(
1765
- "One fully qualified Bloomberg security to observe."
1868
+ const tool2 = "xbbg_depth_snapshot";
1869
+ return z__namespace.object({
1870
+ fields: stringArray2(tool2, "fields", options.maxFields, options.maxStringChars, '["<FIELD>"]').optional().describe("Optional market-depth fields. Omit for Bloomberg defaults."),
1871
+ ticker: nonEmptyString2(
1872
+ tool2,
1873
+ "ticker",
1874
+ options.maxStringChars,
1875
+ "<TICKER> <MARKET_SECTOR>"
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."
1766
1878
  ),
1767
- ...snapshotControlFields(tool3, options)
1879
+ ...snapshotControlFields(tool2, options)
1768
1880
  });
1769
1881
  }
1770
1882
 
@@ -1773,17 +1885,24 @@ function resultString2(resolver, name, value) {
1773
1885
  return createToolResult(name, value, resolver.options.maxRows, resolver.options.maxStringChars);
1774
1886
  }
1775
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
+ }
1776
1893
  function streamOptions(input) {
1777
1894
  return {
1778
1895
  allFields: input.allFields,
1779
1896
  conflate: input.conflate,
1780
- fields: input.fields,
1781
1897
  flushThreshold: input.flushThreshold,
1782
1898
  options: input.options,
1783
1899
  overflowPolicy: input.overflowPolicy,
1784
1900
  streamCapacity: input.streamCapacity
1785
1901
  };
1786
1902
  }
1903
+ function singleTickerStreamOptions(input) {
1904
+ return { ...streamOptions(input), fields: input.fields };
1905
+ }
1787
1906
  function isRecord(value) {
1788
1907
  return typeof value === "object" && value !== null;
1789
1908
  }
@@ -1839,42 +1958,55 @@ function normalizeStreamUpdate(value) {
1839
1958
  const rows = rowsFromArrowTable(value);
1840
1959
  return rows === void 0 ? jsonCompatible(value) : rows.map(jsonCompatible);
1841
1960
  }
1842
- async function nextWithinTimeout(iterator, deadlineMs) {
1961
+ async function nextWithinTimeout(iterator, deadlineMs, signal) {
1962
+ if (signal?.aborted === true) {
1963
+ return STREAM_ABORTED;
1964
+ }
1843
1965
  const remainingMs = deadlineMs - Date.now();
1844
1966
  if (remainingMs <= 0) {
1845
1967
  return STREAM_TIMEOUT;
1846
1968
  }
1847
1969
  const nextPromise = iterator.next();
1848
1970
  let timer;
1849
- const timeoutPromise = new Promise((resolve) => {
1850
- timer = setTimeout(() => resolve(STREAM_TIMEOUT), remainingMs);
1851
- });
1852
- 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);
1853
1987
  if (timer !== void 0) {
1854
1988
  clearTimeout(timer);
1855
1989
  }
1856
- 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) {
1857
1994
  void nextPromise.catch(() => void 0);
1858
1995
  }
1859
1996
  return result;
1860
1997
  }
1861
- async function unsubscribeSnapshot(subscription, drain, priorError) {
1862
- try {
1863
- await subscription.unsubscribe(drain);
1864
- } catch (error) {
1865
- if (priorError === void 0) {
1866
- throw error;
1867
- }
1868
- }
1869
- }
1870
- async function collectSnapshot(subscription, input) {
1998
+ async function collectSnapshot(subscription, input, signal) {
1871
1999
  const updates = [];
1872
2000
  const deadlineMs = Date.now() + input.timeoutMs;
1873
2001
  let reason = "max_updates";
2002
+ let failed = false;
1874
2003
  let caught;
1875
2004
  try {
1876
2005
  while (updates.length < input.maxUpdates) {
1877
- const next = await nextWithinTimeout(subscription, deadlineMs);
2006
+ const next = await nextWithinTimeout(subscription, deadlineMs, signal);
2007
+ if (next === STREAM_ABORTED) {
2008
+ throw abortError(signal);
2009
+ }
1878
2010
  if (next === STREAM_TIMEOUT) {
1879
2011
  reason = "timeout";
1880
2012
  break;
@@ -1885,29 +2017,37 @@ async function collectSnapshot(subscription, input) {
1885
2017
  }
1886
2018
  updates.push(normalizeStreamUpdate(next.value));
1887
2019
  }
1888
- return {
1889
- maxUpdates: input.maxUpdates,
1890
- reason,
1891
- timeoutMs: input.timeoutMs,
1892
- updateCount: updates.length,
1893
- updates
1894
- };
1895
2020
  } catch (error) {
2021
+ failed = true;
1896
2022
  caught = error;
1897
- throw error;
1898
- } finally {
1899
- await unsubscribeSnapshot(subscription, input.drain === true, caught);
1900
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
+ };
1901
2044
  }
1902
2045
  function validationSetting(resolver, value) {
1903
2046
  return value ?? resolver.options.validateFields;
1904
2047
  }
1905
- function enabledTool(resolver, name, creator) {
1906
- return isToolDisabled(resolver.options, name) ? [] : [creator(resolver)];
1907
- }
1908
2048
  function bdpWithResolver(resolver) {
1909
2049
  const name = "xbbg_bdp";
1910
- return tools.tool(
2050
+ return createBloombergStructuredTool(
1911
2051
  async (input) => {
1912
2052
  try {
1913
2053
  const engine = await resolver.getEngine();
@@ -1934,7 +2074,7 @@ function bdpWithResolver(resolver) {
1934
2074
  }
1935
2075
  function bdhWithResolver(resolver) {
1936
2076
  const name = "xbbg_bdh";
1937
- return tools.tool(
2077
+ return createBloombergStructuredTool(
1938
2078
  async (input) => {
1939
2079
  try {
1940
2080
  const engine = await resolver.getEngine();
@@ -1962,13 +2102,12 @@ function bdhWithResolver(resolver) {
1962
2102
  }
1963
2103
  function bdsWithResolver(resolver) {
1964
2104
  const name = "xbbg_bds";
1965
- return tools.tool(
2105
+ return createBloombergStructuredTool(
1966
2106
  async (input) => {
1967
2107
  try {
1968
2108
  const engine = await resolver.getEngine();
1969
2109
  const result = await engine.bds(input.securities, [input.field], {
1970
2110
  backend: "json",
1971
- format: input.format,
1972
2111
  kwargs: input.kwargs,
1973
2112
  overrides: input.overrides,
1974
2113
  validateFields: validationSetting(resolver, input.validateFields)
@@ -1988,7 +2127,7 @@ function bdsWithResolver(resolver) {
1988
2127
  }
1989
2128
  function bdibWithResolver(resolver) {
1990
2129
  const name = "xbbg_bdib";
1991
- return tools.tool(
2130
+ return createBloombergStructuredTool(
1992
2131
  async (input) => {
1993
2132
  try {
1994
2133
  const engine = await resolver.getEngine();
@@ -2017,7 +2156,7 @@ function bdibWithResolver(resolver) {
2017
2156
  }
2018
2157
  function bdtickWithResolver(resolver) {
2019
2158
  const name = "xbbg_bdtick";
2020
- return tools.tool(
2159
+ return createBloombergStructuredTool(
2021
2160
  async (input) => {
2022
2161
  try {
2023
2162
  const engine = await resolver.getEngine();
@@ -2052,13 +2191,12 @@ function bdtickWithResolver(resolver) {
2052
2191
  }
2053
2192
  function bqlWithResolver(resolver) {
2054
2193
  const name = "xbbg_bql";
2055
- return tools.tool(
2194
+ return createBloombergStructuredTool(
2056
2195
  async (input) => {
2057
2196
  try {
2058
2197
  const engine = await resolver.getEngine();
2059
2198
  const result = await engine.bql(input.query, {
2060
2199
  backend: "json",
2061
- format: input.format,
2062
2200
  kwargs: input.kwargs
2063
2201
  });
2064
2202
  return resultString2(resolver, name, result);
@@ -2076,13 +2214,12 @@ function bqlWithResolver(resolver) {
2076
2214
  }
2077
2215
  function bsrchWithResolver(resolver) {
2078
2216
  const name = "xbbg_bsrch";
2079
- return tools.tool(
2217
+ return createBloombergStructuredTool(
2080
2218
  async (input) => {
2081
2219
  try {
2082
2220
  const engine = await resolver.getEngine();
2083
2221
  const result = await engine.bsrch(input.searchSpec, {
2084
2222
  backend: "json",
2085
- format: input.format,
2086
2223
  kwargs: input.kwargs,
2087
2224
  overrides: input.overrides
2088
2225
  });
@@ -2101,7 +2238,7 @@ function bsrchWithResolver(resolver) {
2101
2238
  }
2102
2239
  function bqrWithResolver(resolver) {
2103
2240
  const name = "xbbg_bqr";
2104
- return tools.tool(
2241
+ return createBloombergStructuredTool(
2105
2242
  async (input) => {
2106
2243
  try {
2107
2244
  const engine = await resolver.getEngine();
@@ -2127,14 +2264,13 @@ function bqrWithResolver(resolver) {
2127
2264
  }
2128
2265
  function bfldsWithResolver(resolver) {
2129
2266
  const name = "xbbg_bflds";
2130
- return tools.tool(
2267
+ return createBloombergStructuredTool(
2131
2268
  async (input) => {
2132
2269
  try {
2133
2270
  const engine = await resolver.getEngine();
2134
2271
  const result = await engine.bflds({
2135
2272
  backend: "json",
2136
2273
  fields: input.fields,
2137
- format: input.format,
2138
2274
  kwargs: input.kwargs,
2139
2275
  searchSpec: input.searchSpec
2140
2276
  });
@@ -2153,14 +2289,13 @@ function bfldsWithResolver(resolver) {
2153
2289
  }
2154
2290
  function beqsWithResolver(resolver) {
2155
2291
  const name = "xbbg_beqs";
2156
- return tools.tool(
2292
+ return createBloombergStructuredTool(
2157
2293
  async (input) => {
2158
2294
  try {
2159
2295
  const engine = await resolver.getEngine();
2160
2296
  const result = await engine.beqs(input.screen, {
2161
2297
  asof: input.asof,
2162
2298
  backend: "json",
2163
- format: input.format,
2164
2299
  group: input.group,
2165
2300
  kwargs: input.kwargs,
2166
2301
  overrides: input.overrides,
@@ -2181,7 +2316,7 @@ function beqsWithResolver(resolver) {
2181
2316
  }
2182
2317
  function yasWithResolver(resolver) {
2183
2318
  const name = "xbbg_yas";
2184
- return tools.tool(
2319
+ return createBloombergStructuredTool(
2185
2320
  async (input) => {
2186
2321
  try {
2187
2322
  const engine = await resolver.getEngine();
@@ -2209,7 +2344,7 @@ function yasWithResolver(resolver) {
2209
2344
  }
2210
2345
  function preferredsWithResolver(resolver) {
2211
2346
  const name = "xbbg_preferreds";
2212
- return tools.tool(
2347
+ return createBloombergStructuredTool(
2213
2348
  async (input) => {
2214
2349
  try {
2215
2350
  const engine = await resolver.getEngine();
@@ -2232,7 +2367,7 @@ function preferredsWithResolver(resolver) {
2232
2367
  }
2233
2368
  function corporateBondsWithResolver(resolver) {
2234
2369
  const name = "xbbg_corporate_bonds";
2235
- return tools.tool(
2370
+ return createBloombergStructuredTool(
2236
2371
  async (input) => {
2237
2372
  try {
2238
2373
  const engine = await resolver.getEngine();
@@ -2257,7 +2392,7 @@ function corporateBondsWithResolver(resolver) {
2257
2392
  }
2258
2393
  function indexMembersWithResolver(resolver) {
2259
2394
  const name = "xbbg_index_members";
2260
- return tools.tool(
2395
+ return createBloombergStructuredTool(
2261
2396
  async (input) => {
2262
2397
  try {
2263
2398
  const engine = await resolver.getEngine();
@@ -2281,7 +2416,7 @@ function indexMembersWithResolver(resolver) {
2281
2416
  }
2282
2417
  function resolveIsinsWithResolver(resolver) {
2283
2418
  const name = "xbbg_resolve_isins";
2284
- return tools.tool(
2419
+ return createBloombergStructuredTool(
2285
2420
  async (input) => {
2286
2421
  try {
2287
2422
  const engine = await resolver.getEngine();
@@ -2301,7 +2436,7 @@ function resolveIsinsWithResolver(resolver) {
2301
2436
  }
2302
2437
  function issuerIsinsWithResolver(resolver) {
2303
2438
  const name = "xbbg_issuer_isins";
2304
- return tools.tool(
2439
+ return createBloombergStructuredTool(
2305
2440
  async (input) => {
2306
2441
  try {
2307
2442
  const engine = await resolver.getEngine();
@@ -2321,7 +2456,7 @@ function issuerIsinsWithResolver(resolver) {
2321
2456
  }
2322
2457
  function etfHoldingsWithResolver(resolver) {
2323
2458
  const name = "xbbg_etf_holdings";
2324
- return tools.tool(
2459
+ return createBloombergStructuredTool(
2325
2460
  async (input) => {
2326
2461
  try {
2327
2462
  const engine = await resolver.getEngine();
@@ -2344,12 +2479,14 @@ function etfHoldingsWithResolver(resolver) {
2344
2479
  }
2345
2480
  function streamSnapshotWithResolver(resolver) {
2346
2481
  const name = "xbbg_stream_snapshot";
2347
- return tools.tool(
2348
- async (input) => {
2482
+ return createBloombergStructuredTool(
2483
+ async (input, config) => {
2484
+ const signal = config?.signal;
2349
2485
  try {
2350
2486
  const engine = await resolver.getEngine();
2487
+ signal?.throwIfAborted();
2351
2488
  const subscription = await engine.stream(input.tickers, input.fields, streamOptions(input));
2352
- const result = await collectSnapshot(subscription, input);
2489
+ const result = await collectSnapshot(subscription, input, signal);
2353
2490
  return resultString2(resolver, name, result);
2354
2491
  } catch (error) {
2355
2492
  throwWithToolContext(name, error);
@@ -2365,12 +2502,14 @@ function streamSnapshotWithResolver(resolver) {
2365
2502
  }
2366
2503
  function mktbarSnapshotWithResolver(resolver) {
2367
2504
  const name = "xbbg_mktbar_snapshot";
2368
- return tools.tool(
2369
- async (input) => {
2505
+ return createBloombergStructuredTool(
2506
+ async (input, config) => {
2507
+ const signal = config?.signal;
2370
2508
  try {
2371
2509
  const engine = await resolver.getEngine();
2372
- const subscription = await engine.mktbar(input.ticker, streamOptions(input));
2373
- 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);
2374
2513
  return resultString2(resolver, name, result);
2375
2514
  } catch (error) {
2376
2515
  throwWithToolContext(name, error);
@@ -2386,12 +2525,14 @@ function mktbarSnapshotWithResolver(resolver) {
2386
2525
  }
2387
2526
  function depthSnapshotWithResolver(resolver) {
2388
2527
  const name = "xbbg_depth_snapshot";
2389
- return tools.tool(
2390
- async (input) => {
2528
+ return createBloombergStructuredTool(
2529
+ async (input, config) => {
2530
+ const signal = config?.signal;
2391
2531
  try {
2392
2532
  const engine = await resolver.getEngine();
2393
- const subscription = await engine.depth(input.ticker, streamOptions(input));
2394
- 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);
2395
2536
  return resultString2(resolver, name, result);
2396
2537
  } catch (error) {
2397
2538
  throwWithToolContext(name, error);
@@ -2465,29 +2606,32 @@ function createMktbarSnapshotTool(options = {}) {
2465
2606
  function createDepthSnapshotTool(options = {}) {
2466
2607
  return depthSnapshotWithResolver(createCoreResolver(options));
2467
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
+ ]);
2468
2631
  function createBloombergToolsForResolver(resolver) {
2469
- return [
2470
- ...enabledTool(resolver, "xbbg_bdp", bdpWithResolver),
2471
- ...enabledTool(resolver, "xbbg_bdh", bdhWithResolver),
2472
- ...enabledTool(resolver, "xbbg_bds", bdsWithResolver),
2473
- ...enabledTool(resolver, "xbbg_bdib", bdibWithResolver),
2474
- ...enabledTool(resolver, "xbbg_bdtick", bdtickWithResolver),
2475
- ...enabledTool(resolver, "xbbg_bql", bqlWithResolver),
2476
- ...enabledTool(resolver, "xbbg_bsrch", bsrchWithResolver),
2477
- ...enabledTool(resolver, "xbbg_bqr", bqrWithResolver),
2478
- ...enabledTool(resolver, "xbbg_bflds", bfldsWithResolver),
2479
- ...enabledTool(resolver, "xbbg_beqs", beqsWithResolver),
2480
- ...enabledTool(resolver, "xbbg_yas", yasWithResolver),
2481
- ...enabledTool(resolver, "xbbg_preferreds", preferredsWithResolver),
2482
- ...enabledTool(resolver, "xbbg_corporate_bonds", corporateBondsWithResolver),
2483
- ...enabledTool(resolver, "xbbg_index_members", indexMembersWithResolver),
2484
- ...enabledTool(resolver, "xbbg_resolve_isins", resolveIsinsWithResolver),
2485
- ...enabledTool(resolver, "xbbg_issuer_isins", issuerIsinsWithResolver),
2486
- ...enabledTool(resolver, "xbbg_etf_holdings", etfHoldingsWithResolver),
2487
- ...enabledTool(resolver, "xbbg_stream_snapshot", streamSnapshotWithResolver),
2488
- ...enabledTool(resolver, "xbbg_mktbar_snapshot", mktbarSnapshotWithResolver),
2489
- ...enabledTool(resolver, "xbbg_depth_snapshot", depthSnapshotWithResolver)
2490
- ];
2632
+ return CORE_TOOL_DEFINITIONS.filter(
2633
+ (definition) => !isToolDisabled(resolver.options, definition.name)
2634
+ ).map((definition) => definition.create(resolver));
2491
2635
  }
2492
2636
  function createBloombergTools(options = {}) {
2493
2637
  return createBloombergToolsForResolver(createCoreResolver(options));
@@ -2505,6 +2649,7 @@ function createAllBloombergTools(options = {}) {
2505
2649
  exports.BLOOMBERG_EXT_TOOL_NAMES = BLOOMBERG_EXT_TOOL_NAMES;
2506
2650
  exports.BLOOMBERG_TOOL_INSTRUCTIONS = BLOOMBERG_TOOL_INSTRUCTIONS;
2507
2651
  exports.BLOOMBERG_TOOL_NAMES = BLOOMBERG_TOOL_NAMES;
2652
+ exports.DEFAULT_ENGINE_REQUEST_TIMEOUT_MS = DEFAULT_ENGINE_REQUEST_TIMEOUT_MS;
2508
2653
  exports.createAllBloombergTools = createAllBloombergTools;
2509
2654
  exports.createBdhTool = createBdhTool;
2510
2655
  exports.createBdibTool = createBdibTool;
@@ -2539,5 +2684,6 @@ exports.createResolveIsinsTool = createResolveIsinsTool;
2539
2684
  exports.createStreamSnapshotTool = createStreamSnapshotTool;
2540
2685
  exports.createYasTool = createYasTool;
2541
2686
  exports.getBloombergToolInstructions = getBloombergToolInstructions;
2687
+ exports.toolParameterJsonSchema = toolParameterJsonSchema;
2542
2688
  //# sourceMappingURL=index.js.map
2543
2689
  //# sourceMappingURL=index.js.map