data fixes, partial custom indicator support
This commit is contained in:
@@ -55,6 +55,20 @@ export class ContainerSync {
|
||||
this.logger = logger.child({ component: 'ContainerSync' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a raw MCP callTool response into the tool's return value.
|
||||
* MCP tool results are wrapped as: { content: [{ type: 'text', text: '<json>' }] }
|
||||
*/
|
||||
private parseMcpResult(raw: unknown): unknown {
|
||||
const r = raw as any;
|
||||
const text = r?.content?.[0]?.text ?? r?.[0]?.text;
|
||||
if (typeof text === 'string') {
|
||||
return JSON.parse(text);
|
||||
}
|
||||
// Already unwrapped (shouldn't happen in practice)
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a workspace store from the container.
|
||||
* Returns the stored state or indicates the store doesn't exist.
|
||||
@@ -68,7 +82,7 @@ export class ContainerSync {
|
||||
try {
|
||||
this.logger.debug({ store: storeName }, 'Loading store from container');
|
||||
|
||||
const result = (await this.mcpClient.callTool('workspace_read', {
|
||||
const result = this.parseMcpResult(await this.mcpClient.callTool('workspace_read', {
|
||||
store_name: storeName,
|
||||
})) as { exists: boolean; data?: unknown; error?: string };
|
||||
|
||||
@@ -104,7 +118,7 @@ export class ContainerSync {
|
||||
try {
|
||||
this.logger.debug({ store: storeName }, 'Saving store to container');
|
||||
|
||||
const result = (await this.mcpClient.callTool('workspace_write', {
|
||||
const result = this.parseMcpResult(await this.mcpClient.callTool('workspace_write', {
|
||||
store_name: storeName,
|
||||
data: state,
|
||||
})) as { success: boolean; error?: string };
|
||||
@@ -136,7 +150,7 @@ export class ContainerSync {
|
||||
try {
|
||||
this.logger.debug({ store: storeName, patchOps: patch.length }, 'Patching store in container');
|
||||
|
||||
const result = (await this.mcpClient.callTool('workspace_patch', {
|
||||
const result = this.parseMcpResult(await this.mcpClient.callTool('workspace_patch', {
|
||||
store_name: storeName,
|
||||
patch,
|
||||
})) as { success: boolean; data?: unknown; error?: string };
|
||||
|
||||
@@ -59,12 +59,12 @@ class SyncEntry {
|
||||
|
||||
/**
|
||||
* Set state directly (used for loading from container).
|
||||
* Resets sequence to 0.
|
||||
* Sets sequence to 1 so clients at seq 0 (empty state) receive a full snapshot.
|
||||
*/
|
||||
setState(newState: unknown): void {
|
||||
this.state = deepClone(newState);
|
||||
this.lastSnapshot = deepClone(newState);
|
||||
this.seq = 0;
|
||||
this.seq = 1;
|
||||
this.history = [];
|
||||
}
|
||||
|
||||
|
||||
@@ -272,12 +272,84 @@ export interface Shape {
|
||||
*/
|
||||
export type ShapesStore = Record<string, Shape>;
|
||||
|
||||
/**
|
||||
* Parameter schema entry for a custom indicator.
|
||||
*/
|
||||
export interface CustomIndicatorParam {
|
||||
type: 'int' | 'float' | 'bool' | 'string';
|
||||
default: any;
|
||||
description?: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-series plot configuration for a custom indicator output column.
|
||||
* style maps to LineStudyPlotStyle: 0=Line, 1=Histogram, 3=Dots/Cross,
|
||||
* 4=Area, 5=Columns, 6=Circles, 9=StepLine.
|
||||
*/
|
||||
export interface PlotConfig {
|
||||
style: number;
|
||||
color?: string;
|
||||
linewidth?: number;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shaded region between two plots ("plot_plot") or two bands ("hline_hline").
|
||||
*/
|
||||
export interface FilledAreaConfig {
|
||||
id: string;
|
||||
type: 'plot_plot' | 'hline_hline';
|
||||
series1: string;
|
||||
series2: string;
|
||||
color?: string;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal reference line (e.g. RSI overbought/oversold level).
|
||||
* linestyle: 0=solid, 1=dotted, 2=dashed.
|
||||
*/
|
||||
export interface BandConfig {
|
||||
id: string;
|
||||
value: number;
|
||||
color?: string;
|
||||
linewidth?: number;
|
||||
linestyle?: number;
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output column descriptor for a custom indicator.
|
||||
*/
|
||||
export interface CustomIndicatorColumn {
|
||||
name: string;
|
||||
display_name?: string;
|
||||
description?: string;
|
||||
plot?: PlotConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata needed to auto-construct a TradingView custom study.
|
||||
* Populated by the indicator subagent when adding a custom_ indicator.
|
||||
*/
|
||||
export interface CustomIndicatorMetadata {
|
||||
display_name: string;
|
||||
parameters: Record<string, CustomIndicatorParam>;
|
||||
input_series: string[];
|
||||
output_columns: CustomIndicatorColumn[];
|
||||
pane: 'price' | 'separate';
|
||||
filled_areas?: FilledAreaConfig[];
|
||||
bands?: BandConfig[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicator instance on TradingView chart.
|
||||
*/
|
||||
export interface IndicatorInstance {
|
||||
id: string;
|
||||
talib_name: string;
|
||||
pandas_ta_name: string;
|
||||
instance_name: string;
|
||||
parameters: Record<string, any>;
|
||||
tv_study_id?: string;
|
||||
@@ -289,6 +361,8 @@ export interface IndicatorInstance {
|
||||
created_at?: number;
|
||||
modified_at?: number;
|
||||
original_id?: string;
|
||||
/** Populated for custom_ indicators; drives TV custom study auto-construction. */
|
||||
custom_metadata?: CustomIndicatorMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user