@quantbrasil/cli 0.1.0-beta.7 → 0.1.0-beta.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +12 -0
  2. package/dist/cli/index.d.ts +8 -2
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +22 -3
  5. package/dist/cli/prompt.d.ts +1 -0
  6. package/dist/cli/prompt.d.ts.map +1 -1
  7. package/dist/cli/prompt.js +17 -0
  8. package/dist/cli/skills.d.ts +9 -0
  9. package/dist/cli/skills.d.ts.map +1 -1
  10. package/dist/cli/skills.js +68 -4
  11. package/dist/commands/rankings.d.ts +82 -0
  12. package/dist/commands/rankings.d.ts.map +1 -0
  13. package/dist/commands/rankings.js +202 -0
  14. package/dist/commands/screening.d.ts +44 -0
  15. package/dist/commands/screening.d.ts.map +1 -1
  16. package/dist/commands/screening.js +63 -0
  17. package/dist/commands/skills.js +7 -7
  18. package/dist/commands/update.d.ts +23 -0
  19. package/dist/commands/update.d.ts.map +1 -0
  20. package/dist/commands/update.js +209 -0
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -0
  24. package/dist/vendor/core/capabilities/index.d.ts +1 -0
  25. package/dist/vendor/core/capabilities/index.d.ts.map +1 -1
  26. package/dist/vendor/core/capabilities/index.js +1 -0
  27. package/dist/vendor/core/capabilities/rankings.d.ts +83 -0
  28. package/dist/vendor/core/capabilities/rankings.d.ts.map +1 -0
  29. package/dist/vendor/core/capabilities/rankings.js +95 -0
  30. package/dist/vendor/core/capabilities/registry.d.ts +216 -0
  31. package/dist/vendor/core/capabilities/registry.d.ts.map +1 -1
  32. package/dist/vendor/core/capabilities/registry.js +2 -0
  33. package/dist/vendor/core/capabilities/screening.d.ts +27 -0
  34. package/dist/vendor/core/capabilities/screening.d.ts.map +1 -1
  35. package/dist/vendor/core/capabilities/screening.js +31 -0
  36. package/dist/vendor/core/capabilities/types.d.ts +1 -1
  37. package/dist/vendor/core/capabilities/types.d.ts.map +1 -1
  38. package/package.json +3 -3
  39. package/skills/quantbrasil/SKILL.md +10 -5
  40. package/skills/quantbrasil/references/cli.md +26 -0
  41. package/skills/quantbrasil/references/costs.md +2 -0
  42. package/skills/quantbrasil/references/quality-eval-queries.json +5 -0
  43. package/skills/quantbrasil/references/rankings.md +60 -0
  44. package/skills/quantbrasil/references/screening.md +212 -0
  45. package/skills/quantbrasil/references/workflows.md +29 -3
package/README.md CHANGED
@@ -31,6 +31,7 @@ that file only exists inside this package.
31
31
  node ./bin/quantbrasil.js auth login --api-key qb_live_<id>.<secret>
32
32
  node ./bin/quantbrasil.js whoami
33
33
  node ./bin/quantbrasil.js skills install --all
34
+ node ./bin/quantbrasil.js update
34
35
  node ./bin/quantbrasil.js --status
35
36
  node ./bin/quantbrasil.js auth logout
36
37
  ```
@@ -72,7 +73,12 @@ quantbrasil holdings historical-return 182 --from 2025-01-01 --to 2026-01-01
72
73
  quantbrasil holdings historical-return 182 --period 1y
73
74
  quantbrasil holdings beta 182 --years 3
74
75
  quantbrasil holdings var 182 --years 1 --confidence 95
76
+ quantbrasil rankings list
77
+ quantbrasil rankings current --system momentum-90d --top 20
78
+ quantbrasil rankings current --system magic-formula --top 10
79
+ quantbrasil rankings current --user 123 --top 20
75
80
  quantbrasil screening universes
81
+ quantbrasil screening indicators
76
82
  quantbrasil screening run --system acoes-mais-liquidas --query-file ./screening.json
77
83
  quantbrasil screening run --watchlist 93 --query-file ./screening.json --limit 25
78
84
  cat ./screening.json | quantbrasil screening run --holding 182 --query-file -
@@ -144,8 +150,14 @@ quantbrasil init
144
150
  quantbrasil --status
145
151
  quantbrasil auth login --api-key qb_live_<id>.<secret>
146
152
  quantbrasil skills install --all
153
+ quantbrasil update
147
154
  ```
148
155
 
156
+ `quantbrasil update` checks the current global package against
157
+ `@quantbrasil/cli@beta`, checks whether the bundled skill is missing or stale,
158
+ shows the planned actions, and asks for confirmation before updating. Use
159
+ `quantbrasil update --yes` only in noninteractive automation.
160
+
149
161
  ## Publishing
150
162
 
151
163
  Publish from `monorepo/packages/cli`. The package build vendors the private
@@ -3,9 +3,11 @@ import { type CapabilitiesCommandIO, runCapabilitiesCommand } from "../commands/
3
3
  import { runMarketAssetsCommand, runMarketPriceCommand } from "../commands/market.js";
4
4
  import { runInitCommand } from "../commands/init.js";
5
5
  import { runHoldingCreateCommand, runHoldingBetaCommand, runHoldingGetCommand, runHoldingHistoricalReturnCommand, runHoldingListCommand, runHoldingRenameCommand, runHoldingSetPositionsCommand, runHoldingSetTargetsCommand, runHoldingVarCommand, runWatchlistAddAssetsCommand, runWatchlistCreateCommand, runWatchlistGetCommand, runWatchlistListCommand, runWatchlistRemoveAssetsCommand, runWatchlistRenameCommand } from "../commands/portfolios.js";
6
- import { runScreeningRunCommand, runScreeningUniversesCommand } from "../commands/screening.js";
6
+ import { runRankingsCurrentCommand, runRankingsListCommand } from "../commands/rankings.js";
7
+ import { runScreeningIndicatorsCommand, runScreeningRunCommand, runScreeningUniversesCommand } from "../commands/screening.js";
7
8
  import { runSkillsInstallCommand } from "../commands/skills.js";
8
9
  import { runStatusCommand } from "../commands/status.js";
10
+ import { runUpdateCommand, type UpdateCommandRunner } from "../commands/update.js";
9
11
  import { type TerminalWriter } from "./terminal.js";
10
12
  export interface CliProgramOptions {
11
13
  io?: CapabilitiesCommandIO;
@@ -15,6 +17,8 @@ export interface CliProgramOptions {
15
17
  now?: Date;
16
18
  stderr?: TerminalWriter;
17
19
  suppressCommanderErrors?: boolean;
20
+ updateCommandRunner?: UpdateCommandRunner;
21
+ currentVersion?: string;
18
22
  }
19
23
  export interface CliRunOptions extends CliProgramOptions {
20
24
  stderr?: TerminalWriter;
@@ -26,7 +30,9 @@ export { runAssetOverviewCommand } from "../commands/assets.js";
26
30
  export { runCapabilitiesCommand, runStatusCommand };
27
31
  export { runInitCommand };
28
32
  export { runMarketAssetsCommand, runMarketPriceCommand };
29
- export { runScreeningRunCommand, runScreeningUniversesCommand };
33
+ export { runRankingsCurrentCommand, runRankingsListCommand };
34
+ export { runScreeningIndicatorsCommand, runScreeningRunCommand, runScreeningUniversesCommand, };
30
35
  export { runHoldingBetaCommand, runHoldingCreateCommand, runHoldingGetCommand, runHoldingHistoricalReturnCommand, runHoldingListCommand, runHoldingRenameCommand, runHoldingSetPositionsCommand, runHoldingSetTargetsCommand, runHoldingVarCommand, runWatchlistAddAssetsCommand, runWatchlistCreateCommand, runWatchlistGetCommand, runWatchlistListCommand, runWatchlistRemoveAssetsCommand, runWatchlistRenameCommand, };
31
36
  export { runSkillsInstallCommand };
37
+ export { runUpdateCommand };
32
38
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,OAAO,EACL,KAAK,qBAAqB,EAE1B,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAGL,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,iCAAiC,EACjC,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,sBAAsB,EACtB,4BAA4B,EAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAQvE,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,qBAAqB,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAiEzE;AAeD,wBAAsB,GAAG,CACvB,IAAI,WAAe,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAoCD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,CAAC;AAChE,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,iCAAiC,EACjC,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,yBAAyB,GAC1B,CAAC;AACF,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,OAAO,EACL,KAAK,qBAAqB,EAE1B,sBAAsB,EACvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAGL,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,cAAc,EACf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,iCAAiC,EACjC,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,yBAAyB,EAC1B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAGL,yBAAyB,EACzB,sBAAsB,EACvB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAGL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,EAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,uBAAuB,EACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAGL,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,gBAAgB,EAEhB,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAO/B,OAAO,EAAqB,KAAK,cAAc,EAAE,MAAM,eAAe,CAAC;AAQvE,MAAM,WAAW,iBAAiB;IAChC,EAAE,CAAC,EAAE,qBAAqB,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAgFzE;AAeD,wBAAsB,GAAG,CACvB,IAAI,WAAe,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAoCD,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,CAAC;AAC7D,OAAO,EACL,6BAA6B,EAC7B,sBAAsB,EACtB,4BAA4B,GAC7B,CAAC;AACF,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,iCAAiC,EACjC,qBAAqB,EACrB,uBAAuB,EACvB,6BAA6B,EAC7B,2BAA2B,EAC3B,oBAAoB,EACpB,4BAA4B,EAC5B,yBAAyB,EACzB,sBAAsB,EACtB,uBAAuB,EACvB,+BAA+B,EAC/B,yBAAyB,GAC1B,CAAC;AACF,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
package/dist/cli/index.js CHANGED
@@ -6,9 +6,11 @@ import { registerCapabilitiesCommand, runCapabilitiesCommand, } from "../command
6
6
  import { registerMarketCommands, runMarketAssetsCommand, runMarketPriceCommand, } from "../commands/market.js";
7
7
  import { registerInitCommand, runInitCommand, } from "../commands/init.js";
8
8
  import { registerPortfoliosCommands, runHoldingCreateCommand, runHoldingBetaCommand, runHoldingGetCommand, runHoldingHistoricalReturnCommand, runHoldingListCommand, runHoldingRenameCommand, runHoldingSetPositionsCommand, runHoldingSetTargetsCommand, runHoldingVarCommand, runWatchlistAddAssetsCommand, runWatchlistCreateCommand, runWatchlistGetCommand, runWatchlistListCommand, runWatchlistRemoveAssetsCommand, runWatchlistRenameCommand, } from "../commands/portfolios.js";
9
- import { registerScreeningCommands, runScreeningRunCommand, runScreeningUniversesCommand, } from "../commands/screening.js";
9
+ import { registerRankingsCommands, runRankingsCurrentCommand, runRankingsListCommand, } from "../commands/rankings.js";
10
+ import { registerScreeningCommands, runScreeningIndicatorsCommand, runScreeningRunCommand, runScreeningUniversesCommand, } from "../commands/screening.js";
10
11
  import { registerSkillsCommands, runSkillsInstallCommand, } from "../commands/skills.js";
11
12
  import { registerStatusFlag, runStatusCommand, } from "../commands/status.js";
13
+ import { registerUpdateCommand, runUpdateCommand, } from "../commands/update.js";
12
14
  import { buildCliErrorPayload, formatCliErrorMessage, normalizeCliError, shouldEmitJsonError, } from "./errors.js";
13
15
  import { styleErrorMessage } from "./terminal.js";
14
16
  const requirePackage = createRequire(import.meta.url);
@@ -43,6 +45,11 @@ export function createCliProgram(options = {}) {
43
45
  fetch: options.fetch,
44
46
  now: options.now,
45
47
  };
48
+ const rankingsContext = {
49
+ io: options.io,
50
+ env: options.env,
51
+ fetch: options.fetch,
52
+ };
46
53
  const screeningContext = {
47
54
  io: options.io,
48
55
  env: options.env,
@@ -56,10 +63,18 @@ export function createCliProgram(options = {}) {
56
63
  io: options.io,
57
64
  env: options.env,
58
65
  };
66
+ const updateContext = {
67
+ io: options.io,
68
+ env: options.env,
69
+ prompt: options.prompt,
70
+ commandRunner: options.updateCommandRunner,
71
+ currentVersion: options.currentVersion ?? CLI_VERSION,
72
+ };
59
73
  program
60
74
  .name("quantbrasil")
61
- .description("Public QuantBrasil CLI for deterministic operations")
75
+ .description("CLI pública do QuantBrasil para operações determinísticas")
62
76
  .version(CLI_VERSION)
77
+ .helpOption("-h, --help", "Exibe ajuda do comando")
63
78
  .exitOverride()
64
79
  .showHelpAfterError()
65
80
  .showSuggestionAfterError();
@@ -71,8 +86,10 @@ export function createCliProgram(options = {}) {
71
86
  registerInitCommand(program, initContext);
72
87
  registerMarketCommands(program, marketContext);
73
88
  registerPortfoliosCommands(program, portfoliosContext);
89
+ registerRankingsCommands(program, rankingsContext);
74
90
  registerScreeningCommands(program, screeningContext);
75
91
  registerSkillsCommands(program, skillsContext);
92
+ registerUpdateCommand(program, updateContext);
76
93
  registerStatusFlag(program, statusContext);
77
94
  return program;
78
95
  }
@@ -138,6 +155,8 @@ export { runAssetOverviewCommand } from "../commands/assets.js";
138
155
  export { runCapabilitiesCommand, runStatusCommand };
139
156
  export { runInitCommand };
140
157
  export { runMarketAssetsCommand, runMarketPriceCommand };
141
- export { runScreeningRunCommand, runScreeningUniversesCommand };
158
+ export { runRankingsCurrentCommand, runRankingsListCommand };
159
+ export { runScreeningIndicatorsCommand, runScreeningRunCommand, runScreeningUniversesCommand, };
142
160
  export { runHoldingBetaCommand, runHoldingCreateCommand, runHoldingGetCommand, runHoldingHistoricalReturnCommand, runHoldingListCommand, runHoldingRenameCommand, runHoldingSetPositionsCommand, runHoldingSetTargetsCommand, runHoldingVarCommand, runWatchlistAddAssetsCommand, runWatchlistCreateCommand, runWatchlistGetCommand, runWatchlistListCommand, runWatchlistRemoveAssetsCommand, runWatchlistRenameCommand, };
143
161
  export { runSkillsInstallCommand };
162
+ export { runUpdateCommand };
@@ -1,2 +1,3 @@
1
1
  export declare function promptForSecret(promptLabel: string): Promise<string>;
2
+ export declare function promptForConfirmation(promptLabel: string): Promise<boolean>;
2
3
  //# sourceMappingURL=prompt.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/cli/prompt.ts"],"names":[],"mappings":"AAyBA,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB1E"}
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/cli/prompt.ts"],"names":[],"mappings":"AAyBA,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB1E;AAED,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAmBlB"}
@@ -38,3 +38,20 @@ export async function promptForSecret(promptLabel) {
38
38
  readline.close();
39
39
  }
40
40
  }
41
+ export async function promptForConfirmation(promptLabel) {
42
+ if (!input.isTTY || !output.isTTY) {
43
+ throw createCliConfigError("Confirmação interativa requer um TTY. Use --yes para aplicar a atualização.");
44
+ }
45
+ const readline = createInterface({
46
+ input,
47
+ output,
48
+ terminal: true,
49
+ });
50
+ try {
51
+ const answer = await readline.question(promptLabel);
52
+ return ["s", "sim", "y", "yes"].includes(answer.trim().toLowerCase());
53
+ }
54
+ finally {
55
+ readline.close();
56
+ }
57
+ }
@@ -20,7 +20,16 @@ export interface SkillInstallResult {
20
20
  installed: InstalledSkillTarget[];
21
21
  skipped: SkippedSkillTarget[];
22
22
  }
23
+ export type SkillInstallStatus = "current" | "missing" | "stale" | "skipped";
24
+ export interface SkillInstallTargetStatus extends SkillInstallTarget {
25
+ status: SkillInstallStatus;
26
+ }
27
+ export interface SkillInstallState {
28
+ targets: SkillInstallTargetStatus[];
29
+ needsInstall: boolean;
30
+ }
23
31
  export declare function installBundledSkillEverywhere(env?: NodeJS.ProcessEnv): Promise<SkillInstallResult>;
32
+ export declare function getBundledSkillInstallState(env?: NodeJS.ProcessEnv): Promise<SkillInstallState>;
24
33
  export declare function resolveSkillInstallTargets(env?: NodeJS.ProcessEnv): SkillInstallTarget[];
25
34
  export declare function resolveBundledSkillSourcePath(): string;
26
35
  //# sourceMappingURL=skills.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAcD,wBAAsB,6BAA6B,CACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAmD7B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,kBAAkB,EAAE,CAetB;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/cli/skills.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,sBAAsB,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,OAAO,EAAE,kBAAkB,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;AAE7E,MAAM,WAAW,wBAAyB,SAAQ,kBAAkB;IAClE,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,wBAAwB,EAAE,CAAC;IACpC,YAAY,EAAE,OAAO,CAAC;CACvB;AAcD,wBAAsB,6BAA6B,CACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,kBAAkB,CAAC,CAmD7B;AAED,wBAAsB,2BAA2B,CAC/C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAAC,iBAAiB,CAAC,CA0C5B;AAED,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,kBAAkB,EAAE,CAetB;AAED,wBAAgB,6BAA6B,IAAI,MAAM,CAEtD"}
@@ -1,4 +1,5 @@
1
- import { access, cp, mkdir, rm } from "node:fs/promises";
1
+ import { createHash } from "node:crypto";
2
+ import { access, cp, mkdir, readdir, readFile, rm } from "node:fs/promises";
2
3
  import { homedir } from "node:os";
3
4
  import { dirname, join } from "node:path";
4
5
  import { fileURLToPath } from "node:url";
@@ -45,13 +46,46 @@ export async function installBundledSkillEverywhere(env = process.env) {
45
46
  }
46
47
  if (installed.length === 0) {
47
48
  const checkedRoots = targets.map(target => target.rootDir).join(", ");
48
- throw createCliConfigError(`No supported agent clients detected. Checked: ${checkedRoots}.`);
49
+ throw createCliConfigError(`Nenhum cliente de agente compatível detectado. Verificados: ${checkedRoots}.`);
49
50
  }
50
51
  return {
51
52
  installed,
52
53
  skipped,
53
54
  };
54
55
  }
56
+ export async function getBundledSkillInstallState(env = process.env) {
57
+ const bundledSkillPath = resolveBundledSkillSourcePath();
58
+ await assertBundledSkillExists(bundledSkillPath);
59
+ const bundledHash = await hashDirectory(bundledSkillPath);
60
+ const targets = [];
61
+ for (const target of resolveSkillInstallTargets(env)) {
62
+ if (target.id !== AGENT_SKILLS_CONVENTION_ID &&
63
+ !(await pathExists(target.rootDir))) {
64
+ targets.push({
65
+ ...target,
66
+ status: "skipped",
67
+ });
68
+ continue;
69
+ }
70
+ if (!(await pathExists(join(target.installDir, "SKILL.md")))) {
71
+ targets.push({
72
+ ...target,
73
+ status: "missing",
74
+ });
75
+ continue;
76
+ }
77
+ targets.push({
78
+ ...target,
79
+ status: (await hashDirectory(target.installDir)) === bundledHash
80
+ ? "current"
81
+ : "stale",
82
+ });
83
+ }
84
+ return {
85
+ targets,
86
+ needsInstall: targets.some(target => target.status === "missing" || target.status === "stale"),
87
+ };
88
+ }
55
89
  export function resolveSkillInstallTargets(env = process.env) {
56
90
  const home = resolveCliHomeDirectory(env);
57
91
  return SUPPORTED_SKILL_CLIENTS.map(client => {
@@ -74,12 +108,42 @@ async function assertBundledSkillExists(skillPath) {
74
108
  if (await pathExists(skillEntryPath)) {
75
109
  return;
76
110
  }
77
- throw createCliConfigError(`Bundled QuantBrasil skill not found at ${skillEntryPath}. Reinstall the CLI package.`);
111
+ throw createCliConfigError(`Skill QuantBrasil empacotada não encontrada em ${skillEntryPath}. Reinstale o pacote da CLI.`);
112
+ }
113
+ async function hashDirectory(directory) {
114
+ const hash = createHash("sha256");
115
+ const files = await collectDirectoryFiles(directory);
116
+ for (const file of files) {
117
+ hash.update(file.relativePath);
118
+ hash.update("\0");
119
+ hash.update(await readFile(file.fullPath));
120
+ hash.update("\0");
121
+ }
122
+ return hash.digest("hex");
123
+ }
124
+ async function collectDirectoryFiles(current, relativePrefix = "") {
125
+ const entries = await readdir(current, { withFileTypes: true });
126
+ const sortedEntries = entries.sort((left, right) => left.name.localeCompare(right.name));
127
+ const files = [];
128
+ for (const entry of sortedEntries) {
129
+ const fullPath = join(current, entry.name);
130
+ const relativePath = relativePrefix
131
+ ? `${relativePrefix}/${entry.name}`
132
+ : entry.name;
133
+ if (entry.isDirectory()) {
134
+ files.push(...(await collectDirectoryFiles(fullPath, relativePath)));
135
+ continue;
136
+ }
137
+ if (entry.isFile()) {
138
+ files.push({ fullPath, relativePath });
139
+ }
140
+ }
141
+ return files;
78
142
  }
79
143
  function resolveCliHomeDirectory(env) {
80
144
  const home = env.HOME?.trim() || homedir();
81
145
  if (!home) {
82
- throw createCliConfigError("Could not resolve the HOME directory for skill install.");
146
+ throw createCliConfigError("Não foi possível resolver o diretório HOME para instalar a skill.");
83
147
  }
84
148
  return home;
85
149
  }
@@ -0,0 +1,82 @@
1
+ import { Command } from "commander";
2
+ import type { JsonValue } from "../vendor/core/index.js";
3
+ import { type CliInvokeContext } from "../cli/client.js";
4
+ import { type TerminalWriter } from "../cli/terminal.js";
5
+ export interface RankingsCommandIO {
6
+ stdout: TerminalWriter;
7
+ }
8
+ export interface RankingsListCommandOptions {
9
+ json?: boolean;
10
+ }
11
+ export interface RankingsCurrentCommandOptions {
12
+ system?: string;
13
+ user?: string;
14
+ top?: string;
15
+ json?: boolean;
16
+ }
17
+ export interface RankingMetricOut {
18
+ [key: string]: JsonValue;
19
+ key: string;
20
+ label: string;
21
+ direction: "asc" | "desc";
22
+ unit: string | null;
23
+ }
24
+ export interface RankingDefinitionOut {
25
+ [key: string]: JsonValue;
26
+ id: string;
27
+ name: string;
28
+ kind: "SYSTEM" | "USER";
29
+ description: string | null;
30
+ order_metric: RankingMetricOut;
31
+ metrics: RankingMetricOut[];
32
+ latest_as_of: string | null;
33
+ total_assets: number | null;
34
+ }
35
+ export interface RankingsListResponse {
36
+ [key: string]: JsonValue;
37
+ ok: boolean;
38
+ system: RankingDefinitionOut[];
39
+ user: RankingDefinitionOut[];
40
+ total: number;
41
+ }
42
+ export interface RankingMetricValueOut {
43
+ [key: string]: JsonValue;
44
+ key: string;
45
+ label: string;
46
+ value: string | number | boolean | null;
47
+ unit: string | null;
48
+ direction: "asc" | "desc";
49
+ }
50
+ export interface RankingCurrentRowOut {
51
+ [key: string]: JsonValue;
52
+ rank: number;
53
+ ticker: string;
54
+ name: string | null;
55
+ order_metric: RankingMetricValueOut;
56
+ score: number | null;
57
+ metrics: Record<string, string | number | boolean | null>;
58
+ }
59
+ export interface RankingCurrentResponse {
60
+ [key: string]: JsonValue;
61
+ ok: boolean;
62
+ summary_markdown: string;
63
+ ranking: RankingDefinitionOut;
64
+ as_of: string | null;
65
+ top_n: number;
66
+ count: number;
67
+ rows: RankingCurrentRowOut[];
68
+ }
69
+ export interface RankingsCommandContext extends CliInvokeContext {
70
+ io?: RankingsCommandIO;
71
+ }
72
+ type JsonRecord = {
73
+ [key: string]: JsonValue;
74
+ };
75
+ export declare function registerRankingsCommands(program: Command, context?: RankingsCommandContext): void;
76
+ export declare function runRankingsListCommand(options: RankingsListCommandOptions, context?: RankingsCommandContext): Promise<void>;
77
+ export declare function runRankingsCurrentCommand(options: RankingsCurrentCommandOptions, context?: RankingsCommandContext): Promise<void>;
78
+ export declare function buildRankingsCurrentInput(options: RankingsCurrentCommandOptions): JsonRecord;
79
+ export declare function formatRankingsListHuman(data: RankingsListResponse, theme?: import("../cli/terminal.js").TerminalTheme): string;
80
+ export declare function formatRankingCurrentHuman(data: RankingCurrentResponse, theme?: import("../cli/terminal.js").TerminalTheme): string;
81
+ export {};
82
+ //# sourceMappingURL=rankings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rankings.d.ts","sourceRoot":"","sources":["../../src/commands/rankings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,202 @@
1
+ import { invokeCliCapability } from "../cli/client.js";
2
+ import { createCliValidationError } from "../cli/errors.js";
3
+ import { createTerminalTheme } from "../cli/terminal.js";
4
+ export function registerRankingsCommands(program, context = {}) {
5
+ const rankingsCommand = program
6
+ .command("rankings")
7
+ .description("Consulta rankings do sistema e rankings do usuário");
8
+ rankingsCommand
9
+ .command("list")
10
+ .description("Lista rankings disponíveis")
11
+ .option("--json", "Exibe saída JSON")
12
+ .action(async (options) => {
13
+ await runRankingsListCommand(options, context);
14
+ });
15
+ rankingsCommand
16
+ .command("current")
17
+ .description("Consulta o topo atual de um ranking")
18
+ .option("--system <id>", "ID do ranking do sistema")
19
+ .option("--user <id>", "ID do ranking do usuário")
20
+ .option("--top <n>", "Número de ativos do topo do ranking", "20")
21
+ .option("--json", "Exibe saída JSON")
22
+ .action(async (options) => {
23
+ await runRankingsCurrentCommand(options, context);
24
+ });
25
+ }
26
+ export async function runRankingsListCommand(options, context = {}) {
27
+ const stdout = context.io?.stdout ?? process.stdout;
28
+ const theme = createTerminalTheme(stdout, context.env ?? process.env);
29
+ const response = await invokeCliCapability({
30
+ capability: "rankings.list",
31
+ env: context.env,
32
+ fetch: context.fetch,
33
+ });
34
+ if (options.json) {
35
+ stdout.write(`${JSON.stringify(response.data, null, 2)}\n`);
36
+ return;
37
+ }
38
+ stdout.write(`${formatRankingsListHuman(response.data, theme)}\n`);
39
+ }
40
+ export async function runRankingsCurrentCommand(options, context = {}) {
41
+ const stdout = context.io?.stdout ?? process.stdout;
42
+ const theme = createTerminalTheme(stdout, context.env ?? process.env);
43
+ const response = await invokeCliCapability({
44
+ capability: "rankings.current",
45
+ input: buildRankingsCurrentInput(options),
46
+ env: context.env,
47
+ fetch: context.fetch,
48
+ });
49
+ if (options.json) {
50
+ stdout.write(`${JSON.stringify(response.data, null, 2)}\n`);
51
+ return;
52
+ }
53
+ stdout.write(`${formatRankingCurrentHuman(response.data, theme)}\n`);
54
+ }
55
+ export function buildRankingsCurrentInput(options) {
56
+ const hasSystem = options.system !== undefined;
57
+ const hasUser = options.user !== undefined;
58
+ if (Number(hasSystem) + Number(hasUser) !== 1) {
59
+ throw createCliValidationError("Use exatamente um seletor: --system ou --user.");
60
+ }
61
+ const input = {
62
+ top_n: parseTopOption(options.top),
63
+ };
64
+ if (hasSystem) {
65
+ input.system_id = normalizeRequiredString(options.system, "--system");
66
+ }
67
+ if (hasUser) {
68
+ input.user_ranking_id = parsePositiveInteger(options.user, "--user");
69
+ }
70
+ return input;
71
+ }
72
+ export function formatRankingsListHuman(data, theme = createTerminalTheme(process.stdout)) {
73
+ const lines = [
74
+ theme.label("Rankings"),
75
+ "",
76
+ `${theme.label("Total:")} ${formatInteger(data.total)}`,
77
+ ];
78
+ lines.push("");
79
+ lines.push(...formatRankingGroup("Sistema", data.system, theme));
80
+ lines.push("");
81
+ lines.push(...formatRankingGroup("Meus rankings", data.user, theme));
82
+ return lines.join("\n");
83
+ }
84
+ export function formatRankingCurrentHuman(data, theme = createTerminalTheme(process.stdout)) {
85
+ const lines = [
86
+ theme.label("Ranking atual"),
87
+ "",
88
+ `${theme.bold(data.ranking.name)} ${theme.dim(`(${formatRankingKind(data.ranking.kind)})`)}`,
89
+ `${theme.label("ID:")} ${data.ranking.id}`,
90
+ `${theme.label("Métrica:")} ${formatMetricDefinition(data.ranking.order_metric)}`,
91
+ `${theme.label("Top:")} ${formatInteger(data.top_n)}`,
92
+ `${theme.label("Ativos retornados:")} ${formatInteger(data.count)}`,
93
+ ];
94
+ if (data.as_of) {
95
+ lines.push(`${theme.label("Data:")} ${data.as_of}`);
96
+ }
97
+ if (data.rows.length === 0) {
98
+ lines.push("");
99
+ lines.push(theme.dim("Nenhum ativo retornado."));
100
+ return lines.join("\n");
101
+ }
102
+ lines.push("");
103
+ lines.push(...formatRankingRows(data.rows, data.ranking.order_metric.label));
104
+ return lines.join("\n");
105
+ }
106
+ function formatRankingGroup(title, rankings, theme) {
107
+ const lines = [
108
+ `${theme.label(title)} ${theme.dim(`(${formatInteger(rankings.length)})`)}`,
109
+ ];
110
+ if (rankings.length === 0) {
111
+ lines.push(` ${theme.dim("Nenhum ranking disponível.")}`);
112
+ return lines;
113
+ }
114
+ for (const ranking of rankings) {
115
+ lines.push(` ${theme.bold(ranking.id)} - ${ranking.name}`);
116
+ lines.push(` ${theme.label("Métrica:")} ${formatMetricDefinition(ranking.order_metric)}`);
117
+ if (ranking.latest_as_of) {
118
+ lines.push(` ${theme.label("Atualizado em:")} ${ranking.latest_as_of}`);
119
+ }
120
+ if (ranking.total_assets !== null) {
121
+ lines.push(` ${theme.label("Ativos:")} ${formatInteger(ranking.total_assets)}`);
122
+ }
123
+ lines.push(` ${theme.label("Uso:")} ${formatRankingUsage(ranking)}`);
124
+ }
125
+ return lines;
126
+ }
127
+ function formatRankingRows(rows, metricLabel) {
128
+ const metricHeader = truncate(metricLabel, 26);
129
+ const header = `${"#".padEnd(4)}${"Ativo".padEnd(12)}${metricHeader}`;
130
+ const divider = "-".repeat(header.length);
131
+ const lines = [header, divider];
132
+ for (const row of rows) {
133
+ lines.push(`${formatInteger(row.rank).padEnd(4)}${row.ticker.padEnd(12)}${formatMetricValue(row.order_metric)}`);
134
+ }
135
+ return lines;
136
+ }
137
+ function formatRankingUsage(ranking) {
138
+ if (ranking.kind === "USER") {
139
+ const id = ranking.id.startsWith("user:")
140
+ ? ranking.id.slice("user:".length)
141
+ : ranking.id;
142
+ return `quantbrasil rankings current --user ${id} --top 20`;
143
+ }
144
+ return `quantbrasil rankings current --system ${ranking.id} --top 20`;
145
+ }
146
+ function formatRankingKind(kind) {
147
+ return kind === "SYSTEM" ? "sistema" : "usuário";
148
+ }
149
+ function formatMetricDefinition(metric) {
150
+ return `${metric.label} (${metric.direction})`;
151
+ }
152
+ function formatMetricValue(metric) {
153
+ if (metric.value === null) {
154
+ return "-";
155
+ }
156
+ if (typeof metric.value === "number") {
157
+ if (metric.unit === "ratio") {
158
+ return `${formatNumber(metric.value * 100)}%`;
159
+ }
160
+ return formatNumber(metric.value);
161
+ }
162
+ return String(metric.value);
163
+ }
164
+ function parseTopOption(rawTop) {
165
+ if (rawTop === undefined) {
166
+ return 20;
167
+ }
168
+ return parsePositiveInteger(rawTop, "--top");
169
+ }
170
+ function parsePositiveInteger(rawValue, label) {
171
+ const normalized = normalizeRequiredString(rawValue, label);
172
+ const parsed = Number.parseInt(normalized, 10);
173
+ if (!Number.isInteger(parsed) ||
174
+ parsed <= 0 ||
175
+ String(parsed) !== normalized) {
176
+ throw createCliValidationError(`${label} deve ser um inteiro positivo.`);
177
+ }
178
+ return parsed;
179
+ }
180
+ function normalizeRequiredString(rawValue, label) {
181
+ const normalized = rawValue?.trim();
182
+ if (!normalized) {
183
+ throw createCliValidationError(`${label} não pode ser vazio.`);
184
+ }
185
+ return normalized;
186
+ }
187
+ function formatInteger(value) {
188
+ return new Intl.NumberFormat("pt-BR", {
189
+ maximumFractionDigits: 0,
190
+ }).format(value);
191
+ }
192
+ function formatNumber(value) {
193
+ return new Intl.NumberFormat("pt-BR", {
194
+ maximumFractionDigits: 4,
195
+ }).format(value);
196
+ }
197
+ function truncate(value, maxLength) {
198
+ if (value.length <= maxLength) {
199
+ return value;
200
+ }
201
+ return `${value.slice(0, maxLength - 3)}...`;
202
+ }
@@ -8,6 +8,9 @@ export interface ScreeningCommandIO {
8
8
  export interface ScreeningUniversesCommandOptions {
9
9
  json?: boolean;
10
10
  }
11
+ export interface ScreeningIndicatorsCommandOptions {
12
+ json?: boolean;
13
+ }
11
14
  export interface ScreeningRunCommandOptions {
12
15
  system?: string;
13
16
  watchlist?: string;
@@ -33,6 +36,45 @@ export interface ScreeningUniversesResponse {
33
36
  holdings: ScreeningUniverseOut[];
34
37
  total: number;
35
38
  }
39
+ export type ScreeningIndicatorScalar = string | number | boolean;
40
+ export interface ScreeningIndicatorParamOut {
41
+ [key: string]: JsonValue;
42
+ name: string;
43
+ type: "integer" | "number" | "enum" | "string" | "boolean";
44
+ required: boolean;
45
+ default: ScreeningIndicatorScalar | null;
46
+ description: string;
47
+ enum_values: string[] | null;
48
+ examples: ScreeningIndicatorScalar[];
49
+ }
50
+ export interface ScreeningIndicatorRef {
51
+ [key: string]: JsonValue;
52
+ name: string;
53
+ timeframe: string;
54
+ offset: number;
55
+ params: Record<string, JsonValue>;
56
+ }
57
+ export interface ScreeningIndicatorExampleOut {
58
+ [key: string]: JsonValue;
59
+ label: string;
60
+ description: string;
61
+ indicator: ScreeningIndicatorRef;
62
+ }
63
+ export interface ScreeningIndicatorOut {
64
+ [key: string]: JsonValue;
65
+ name: string;
66
+ display_name: string;
67
+ description: string;
68
+ timeframes: string[];
69
+ params: ScreeningIndicatorParamOut[];
70
+ examples: ScreeningIndicatorExampleOut[];
71
+ }
72
+ export interface ScreeningIndicatorsResponse {
73
+ [key: string]: JsonValue;
74
+ ok: boolean;
75
+ indicators: ScreeningIndicatorOut[];
76
+ operators: string[];
77
+ }
36
78
  export interface IndicatorResult {
37
79
  [key: string]: JsonValue;
38
80
  value: number;
@@ -68,9 +110,11 @@ type JsonRecord = {
68
110
  };
69
111
  export declare function registerScreeningCommands(program: Command, context?: ScreeningCommandContext): void;
70
112
  export declare function runScreeningUniversesCommand(options: ScreeningUniversesCommandOptions, context?: ScreeningCommandContext): Promise<void>;
113
+ export declare function runScreeningIndicatorsCommand(options: ScreeningIndicatorsCommandOptions, context?: ScreeningCommandContext): Promise<void>;
71
114
  export declare function runScreeningRunCommand(options: ScreeningRunCommandOptions, context?: ScreeningCommandContext): Promise<void>;
72
115
  export declare function buildScreeningRunInput(options: ScreeningRunCommandOptions): Promise<JsonRecord>;
73
116
  export declare function formatScreeningUniversesHuman(data: ScreeningUniversesResponse, theme?: import("../cli/terminal.js").TerminalTheme): string;
117
+ export declare function formatScreeningIndicatorsHuman(data: ScreeningIndicatorsResponse, theme?: import("../cli/terminal.js").TerminalTheme): string;
74
118
  export declare function formatScreeningRunHuman(data: ScreeningRunResponse, theme?: import("../cli/terminal.js").TerminalTheme): string;
75
119
  export {};
76
120
  //# sourceMappingURL=screening.d.ts.map