horizon-code 0.3.3 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ai/client.ts +2 -2
- package/src/app.ts +23 -9
- package/src/components/code-panel.ts +2 -2
- package/src/strategy/dashboard.ts +459 -217
- package/src/strategy/prompts.ts +212 -13
- package/src/strategy/tools.ts +211 -23
- package/src/strategy/validator.ts +25 -1
- package/src/strategy/workspace.ts +175 -0
- package/src/syntax/setup.ts +22 -4
package/package.json
CHANGED
package/src/ai/client.ts
CHANGED
|
@@ -242,7 +242,7 @@ export async function* chat(
|
|
|
242
242
|
const serverMessages = messages.map((m) => ({ role: m.role, content: m.content }));
|
|
243
243
|
|
|
244
244
|
let step = 0;
|
|
245
|
-
const MAX_STEPS =
|
|
245
|
+
const MAX_STEPS = 15;
|
|
246
246
|
|
|
247
247
|
while (step < MAX_STEPS) {
|
|
248
248
|
step++;
|
|
@@ -379,7 +379,7 @@ export async function* chat(
|
|
|
379
379
|
// Add as assistant message — the LLM sees it already ran the tools
|
|
380
380
|
serverMessages.push({ role: "assistant", content: assistantParts.join("\n\n") });
|
|
381
381
|
// Prompt the LLM to continue with its response based on the tool results
|
|
382
|
-
serverMessages.push({ role: "user", content:
|
|
382
|
+
serverMessages.push({ role: "user", content: `Now respond to the user based on the tool results above. Do NOT call the same tools again. [Step ${step}/${MAX_STEPS} used]` });
|
|
383
383
|
|
|
384
384
|
// Reset structured output state for next turn
|
|
385
385
|
if (structuredActive) {
|
package/src/app.ts
CHANGED
|
@@ -456,8 +456,8 @@ export class App {
|
|
|
456
456
|
if (m.proc.exitCode === null) {
|
|
457
457
|
alive++;
|
|
458
458
|
// Filter out __HZ_METRICS__ lines from visible logs
|
|
459
|
-
const stdoutLines = m.stdout.slice(-
|
|
460
|
-
const stderrLines = m.stderr.slice(-
|
|
459
|
+
const stdoutLines = m.stdout.slice(-100);
|
|
460
|
+
const stderrLines = m.stderr.slice(-50).filter((l: string) => !l.startsWith("__HZ_METRICS__"));
|
|
461
461
|
latestLogs = stdoutLines.join("\n") + (stderrLines.length > 0 ? "\n--- stderr ---\n" + stderrLines.join("\n") : "");
|
|
462
462
|
|
|
463
463
|
// Parse latest metrics from this process
|
|
@@ -466,8 +466,22 @@ export class App {
|
|
|
466
466
|
localMetricsData = metrics;
|
|
467
467
|
localProcessStartedAt = m.startedAt;
|
|
468
468
|
}
|
|
469
|
-
} else
|
|
470
|
-
|
|
469
|
+
} else {
|
|
470
|
+
// Process exited — check if it crashed (only notify once)
|
|
471
|
+
const exitCode = m.proc.exitCode;
|
|
472
|
+
if (exitCode !== null && exitCode !== 0 && !(m as any)._crashNotified) {
|
|
473
|
+
(m as any)._crashNotified = true;
|
|
474
|
+
const lastStderr = m.stderr.slice(-5).join("\n");
|
|
475
|
+
const crashMsg = `[CRASH] Process ${pid} exited with code ${exitCode}`;
|
|
476
|
+
this.codePanel.appendLog(crashMsg);
|
|
477
|
+
if (lastStderr) {
|
|
478
|
+
this.codePanel.appendLog(lastStderr);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// Clean up dead processes after 5 minutes
|
|
482
|
+
if (now - m.startedAt > 300000) {
|
|
483
|
+
deadPids.push(pid);
|
|
484
|
+
}
|
|
471
485
|
}
|
|
472
486
|
}
|
|
473
487
|
for (const pid of deadPids) runningProcesses.delete(pid);
|
|
@@ -485,13 +499,13 @@ export class App {
|
|
|
485
499
|
total_pnl: localMetricsData.pnl,
|
|
486
500
|
realized_pnl: localMetricsData.rpnl,
|
|
487
501
|
unrealized_pnl: localMetricsData.upnl,
|
|
488
|
-
total_exposure: 0,
|
|
502
|
+
total_exposure: localMetricsData.exposure ?? 0,
|
|
489
503
|
position_count: localMetricsData.positions,
|
|
490
504
|
open_order_count: localMetricsData.orders,
|
|
491
|
-
win_rate: 0,
|
|
492
|
-
total_trades: 0,
|
|
493
|
-
max_drawdown_pct: 0,
|
|
494
|
-
sharpe_ratio: 0,
|
|
505
|
+
win_rate: localMetricsData.win_rate ?? 0,
|
|
506
|
+
total_trades: localMetricsData.trades ?? 0,
|
|
507
|
+
max_drawdown_pct: localMetricsData.max_dd ?? 0,
|
|
508
|
+
sharpe_ratio: localMetricsData.sharpe ?? 0,
|
|
495
509
|
profit_factor: 0,
|
|
496
510
|
avg_return_per_trade: 0,
|
|
497
511
|
gross_profit: 0,
|
|
@@ -339,9 +339,9 @@ export class CodePanel {
|
|
|
339
339
|
|
|
340
340
|
appendLog(line: string): void {
|
|
341
341
|
this._logs += (this._logs ? "\n" : "") + line;
|
|
342
|
-
// Keep last
|
|
342
|
+
// Keep last 1000 lines
|
|
343
343
|
const lines = this._logs.split("\n");
|
|
344
|
-
if (lines.length >
|
|
344
|
+
if (lines.length > 1000) this._logs = lines.slice(-1000).join("\n");
|
|
345
345
|
if (this._activeTab === "logs") this.updateLogsContent();
|
|
346
346
|
}
|
|
347
347
|
|