@alphafox/cli 0.3.3 → 0.3.5

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 (86) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +28 -9
  3. package/dist/auth/loopback-callback.js +3 -3
  4. package/dist/catalog/allowlist.d.ts +1 -1
  5. package/dist/catalog/allowlist.js +1 -1
  6. package/dist/catalog/generated/registry.json +338 -49
  7. package/dist/catalog/generated/schemas.json +1880 -779
  8. package/dist/catalog/omit.d.ts +6 -0
  9. package/dist/catalog/omit.js +11 -0
  10. package/dist/catalog/operations.d.ts +1 -1
  11. package/dist/catalog/operations.js +5 -2
  12. package/dist/commands/run.js +25 -3
  13. package/dist/engine-backtest/load-config.d.ts +4 -0
  14. package/dist/engine-backtest/load-config.js +44 -0
  15. package/dist/engine-backtest/parse-args.d.ts +3 -1
  16. package/dist/engine-backtest/parse-args.js +87 -3
  17. package/dist/engine-backtest/parse-axes.d.ts +3 -0
  18. package/dist/engine-backtest/parse-axes.js +167 -0
  19. package/dist/engine-backtest/persist.d.ts +60 -1
  20. package/dist/engine-backtest/persist.js +196 -1
  21. package/dist/engine-backtest/return-curve.d.ts +27 -0
  22. package/dist/engine-backtest/return-curve.js +80 -0
  23. package/dist/engine-backtest/run-command.d.ts +1 -4
  24. package/dist/engine-backtest/run-command.js +61 -45
  25. package/dist/engine-backtest/sweep-command.d.ts +13 -0
  26. package/dist/engine-backtest/sweep-command.js +749 -0
  27. package/dist/engine-backtest/sweep-kernel/caps.d.ts +26 -0
  28. package/dist/engine-backtest/sweep-kernel/caps.js +48 -0
  29. package/dist/engine-backtest/sweep-kernel/index.d.ts +13 -0
  30. package/dist/engine-backtest/sweep-kernel/index.js +34 -0
  31. package/dist/engine-backtest/sweep-kernel/plan.d.ts +22 -0
  32. package/dist/engine-backtest/sweep-kernel/plan.js +320 -0
  33. package/dist/engine-backtest/sweep-kernel/results.d.ts +72 -0
  34. package/dist/engine-backtest/sweep-kernel/results.js +150 -0
  35. package/dist/engine-backtest/sweep-kernel/session.d.ts +55 -0
  36. package/dist/engine-backtest/sweep-kernel/session.js +56 -0
  37. package/dist/engine-backtest/sweep-kernel/types.d.ts +36 -0
  38. package/dist/engine-backtest/sweep-kernel/types.js +2 -0
  39. package/dist/engine-backtest/types.d.ts +130 -0
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.js +16 -1
  42. package/dist/install/types.d.ts +8 -1
  43. package/dist/install/types.js +1 -0
  44. package/dist/install/wizard.js +92 -55
  45. package/dist/keychain/windows-credential.d.ts +1 -1
  46. package/dist/keychain/windows-credential.js +1 -1
  47. package/dist/resolve-symbols/catalog.d.ts +3 -0
  48. package/dist/resolve-symbols/catalog.js +50 -0
  49. package/dist/resolve-symbols/errors.d.ts +18 -0
  50. package/dist/resolve-symbols/errors.js +26 -0
  51. package/dist/resolve-symbols/exchanges.d.ts +8 -0
  52. package/dist/resolve-symbols/exchanges.js +53 -0
  53. package/dist/resolve-symbols/match.d.ts +6 -0
  54. package/dist/resolve-symbols/match.js +250 -0
  55. package/dist/resolve-symbols/parse-args.d.ts +5 -0
  56. package/dist/resolve-symbols/parse-args.js +106 -0
  57. package/dist/resolve-symbols/run-command.d.ts +21 -0
  58. package/dist/resolve-symbols/run-command.js +149 -0
  59. package/dist/resolve-symbols/types.d.ts +37 -0
  60. package/dist/resolve-symbols/types.js +2 -0
  61. package/dist/skills/manager.d.ts +96 -0
  62. package/dist/skills/manager.js +445 -0
  63. package/dist/skills/run-command.d.ts +22 -0
  64. package/dist/skills/run-command.js +143 -0
  65. package/dist/skills-manifest.json +141 -0
  66. package/dist/update/run-command.d.ts +41 -0
  67. package/dist/update/run-command.js +204 -0
  68. package/dist/version.d.ts +1 -1
  69. package/dist/version.js +1 -1
  70. package/docs/agents/issue-tracker.md +2 -2
  71. package/docs/agents/triage-labels.md +1 -1
  72. package/docs/alphafox-cli-installation-guide.md +16 -17
  73. package/docs/index.html +11 -11
  74. package/docs/release-supply-chain.md +11 -6
  75. package/package.json +2 -2
  76. package/skills/account/SKILL.md +1 -1
  77. package/skills/admin/SKILL.md +1 -1
  78. package/skills/alphafox/SKILL.md +38 -0
  79. package/skills/alphafox-shared/SKILL.md +20 -4
  80. package/skills/auth/SKILL.md +2 -2
  81. package/skills/engine-backtest/SKILL.md +48 -6
  82. package/skills/exchange/SKILL.md +1 -1
  83. package/skills/market/SKILL.md +27 -4
  84. package/skills/notification/SKILL.md +1 -1
  85. package/skills/strategy/SKILL.md +7 -20
  86. package/skills/trading/SKILL.md +3 -1
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RESOLVE_SYMBOLS_USAGE = exports.RESOLVE_SYMBOLS_MAX_LIMIT = exports.RESOLVE_SYMBOLS_DEFAULT_LIMIT = void 0;
4
+ exports.parseResolveSymbolsArgs = parseResolveSymbolsArgs;
5
+ const errors_1 = require("./errors");
6
+ const exchanges_1 = require("./exchanges");
7
+ exports.RESOLVE_SYMBOLS_DEFAULT_LIMIT = 8;
8
+ exports.RESOLVE_SYMBOLS_MAX_LIMIT = 25;
9
+ exports.RESOLVE_SYMBOLS_USAGE = [
10
+ "alphafox resolve-symbols <query...> [--exchange binance] [--limit 8]",
11
+ "alphafox resolve-symbols --query BTC --query ETH --exchange okx",
12
+ ];
13
+ function usage(message, subtype = "invalid_args") {
14
+ throw new errors_1.ResolveSymbolsError({
15
+ type: "usage",
16
+ subtype,
17
+ message,
18
+ hint: exports.RESOLVE_SYMBOLS_USAGE[0],
19
+ status: 400,
20
+ });
21
+ }
22
+ function takeValue(args, i, flag) {
23
+ const next = args[i + 1];
24
+ if (next === undefined || next.startsWith("--")) {
25
+ usage(`Missing value for ${flag}`, "missing_flag_value");
26
+ }
27
+ return { value: next, next: i + 1 };
28
+ }
29
+ function parseResolveSymbolsArgs(args) {
30
+ const queries = [];
31
+ let exchange = exchanges_1.RESOLVE_SYMBOLS_DEFAULT_EXCHANGE;
32
+ let limit = exports.RESOLVE_SYMBOLS_DEFAULT_LIMIT;
33
+ let help = false;
34
+ for (let i = 0; i < args.length; i += 1) {
35
+ const a = args[i];
36
+ if (a === "--help" || a === "-h") {
37
+ help = true;
38
+ continue;
39
+ }
40
+ if (!a.startsWith("--")) {
41
+ queries.push(a);
42
+ continue;
43
+ }
44
+ const eq = a.indexOf("=");
45
+ const flag = eq >= 0 ? a.slice(0, eq) : a;
46
+ const inline = eq >= 0 ? a.slice(eq + 1) : undefined;
47
+ const read = () => {
48
+ if (inline !== undefined)
49
+ return inline;
50
+ const taken = takeValue(args, i, flag);
51
+ i = taken.next;
52
+ return taken.value;
53
+ };
54
+ switch (flag) {
55
+ case "--query":
56
+ case "--symbol":
57
+ queries.push(read());
58
+ break;
59
+ case "--exchange":
60
+ exchange = read();
61
+ break;
62
+ case "--limit": {
63
+ const n = Number(read());
64
+ if (!Number.isInteger(n) || n <= 0 || n > exports.RESOLVE_SYMBOLS_MAX_LIMIT) {
65
+ usage(`--limit must be an integer 1..${exports.RESOLVE_SYMBOLS_MAX_LIMIT}`, "invalid_limit");
66
+ }
67
+ limit = n;
68
+ break;
69
+ }
70
+ default:
71
+ usage(`Unknown flag: ${flag}`, "unknown_flag");
72
+ }
73
+ }
74
+ if (help) {
75
+ return { help: true, queries: [], exchange, limit };
76
+ }
77
+ const normalizedQueries = queries.map((item) => item.trim()).filter(Boolean);
78
+ if (normalizedQueries.length === 0) {
79
+ usage("Provide at least one symbol query", "missing_query");
80
+ }
81
+ let resolvedExchange;
82
+ try {
83
+ resolvedExchange = (0, exchanges_1.resolveSymbolsExchangeId)(exchange).id;
84
+ }
85
+ catch (err) {
86
+ usage(err instanceof Error ? err.message : String(err), "invalid_exchange");
87
+ }
88
+ return {
89
+ help: false,
90
+ queries: uniqueQueries(normalizedQueries),
91
+ exchange: resolvedExchange,
92
+ limit,
93
+ };
94
+ }
95
+ function uniqueQueries(queries) {
96
+ const seen = new Set();
97
+ const out = [];
98
+ for (const query of queries) {
99
+ const key = query.toUpperCase();
100
+ if (seen.has(key))
101
+ continue;
102
+ seen.add(key);
103
+ out.push(query);
104
+ }
105
+ return out;
106
+ }
@@ -0,0 +1,21 @@
1
+ import type { ApiRequestOptions, ApiResponse } from "../http/client";
2
+ import type { ResolveSymbolsRunArgs, ResolveSymbolsSuccess } from "./types";
3
+ export interface ResolveSymbolsCliFlags {
4
+ readonly profile?: string;
5
+ readonly format: "json" | "jsonl" | "text";
6
+ readonly yes: boolean;
7
+ readonly dryRun: boolean;
8
+ readonly noInput: boolean;
9
+ readonly unsafeCustomEndpoint?: string;
10
+ readonly jq?: string;
11
+ }
12
+ export interface ResolveSymbolsRunDeps {
13
+ readonly apiRequest?: (options: ApiRequestOptions, env?: NodeJS.ProcessEnv) => Promise<ApiResponse>;
14
+ }
15
+ export declare function resolveSymbolsHelpData(): {
16
+ readonly name: string;
17
+ readonly usage: string[];
18
+ readonly notes: string[];
19
+ };
20
+ export declare function executeResolveSymbols(args: ResolveSymbolsRunArgs, flags: ResolveSymbolsCliFlags, env?: NodeJS.ProcessEnv, deps?: ResolveSymbolsRunDeps): Promise<ResolveSymbolsSuccess>;
21
+ export declare function cmdResolveSymbols(args: string[], flags: ResolveSymbolsCliFlags, env?: NodeJS.ProcessEnv, deps?: ResolveSymbolsRunDeps): Promise<number>;
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveSymbolsHelpData = resolveSymbolsHelpData;
4
+ exports.executeResolveSymbols = executeResolveSymbols;
5
+ exports.cmdResolveSymbols = cmdResolveSymbols;
6
+ const profiles_1 = require("../config/profiles");
7
+ const envelope_1 = require("../envelope");
8
+ const client_1 = require("../http/client");
9
+ const catalog_1 = require("./catalog");
10
+ const errors_1 = require("./errors");
11
+ const exchanges_1 = require("./exchanges");
12
+ const match_1 = require("./match");
13
+ const parse_args_1 = require("./parse-args");
14
+ function extractErrorMessage(json, fallback) {
15
+ if (json && typeof json === "object") {
16
+ const o = json;
17
+ if (typeof o.message === "string")
18
+ return o.message;
19
+ if (typeof o.detail === "string")
20
+ return o.detail;
21
+ if (typeof o.error === "string")
22
+ return o.error;
23
+ if (o.error && typeof o.error === "object") {
24
+ const e = o.error;
25
+ if (typeof e.message === "string")
26
+ return e.message;
27
+ }
28
+ }
29
+ return fallback || "Request failed";
30
+ }
31
+ function extractErrorCode(json) {
32
+ if (json && typeof json === "object") {
33
+ const o = json;
34
+ if (typeof o.code === "string" || typeof o.code === "number")
35
+ return o.code;
36
+ }
37
+ return undefined;
38
+ }
39
+ function resolveSymbolsHelpData() {
40
+ return {
41
+ name: "resolve-symbols",
42
+ usage: parse_args_1.RESOLVE_SYMBOLS_USAGE,
43
+ notes: [
44
+ "Resolves user-mentioned tickers against the public linear-perp catalog from market.symbols.list",
45
+ "Default --exchange is binance (binance_perp_usdt). Aliases: binance|okx|bybit|bitget|hyperliquid|aster",
46
+ "Do not guess CCXT symbols. Exact match may be used directly; a single close match needs user confirmation; multiple close matches must be chosen by the user",
47
+ "Catalog CRUD remains alphafox market symbols list --exchange <id>",
48
+ ],
49
+ };
50
+ }
51
+ async function executeResolveSymbols(args, flags, env = process.env, deps = {}) {
52
+ if (args.help) {
53
+ throw new errors_1.ResolveSymbolsError({
54
+ type: "usage",
55
+ message: "internal: help should be handled by the command wrapper",
56
+ });
57
+ }
58
+ const exchange = (0, exchanges_1.resolveSymbolsExchangeId)(args.exchange);
59
+ const profile = (0, profiles_1.resolveProfile)(flags.profile, env, {
60
+ unsafeCustomEndpoint: flags.unsafeCustomEndpoint,
61
+ });
62
+ const api = deps.apiRequest ?? client_1.apiRequest;
63
+ const res = await api({
64
+ method: "GET",
65
+ path: (0, catalog_1.marketSymbolsPath)(exchange.id),
66
+ profile,
67
+ }, env);
68
+ if (res.status >= 400) {
69
+ throw new errors_1.ResolveSymbolsError({
70
+ type: "http",
71
+ status: res.status,
72
+ message: extractErrorMessage(res.json, res.bodyText),
73
+ code: extractErrorCode(res.json),
74
+ hint: res.status === 401 || res.status === 403
75
+ ? "Run alphafox auth login. Tokens live in the OS keychain."
76
+ : undefined,
77
+ details: res.json,
78
+ });
79
+ }
80
+ const catalog = (0, match_1.indexCatalogSymbols)((0, catalog_1.extractCatalogSymbols)(res.json));
81
+ return {
82
+ exchange: exchange.id,
83
+ exchangeLabel: exchange.label,
84
+ catalogSize: catalog.length,
85
+ queries: args.queries.map((query) => (0, match_1.resolveQueryAgainstCatalog)(query, catalog, args.limit)),
86
+ };
87
+ }
88
+ async function cmdResolveSymbols(args, flags, env = process.env, deps = {}) {
89
+ let parsed;
90
+ try {
91
+ parsed = (0, parse_args_1.parseResolveSymbolsArgs)(args);
92
+ }
93
+ catch (err) {
94
+ if ((0, errors_1.isResolveSymbolsError)(err)) {
95
+ (0, envelope_1.writeError)({
96
+ type: err.type,
97
+ subtype: err.subtype,
98
+ message: err.message,
99
+ hint: err.hint,
100
+ status: err.status,
101
+ details: err.details,
102
+ }, { exitCode: err.status === 401 || err.status === 403 ? 77 : undefined });
103
+ }
104
+ throw err;
105
+ }
106
+ if (parsed.help) {
107
+ (0, envelope_1.writeSuccess)(resolveSymbolsHelpData(), {
108
+ format: flags.format,
109
+ jq: flags.jq,
110
+ });
111
+ return 0;
112
+ }
113
+ const exchange = (0, exchanges_1.resolveSymbolsExchangeId)(parsed.exchange);
114
+ if (flags.dryRun) {
115
+ (0, envelope_1.writeSuccess)({
116
+ dryRun: true,
117
+ operationId: "market.symbols.list",
118
+ method: "GET",
119
+ path: (0, catalog_1.marketSymbolsPath)(exchange.id),
120
+ exchange: exchange.id,
121
+ exchangeLabel: exchange.label,
122
+ queries: parsed.queries,
123
+ }, { format: flags.format, jq: flags.jq });
124
+ return 0;
125
+ }
126
+ try {
127
+ const result = await executeResolveSymbols(parsed, flags, env, deps);
128
+ (0, envelope_1.writeSuccess)(result, {
129
+ format: flags.format,
130
+ jq: flags.jq,
131
+ meta: { operationId: "market.symbols.list" },
132
+ });
133
+ return 0;
134
+ }
135
+ catch (err) {
136
+ if ((0, errors_1.isResolveSymbolsError)(err)) {
137
+ (0, envelope_1.writeError)({
138
+ type: err.type,
139
+ subtype: err.subtype,
140
+ message: err.message,
141
+ hint: err.hint,
142
+ status: err.status,
143
+ code: err.code,
144
+ details: err.details,
145
+ }, { exitCode: err.status === 401 || err.status === 403 ? 77 : undefined });
146
+ }
147
+ throw err;
148
+ }
149
+ }
@@ -0,0 +1,37 @@
1
+ export type ResolveSymbolsStatus = "exact" | "close" | "ambiguous" | "none";
2
+ export type ResolveSymbolsMatchReason = "exact_canonical" | "exact_compact" | "exact_pair" | "exact_base" | "prefix" | "contains" | "close";
3
+ export interface ResolveSymbolsMatch {
4
+ readonly symbol: string;
5
+ readonly reason: ResolveSymbolsMatchReason;
6
+ readonly score: number;
7
+ }
8
+ export interface ResolveSymbolsQueryResult {
9
+ readonly query: string;
10
+ readonly status: ResolveSymbolsStatus;
11
+ readonly resolved: string | null;
12
+ readonly needsConfirmation: boolean;
13
+ readonly matches: readonly ResolveSymbolsMatch[];
14
+ readonly matchCount: number;
15
+ }
16
+ export interface ResolveSymbolsSuccess {
17
+ readonly exchange: string;
18
+ readonly exchangeLabel: string;
19
+ readonly catalogSize: number;
20
+ readonly queries: readonly ResolveSymbolsQueryResult[];
21
+ }
22
+ export interface ResolveSymbolsRunArgs {
23
+ readonly help: boolean;
24
+ readonly queries: readonly string[];
25
+ readonly exchange: string;
26
+ readonly limit: number;
27
+ }
28
+ export interface CatalogSymbol {
29
+ readonly symbol: string;
30
+ readonly base: string;
31
+ readonly quote: string;
32
+ readonly pair: string;
33
+ readonly compact: string;
34
+ readonly searchKey: string;
35
+ readonly baseKey: string;
36
+ readonly compactKey: string;
37
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,96 @@
1
+ export interface SkillManifestFile {
2
+ readonly path: string;
3
+ readonly sha256: string;
4
+ readonly size: number;
5
+ }
6
+ export interface SkillManifestEntry {
7
+ readonly name: string;
8
+ readonly version: string;
9
+ readonly hash: string;
10
+ readonly files: readonly SkillManifestFile[];
11
+ }
12
+ export interface SkillsBundleManifest {
13
+ readonly schemaVersion: 1;
14
+ readonly packageName: "@alphafox/cli";
15
+ readonly packageVersion: string;
16
+ readonly contractVersion: string;
17
+ readonly bundleHash: string;
18
+ readonly skills: readonly SkillManifestEntry[];
19
+ }
20
+ export interface InstalledSkillState {
21
+ readonly version: string;
22
+ readonly hash: string;
23
+ }
24
+ export interface SkillsInstallState {
25
+ readonly schemaVersion: 1;
26
+ readonly packageVersion: string;
27
+ readonly contractVersion: string;
28
+ readonly bundleHash: string;
29
+ readonly syncedAt: string;
30
+ readonly skills: Readonly<Record<string, InstalledSkillState>>;
31
+ }
32
+ export type SkillStatus = "current" | "missing" | "stale" | "modified";
33
+ export interface InspectedSkill {
34
+ readonly name: string;
35
+ readonly expectedVersion: string;
36
+ readonly installedVersion: string | null;
37
+ readonly expectedHash: string;
38
+ readonly installedHash: string | null;
39
+ readonly status: SkillStatus;
40
+ readonly managed: boolean;
41
+ }
42
+ export interface SkillsStatus {
43
+ readonly bundleVersion: string;
44
+ readonly contractVersion: string;
45
+ readonly bundleHash: string;
46
+ readonly installedRoot: string;
47
+ readonly skills: readonly InspectedSkill[];
48
+ readonly orphans: readonly {
49
+ readonly name: string;
50
+ readonly installedHash: string;
51
+ readonly recordedHash: string;
52
+ readonly modified: boolean;
53
+ }[];
54
+ readonly summary: Readonly<Record<SkillStatus, number>>;
55
+ readonly restartRequired: boolean;
56
+ }
57
+ export interface SkillsSyncResult {
58
+ readonly action: "synced" | "planned" | "skipped";
59
+ readonly updated: readonly string[];
60
+ readonly removed: readonly string[];
61
+ readonly blocked: readonly string[];
62
+ readonly backupDir?: string;
63
+ readonly status: SkillsStatus;
64
+ readonly restartRequired: boolean;
65
+ }
66
+ export interface SkillsSyncDeps {
67
+ readonly install: (names: readonly string[]) => Promise<void>;
68
+ readonly remove?: (names: readonly string[]) => Promise<void>;
69
+ readonly now?: () => Date;
70
+ }
71
+ export declare function buildSkillsManifest(packageRoot: string, versions: {
72
+ readonly packageVersion: string;
73
+ readonly contractVersion: string;
74
+ }): SkillsBundleManifest;
75
+ export declare function writeSkillsManifest(packageRoot: string, outputPath: string, versions: {
76
+ readonly packageVersion: string;
77
+ readonly contractVersion: string;
78
+ }): SkillsBundleManifest;
79
+ export declare function loadAndVerifySkillsManifest(packageRoot: string, manifestPath?: string): SkillsBundleManifest;
80
+ export declare function inspectSkills(input: {
81
+ readonly manifest: SkillsBundleManifest;
82
+ readonly installedRoot: string;
83
+ readonly state: SkillsInstallState | null;
84
+ }): SkillsStatus;
85
+ export declare function syncSkills(input: {
86
+ readonly manifest: SkillsBundleManifest;
87
+ readonly packageRoot: string;
88
+ readonly installedRoot: string;
89
+ readonly statePath: string;
90
+ readonly dryRun: boolean;
91
+ readonly force: boolean;
92
+ }, deps: SkillsSyncDeps): Promise<SkillsSyncResult>;
93
+ export declare function loadSkillsState(path: string): SkillsInstallState | null;
94
+ export declare function hashSkillDirectory(skillRoot: string): string;
95
+ export declare function readSkillVersion(skillPath: string): string | null;
96
+ export declare function readSkillName(skillPath: string): string | null;