edgar-cli 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,623 +0,0 @@
1
- import { mkdir, readFile, stat, writeFile } from 'node:fs/promises';
2
- import os from 'node:os';
3
- import path from 'node:path';
4
- import { runFilingsGet, runFilingsList } from './filings.js';
5
- import { CLIError, ErrorCode } from '../core/errors.js';
6
- import { resolveEntity } from '../sec/ticker-map.js';
7
- const PROFILE_RULES = {
8
- core: [
9
- { form: '10-K', queryLimit: 1 },
10
- { form: '10-Q', queryLimit: 3 },
11
- { form: '8-K', queryLimit: 12, recentDays: 180 }
12
- ],
13
- events: [{ form: '8-K', queryLimit: 24, recentDays: 365 }],
14
- financials: [
15
- { form: '10-K', queryLimit: 2 },
16
- { form: '10-Q', queryLimit: 6 }
17
- ]
18
- };
19
- function nowIso() {
20
- return new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
21
- }
22
- function formatDateUtc(date) {
23
- return date.toISOString().slice(0, 10);
24
- }
25
- function dateDaysAgo(days) {
26
- const date = new Date();
27
- date.setUTCDate(date.getUTCDate() - days);
28
- return formatDateUtc(date);
29
- }
30
- function defaultCacheRoot() {
31
- if (process.env.EDGAR_CACHE_DIR && process.env.EDGAR_CACHE_DIR.trim().length > 0) {
32
- return path.resolve(process.env.EDGAR_CACHE_DIR);
33
- }
34
- if (process.env.XDG_CACHE_HOME && process.env.XDG_CACHE_HOME.trim().length > 0) {
35
- return path.resolve(process.env.XDG_CACHE_HOME, 'edgar-cli');
36
- }
37
- return path.resolve(os.homedir(), '.cache', 'edgar-cli');
38
- }
39
- function resolveCacheRoot(cacheDir) {
40
- if (cacheDir && cacheDir.trim().length > 0) {
41
- return path.resolve(cacheDir);
42
- }
43
- return defaultCacheRoot();
44
- }
45
- function companyCacheDir(cacheRoot, cik) {
46
- return path.join(cacheRoot, 'research', 'companies', cik);
47
- }
48
- function profileManifestPath(cacheRoot, cik, profile) {
49
- return path.join(companyCacheDir(cacheRoot, cik), 'profiles', `${profile}.json`);
50
- }
51
- function filingDocPath(cacheRoot, cik, accession) {
52
- return path.join(companyCacheDir(cacheRoot, cik), 'filings', `${accession}.md`);
53
- }
54
- function parseCachedManifest(value) {
55
- if (!value || typeof value !== 'object') {
56
- throw new CLIError(ErrorCode.PARSE_ERROR, 'Cached manifest is malformed');
57
- }
58
- const manifest = value;
59
- if (manifest.version !== 1 ||
60
- typeof manifest.cik !== 'string' ||
61
- !Array.isArray(manifest.docs) ||
62
- !manifest.docs.every((doc) => doc && typeof doc.path === 'string' && typeof doc.accession === 'string')) {
63
- throw new CLIError(ErrorCode.PARSE_ERROR, 'Cached manifest is malformed');
64
- }
65
- return manifest;
66
- }
67
- async function readCachedManifest(cacheRoot, cik, profile) {
68
- const manifestPath = profileManifestPath(cacheRoot, cik, profile);
69
- let raw;
70
- try {
71
- raw = await readFile(manifestPath, 'utf8');
72
- }
73
- catch (error) {
74
- const err = error;
75
- if (err.code === 'ENOENT') {
76
- return null;
77
- }
78
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Unable to read cached manifest ${manifestPath}: ${err.message}`);
79
- }
80
- let parsed;
81
- try {
82
- parsed = JSON.parse(raw);
83
- }
84
- catch {
85
- throw new CLIError(ErrorCode.PARSE_ERROR, `Cached manifest is not valid JSON: ${manifestPath}`);
86
- }
87
- return parseCachedManifest(parsed);
88
- }
89
- async function writeCachedManifest(cacheRoot, manifest) {
90
- const manifestPath = profileManifestPath(cacheRoot, manifest.cik, manifest.profile);
91
- await mkdir(path.dirname(manifestPath), { recursive: true });
92
- await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
93
- return { manifestPath };
94
- }
95
- async function fileExists(filePath) {
96
- try {
97
- const fileStat = await stat(filePath);
98
- return fileStat.isFile();
99
- }
100
- catch (error) {
101
- const err = error;
102
- if (err.code === 'ENOENT') {
103
- return false;
104
- }
105
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Unable to stat ${filePath}: ${err.message}`);
106
- }
107
- }
108
- export function parseResearchProfile(value) {
109
- const normalized = value.trim().toLowerCase();
110
- if (normalized === 'core' || normalized === 'events' || normalized === 'financials') {
111
- return normalized;
112
- }
113
- throw new CLIError(ErrorCode.VALIDATION_ERROR, '--profile must be one of core|events|financials');
114
- }
115
- function tokenize(value) {
116
- return (value.toLowerCase().match(/[a-z0-9]+/g) ?? []).filter((token) => token.length >= 2);
117
- }
118
- const QUERY_STOPWORDS = new Set([
119
- 'a',
120
- 'an',
121
- 'and',
122
- 'are',
123
- 'as',
124
- 'at',
125
- 'be',
126
- 'by',
127
- 'for',
128
- 'from',
129
- 'how',
130
- 'in',
131
- 'into',
132
- 'is',
133
- 'it',
134
- 'its',
135
- 'of',
136
- 'on',
137
- 'or',
138
- 'that',
139
- 'the',
140
- 'their',
141
- 'there',
142
- 'these',
143
- 'they',
144
- 'this',
145
- 'to',
146
- 'was',
147
- 'were',
148
- 'what',
149
- 'when',
150
- 'where',
151
- 'which',
152
- 'who',
153
- 'why',
154
- 'with'
155
- ]);
156
- const COVER_BOILERPLATE_PATTERNS = [
157
- /securities registered pursuant to section 12\(b\)/i,
158
- /indicate by check mark/i,
159
- /commission file number/i,
160
- /for the quarterly period ended/i,
161
- /for the fiscal year ended/i
162
- ];
163
- function uniqueTokens(tokens) {
164
- return [...new Set(tokens)];
165
- }
166
- function buildQueryTerms(query) {
167
- const rawTokens = tokenize(query);
168
- const filtered = rawTokens.filter((token) => !QUERY_STOPWORDS.has(token));
169
- const terms = filtered.length > 0 ? filtered : rawTokens;
170
- return uniqueTokens(terms);
171
- }
172
- function buildQueryBigrams(queryTerms) {
173
- const bigrams = [];
174
- for (let idx = 0; idx < queryTerms.length - 1; idx += 1) {
175
- bigrams.push(`${queryTerms[idx]} ${queryTerms[idx + 1]}`);
176
- }
177
- return uniqueTokens(bigrams);
178
- }
179
- function countTermHits(queryTerms, termFrequency) {
180
- return queryTerms.reduce((hits, term) => hits + ((termFrequency.get(term) ?? 0) > 0 ? 1 : 0), 0);
181
- }
182
- function countBigramHits(chunkText, queryBigrams) {
183
- if (queryBigrams.length === 0) {
184
- return 0;
185
- }
186
- const text = chunkText.toLowerCase();
187
- return queryBigrams.reduce((hits, bigram) => hits + (text.includes(bigram) ? 1 : 0), 0);
188
- }
189
- function looksLikeCoverBoilerplate(chunk) {
190
- if (chunk.lineStart > 140) {
191
- return false;
192
- }
193
- return COVER_BOILERPLATE_PATTERNS.some((pattern) => pattern.test(chunk.text));
194
- }
195
- function buildTermFrequency(tokens) {
196
- const frequency = new Map();
197
- for (const token of tokens) {
198
- frequency.set(token, (frequency.get(token) ?? 0) + 1);
199
- }
200
- return frequency;
201
- }
202
- function extractAccession(docPath) {
203
- const match = docPath.match(/\d{10}-\d{2}-\d{6}/);
204
- return match?.[0] ?? null;
205
- }
206
- function parseManifest(value) {
207
- if (Array.isArray(value) && value.every((entry) => typeof entry === 'string')) {
208
- return { docs: value };
209
- }
210
- if (value &&
211
- typeof value === 'object' &&
212
- Array.isArray(value.docs) &&
213
- value.docs.every((entry) => typeof entry === 'string')) {
214
- return { docs: value.docs };
215
- }
216
- throw new CLIError(ErrorCode.VALIDATION_ERROR, 'Manifest must be a JSON array of strings or object with a docs string array');
217
- }
218
- async function loadDocPaths(params) {
219
- const fromOptions = params.docs.map((docPath) => docPath.trim()).filter((docPath) => docPath.length > 0);
220
- const fromManifest = [];
221
- if (params.manifestPath) {
222
- const resolvedManifestPath = path.resolve(params.manifestPath);
223
- let manifestRaw;
224
- try {
225
- manifestRaw = await readFile(resolvedManifestPath, 'utf8');
226
- }
227
- catch (error) {
228
- const err = error;
229
- if (err.code === 'ENOENT') {
230
- throw new CLIError(ErrorCode.NOT_FOUND, `Manifest not found: ${resolvedManifestPath}`);
231
- }
232
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Unable to read manifest ${resolvedManifestPath}: ${err.message}`);
233
- }
234
- let manifestJson;
235
- try {
236
- manifestJson = JSON.parse(manifestRaw);
237
- }
238
- catch {
239
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Manifest is not valid JSON: ${resolvedManifestPath}`);
240
- }
241
- const parsed = parseManifest(manifestJson);
242
- fromManifest.push(...parsed.docs.map((docPath) => docPath.trim()).filter((docPath) => docPath.length > 0));
243
- }
244
- const resolved = [...fromOptions, ...fromManifest].map((docPath) => path.resolve(docPath));
245
- return [...new Set(resolved)];
246
- }
247
- async function ensureReadableTextFile(filePath) {
248
- let fileStat;
249
- try {
250
- fileStat = await stat(filePath);
251
- }
252
- catch (error) {
253
- const err = error;
254
- if (err.code === 'ENOENT') {
255
- throw new CLIError(ErrorCode.NOT_FOUND, `Document not found: ${filePath}`);
256
- }
257
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Unable to stat document ${filePath}: ${err.message}`);
258
- }
259
- if (!fileStat.isFile()) {
260
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Path is not a file: ${filePath}`);
261
- }
262
- let content;
263
- try {
264
- content = await readFile(filePath, 'utf8');
265
- }
266
- catch (error) {
267
- const err = error;
268
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `Unable to read document ${filePath}: ${err.message}`);
269
- }
270
- if (content.includes('\u0000')) {
271
- throw new CLIError(ErrorCode.VALIDATION_ERROR, `File appears to be binary: ${filePath}`);
272
- }
273
- return content;
274
- }
275
- function chunkDocument(params) {
276
- const lines = params.content.split(/\r?\n/);
277
- const step = Math.max(1, params.chunkLines - params.chunkOverlap);
278
- const chunks = [];
279
- const accession = extractAccession(params.docPath);
280
- for (let lineIdx = 0; lineIdx < lines.length; lineIdx += step) {
281
- const start = lineIdx;
282
- const endExclusive = Math.min(lines.length, start + params.chunkLines);
283
- const chunkLines = lines.slice(start, endExclusive);
284
- const text = chunkLines.join('\n').trim();
285
- if (text.length === 0) {
286
- if (endExclusive >= lines.length) {
287
- break;
288
- }
289
- continue;
290
- }
291
- const tokens = tokenize(text);
292
- chunks.push({
293
- docPath: params.docPath,
294
- accession,
295
- lineStart: start + 1,
296
- lineEnd: endExclusive,
297
- text,
298
- tokenCount: tokens.length,
299
- termFrequency: buildTermFrequency(tokens)
300
- });
301
- if (endExclusive >= lines.length) {
302
- break;
303
- }
304
- }
305
- return chunks;
306
- }
307
- function bm25Score(params) {
308
- const k1 = 1.2;
309
- const b = 0.75;
310
- return params.queryTerms.reduce((score, term) => {
311
- const tf = params.chunk.termFrequency.get(term) ?? 0;
312
- if (tf === 0) {
313
- return score;
314
- }
315
- const df = params.docFrequencyByTerm.get(term) ?? 0;
316
- const idf = Math.log(1 + (params.totalChunkCount - df + 0.5) / (df + 0.5));
317
- const normalizedLength = params.averageChunkLength > 0 ? params.chunk.tokenCount / params.averageChunkLength : 1;
318
- const denominator = tf + k1 * (1 - b + b * normalizedLength);
319
- const termScore = idf * ((tf * (k1 + 1)) / denominator);
320
- return score + termScore;
321
- }, 0);
322
- }
323
- function adjustedChunkScore(params) {
324
- if (params.baseScore <= 0) {
325
- return 0;
326
- }
327
- const termHits = countTermHits(params.queryTerms, params.chunk.termFrequency);
328
- if (params.queryTerms.length >= 3 && termHits < 2) {
329
- return 0;
330
- }
331
- const coverage = termHits / Math.max(1, params.queryTerms.length);
332
- const bigramHits = countBigramHits(params.chunk.text, params.queryBigrams);
333
- let multiplier = 1;
334
- if (coverage >= 1) {
335
- multiplier *= 1.25;
336
- }
337
- else if (coverage >= 0.7) {
338
- multiplier *= 1.15;
339
- }
340
- else if (coverage >= 0.5) {
341
- multiplier *= 1.08;
342
- }
343
- else if (params.queryTerms.length >= 3 && coverage <= 0.25) {
344
- multiplier *= 0.8;
345
- }
346
- if (bigramHits > 0) {
347
- multiplier *= 1 + Math.min(0.24, bigramHits * 0.08);
348
- }
349
- if (looksLikeCoverBoilerplate(params.chunk)) {
350
- multiplier *= 0.45;
351
- }
352
- return params.baseScore * multiplier;
353
- }
354
- function compactWhitespace(value) {
355
- return value.replace(/[ \t]+/g, ' ').replace(/\n{3,}/g, '\n\n').trim();
356
- }
357
- function trimExcerpt(value, maxChars) {
358
- if (value.length <= maxChars) {
359
- return value;
360
- }
361
- return `${value.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
362
- }
363
- async function runLexicalSearch(params) {
364
- const query = params.query.trim();
365
- if (query.length === 0) {
366
- throw new CLIError(ErrorCode.VALIDATION_ERROR, 'Query must not be empty');
367
- }
368
- if (params.chunkOverlap >= params.chunkLines) {
369
- throw new CLIError(ErrorCode.VALIDATION_ERROR, '--chunk-overlap must be less than --chunk-lines');
370
- }
371
- const docs = await Promise.all(params.docPaths.map(async (docPath) => {
372
- const content = await ensureReadableTextFile(docPath);
373
- return {
374
- path: docPath,
375
- bytes: Buffer.byteLength(content, 'utf8'),
376
- lineCount: content.split(/\r?\n/).length,
377
- chunks: chunkDocument({
378
- docPath,
379
- content,
380
- chunkLines: params.chunkLines,
381
- chunkOverlap: params.chunkOverlap
382
- })
383
- };
384
- }));
385
- const allChunks = docs.flatMap((doc) => doc.chunks);
386
- if (allChunks.length === 0) {
387
- return {
388
- data: {
389
- query,
390
- backend: 'lexical',
391
- docs: docs.map((doc) => ({
392
- path: doc.path,
393
- bytes: doc.bytes,
394
- line_count: doc.lineCount
395
- })),
396
- result_count: 0,
397
- results: []
398
- }
399
- };
400
- }
401
- const queryTerms = buildQueryTerms(query);
402
- if (queryTerms.length === 0) {
403
- throw new CLIError(ErrorCode.VALIDATION_ERROR, 'Query must contain at least one alphanumeric token');
404
- }
405
- const queryBigrams = buildQueryBigrams(queryTerms);
406
- const docFrequencyByTerm = new Map();
407
- for (const term of queryTerms) {
408
- let count = 0;
409
- for (const chunk of allChunks) {
410
- if ((chunk.termFrequency.get(term) ?? 0) > 0) {
411
- count += 1;
412
- }
413
- }
414
- docFrequencyByTerm.set(term, count);
415
- }
416
- const averageChunkLength = allChunks.reduce((sum, chunk) => sum + chunk.tokenCount, 0) / Math.max(allChunks.length, 1);
417
- const scored = allChunks
418
- .map((chunk) => {
419
- const baseScore = bm25Score({
420
- queryTerms,
421
- chunk,
422
- docFrequencyByTerm,
423
- totalChunkCount: allChunks.length,
424
- averageChunkLength
425
- });
426
- return {
427
- chunk,
428
- score: adjustedChunkScore({
429
- chunk,
430
- baseScore,
431
- queryTerms,
432
- queryBigrams
433
- })
434
- };
435
- })
436
- .filter((item) => item.score > 0)
437
- .sort((a, b) => b.score - a.score)
438
- .slice(0, params.topK);
439
- return {
440
- data: {
441
- query,
442
- backend: 'lexical',
443
- query_terms: queryTerms,
444
- docs: docs.map((doc) => ({
445
- path: doc.path,
446
- bytes: doc.bytes,
447
- line_count: doc.lineCount
448
- })),
449
- chunk_count: allChunks.length,
450
- result_count: scored.length,
451
- results: scored.map((item, idx) => ({
452
- rank: idx + 1,
453
- score: Number(item.score.toFixed(6)),
454
- path: item.chunk.docPath,
455
- accession: item.chunk.accession,
456
- line_start: item.chunk.lineStart,
457
- line_end: item.chunk.lineEnd,
458
- excerpt: trimExcerpt(compactWhitespace(item.chunk.text), 1200)
459
- }))
460
- }
461
- };
462
- }
463
- export async function runResearchSync(params, context) {
464
- const entity = await resolveEntity(params.id, context.secClient, { strictMapMatch: false });
465
- const cacheRoot = resolveCacheRoot(params.cacheDir);
466
- const rules = PROFILE_RULES[params.profile];
467
- const selectedByAccession = new Map();
468
- for (const rule of rules) {
469
- const listResult = await runFilingsList({
470
- id: entity.cik,
471
- form: rule.form,
472
- from: rule.recentDays ? dateDaysAgo(rule.recentDays) : undefined,
473
- queryLimit: rule.queryLimit
474
- }, context);
475
- const rows = listResult.data;
476
- for (const row of rows) {
477
- if (!selectedByAccession.has(row.accession)) {
478
- selectedByAccession.set(row.accession, row);
479
- }
480
- }
481
- }
482
- const selectedRows = [...selectedByAccession.values()].sort((a, b) => (b.filingDate ?? '').localeCompare(a.filingDate ?? ''));
483
- const docs = [];
484
- const skipped = [];
485
- let fetchedCount = 0;
486
- let reusedCount = 0;
487
- for (const row of selectedRows) {
488
- const docPath = filingDocPath(cacheRoot, entity.cik, row.accession);
489
- const shouldUseCache = !params.refresh && (await fileExists(docPath));
490
- if (!shouldUseCache) {
491
- try {
492
- const filingResult = await runFilingsGet({
493
- id: entity.cik,
494
- accession: row.accession,
495
- format: 'markdown'
496
- }, context);
497
- const filingData = filingResult.data;
498
- if (typeof filingData.content !== 'string') {
499
- throw new CLIError(ErrorCode.PARSE_ERROR, `Unable to parse markdown content for accession ${row.accession}`);
500
- }
501
- await mkdir(path.dirname(docPath), { recursive: true });
502
- const content = filingData.content.endsWith('\n') ? filingData.content : `${filingData.content}\n`;
503
- await writeFile(docPath, content, 'utf8');
504
- fetchedCount += 1;
505
- }
506
- catch (error) {
507
- if (error instanceof CLIError && error.code === ErrorCode.NOT_FOUND) {
508
- skipped.push({ accession: row.accession, reason: error.message });
509
- continue;
510
- }
511
- throw error;
512
- }
513
- }
514
- else {
515
- reusedCount += 1;
516
- }
517
- docs.push({
518
- accession: row.accession,
519
- form: row.form,
520
- filing_date: row.filingDate,
521
- report_date: row.reportDate,
522
- filing_url: row.filingUrl,
523
- path: docPath
524
- });
525
- }
526
- const manifest = {
527
- version: 1,
528
- id_input: params.id,
529
- cik: entity.cik,
530
- ticker: entity.ticker,
531
- title: entity.title,
532
- profile: params.profile,
533
- synced_at: nowIso(),
534
- docs
535
- };
536
- const { manifestPath } = await writeCachedManifest(cacheRoot, manifest);
537
- return {
538
- data: {
539
- id: params.id,
540
- cik: entity.cik,
541
- ticker: entity.ticker,
542
- title: entity.title,
543
- profile: params.profile,
544
- cache_root: cacheRoot,
545
- manifest_path: manifestPath,
546
- docs_count: docs.length,
547
- fetched_count: fetchedCount,
548
- reused_count: reusedCount,
549
- skipped_count: skipped.length,
550
- skipped,
551
- docs
552
- }
553
- };
554
- }
555
- export async function runResearchAsk(params, context) {
556
- void context;
557
- const docPaths = await loadDocPaths({ docs: params.docs, manifestPath: params.manifestPath });
558
- if (docPaths.length === 0) {
559
- throw new CLIError(ErrorCode.DOCS_REQUIRED, 'At least one document is required. Pass --doc <path> and/or --manifest <path>.');
560
- }
561
- return runLexicalSearch({
562
- query: params.query,
563
- docPaths,
564
- topK: params.topK,
565
- chunkLines: params.chunkLines,
566
- chunkOverlap: params.chunkOverlap
567
- });
568
- }
569
- export async function runResearchAskById(params, context) {
570
- const cacheRoot = resolveCacheRoot(params.cacheDir);
571
- const entity = await resolveEntity(params.id, context.secClient, { strictMapMatch: false });
572
- let manifest = !params.refresh
573
- ? await readCachedManifest(cacheRoot, entity.cik, params.profile)
574
- : null;
575
- let syncData = null;
576
- if (!manifest || manifest.docs.length === 0) {
577
- const syncResult = await runResearchSync({
578
- id: params.id,
579
- profile: params.profile,
580
- cacheDir: params.cacheDir,
581
- refresh: params.refresh
582
- }, context);
583
- const syncPayload = syncResult.data;
584
- syncData = {
585
- fetched_count: typeof syncPayload.fetched_count === 'number' ? syncPayload.fetched_count : 0,
586
- reused_count: typeof syncPayload.reused_count === 'number' ? syncPayload.reused_count : 0,
587
- docs_count: typeof syncPayload.docs_count === 'number' ? syncPayload.docs_count : 0,
588
- skipped_count: typeof syncPayload.skipped_count === 'number' ? syncPayload.skipped_count : 0
589
- };
590
- manifest = await readCachedManifest(cacheRoot, entity.cik, params.profile);
591
- }
592
- if (!manifest || manifest.docs.length === 0) {
593
- throw new CLIError(ErrorCode.DOCS_REQUIRED, `No cached documents found for ${params.id} profile ${params.profile}. Run research sync first.`);
594
- }
595
- const docPaths = manifest.docs.map((doc) => doc.path);
596
- const searchResult = await runLexicalSearch({
597
- query: params.query,
598
- docPaths,
599
- topK: params.topK,
600
- chunkLines: params.chunkLines,
601
- chunkOverlap: params.chunkOverlap
602
- });
603
- const searchData = searchResult.data;
604
- return {
605
- data: {
606
- ...searchData,
607
- id: params.id,
608
- cik: entity.cik,
609
- ticker: entity.ticker,
610
- title: entity.title,
611
- profile: params.profile,
612
- cache_root: cacheRoot,
613
- manifest_path: profileManifestPath(cacheRoot, entity.cik, params.profile),
614
- corpus_docs_count: manifest.docs.length,
615
- sync: syncData ?? {
616
- fetched_count: 0,
617
- reused_count: manifest.docs.length,
618
- docs_count: manifest.docs.length,
619
- skipped_count: 0
620
- }
621
- }
622
- };
623
- }
@@ -1,2 +0,0 @@
1
- import { CommandContext, CommandResult } from '../core/runtime.js';
2
- export declare function runResolve(id: string, context: CommandContext): Promise<CommandResult>;
@@ -1,7 +0,0 @@
1
- import { resolveEntity } from '../sec/ticker-map.js';
2
- export async function runResolve(id, context) {
3
- const entity = await resolveEntity(id, context.secClient, { strictMapMatch: true });
4
- return {
5
- data: entity
6
- };
7
- }
@@ -1,23 +0,0 @@
1
- export interface RuntimeOptions {
2
- jsonMode: boolean;
3
- humanMode: boolean;
4
- view: 'summary' | 'full';
5
- fields?: string[];
6
- limit?: number;
7
- verbose: boolean;
8
- userAgent?: string;
9
- }
10
- export interface RuntimeInput {
11
- json?: boolean;
12
- human?: boolean;
13
- view?: string;
14
- fields?: string;
15
- limit?: string | number;
16
- verbose?: boolean;
17
- userAgent?: string;
18
- }
19
- export declare function buildRuntimeOptions(input: RuntimeInput, env: NodeJS.ProcessEnv): RuntimeOptions;
20
- export declare function requireUserAgent(userAgent: string | undefined): string;
21
- export declare function parsePositiveInt(value: string, argName: string): number;
22
- export declare function parseNonNegativeInt(value: string, argName: string): number;
23
- export declare function parseDateString(value: string, argName: string): string;