@almanak/mcp-server 0.2.8 → 0.2.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.
- package/dist/backtest-v3.d.ts +2 -2
- package/dist/backtest-v3.js.map +1 -1
- package/dist/client.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.js.map +1 -1
- package/dist/testing/__tests__/backtest-results-tool.test.js.map +1 -1
- package/dist/testing/__tests__/backtest-tool.test.js.map +1 -1
- package/dist/testing/__tests__/backtest-v3-tool.test.js +10 -13
- package/dist/testing/__tests__/backtest-v3-tool.test.js.map +1 -1
- package/dist/testing/__tests__/controller-client.test.js.map +1 -1
- package/dist/testing/__tests__/fixtures/pre-v3-backtest-tools.d.ts +4 -4
- package/dist/testing/__tests__/platform-client.test.js.map +1 -1
- package/dist/testing/__tests__/runner.test.js.map +1 -1
- package/dist/testing/__tests__/workspace-export-tools.test.js.map +1 -1
- package/dist/testing/controller-client.js.map +1 -1
- package/dist/testing/runner.js.map +1 -1
- package/dist/tools.js +78 -82
- package/dist/tools.js.map +1 -1
- package/dist/workspace-git.js.map +1 -1
- package/package.json +6 -5
package/dist/tools.js
CHANGED
|
@@ -876,17 +876,14 @@ class PlatformToolHandler {
|
|
|
876
876
|
},
|
|
877
877
|
required: ['agent_id'],
|
|
878
878
|
},
|
|
879
|
-
}, (args) => {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
searchText: args.search_text,
|
|
888
|
-
});
|
|
889
|
-
});
|
|
879
|
+
}, (args) => { var _a, _b; return this.fetchAgentLogsToFile({
|
|
880
|
+
agentId: args.agent_id,
|
|
881
|
+
navigationMode: (_a = args.navigation_mode) !== null && _a !== void 0 ? _a : 'GO_TO_END',
|
|
882
|
+
page: (_b = args.page) !== null && _b !== void 0 ? _b : 1,
|
|
883
|
+
targetTimestamp: args.target_timestamp,
|
|
884
|
+
severity: args.severity,
|
|
885
|
+
searchText: args.search_text,
|
|
886
|
+
}); });
|
|
890
887
|
this.register('agents', {
|
|
891
888
|
name: 'agents_pnl',
|
|
892
889
|
description: 'Get profit and loss data for an agent including current value, returns, and APY.',
|
|
@@ -909,15 +906,12 @@ class PlatformToolHandler {
|
|
|
909
906
|
},
|
|
910
907
|
required: ['agent_id'],
|
|
911
908
|
},
|
|
912
|
-
}, (args) => {
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
sort: (_c = args.sort) !== null && _c !== void 0 ? _c : 'desc',
|
|
919
|
-
});
|
|
920
|
-
});
|
|
909
|
+
}, (args) => { var _a, _b, _c; return this.client.getAgentTransactions({
|
|
910
|
+
agentId: args.agent_id,
|
|
911
|
+
page: (_a = args.page) !== null && _a !== void 0 ? _a : 1,
|
|
912
|
+
offset: (_b = args.offset) !== null && _b !== void 0 ? _b : 25,
|
|
913
|
+
sort: (_c = args.sort) !== null && _c !== void 0 ? _c : 'desc',
|
|
914
|
+
}); });
|
|
921
915
|
this.register('agents', {
|
|
922
916
|
name: 'agents_sync_status',
|
|
923
917
|
description: 'Check if a deployed agent is in sync with its linked strategy repository. Returns IN_SYNC, OUT_OF_SYNC, or UNKNOWN.',
|
|
@@ -1004,16 +998,13 @@ class PlatformToolHandler {
|
|
|
1004
998
|
},
|
|
1005
999
|
required: ['wallet_id', 'eoa_address', 'chain_id'],
|
|
1006
1000
|
},
|
|
1007
|
-
}, async (args) => {
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
show_widget: true,
|
|
1015
|
-
});
|
|
1016
|
-
});
|
|
1001
|
+
}, async (args) => { var _a; return ({
|
|
1002
|
+
wallet_id: args.wallet_id,
|
|
1003
|
+
eoa_address: args.eoa_address,
|
|
1004
|
+
chain_id: args.chain_id,
|
|
1005
|
+
chain_name: (_a = args.chain_name) !== null && _a !== void 0 ? _a : '',
|
|
1006
|
+
show_widget: true,
|
|
1007
|
+
}); });
|
|
1017
1008
|
// ─── Strategy tools ─────────────────────────────────────────
|
|
1018
1009
|
this.register('strategies', {
|
|
1019
1010
|
name: 'strategies_token_funding',
|
|
@@ -1040,23 +1031,25 @@ class PlatformToolHandler {
|
|
|
1040
1031
|
},
|
|
1041
1032
|
required: ['tokens'],
|
|
1042
1033
|
},
|
|
1043
|
-
}, async (args) => {
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
show_widget: true,
|
|
1049
|
-
});
|
|
1050
|
-
});
|
|
1034
|
+
}, async (args) => { var _a, _b; return ({
|
|
1035
|
+
tokens: (_a = args.tokens) !== null && _a !== void 0 ? _a : [],
|
|
1036
|
+
prompt: (_b = args.prompt) !== null && _b !== void 0 ? _b : 'How much (in USD) do you want to allocate per token?',
|
|
1037
|
+
show_widget: true,
|
|
1038
|
+
}); });
|
|
1051
1039
|
this.register('strategies', {
|
|
1052
1040
|
name: 'strategies_spec',
|
|
1053
|
-
description: "Show the user an editable Strategy Spec panel to review and approve the strategy's risk posture BEFORE building. Call early — after confirming protocol support, before scaffolding. Pass plainSummary (one-line plain-language money-at-risk), fields (the few user-facing posture choices, each {key,label,description,value,unit}), the full content (the SPEC.json values), optional presets (conservative/balanced/aggressive content variants), and show_widget=true. content must include an `exit` object stating what stop/teardown does (close actions, asset policy), and fields must include an `exit.*` entry so the user sees it. If user constraints conflict with a clean exit, surface the resolution here rather than deciding silently. Give each field the unit that matches its meaning (see fields[].unit): a plain percentage such as an LP range width is `pct`, never `pct_of_balance`. Execution pauses; the user reviews/edits, then the reply is a fenced ```json``` block `{action, content}` — use the returned `content` as the approved build contract (the full SPEC values with the user's edits applied). Surface only genuine posture choices the strategy actually consults — keep safety internals in config.json.",
|
|
1041
|
+
description: "Show the user an editable Strategy Spec panel to review and approve the strategy's risk posture BEFORE building. Call early — after confirming protocol support, before scaffolding. Pass plainSummary (one-line plain-language money-at-risk), fields (the few user-facing posture choices, each {key,label,description,value,unit}), the full content (the SPEC.json values), optional presets (conservative/balanced/aggressive content variants), and show_widget=true. content must include an `exit` object stating what stop/teardown does (close actions, asset policy), and fields must include an `exit.*` entry so the user sees it. If user constraints conflict with a clean exit, surface the resolution here rather than deciding silently. Give each field the unit that matches its meaning (see fields[].unit): a plain percentage such as an LP range width is `pct`, never `pct_of_balance`. Execution pauses; the user reviews/edits, then the reply is a fenced ```json``` block `{action, content}` — use the returned `content` as the approved build contract (the full SPEC values with the user's edits applied). If the reply's action is `revise` it also carries `note` (a change the user asked for) and is NOT an approval: apply the note to `content` (keep fields, `behavior` and `exit` consistent), say in one line what changed or what cannot be done and the closest option, then call strategies_spec again for approval. Surface only genuine posture choices the strategy actually consults — keep safety internals in config.json.",
|
|
1054
1042
|
inputSchema: {
|
|
1055
1043
|
type: 'object',
|
|
1056
1044
|
properties: {
|
|
1057
1045
|
widgetId: { type: 'string', description: 'Widget identifier (default: "spec").' },
|
|
1058
1046
|
plainSummary: { type: 'string', description: 'One-line plain-language summary of what the strategy does and risks.' },
|
|
1059
|
-
content: {
|
|
1047
|
+
content: {
|
|
1048
|
+
type: 'object',
|
|
1049
|
+
description: 'The SPEC.json values (the build contract). Optional `behavior`: an array of 3–6 plain-language ' +
|
|
1050
|
+
'trigger → action lines (entry, while a position is held, missing data, stop), shown read-only ' +
|
|
1051
|
+
'under the fields as "How it behaves".',
|
|
1052
|
+
},
|
|
1060
1053
|
fields: {
|
|
1061
1054
|
type: 'array',
|
|
1062
1055
|
description: 'User-facing posture fields to render. Each references a key in content.',
|
|
@@ -1683,19 +1676,20 @@ class PlatformToolHandler {
|
|
|
1683
1676
|
* turn into a widget (the error card auto-resolves the gate immediately).
|
|
1684
1677
|
*/
|
|
1685
1678
|
async runBacktest(args) {
|
|
1686
|
-
var _a
|
|
1687
|
-
|
|
1688
|
-
const
|
|
1679
|
+
var _a;
|
|
1680
|
+
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
1681
|
+
const strategyLinkId = String((_b = args.strategy_link_id) !== null && _b !== void 0 ? _b : '').trim();
|
|
1682
|
+
const startTime = String((_c = args.start_time) !== null && _c !== void 0 ? _c : '').trim();
|
|
1689
1683
|
// required[] only checks presence — an empty/whitespace id would call
|
|
1690
1684
|
// getStrategy('') → GET /github/strategies/ (the list route). Fail early.
|
|
1691
1685
|
if (!strategyLinkId) {
|
|
1692
1686
|
return {
|
|
1693
1687
|
statusCode: 400,
|
|
1694
1688
|
error: 'strategy_link_id is required — pass the linked strategy id (from strategies_list or the strategies_export_workspace result).',
|
|
1695
|
-
backtest_config: { start_time: startTime, end_time: String((
|
|
1689
|
+
backtest_config: { start_time: startTime, end_time: String((_d = args.end_time) !== null && _d !== void 0 ? _d : '').trim(), include_gas_costs: args.include_gas_costs !== false },
|
|
1696
1690
|
};
|
|
1697
1691
|
}
|
|
1698
|
-
const endTime = String((
|
|
1692
|
+
const endTime = String((_e = args.end_time) !== null && _e !== void 0 ? _e : '').trim();
|
|
1699
1693
|
const includeGasCosts = args.include_gas_costs !== false;
|
|
1700
1694
|
const backtestConfig = { start_time: startTime, end_time: endTime, include_gas_costs: includeGasCosts };
|
|
1701
1695
|
const fail = (statusCode, error, extra) => ({
|
|
@@ -1728,7 +1722,7 @@ class PlatformToolHandler {
|
|
|
1728
1722
|
try {
|
|
1729
1723
|
const strategyRes = await this.client.getStrategy(strategyLinkId);
|
|
1730
1724
|
if ((strategyRes === null || strategyRes === void 0 ? void 0 : strategyRes.valid) === false || !(strategyRes === null || strategyRes === void 0 ? void 0 : strategyRes.data)) {
|
|
1731
|
-
return fail((
|
|
1725
|
+
return fail((_f = strategyRes === null || strategyRes === void 0 ? void 0 : strategyRes.statusCode) !== null && _f !== void 0 ? _f : 404, (_h = (_g = strategyRes === null || strategyRes === void 0 ? void 0 : strategyRes.message) !== null && _g !== void 0 ? _g : strategyRes === null || strategyRes === void 0 ? void 0 : strategyRes.error) !== null && _h !== void 0 ? _h : 'Strategy not found');
|
|
1732
1726
|
}
|
|
1733
1727
|
const strategy = strategyRes.data;
|
|
1734
1728
|
// The stored framework_version is authoritative for which runner family serves the strategy.
|
|
@@ -1743,7 +1737,7 @@ class PlatformToolHandler {
|
|
|
1743
1737
|
return await this.runV3Backtest(args, strategyLinkId, strategy);
|
|
1744
1738
|
}
|
|
1745
1739
|
if (sessionIsV3) {
|
|
1746
|
-
return fail(400, `The strategy link is stored as SDK ${String((
|
|
1740
|
+
return fail(400, `The strategy link is stored as SDK ${String((_j = strategy.framework_version) !== null && _j !== void 0 ? _j : 'v2').toLowerCase()}, but this chat session ` +
|
|
1747
1741
|
'runs the SDK v3 lane. The stored generation decides which backtest runs, and the two disagree, so nothing was ' +
|
|
1748
1742
|
'submitted. Do not add SDK v2 window inputs; tell the user the strategy link is not recognised as SDK v3 ' +
|
|
1749
1743
|
'(its repository must resolve almanak 3.x and carry strategy.py and config.yaml at the root).', { errorCode: 'SDK_GENERATION_MISMATCH' });
|
|
@@ -1778,19 +1772,19 @@ class PlatformToolHandler {
|
|
|
1778
1772
|
const refType = explicitSha ? 'commit' : 'branch';
|
|
1779
1773
|
const refConfigRes = await this.client.getStrategyRefConfig(strategyLinkId, ref, refType);
|
|
1780
1774
|
if ((refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.valid) === false || !(refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.data)) {
|
|
1781
|
-
const baseError = (
|
|
1775
|
+
const baseError = (_l = (_k = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.message) !== null && _k !== void 0 ? _k : refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.error) !== null && _l !== void 0 ? _l : `Could not resolve ref "${ref}" for the linked strategy repository.`;
|
|
1782
1776
|
const recoveryGuidance = explicitSha
|
|
1783
1777
|
? ` Omit commit_sha only if the user explicitly approves running the latest commit on ${defaultBranch}; ` +
|
|
1784
1778
|
'do not retry with different code automatically.'
|
|
1785
1779
|
: '';
|
|
1786
|
-
return fail((
|
|
1787
|
-
errorCode: (
|
|
1780
|
+
return fail((_m = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.statusCode) !== null && _m !== void 0 ? _m : 400, `${baseError}${recoveryGuidance}`, {
|
|
1781
|
+
errorCode: (_o = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.errorCode) !== null && _o !== void 0 ? _o : 'INTERNAL_ERROR',
|
|
1788
1782
|
retryable: (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.retryable) === true,
|
|
1789
1783
|
...recoveryContext,
|
|
1790
1784
|
});
|
|
1791
1785
|
}
|
|
1792
1786
|
const refConfig = refConfigRes.data;
|
|
1793
|
-
const commitSha = (
|
|
1787
|
+
const commitSha = (_p = refConfig.github_commit_sha) !== null && _p !== void 0 ? _p : '';
|
|
1794
1788
|
if (!FULL_COMMIT_SHA_RE.test(commitSha)) {
|
|
1795
1789
|
return fail(400, `Could not resolve "${ref}" to a full commit SHA — has the strategy been pushed to its repository?`, {
|
|
1796
1790
|
errorCode: 'COMMIT_UNRESOLVED',
|
|
@@ -1801,13 +1795,13 @@ class PlatformToolHandler {
|
|
|
1801
1795
|
// /ref-config — pin it to the resolved commit so it matches the config.
|
|
1802
1796
|
const refMetaRes = await this.client.getStrategyRefMetadata(strategyLinkId, commitSha);
|
|
1803
1797
|
if ((refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.valid) === false || !(refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.data)) {
|
|
1804
|
-
return fail((
|
|
1798
|
+
return fail((_q = refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.statusCode) !== null && _q !== void 0 ? _q : 400, (_s = (_r = refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.message) !== null && _r !== void 0 ? _r : refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.error) !== null && _s !== void 0 ? _s : 'Could not load strategy ref metadata');
|
|
1805
1799
|
}
|
|
1806
|
-
const sdkVersion = (
|
|
1800
|
+
const sdkVersion = (_t = refMetaRes.data.almanak_sdk_version) !== null && _t !== void 0 ? _t : null;
|
|
1807
1801
|
if (!sdkVersion) {
|
|
1808
1802
|
return fail(400, 'Could not detect the Almanak SDK version from pyproject.toml at the selected commit.');
|
|
1809
1803
|
}
|
|
1810
|
-
if (((_u = (
|
|
1804
|
+
if (((_u = (_a = parseSdkVersion(sdkVersion)) === null || _a === void 0 ? void 0 : _a.major) !== null && _u !== void 0 ? _u : 0) >= 3) {
|
|
1811
1805
|
// The backend refuses a v3 SDK against a V2 record; say why instead of submitting the v2 shape.
|
|
1812
1806
|
return fail(400, `Commit ${commitSha.slice(0, 7)} resolves almanak ${sdkVersion} (SDK v3), but the strategy link is stored as SDK v2. ` +
|
|
1813
1807
|
'The generations disagree, so nothing was submitted; SDK v2 window inputs cannot backtest an SDK v3 repository.', { errorCode: 'SDK_GENERATION_MISMATCH', commit_sha: commitSha, sdk_version: sdkVersion });
|
|
@@ -1857,7 +1851,8 @@ class PlatformToolHandler {
|
|
|
1857
1851
|
* throws and every path returns a widget-renderable shape.
|
|
1858
1852
|
*/
|
|
1859
1853
|
async runV3Backtest(args, strategyLinkId, strategy) {
|
|
1860
|
-
var _a, _b, _c
|
|
1854
|
+
var _a, _b, _c;
|
|
1855
|
+
var _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
1861
1856
|
const strategyName = (typeof strategy.display_name === 'string' && strategy.display_name) ||
|
|
1862
1857
|
(typeof strategy.github_repo_name === 'string' && strategy.github_repo_name) ||
|
|
1863
1858
|
null;
|
|
@@ -1906,18 +1901,18 @@ class PlatformToolHandler {
|
|
|
1906
1901
|
const recoveryContext = { requestedCommit: explicitSha || null, linkedRepo, defaultBranch };
|
|
1907
1902
|
try {
|
|
1908
1903
|
const refConfigRes = await this.client.getStrategyRefConfig(strategyLinkId, ref, refType);
|
|
1909
|
-
const commitSha = (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.valid) === false ? '' : String((
|
|
1904
|
+
const commitSha = (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.valid) === false ? '' : String((_d = (_a = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.data) === null || _a === void 0 ? void 0 : _a.github_commit_sha) !== null && _d !== void 0 ? _d : '');
|
|
1910
1905
|
if (!FULL_COMMIT_SHA_RE.test(commitSha)) {
|
|
1911
|
-
const baseError = (
|
|
1906
|
+
const baseError = (_f = (_e = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.message) !== null && _e !== void 0 ? _e : refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.error) !== null && _f !== void 0 ? _f : `Could not resolve ${refType} "${ref}" in the linked strategy repository.`;
|
|
1912
1907
|
// Push advice fits only a ref the repository does not have; access and availability errors keep their own text.
|
|
1913
|
-
const errorCode = (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.valid) === false ? ((
|
|
1908
|
+
const errorCode = (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.valid) === false ? ((_g = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.errorCode) !== null && _g !== void 0 ? _g : 'INTERNAL_ERROR') : 'COMMIT_UNRESOLVED';
|
|
1914
1909
|
const guidance = errorCode !== 'COMMIT_UNRESOLVED'
|
|
1915
1910
|
? ''
|
|
1916
1911
|
: explicitSha
|
|
1917
1912
|
? ` Only pushed commits can be backtested: make sure the commit is pushed to ${linkedRepo !== null && linkedRepo !== void 0 ? linkedRepo : 'the linked repository'} ` +
|
|
1918
1913
|
'(git push, then git rev-parse HEAD) and call again with that SHA. Do not switch to a different commit without the user.'
|
|
1919
1914
|
: ` Push the branch to ${linkedRepo !== null && linkedRepo !== void 0 ? linkedRepo : 'the linked repository'} first.`;
|
|
1920
|
-
return fail((
|
|
1915
|
+
return fail((_h = refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.statusCode) !== null && _h !== void 0 ? _h : 400, `${baseError}${guidance}`, {
|
|
1921
1916
|
errorCode,
|
|
1922
1917
|
retryable: (refConfigRes === null || refConfigRes === void 0 ? void 0 : refConfigRes.retryable) === true,
|
|
1923
1918
|
...recoveryContext,
|
|
@@ -1926,7 +1921,7 @@ class PlatformToolHandler {
|
|
|
1926
1921
|
context.commit_sha = commitSha;
|
|
1927
1922
|
const refMetaRes = await this.client.getStrategyRefMetadata(strategyLinkId, commitSha);
|
|
1928
1923
|
if ((refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.valid) === false || !(refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.data)) {
|
|
1929
|
-
return fail((
|
|
1924
|
+
return fail((_j = refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.statusCode) !== null && _j !== void 0 ? _j : 400, (_l = (_k = refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.message) !== null && _k !== void 0 ? _k : refMetaRes === null || refMetaRes === void 0 ? void 0 : refMetaRes.error) !== null && _l !== void 0 ? _l : 'Could not load strategy ref metadata');
|
|
1930
1925
|
}
|
|
1931
1926
|
const meta = refMetaRes.data;
|
|
1932
1927
|
const sdkVersion = typeof meta.almanak_sdk_version === 'string' ? meta.almanak_sdk_version : '';
|
|
@@ -1936,7 +1931,7 @@ class PlatformToolHandler {
|
|
|
1936
1931
|
});
|
|
1937
1932
|
}
|
|
1938
1933
|
context.sdk_version = sdkVersion;
|
|
1939
|
-
if (((
|
|
1934
|
+
if (((_m = (_b = parseSdkVersion(sdkVersion)) === null || _b === void 0 ? void 0 : _b.major) !== null && _m !== void 0 ? _m : 0) < 3 || !isSdkVersionBacktestable(sdkVersion, backtest_v3_1.MIN_BACKTEST_SDK_VERSION_V3)) {
|
|
1940
1935
|
return fail(400, `Hosted SDK v3 backtests need almanak ${backtest_v3_1.MIN_BACKTEST_SDK_VERSION_V3} or newer; commit ${commitSha.slice(0, 7)} resolves ` +
|
|
1941
1936
|
`${sdkVersion}. Update the almanak pin (uv.lock / pyproject.toml), commit, push and re-run.`, { errorCode: 'V3_BACKTEST_INPUT_INVALID' });
|
|
1942
1937
|
}
|
|
@@ -1967,7 +1962,7 @@ class PlatformToolHandler {
|
|
|
1967
1962
|
// The file must exist at the commit; its contents are validated by the runner's pinned SDK, not here.
|
|
1968
1963
|
if (committed[backtestPath] === undefined) {
|
|
1969
1964
|
const fileRes = await this.client.getStrategyFileContent(strategyLinkId, backtestPath, commitSha);
|
|
1970
|
-
const file = (fileRes === null || fileRes === void 0 ? void 0 : fileRes.valid) === false ? null : (
|
|
1965
|
+
const file = (fileRes === null || fileRes === void 0 ? void 0 : fileRes.valid) === false ? null : (_c = fileRes === null || fileRes === void 0 ? void 0 : fileRes.data) === null || _c === void 0 ? void 0 : _c.file;
|
|
1971
1966
|
const lookupError = (fileRes === null || fileRes === void 0 ? void 0 : fileRes.valid) === false ? String((_p = (_o = fileRes === null || fileRes === void 0 ? void 0 : fileRes.message) !== null && _o !== void 0 ? _o : fileRes === null || fileRes === void 0 ? void 0 : fileRes.error) !== null && _p !== void 0 ? _p : '') : '';
|
|
1972
1967
|
if (file && typeof file.content !== 'string') {
|
|
1973
1968
|
// The preview refuses some present files (build/dist/venv paths, directories, oversized files) with a reason.
|
|
@@ -2021,7 +2016,8 @@ class PlatformToolHandler {
|
|
|
2021
2016
|
* path returned — equity curves and per-trade detail are read on demand.
|
|
2022
2017
|
*/
|
|
2023
2018
|
async getBacktestResults(args) {
|
|
2024
|
-
var _a, _b
|
|
2019
|
+
var _a, _b;
|
|
2020
|
+
var _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
2025
2021
|
const backtestId = typeof args.backtest_id === 'string' ? args.backtest_id.trim() : '';
|
|
2026
2022
|
if (!backtestId) {
|
|
2027
2023
|
return {
|
|
@@ -2034,30 +2030,30 @@ class PlatformToolHandler {
|
|
|
2034
2030
|
run = await this.client.getBacktest(backtestId);
|
|
2035
2031
|
}
|
|
2036
2032
|
catch (err) {
|
|
2037
|
-
return { statusCode: 502, error: `Backtest lookup failed: ${(
|
|
2033
|
+
return { statusCode: 502, error: `Backtest lookup failed: ${(_c = err === null || err === void 0 ? void 0 : err.message) !== null && _c !== void 0 ? _c : String(err)}` };
|
|
2038
2034
|
}
|
|
2039
2035
|
if (!run || run.valid === false) {
|
|
2040
2036
|
return {
|
|
2041
|
-
statusCode: (
|
|
2042
|
-
error: (
|
|
2037
|
+
statusCode: (_d = run === null || run === void 0 ? void 0 : run.statusCode) !== null && _d !== void 0 ? _d : 404,
|
|
2038
|
+
error: (_e = run === null || run === void 0 ? void 0 : run.error) !== null && _e !== void 0 ? _e : 'Backtest run not found',
|
|
2043
2039
|
backtest_id: backtestId,
|
|
2044
2040
|
};
|
|
2045
2041
|
}
|
|
2046
2042
|
if ((0, backtest_v3_1.isV3BacktestRun)(run)) {
|
|
2047
2043
|
return this.getV3BacktestResults(backtestId, run);
|
|
2048
2044
|
}
|
|
2049
|
-
const summaryVerdict = summarizeRunValidity((
|
|
2045
|
+
const summaryVerdict = summarizeRunValidity((_a = run.result_summary) === null || _a === void 0 ? void 0 : _a.run_validity);
|
|
2050
2046
|
const base = {
|
|
2051
|
-
backtest_id: (
|
|
2047
|
+
backtest_id: (_f = run.id) !== null && _f !== void 0 ? _f : backtestId,
|
|
2052
2048
|
status: run.status,
|
|
2053
|
-
created_at: (
|
|
2054
|
-
completed_at: (
|
|
2055
|
-
strategy_link_id: (
|
|
2056
|
-
commit_sha: (
|
|
2057
|
-
sdk_version: (
|
|
2058
|
-
result_summary: (
|
|
2049
|
+
created_at: (_g = run.created_at) !== null && _g !== void 0 ? _g : null,
|
|
2050
|
+
completed_at: (_h = run.completed_at) !== null && _h !== void 0 ? _h : null,
|
|
2051
|
+
strategy_link_id: (_j = run.github_strategy_link_id) !== null && _j !== void 0 ? _j : null,
|
|
2052
|
+
commit_sha: (_k = run.commit_sha) !== null && _k !== void 0 ? _k : null,
|
|
2053
|
+
sdk_version: (_l = run.sdk_version) !== null && _l !== void 0 ? _l : null,
|
|
2054
|
+
result_summary: (_m = run.result_summary) !== null && _m !== void 0 ? _m : null,
|
|
2059
2055
|
run_validity: summaryVerdict,
|
|
2060
|
-
error_message: (
|
|
2056
|
+
error_message: (_o = run.error_message) !== null && _o !== void 0 ? _o : null,
|
|
2061
2057
|
};
|
|
2062
2058
|
if (run.status !== 'COMPLETED') {
|
|
2063
2059
|
let hint;
|
|
@@ -2086,24 +2082,24 @@ class PlatformToolHandler {
|
|
|
2086
2082
|
doc = await this.client.getBacktestResult(backtestId);
|
|
2087
2083
|
}
|
|
2088
2084
|
catch (err) {
|
|
2089
|
-
return { ...base, result_fetch_error: `Result fetch failed: ${(
|
|
2085
|
+
return { ...base, result_fetch_error: `Result fetch failed: ${(_p = err === null || err === void 0 ? void 0 : err.message) !== null && _p !== void 0 ? _p : String(err)}` };
|
|
2090
2086
|
}
|
|
2091
2087
|
if (!doc || doc.valid === false) {
|
|
2092
|
-
return { ...base, result_fetch_error: (
|
|
2088
|
+
return { ...base, result_fetch_error: (_q = doc === null || doc === void 0 ? void 0 : doc.error) !== null && _q !== void 0 ? _q : 'Backtest result not found' };
|
|
2093
2089
|
}
|
|
2094
2090
|
// Compute the compact inline fields BEFORE artifact persistence, so a
|
|
2095
2091
|
// failed write degrades to summaries-without-a-file instead of losing
|
|
2096
2092
|
// the whole (successful) lookup.
|
|
2097
|
-
const result = (
|
|
2093
|
+
const result = (_r = doc.result) !== null && _r !== void 0 ? _r : {};
|
|
2098
2094
|
const trades = Array.isArray(result.trades) ? result.trades : [];
|
|
2099
|
-
const decisionSummary = (
|
|
2100
|
-
const runValidity = (
|
|
2095
|
+
const decisionSummary = (_s = result.decision_summary) !== null && _s !== void 0 ? _s : null;
|
|
2096
|
+
const runValidity = (_t = summarizeRunValidity(result.run_validity)) !== null && _t !== void 0 ? _t : summaryVerdict;
|
|
2101
2097
|
const inline = {
|
|
2102
2098
|
...base,
|
|
2103
2099
|
run_validity: runValidity,
|
|
2104
2100
|
decision_summary: decisionSummary,
|
|
2105
|
-
decision_input_failures: (
|
|
2106
|
-
data_manifest_summary: (_v = (
|
|
2101
|
+
decision_input_failures: (_u = result.decision_input_failures) !== null && _u !== void 0 ? _u : [],
|
|
2102
|
+
data_manifest_summary: (_v = (_b = result.data_manifest) === null || _b === void 0 ? void 0 : _b.summary) !== null && _v !== void 0 ? _v : null,
|
|
2107
2103
|
trades_count: trades.length,
|
|
2108
2104
|
};
|
|
2109
2105
|
const passiveHint = (runValidity === null || runValidity === void 0 ? void 0 : runValidity.passive_only) === true
|