prod deployment

This commit is contained in:
2026-04-01 18:34:08 -04:00
parent ca44e68f64
commit eab581f8cb
62 changed files with 1922 additions and 286 deletions

View File

@@ -348,8 +348,8 @@ export class WebSocketHandler {
/**
* Derive the container's XPUB event endpoint from the MCP server URL.
*
* MCP URL format: http://sandbox-user-abc123.dexorder-sandboxes.svc.cluster.local:3000
* Event endpoint: tcp://sandbox-user-abc123.dexorder-sandboxes.svc.cluster.local:5570
* MCP URL format: http://sandbox-user-abc123.sandbox.svc.cluster.local:3000
* Event endpoint: tcp://sandbox-user-abc123.sandbox.svc.cluster.local:5570
*/
private getContainerEventEndpoint(mcpServerUrl: string): string {
try {

View File

@@ -30,7 +30,7 @@ type hints, docstrings, and examples.
### api.py
```python
"""
Main DexOrder API - provides access to market data and charting.
Main Dexorder API - provides access to market data and charting.
"""
import logging
@@ -311,8 +311,10 @@ class ChartingAPI(ABC):
)
# Overlay moving average
# NOTE: mplfinance uses integer x-positions (0..N-1) internally,
# so overlays must use range(len(df)), not df.index.
fig, ax = api.plot_ohlc(df)
ax.plot(df.index, df['sma_20'], label="SMA 20", color="blue")
ax.plot(range(len(df)), df['sma_20'], label="SMA 20", color="blue")
ax.legend()
"""
pass
@@ -406,7 +408,7 @@ class ChartingAPI(ABC):
### __init__.py
```python
"""
DexOrder API - market data and charting for research and trading.
Dexorder API - market data and charting for research and trading.
For research scripts, import and use get_api() to access the API:

View File

@@ -214,7 +214,7 @@ df['macd_signal'] = macd_df.iloc[:, 2]
# Main price chart with EMA overlay
fig, ax = api.charting.plot_ohlc(df, title="BTC/USDT 1H", volume=True)
ax.plot(df.index, df['ema_20'], label="EMA 20", color="orange", linewidth=1.5)
ax.plot(range(len(df)), df['ema_20'], label="EMA 20", color="orange", linewidth=1.5) # range(len(df)), not df.index
ax.legend()
# RSI panel

View File

@@ -137,7 +137,8 @@ df['rsi'] = ta.rsi(df['close'], length=14)
fig, ax = api.charting.plot_ohlc(df, title="BTC/USDT with SMA")
# Overlay the SMA on the price chart
ax.plot(df.index, df['sma_20'], label="SMA 20", color="blue", linewidth=2)
# NOTE: mplfinance uses integer x-positions (0..N-1); use range(len(df)), not df.index.
ax.plot(range(len(df)), df['sma_20'], label="SMA 20", color="blue", linewidth=2)
ax.legend()
# Add RSI indicator panel below
@@ -211,8 +212,9 @@ fig, ax = api.charting.plot_ohlc(
)
# Overlay moving averages
ax.plot(df.index, df['sma_20'], label="SMA 20", color="blue", linewidth=1.5)
ax.plot(df.index, df['ema_50'], label="EMA 50", color="red", linewidth=1.5)
# NOTE: mplfinance uses integer x-positions (0..N-1); use range(len(df)), not df.index.
ax.plot(range(len(df)), df['sma_20'], label="SMA 20", color="blue", linewidth=1.5)
ax.plot(range(len(df)), df['ema_50'], label="EMA 50", color="red", linewidth=1.5)
ax.legend()
# Print summary statistics

View File

@@ -24,6 +24,7 @@ export interface DeploymentSpec {
sidecarImage: string;
storageClass: string;
imagePullPolicy?: string;
serviceNamespace: string; // namespace where relay/minio/iceberg/gateway services live
}
/**
@@ -139,7 +140,8 @@ export class KubernetesClient {
.replace(/\{\{storage\}\}/g, r.storage)
.replace(/\{\{tmpSizeLimit\}\}/g, r.tmpSizeLimit)
.replace(/\{\{enableIdleShutdown\}\}/g, String(r.enableIdleShutdown))
.replace(/\{\{idleTimeoutMinutes\}\}/g, String(r.idleTimeoutMinutes));
.replace(/\{\{idleTimeoutMinutes\}\}/g, String(r.idleTimeoutMinutes))
.replace(/\{\{serviceNamespace\}\}/g, spec.serviceNamespace);
// Parse YAML documents (deployment, pvc, service)
const documents = yaml.loadAll(rendered) as any[];

View File

@@ -9,6 +9,7 @@ export interface ContainerManagerConfig {
storageClass: string;
imagePullPolicy?: string;
namespace: string;
serviceNamespace: string;
logger: FastifyBaseLogger;
}
@@ -85,6 +86,7 @@ export class ContainerManager {
sidecarImage: this.config.sidecarImage,
storageClass: this.config.storageClass,
imagePullPolicy: this.config.imagePullPolicy,
serviceNamespace: this.config.serviceNamespace,
};
await this.config.k8sClient.createAgentDeployment(spec);

View File

@@ -1,7 +1,7 @@
# Sandbox deployment template — variables are populated from the user's License k8sResources.
# Variables: {{userId}}, {{deploymentName}}, {{pvcName}}, {{serviceName}},
# {{sandboxImage}}, {{sidecarImage}}, {{imagePullPolicy}}, {{storageClass}},
# {{licenseType}},
# {{serviceNamespace}}, {{licenseType}},
# {{memoryRequest}}, {{memoryLimit}}, {{cpuRequest}}, {{cpuLimit}},
# {{storage}}, {{tmpSizeLimit}},
# {{enableIdleShutdown}}, {{idleTimeoutMinutes}}
@@ -10,7 +10,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{deploymentName}}
namespace: dexorder-sandboxes
labels:
app.kubernetes.io/name: sandbox
app.kubernetes.io/component: user-sandbox
@@ -77,15 +76,15 @@ spec:
- name: ZMQ_CONTROL_PORT
value: "5555"
- name: ZMQ_GATEWAY_ENDPOINT
value: "tcp://gateway.default.svc.cluster.local:5571"
value: "tcp://gateway.{{serviceNamespace}}.svc.cluster.local:5571"
- name: ICEBERG_CATALOG_URI
value: "http://iceberg-catalog.default.svc.cluster.local:8181"
value: "http://iceberg-catalog.{{serviceNamespace}}.svc.cluster.local:8181"
- name: ICEBERG_NAMESPACE
value: "trading"
- name: S3_ENDPOINT
value: "http://minio.default.svc.cluster.local:9000"
value: "http://minio.{{serviceNamespace}}.svc.cluster.local:9000"
- name: RELAY_ENDPOINT
value: "tcp://relay.default.svc.cluster.local:5559"
value: "tcp://relay.{{serviceNamespace}}.svc.cluster.local:5559"
ports:
- name: mcp
@@ -188,7 +187,6 @@ apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{pvcName}}
namespace: dexorder-sandboxes
labels:
dexorder.io/user-id: {{userId}}
dexorder.io/license-tier: {{licenseType}}
@@ -204,7 +202,6 @@ apiVersion: v1
kind: Service
metadata:
name: {{serviceName}}
namespace: dexorder-sandboxes
labels:
dexorder.io/user-id: {{userId}}
dexorder.io/license-tier: {{licenseType}}

View File

@@ -172,7 +172,8 @@ function loadConfig() {
// Kubernetes configuration
kubernetes: {
namespace: configData.kubernetes?.namespace || process.env.KUBERNETES_NAMESPACE || 'dexorder-sandboxes',
namespace: configData.kubernetes?.namespace || process.env.KUBERNETES_NAMESPACE || 'sandbox',
serviceNamespace: configData.kubernetes?.service_namespace || process.env.KUBERNETES_SERVICE_NAMESPACE || 'default',
inCluster: configData.kubernetes?.in_cluster ?? (process.env.KUBERNETES_IN_CLUSTER === 'true'),
context: configData.kubernetes?.context || process.env.KUBERNETES_CONTEXT,
sandboxImage: configData.kubernetes?.sandbox_image || process.env.SANDBOX_IMAGE || 'ghcr.io/dexorder/sandbox:latest',
@@ -312,6 +313,7 @@ const containerManager = new ContainerManager({
storageClass: config.kubernetes.storageClass,
imagePullPolicy: config.kubernetes.imagePullPolicy,
namespace: config.kubernetes.namespace,
serviceNamespace: config.kubernetes.serviceNamespace,
logger: app.log,
});
app.log.debug('Container manager initialized');