@agenticmail/enterprise 0.5.94 → 0.5.95
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.
|
@@ -3745,35 +3745,89 @@ function DeploymentSection(props) {
|
|
|
3745
3745
|
var deployForm = _deployForm[0]; var setDeployForm = _deployForm[1];
|
|
3746
3746
|
|
|
3747
3747
|
var startDeployEdit = function() {
|
|
3748
|
+
var cloud = deployment.config?.cloud || {};
|
|
3749
|
+
var docker = deployment.config?.docker || {};
|
|
3750
|
+
var vps = deployment.config?.vps || {};
|
|
3751
|
+
var aws = deployment.config?.aws || {};
|
|
3752
|
+
var gcp = deployment.config?.gcp || {};
|
|
3753
|
+
var az = deployment.config?.azure || {};
|
|
3754
|
+
var rail = deployment.config?.railway || {};
|
|
3748
3755
|
setDeployForm({
|
|
3749
3756
|
target: deployment.target || 'fly',
|
|
3750
|
-
region: deployment.region ||
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3757
|
+
region: deployment.region || cloud.region || 'iad',
|
|
3758
|
+
// Fly.io
|
|
3759
|
+
flyApiToken: cloud.apiToken || '',
|
|
3760
|
+
flyAppName: cloud.appName || '',
|
|
3761
|
+
flyOrg: cloud.org || 'personal',
|
|
3762
|
+
flyVmSize: cloud.vmSize || 'shared-cpu-1x',
|
|
3763
|
+
flyVmMemory: cloud.vmMemory || '256',
|
|
3764
|
+
// Docker
|
|
3765
|
+
dockerImage: docker.image || 'agenticmail/agent',
|
|
3766
|
+
dockerTag: docker.tag || 'latest',
|
|
3767
|
+
dockerMemory: docker.memory || '512m',
|
|
3768
|
+
dockerCpu: docker.cpu || '0.5',
|
|
3769
|
+
dockerPorts: (docker.ports || [3000]).join(', '),
|
|
3770
|
+
dockerNetwork: docker.network || '',
|
|
3771
|
+
dockerRestart: docker.restart || 'unless-stopped',
|
|
3772
|
+
// VPS
|
|
3773
|
+
vpsHost: vps.host || '',
|
|
3774
|
+
vpsPort: vps.port || '22',
|
|
3775
|
+
vpsUser: vps.user || 'root',
|
|
3776
|
+
vpsKeyPath: vps.keyPath || '~/.ssh/id_rsa',
|
|
3777
|
+
vpsWorkDir: vps.workDir || '/opt/agenticmail',
|
|
3778
|
+
// AWS
|
|
3779
|
+
awsRegion: aws.region || 'us-east-1',
|
|
3780
|
+
awsAccessKeyId: aws.accessKeyId || '',
|
|
3781
|
+
awsSecretAccessKey: aws.secretAccessKey || '',
|
|
3782
|
+
awsInstanceType: aws.instanceType || 't3.micro',
|
|
3783
|
+
awsAmi: aws.ami || '',
|
|
3784
|
+
awsSubnetId: aws.subnetId || '',
|
|
3785
|
+
awsSecurityGroupId: aws.securityGroupId || '',
|
|
3786
|
+
awsKeyPairName: aws.keyPairName || '',
|
|
3787
|
+
// GCP
|
|
3788
|
+
gcpProject: gcp.projectId || '',
|
|
3789
|
+
gcpRegion: gcp.region || 'us-central1',
|
|
3790
|
+
gcpZone: gcp.zone || 'us-central1-a',
|
|
3791
|
+
gcpMachineType: gcp.machineType || 'e2-micro',
|
|
3792
|
+
gcpServiceAccountKey: gcp.serviceAccountKey || '',
|
|
3793
|
+
// Azure
|
|
3794
|
+
azureSubscriptionId: az.subscriptionId || '',
|
|
3795
|
+
azureResourceGroup: az.resourceGroup || '',
|
|
3796
|
+
azureRegion: az.region || 'eastus',
|
|
3797
|
+
azureVmSize: az.vmSize || 'Standard_B1s',
|
|
3798
|
+
azureTenantId: az.tenantId || '',
|
|
3799
|
+
azureClientId: az.clientId || '',
|
|
3800
|
+
azureClientSecret: az.clientSecret || '',
|
|
3801
|
+
// Railway
|
|
3802
|
+
railwayApiToken: rail.apiToken || '',
|
|
3803
|
+
railwayProjectId: rail.projectId || '',
|
|
3804
|
+
railwayServiceName: rail.serviceName || '',
|
|
3760
3805
|
});
|
|
3761
3806
|
setEditingDeploy(true);
|
|
3762
3807
|
};
|
|
3763
3808
|
|
|
3764
3809
|
var saveDeploy = function() {
|
|
3765
3810
|
setSavingDeploy(true);
|
|
3811
|
+
var t = deployForm.target;
|
|
3766
3812
|
var deployConfig = {};
|
|
3767
|
-
if (
|
|
3768
|
-
deployConfig = { cloud: { provider: 'fly', region: deployForm.region || 'iad', apiToken: deployForm.flyApiToken || undefined, appName: deployForm.flyAppName || undefined } };
|
|
3769
|
-
} else if (
|
|
3770
|
-
deployConfig = { docker: { image: 'agenticmail/agent', tag: deployForm.
|
|
3771
|
-
} else if (
|
|
3772
|
-
deployConfig = { vps: { host: deployForm.vpsHost ||
|
|
3813
|
+
if (t === 'fly') {
|
|
3814
|
+
deployConfig = { cloud: { provider: 'fly', region: deployForm.region || 'iad', apiToken: deployForm.flyApiToken || undefined, appName: deployForm.flyAppName || undefined, org: deployForm.flyOrg || 'personal', vmSize: deployForm.flyVmSize || 'shared-cpu-1x', vmMemory: deployForm.flyVmMemory || '256' } };
|
|
3815
|
+
} else if (t === 'docker') {
|
|
3816
|
+
deployConfig = { docker: { image: deployForm.dockerImage || 'agenticmail/agent', tag: deployForm.dockerTag || 'latest', ports: (deployForm.dockerPorts || '3000').split(',').map(function(p) { return parseInt(p.trim()) || 3000; }), memory: deployForm.dockerMemory || '512m', cpu: deployForm.dockerCpu || '0.5', network: deployForm.dockerNetwork || undefined, restart: deployForm.dockerRestart || 'unless-stopped' } };
|
|
3817
|
+
} else if (t === 'vps') {
|
|
3818
|
+
deployConfig = { vps: { host: deployForm.vpsHost, port: parseInt(deployForm.vpsPort) || 22, user: deployForm.vpsUser || 'root', keyPath: deployForm.vpsKeyPath || '~/.ssh/id_rsa', workDir: deployForm.vpsWorkDir || '/opt/agenticmail' } };
|
|
3819
|
+
} else if (t === 'aws') {
|
|
3820
|
+
deployConfig = { aws: { region: deployForm.awsRegion || 'us-east-1', accessKeyId: deployForm.awsAccessKeyId || undefined, secretAccessKey: deployForm.awsSecretAccessKey || undefined, instanceType: deployForm.awsInstanceType || 't3.micro', ami: deployForm.awsAmi || undefined, subnetId: deployForm.awsSubnetId || undefined, securityGroupId: deployForm.awsSecurityGroupId || undefined, keyPairName: deployForm.awsKeyPairName || undefined } };
|
|
3821
|
+
} else if (t === 'gcp') {
|
|
3822
|
+
deployConfig = { gcp: { projectId: deployForm.gcpProject, region: deployForm.gcpRegion || 'us-central1', zone: deployForm.gcpZone || 'us-central1-a', machineType: deployForm.gcpMachineType || 'e2-micro', serviceAccountKey: deployForm.gcpServiceAccountKey || undefined } };
|
|
3823
|
+
} else if (t === 'azure') {
|
|
3824
|
+
deployConfig = { azure: { subscriptionId: deployForm.azureSubscriptionId, resourceGroup: deployForm.azureResourceGroup, region: deployForm.azureRegion || 'eastus', vmSize: deployForm.azureVmSize || 'Standard_B1s', tenantId: deployForm.azureTenantId || undefined, clientId: deployForm.azureClientId || undefined, clientSecret: deployForm.azureClientSecret || undefined } };
|
|
3825
|
+
} else if (t === 'railway') {
|
|
3826
|
+
deployConfig = { railway: { apiToken: deployForm.railwayApiToken || undefined, projectId: deployForm.railwayProjectId || undefined, serviceName: deployForm.railwayServiceName || undefined, region: deployForm.region || undefined } };
|
|
3773
3827
|
}
|
|
3774
3828
|
var updates = {
|
|
3775
3829
|
deployment: {
|
|
3776
|
-
target:
|
|
3830
|
+
target: t,
|
|
3777
3831
|
region: deployForm.region,
|
|
3778
3832
|
config: deployConfig
|
|
3779
3833
|
}
|
|
@@ -3844,57 +3898,313 @@ function DeploymentSection(props) {
|
|
|
3844
3898
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Target'),
|
|
3845
3899
|
h('select', { className: 'input', value: deployForm.target, onChange: function(e) { setDf('target', e.target.value); } },
|
|
3846
3900
|
h('option', { value: 'fly' }, 'Fly.io'),
|
|
3847
|
-
h('option', { value: '
|
|
3901
|
+
h('option', { value: 'aws' }, 'AWS (EC2)'),
|
|
3902
|
+
h('option', { value: 'gcp' }, 'Google Cloud (GCE)'),
|
|
3903
|
+
h('option', { value: 'azure' }, 'Microsoft Azure'),
|
|
3848
3904
|
h('option', { value: 'railway' }, 'Railway'),
|
|
3849
|
-
h('option', { value: '
|
|
3850
|
-
h('option', { value: '
|
|
3905
|
+
h('option', { value: 'docker' }, 'Docker'),
|
|
3906
|
+
h('option', { value: 'vps' }, 'VPS / Bare Metal'),
|
|
3907
|
+
h('option', { value: 'local' }, 'Local (In-Process)')
|
|
3851
3908
|
)
|
|
3852
3909
|
),
|
|
3910
|
+
// Region selector for cloud providers
|
|
3853
3911
|
(deployForm.target === 'fly' || deployForm.target === 'railway') && h('div', { className: 'form-group' },
|
|
3854
3912
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
3855
3913
|
h('select', { className: 'input', value: deployForm.region, onChange: function(e) { setDf('region', e.target.value); } },
|
|
3856
|
-
h('option', { value: 'iad' }, 'Ashburn (iad)'),
|
|
3857
|
-
h('option', { value: 'ord' }, 'Chicago (ord)'),
|
|
3858
|
-
h('option', { value: '
|
|
3914
|
+
h('option', { value: 'iad' }, 'Ashburn, VA (iad)'),
|
|
3915
|
+
h('option', { value: 'ord' }, 'Chicago, IL (ord)'),
|
|
3916
|
+
h('option', { value: 'dfw' }, 'Dallas, TX (dfw)'),
|
|
3917
|
+
h('option', { value: 'lax' }, 'Los Angeles, CA (lax)'),
|
|
3918
|
+
h('option', { value: 'sea' }, 'Seattle, WA (sea)'),
|
|
3919
|
+
h('option', { value: 'sjc' }, 'San Jose, CA (sjc)'),
|
|
3920
|
+
h('option', { value: 'yyz' }, 'Toronto (yyz)'),
|
|
3859
3921
|
h('option', { value: 'lhr' }, 'London (lhr)'),
|
|
3860
3922
|
h('option', { value: 'ams' }, 'Amsterdam (ams)'),
|
|
3861
|
-
h('option', { value: '
|
|
3923
|
+
h('option', { value: 'fra' }, 'Frankfurt (fra)'),
|
|
3924
|
+
h('option', { value: 'cdg' }, 'Paris (cdg)'),
|
|
3925
|
+
h('option', { value: 'waw' }, 'Warsaw (waw)'),
|
|
3926
|
+
h('option', { value: 'nrt' }, 'Tokyo (nrt)'),
|
|
3927
|
+
h('option', { value: 'sin' }, 'Singapore (sin)'),
|
|
3928
|
+
h('option', { value: 'hkg' }, 'Hong Kong (hkg)'),
|
|
3929
|
+
h('option', { value: 'syd' }, 'Sydney (syd)'),
|
|
3930
|
+
h('option', { value: 'gru' }, 'São Paulo (gru)'),
|
|
3931
|
+
h('option', { value: 'jnb' }, 'Johannesburg (jnb)')
|
|
3862
3932
|
)
|
|
3863
3933
|
)
|
|
3864
3934
|
),
|
|
3935
|
+
|
|
3936
|
+
// ── Fly.io ──────────────────────────────────────────
|
|
3865
3937
|
deployForm.target === 'fly' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
3866
3938
|
h('div', { className: 'form-group' },
|
|
3867
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3939
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'API Token'),
|
|
3868
3940
|
h('input', { className: 'input', type: 'password', value: deployForm.flyApiToken, onChange: function(e) { setDf('flyApiToken', e.target.value); }, placeholder: 'fo1_...' }),
|
|
3869
3941
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 } }, 'From fly.io/user/personal_access_tokens')
|
|
3870
3942
|
),
|
|
3871
3943
|
h('div', { className: 'form-group' },
|
|
3872
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'App Name
|
|
3944
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'App Name'),
|
|
3873
3945
|
h('input', { className: 'input', value: deployForm.flyAppName, onChange: function(e) { setDf('flyAppName', e.target.value); }, placeholder: 'Auto-generated if empty' })
|
|
3946
|
+
),
|
|
3947
|
+
h('div', { className: 'form-group' },
|
|
3948
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Organization'),
|
|
3949
|
+
h('input', { className: 'input', value: deployForm.flyOrg, onChange: function(e) { setDf('flyOrg', e.target.value); }, placeholder: 'personal' })
|
|
3950
|
+
),
|
|
3951
|
+
h('div', { className: 'form-group' },
|
|
3952
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'VM Size'),
|
|
3953
|
+
h('select', { className: 'input', value: deployForm.flyVmSize, onChange: function(e) { setDf('flyVmSize', e.target.value); } },
|
|
3954
|
+
h('option', { value: 'shared-cpu-1x' }, 'Shared 1x (256MB) — $1.94/mo'),
|
|
3955
|
+
h('option', { value: 'shared-cpu-2x' }, 'Shared 2x (512MB) — $3.88/mo'),
|
|
3956
|
+
h('option', { value: 'shared-cpu-4x' }, 'Shared 4x (1GB) — $7.76/mo'),
|
|
3957
|
+
h('option', { value: 'shared-cpu-8x' }, 'Shared 8x (2GB) — $15.52/mo'),
|
|
3958
|
+
h('option', { value: 'performance-1x' }, 'Performance 1x (2GB) — $29.04/mo'),
|
|
3959
|
+
h('option', { value: 'performance-2x' }, 'Performance 2x (4GB) — $58.09/mo'),
|
|
3960
|
+
h('option', { value: 'performance-4x' }, 'Performance 4x (8GB) — $116.18/mo'),
|
|
3961
|
+
h('option', { value: 'performance-8x' }, 'Performance 8x (16GB) — $232.36/mo')
|
|
3962
|
+
)
|
|
3874
3963
|
)
|
|
3875
3964
|
),
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3965
|
+
|
|
3966
|
+
// ── AWS EC2 ─────────────────────────────────────────
|
|
3967
|
+
deployForm.target === 'aws' && h(Fragment, null,
|
|
3968
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
3969
|
+
h('div', { className: 'form-group' },
|
|
3970
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Access Key ID'),
|
|
3971
|
+
h('input', { className: 'input', type: 'password', value: deployForm.awsAccessKeyId, onChange: function(e) { setDf('awsAccessKeyId', e.target.value); }, placeholder: 'AKIA...' })
|
|
3972
|
+
),
|
|
3973
|
+
h('div', { className: 'form-group' },
|
|
3974
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Secret Access Key'),
|
|
3975
|
+
h('input', { className: 'input', type: 'password', value: deployForm.awsSecretAccessKey, onChange: function(e) { setDf('awsSecretAccessKey', e.target.value); }, placeholder: '••••••••' })
|
|
3976
|
+
)
|
|
3977
|
+
),
|
|
3978
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
3979
|
+
h('div', { className: 'form-group' },
|
|
3980
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
3981
|
+
h('select', { className: 'input', value: deployForm.awsRegion, onChange: function(e) { setDf('awsRegion', e.target.value); } },
|
|
3982
|
+
h('option', { value: 'us-east-1' }, 'US East (N. Virginia)'),
|
|
3983
|
+
h('option', { value: 'us-east-2' }, 'US East (Ohio)'),
|
|
3984
|
+
h('option', { value: 'us-west-1' }, 'US West (N. California)'),
|
|
3985
|
+
h('option', { value: 'us-west-2' }, 'US West (Oregon)'),
|
|
3986
|
+
h('option', { value: 'eu-west-1' }, 'EU (Ireland)'),
|
|
3987
|
+
h('option', { value: 'eu-west-2' }, 'EU (London)'),
|
|
3988
|
+
h('option', { value: 'eu-central-1' }, 'EU (Frankfurt)'),
|
|
3989
|
+
h('option', { value: 'ap-southeast-1' }, 'Asia Pacific (Singapore)'),
|
|
3990
|
+
h('option', { value: 'ap-northeast-1' }, 'Asia Pacific (Tokyo)'),
|
|
3991
|
+
h('option', { value: 'ap-south-1' }, 'Asia Pacific (Mumbai)'),
|
|
3992
|
+
h('option', { value: 'sa-east-1' }, 'South America (São Paulo)'),
|
|
3993
|
+
h('option', { value: 'af-south-1' }, 'Africa (Cape Town)')
|
|
3994
|
+
)
|
|
3995
|
+
),
|
|
3996
|
+
h('div', { className: 'form-group' },
|
|
3997
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Instance Type'),
|
|
3998
|
+
h('select', { className: 'input', value: deployForm.awsInstanceType, onChange: function(e) { setDf('awsInstanceType', e.target.value); } },
|
|
3999
|
+
h('option', { value: 't3.micro' }, 't3.micro (1 vCPU, 1GB) — ~$7.59/mo'),
|
|
4000
|
+
h('option', { value: 't3.small' }, 't3.small (2 vCPU, 2GB) — ~$15.18/mo'),
|
|
4001
|
+
h('option', { value: 't3.medium' }, 't3.medium (2 vCPU, 4GB) — ~$30.37/mo'),
|
|
4002
|
+
h('option', { value: 't3.large' }, 't3.large (2 vCPU, 8GB) — ~$60.74/mo'),
|
|
4003
|
+
h('option', { value: 'm5.large' }, 'm5.large (2 vCPU, 8GB) — ~$69.12/mo'),
|
|
4004
|
+
h('option', { value: 'm5.xlarge' }, 'm5.xlarge (4 vCPU, 16GB) — ~$138.24/mo'),
|
|
4005
|
+
h('option', { value: 'c5.large' }, 'c5.large (2 vCPU, 4GB) — ~$61.20/mo'),
|
|
4006
|
+
h('option', { value: 'c5.xlarge' }, 'c5.xlarge (4 vCPU, 8GB) — ~$122.40/mo')
|
|
4007
|
+
)
|
|
4008
|
+
),
|
|
4009
|
+
h('div', { className: 'form-group' },
|
|
4010
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Key Pair Name'),
|
|
4011
|
+
h('input', { className: 'input', value: deployForm.awsKeyPairName, onChange: function(e) { setDf('awsKeyPairName', e.target.value); }, placeholder: 'my-keypair' })
|
|
4012
|
+
)
|
|
4013
|
+
),
|
|
4014
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4015
|
+
h('div', { className: 'form-group' },
|
|
4016
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'AMI ID (optional)'),
|
|
4017
|
+
h('input', { className: 'input', value: deployForm.awsAmi, onChange: function(e) { setDf('awsAmi', e.target.value); }, placeholder: 'ami-... (default: Ubuntu 22.04)' })
|
|
4018
|
+
),
|
|
4019
|
+
h('div', { className: 'form-group' },
|
|
4020
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Subnet ID (optional)'),
|
|
4021
|
+
h('input', { className: 'input', value: deployForm.awsSubnetId, onChange: function(e) { setDf('awsSubnetId', e.target.value); }, placeholder: 'subnet-...' })
|
|
4022
|
+
),
|
|
4023
|
+
h('div', { className: 'form-group' },
|
|
4024
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Security Group (optional)'),
|
|
4025
|
+
h('input', { className: 'input', value: deployForm.awsSecurityGroupId, onChange: function(e) { setDf('awsSecurityGroupId', e.target.value); }, placeholder: 'sg-...' })
|
|
4026
|
+
)
|
|
4027
|
+
)
|
|
4028
|
+
),
|
|
4029
|
+
|
|
4030
|
+
// ── Google Cloud GCE ────────────────────────────────
|
|
4031
|
+
deployForm.target === 'gcp' && h(Fragment, null,
|
|
4032
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
4033
|
+
h('div', { className: 'form-group' },
|
|
4034
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Project ID'),
|
|
4035
|
+
h('input', { className: 'input', value: deployForm.gcpProject, onChange: function(e) { setDf('gcpProject', e.target.value); }, placeholder: 'my-project-123' })
|
|
4036
|
+
),
|
|
4037
|
+
h('div', { className: 'form-group' },
|
|
4038
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Service Account Key (JSON)'),
|
|
4039
|
+
h('input', { className: 'input', type: 'password', value: deployForm.gcpServiceAccountKey, onChange: function(e) { setDf('gcpServiceAccountKey', e.target.value); }, placeholder: 'Paste JSON key or path' })
|
|
4040
|
+
)
|
|
3880
4041
|
),
|
|
4042
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4043
|
+
h('div', { className: 'form-group' },
|
|
4044
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
4045
|
+
h('select', { className: 'input', value: deployForm.gcpRegion, onChange: function(e) { setDf('gcpRegion', e.target.value); } },
|
|
4046
|
+
h('option', { value: 'us-central1' }, 'US Central (Iowa)'),
|
|
4047
|
+
h('option', { value: 'us-east1' }, 'US East (S. Carolina)'),
|
|
4048
|
+
h('option', { value: 'us-west1' }, 'US West (Oregon)'),
|
|
4049
|
+
h('option', { value: 'europe-west1' }, 'EU West (Belgium)'),
|
|
4050
|
+
h('option', { value: 'europe-west2' }, 'EU West (London)'),
|
|
4051
|
+
h('option', { value: 'europe-west3' }, 'EU West (Frankfurt)'),
|
|
4052
|
+
h('option', { value: 'asia-east1' }, 'Asia East (Taiwan)'),
|
|
4053
|
+
h('option', { value: 'asia-northeast1' }, 'Asia NE (Tokyo)'),
|
|
4054
|
+
h('option', { value: 'asia-southeast1' }, 'Asia SE (Singapore)'),
|
|
4055
|
+
h('option', { value: 'australia-southeast1' }, 'Australia (Sydney)'),
|
|
4056
|
+
h('option', { value: 'southamerica-east1' }, 'South America (São Paulo)')
|
|
4057
|
+
)
|
|
4058
|
+
),
|
|
4059
|
+
h('div', { className: 'form-group' },
|
|
4060
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Zone'),
|
|
4061
|
+
h('input', { className: 'input', value: deployForm.gcpZone, onChange: function(e) { setDf('gcpZone', e.target.value); }, placeholder: 'us-central1-a' })
|
|
4062
|
+
),
|
|
4063
|
+
h('div', { className: 'form-group' },
|
|
4064
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Machine Type'),
|
|
4065
|
+
h('select', { className: 'input', value: deployForm.gcpMachineType, onChange: function(e) { setDf('gcpMachineType', e.target.value); } },
|
|
4066
|
+
h('option', { value: 'e2-micro' }, 'e2-micro (0.25 vCPU, 1GB) — ~$6.11/mo'),
|
|
4067
|
+
h('option', { value: 'e2-small' }, 'e2-small (0.5 vCPU, 2GB) — ~$12.23/mo'),
|
|
4068
|
+
h('option', { value: 'e2-medium' }, 'e2-medium (1 vCPU, 4GB) — ~$24.46/mo'),
|
|
4069
|
+
h('option', { value: 'e2-standard-2' }, 'e2-standard-2 (2 vCPU, 8GB) — ~$48.92/mo'),
|
|
4070
|
+
h('option', { value: 'e2-standard-4' }, 'e2-standard-4 (4 vCPU, 16GB) — ~$97.83/mo'),
|
|
4071
|
+
h('option', { value: 'n2-standard-2' }, 'n2-standard-2 (2 vCPU, 8GB) — ~$56.52/mo'),
|
|
4072
|
+
h('option', { value: 'c2-standard-4' }, 'c2-standard-4 (4 vCPU, 16GB) — ~$124.49/mo')
|
|
4073
|
+
)
|
|
4074
|
+
)
|
|
4075
|
+
)
|
|
4076
|
+
),
|
|
4077
|
+
|
|
4078
|
+
// ── Microsoft Azure ─────────────────────────────────
|
|
4079
|
+
deployForm.target === 'azure' && h(Fragment, null,
|
|
4080
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
4081
|
+
h('div', { className: 'form-group' },
|
|
4082
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Subscription ID'),
|
|
4083
|
+
h('input', { className: 'input', value: deployForm.azureSubscriptionId, onChange: function(e) { setDf('azureSubscriptionId', e.target.value); }, placeholder: 'xxxxxxxx-xxxx-...' })
|
|
4084
|
+
),
|
|
4085
|
+
h('div', { className: 'form-group' },
|
|
4086
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Resource Group'),
|
|
4087
|
+
h('input', { className: 'input', value: deployForm.azureResourceGroup, onChange: function(e) { setDf('azureResourceGroup', e.target.value); }, placeholder: 'my-resource-group' })
|
|
4088
|
+
),
|
|
4089
|
+
h('div', { className: 'form-group' },
|
|
4090
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
4091
|
+
h('select', { className: 'input', value: deployForm.azureRegion, onChange: function(e) { setDf('azureRegion', e.target.value); } },
|
|
4092
|
+
h('option', { value: 'eastus' }, 'East US'),
|
|
4093
|
+
h('option', { value: 'eastus2' }, 'East US 2'),
|
|
4094
|
+
h('option', { value: 'westus2' }, 'West US 2'),
|
|
4095
|
+
h('option', { value: 'westus3' }, 'West US 3'),
|
|
4096
|
+
h('option', { value: 'centralus' }, 'Central US'),
|
|
4097
|
+
h('option', { value: 'northeurope' }, 'North Europe (Ireland)'),
|
|
4098
|
+
h('option', { value: 'westeurope' }, 'West Europe (Netherlands)'),
|
|
4099
|
+
h('option', { value: 'uksouth' }, 'UK South'),
|
|
4100
|
+
h('option', { value: 'germanywestcentral' }, 'Germany West Central'),
|
|
4101
|
+
h('option', { value: 'eastasia' }, 'East Asia (Hong Kong)'),
|
|
4102
|
+
h('option', { value: 'southeastasia' }, 'Southeast Asia (Singapore)'),
|
|
4103
|
+
h('option', { value: 'japaneast' }, 'Japan East'),
|
|
4104
|
+
h('option', { value: 'australiaeast' }, 'Australia East'),
|
|
4105
|
+
h('option', { value: 'brazilsouth' }, 'Brazil South'),
|
|
4106
|
+
h('option', { value: 'southafricanorth' }, 'South Africa North')
|
|
4107
|
+
)
|
|
4108
|
+
)
|
|
4109
|
+
),
|
|
4110
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4111
|
+
h('div', { className: 'form-group' },
|
|
4112
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'VM Size'),
|
|
4113
|
+
h('select', { className: 'input', value: deployForm.azureVmSize, onChange: function(e) { setDf('azureVmSize', e.target.value); } },
|
|
4114
|
+
h('option', { value: 'Standard_B1s' }, 'B1s (1 vCPU, 1GB) — ~$7.59/mo'),
|
|
4115
|
+
h('option', { value: 'Standard_B1ms' }, 'B1ms (1 vCPU, 2GB) — ~$15.11/mo'),
|
|
4116
|
+
h('option', { value: 'Standard_B2s' }, 'B2s (2 vCPU, 4GB) — ~$30.37/mo'),
|
|
4117
|
+
h('option', { value: 'Standard_B2ms' }, 'B2ms (2 vCPU, 8GB) — ~$60.74/mo'),
|
|
4118
|
+
h('option', { value: 'Standard_D2s_v5' }, 'D2s v5 (2 vCPU, 8GB) — ~$70.08/mo'),
|
|
4119
|
+
h('option', { value: 'Standard_D4s_v5' }, 'D4s v5 (4 vCPU, 16GB) — ~$140.16/mo'),
|
|
4120
|
+
h('option', { value: 'Standard_F2s_v2' }, 'F2s v2 (2 vCPU, 4GB) — ~$61.25/mo'),
|
|
4121
|
+
h('option', { value: 'Standard_E2s_v5' }, 'E2s v5 (2 vCPU, 16GB) — ~$91.98/mo')
|
|
4122
|
+
)
|
|
4123
|
+
),
|
|
4124
|
+
h('div', { className: 'form-group' },
|
|
4125
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Tenant ID (optional)'),
|
|
4126
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureTenantId, onChange: function(e) { setDf('azureTenantId', e.target.value); }, placeholder: 'For service principal auth' })
|
|
4127
|
+
)
|
|
4128
|
+
),
|
|
4129
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4130
|
+
h('div', { className: 'form-group' },
|
|
4131
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Client ID (optional)'),
|
|
4132
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureClientId, onChange: function(e) { setDf('azureClientId', e.target.value); }, placeholder: 'App registration client ID' })
|
|
4133
|
+
),
|
|
4134
|
+
h('div', { className: 'form-group' },
|
|
4135
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Client Secret (optional)'),
|
|
4136
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureClientSecret, onChange: function(e) { setDf('azureClientSecret', e.target.value); }, placeholder: '••••••••' })
|
|
4137
|
+
)
|
|
4138
|
+
)
|
|
4139
|
+
),
|
|
4140
|
+
|
|
4141
|
+
// ── Railway ─────────────────────────────────────────
|
|
4142
|
+
deployForm.target === 'railway' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
3881
4143
|
h('div', { className: 'form-group' },
|
|
3882
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3883
|
-
h('input', { className: 'input', value: deployForm.
|
|
4144
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'API Token'),
|
|
4145
|
+
h('input', { className: 'input', type: 'password', value: deployForm.railwayApiToken, onChange: function(e) { setDf('railwayApiToken', e.target.value); }, placeholder: 'railway_...' }),
|
|
4146
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 } }, 'From railway.app/account/tokens')
|
|
3884
4147
|
),
|
|
3885
4148
|
h('div', { className: 'form-group' },
|
|
3886
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3887
|
-
h('input', { className: 'input', value: deployForm.
|
|
4149
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Project ID (optional)'),
|
|
4150
|
+
h('input', { className: 'input', value: deployForm.railwayProjectId, onChange: function(e) { setDf('railwayProjectId', e.target.value); }, placeholder: 'Auto-created if empty' })
|
|
3888
4151
|
),
|
|
3889
4152
|
h('div', { className: 'form-group' },
|
|
3890
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3891
|
-
h('input', { className: 'input', value: deployForm.
|
|
4153
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Service Name'),
|
|
4154
|
+
h('input', { className: 'input', value: deployForm.railwayServiceName, onChange: function(e) { setDf('railwayServiceName', e.target.value); }, placeholder: 'agenticmail-agent' })
|
|
3892
4155
|
)
|
|
3893
4156
|
),
|
|
4157
|
+
|
|
4158
|
+
// ── Docker ──────────────────────────────────────────
|
|
4159
|
+
deployForm.target === 'docker' && h(Fragment, null,
|
|
4160
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
4161
|
+
h('div', { className: 'form-group' },
|
|
4162
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Image'),
|
|
4163
|
+
h('input', { className: 'input', value: deployForm.dockerImage, onChange: function(e) { setDf('dockerImage', e.target.value); }, placeholder: 'agenticmail/agent' })
|
|
4164
|
+
),
|
|
4165
|
+
h('div', { className: 'form-group' },
|
|
4166
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Tag'),
|
|
4167
|
+
h('input', { className: 'input', value: deployForm.dockerTag, onChange: function(e) { setDf('dockerTag', e.target.value); }, placeholder: 'latest' })
|
|
4168
|
+
),
|
|
4169
|
+
h('div', { className: 'form-group' },
|
|
4170
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Ports'),
|
|
4171
|
+
h('input', { className: 'input', value: deployForm.dockerPorts, onChange: function(e) { setDf('dockerPorts', e.target.value); }, placeholder: '3000' })
|
|
4172
|
+
)
|
|
4173
|
+
),
|
|
4174
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4175
|
+
h('div', { className: 'form-group' },
|
|
4176
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Memory'),
|
|
4177
|
+
h('input', { className: 'input', value: deployForm.dockerMemory, onChange: function(e) { setDf('dockerMemory', e.target.value); }, placeholder: '512m' })
|
|
4178
|
+
),
|
|
4179
|
+
h('div', { className: 'form-group' },
|
|
4180
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'CPU'),
|
|
4181
|
+
h('input', { className: 'input', value: deployForm.dockerCpu, onChange: function(e) { setDf('dockerCpu', e.target.value); }, placeholder: '0.5' })
|
|
4182
|
+
),
|
|
4183
|
+
h('div', { className: 'form-group' },
|
|
4184
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Network'),
|
|
4185
|
+
h('input', { className: 'input', value: deployForm.dockerNetwork, onChange: function(e) { setDf('dockerNetwork', e.target.value); }, placeholder: 'bridge (default)' })
|
|
4186
|
+
),
|
|
4187
|
+
h('div', { className: 'form-group' },
|
|
4188
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Restart Policy'),
|
|
4189
|
+
h('select', { className: 'input', value: deployForm.dockerRestart, onChange: function(e) { setDf('dockerRestart', e.target.value); } },
|
|
4190
|
+
h('option', { value: 'unless-stopped' }, 'Unless Stopped'),
|
|
4191
|
+
h('option', { value: 'always' }, 'Always'),
|
|
4192
|
+
h('option', { value: 'on-failure' }, 'On Failure'),
|
|
4193
|
+
h('option', { value: 'no' }, 'Never')
|
|
4194
|
+
)
|
|
4195
|
+
)
|
|
4196
|
+
)
|
|
4197
|
+
),
|
|
4198
|
+
|
|
4199
|
+
// ── VPS / Bare Metal ────────────────────────────────
|
|
3894
4200
|
deployForm.target === 'vps' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
3895
4201
|
h('div', { className: 'form-group' },
|
|
3896
4202
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Host'),
|
|
3897
|
-
h('input', { className: 'input', value: deployForm.vpsHost, onChange: function(e) { setDf('vpsHost', e.target.value); }, placeholder: '192.168.1.100' })
|
|
4203
|
+
h('input', { className: 'input', value: deployForm.vpsHost, onChange: function(e) { setDf('vpsHost', e.target.value); }, placeholder: '192.168.1.100 or hostname' })
|
|
4204
|
+
),
|
|
4205
|
+
h('div', { className: 'form-group' },
|
|
4206
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'SSH Port'),
|
|
4207
|
+
h('input', { className: 'input', type: 'number', value: deployForm.vpsPort, onChange: function(e) { setDf('vpsPort', e.target.value); }, placeholder: '22' })
|
|
3898
4208
|
),
|
|
3899
4209
|
h('div', { className: 'form-group' },
|
|
3900
4210
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'User'),
|
|
@@ -3903,7 +4213,16 @@ function DeploymentSection(props) {
|
|
|
3903
4213
|
h('div', { className: 'form-group' },
|
|
3904
4214
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'SSH Key Path'),
|
|
3905
4215
|
h('input', { className: 'input', value: deployForm.vpsKeyPath, onChange: function(e) { setDf('vpsKeyPath', e.target.value); }, placeholder: '~/.ssh/id_rsa' })
|
|
4216
|
+
),
|
|
4217
|
+
h('div', { className: 'form-group' },
|
|
4218
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Work Directory'),
|
|
4219
|
+
h('input', { className: 'input', value: deployForm.vpsWorkDir, onChange: function(e) { setDf('vpsWorkDir', e.target.value); }, placeholder: '/opt/agenticmail' })
|
|
3906
4220
|
)
|
|
4221
|
+
),
|
|
4222
|
+
|
|
4223
|
+
// ── Local ───────────────────────────────────────────
|
|
4224
|
+
deployForm.target === 'local' && h('div', { style: { padding: 16, background: 'var(--bg-tertiary)', borderRadius: 8, fontSize: 13, color: 'var(--text-muted)' } },
|
|
4225
|
+
'Agent will run in-process on this server. No external deployment required. Best for development and testing.'
|
|
3907
4226
|
)
|
|
3908
4227
|
)
|
|
3909
4228
|
),
|
package/package.json
CHANGED
|
@@ -3745,35 +3745,89 @@ function DeploymentSection(props) {
|
|
|
3745
3745
|
var deployForm = _deployForm[0]; var setDeployForm = _deployForm[1];
|
|
3746
3746
|
|
|
3747
3747
|
var startDeployEdit = function() {
|
|
3748
|
+
var cloud = deployment.config?.cloud || {};
|
|
3749
|
+
var docker = deployment.config?.docker || {};
|
|
3750
|
+
var vps = deployment.config?.vps || {};
|
|
3751
|
+
var aws = deployment.config?.aws || {};
|
|
3752
|
+
var gcp = deployment.config?.gcp || {};
|
|
3753
|
+
var az = deployment.config?.azure || {};
|
|
3754
|
+
var rail = deployment.config?.railway || {};
|
|
3748
3755
|
setDeployForm({
|
|
3749
3756
|
target: deployment.target || 'fly',
|
|
3750
|
-
region: deployment.region ||
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3757
|
+
region: deployment.region || cloud.region || 'iad',
|
|
3758
|
+
// Fly.io
|
|
3759
|
+
flyApiToken: cloud.apiToken || '',
|
|
3760
|
+
flyAppName: cloud.appName || '',
|
|
3761
|
+
flyOrg: cloud.org || 'personal',
|
|
3762
|
+
flyVmSize: cloud.vmSize || 'shared-cpu-1x',
|
|
3763
|
+
flyVmMemory: cloud.vmMemory || '256',
|
|
3764
|
+
// Docker
|
|
3765
|
+
dockerImage: docker.image || 'agenticmail/agent',
|
|
3766
|
+
dockerTag: docker.tag || 'latest',
|
|
3767
|
+
dockerMemory: docker.memory || '512m',
|
|
3768
|
+
dockerCpu: docker.cpu || '0.5',
|
|
3769
|
+
dockerPorts: (docker.ports || [3000]).join(', '),
|
|
3770
|
+
dockerNetwork: docker.network || '',
|
|
3771
|
+
dockerRestart: docker.restart || 'unless-stopped',
|
|
3772
|
+
// VPS
|
|
3773
|
+
vpsHost: vps.host || '',
|
|
3774
|
+
vpsPort: vps.port || '22',
|
|
3775
|
+
vpsUser: vps.user || 'root',
|
|
3776
|
+
vpsKeyPath: vps.keyPath || '~/.ssh/id_rsa',
|
|
3777
|
+
vpsWorkDir: vps.workDir || '/opt/agenticmail',
|
|
3778
|
+
// AWS
|
|
3779
|
+
awsRegion: aws.region || 'us-east-1',
|
|
3780
|
+
awsAccessKeyId: aws.accessKeyId || '',
|
|
3781
|
+
awsSecretAccessKey: aws.secretAccessKey || '',
|
|
3782
|
+
awsInstanceType: aws.instanceType || 't3.micro',
|
|
3783
|
+
awsAmi: aws.ami || '',
|
|
3784
|
+
awsSubnetId: aws.subnetId || '',
|
|
3785
|
+
awsSecurityGroupId: aws.securityGroupId || '',
|
|
3786
|
+
awsKeyPairName: aws.keyPairName || '',
|
|
3787
|
+
// GCP
|
|
3788
|
+
gcpProject: gcp.projectId || '',
|
|
3789
|
+
gcpRegion: gcp.region || 'us-central1',
|
|
3790
|
+
gcpZone: gcp.zone || 'us-central1-a',
|
|
3791
|
+
gcpMachineType: gcp.machineType || 'e2-micro',
|
|
3792
|
+
gcpServiceAccountKey: gcp.serviceAccountKey || '',
|
|
3793
|
+
// Azure
|
|
3794
|
+
azureSubscriptionId: az.subscriptionId || '',
|
|
3795
|
+
azureResourceGroup: az.resourceGroup || '',
|
|
3796
|
+
azureRegion: az.region || 'eastus',
|
|
3797
|
+
azureVmSize: az.vmSize || 'Standard_B1s',
|
|
3798
|
+
azureTenantId: az.tenantId || '',
|
|
3799
|
+
azureClientId: az.clientId || '',
|
|
3800
|
+
azureClientSecret: az.clientSecret || '',
|
|
3801
|
+
// Railway
|
|
3802
|
+
railwayApiToken: rail.apiToken || '',
|
|
3803
|
+
railwayProjectId: rail.projectId || '',
|
|
3804
|
+
railwayServiceName: rail.serviceName || '',
|
|
3760
3805
|
});
|
|
3761
3806
|
setEditingDeploy(true);
|
|
3762
3807
|
};
|
|
3763
3808
|
|
|
3764
3809
|
var saveDeploy = function() {
|
|
3765
3810
|
setSavingDeploy(true);
|
|
3811
|
+
var t = deployForm.target;
|
|
3766
3812
|
var deployConfig = {};
|
|
3767
|
-
if (
|
|
3768
|
-
deployConfig = { cloud: { provider: 'fly', region: deployForm.region || 'iad', apiToken: deployForm.flyApiToken || undefined, appName: deployForm.flyAppName || undefined } };
|
|
3769
|
-
} else if (
|
|
3770
|
-
deployConfig = { docker: { image: 'agenticmail/agent', tag: deployForm.
|
|
3771
|
-
} else if (
|
|
3772
|
-
deployConfig = { vps: { host: deployForm.vpsHost ||
|
|
3813
|
+
if (t === 'fly') {
|
|
3814
|
+
deployConfig = { cloud: { provider: 'fly', region: deployForm.region || 'iad', apiToken: deployForm.flyApiToken || undefined, appName: deployForm.flyAppName || undefined, org: deployForm.flyOrg || 'personal', vmSize: deployForm.flyVmSize || 'shared-cpu-1x', vmMemory: deployForm.flyVmMemory || '256' } };
|
|
3815
|
+
} else if (t === 'docker') {
|
|
3816
|
+
deployConfig = { docker: { image: deployForm.dockerImage || 'agenticmail/agent', tag: deployForm.dockerTag || 'latest', ports: (deployForm.dockerPorts || '3000').split(',').map(function(p) { return parseInt(p.trim()) || 3000; }), memory: deployForm.dockerMemory || '512m', cpu: deployForm.dockerCpu || '0.5', network: deployForm.dockerNetwork || undefined, restart: deployForm.dockerRestart || 'unless-stopped' } };
|
|
3817
|
+
} else if (t === 'vps') {
|
|
3818
|
+
deployConfig = { vps: { host: deployForm.vpsHost, port: parseInt(deployForm.vpsPort) || 22, user: deployForm.vpsUser || 'root', keyPath: deployForm.vpsKeyPath || '~/.ssh/id_rsa', workDir: deployForm.vpsWorkDir || '/opt/agenticmail' } };
|
|
3819
|
+
} else if (t === 'aws') {
|
|
3820
|
+
deployConfig = { aws: { region: deployForm.awsRegion || 'us-east-1', accessKeyId: deployForm.awsAccessKeyId || undefined, secretAccessKey: deployForm.awsSecretAccessKey || undefined, instanceType: deployForm.awsInstanceType || 't3.micro', ami: deployForm.awsAmi || undefined, subnetId: deployForm.awsSubnetId || undefined, securityGroupId: deployForm.awsSecurityGroupId || undefined, keyPairName: deployForm.awsKeyPairName || undefined } };
|
|
3821
|
+
} else if (t === 'gcp') {
|
|
3822
|
+
deployConfig = { gcp: { projectId: deployForm.gcpProject, region: deployForm.gcpRegion || 'us-central1', zone: deployForm.gcpZone || 'us-central1-a', machineType: deployForm.gcpMachineType || 'e2-micro', serviceAccountKey: deployForm.gcpServiceAccountKey || undefined } };
|
|
3823
|
+
} else if (t === 'azure') {
|
|
3824
|
+
deployConfig = { azure: { subscriptionId: deployForm.azureSubscriptionId, resourceGroup: deployForm.azureResourceGroup, region: deployForm.azureRegion || 'eastus', vmSize: deployForm.azureVmSize || 'Standard_B1s', tenantId: deployForm.azureTenantId || undefined, clientId: deployForm.azureClientId || undefined, clientSecret: deployForm.azureClientSecret || undefined } };
|
|
3825
|
+
} else if (t === 'railway') {
|
|
3826
|
+
deployConfig = { railway: { apiToken: deployForm.railwayApiToken || undefined, projectId: deployForm.railwayProjectId || undefined, serviceName: deployForm.railwayServiceName || undefined, region: deployForm.region || undefined } };
|
|
3773
3827
|
}
|
|
3774
3828
|
var updates = {
|
|
3775
3829
|
deployment: {
|
|
3776
|
-
target:
|
|
3830
|
+
target: t,
|
|
3777
3831
|
region: deployForm.region,
|
|
3778
3832
|
config: deployConfig
|
|
3779
3833
|
}
|
|
@@ -3844,57 +3898,313 @@ function DeploymentSection(props) {
|
|
|
3844
3898
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Target'),
|
|
3845
3899
|
h('select', { className: 'input', value: deployForm.target, onChange: function(e) { setDf('target', e.target.value); } },
|
|
3846
3900
|
h('option', { value: 'fly' }, 'Fly.io'),
|
|
3847
|
-
h('option', { value: '
|
|
3901
|
+
h('option', { value: 'aws' }, 'AWS (EC2)'),
|
|
3902
|
+
h('option', { value: 'gcp' }, 'Google Cloud (GCE)'),
|
|
3903
|
+
h('option', { value: 'azure' }, 'Microsoft Azure'),
|
|
3848
3904
|
h('option', { value: 'railway' }, 'Railway'),
|
|
3849
|
-
h('option', { value: '
|
|
3850
|
-
h('option', { value: '
|
|
3905
|
+
h('option', { value: 'docker' }, 'Docker'),
|
|
3906
|
+
h('option', { value: 'vps' }, 'VPS / Bare Metal'),
|
|
3907
|
+
h('option', { value: 'local' }, 'Local (In-Process)')
|
|
3851
3908
|
)
|
|
3852
3909
|
),
|
|
3910
|
+
// Region selector for cloud providers
|
|
3853
3911
|
(deployForm.target === 'fly' || deployForm.target === 'railway') && h('div', { className: 'form-group' },
|
|
3854
3912
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
3855
3913
|
h('select', { className: 'input', value: deployForm.region, onChange: function(e) { setDf('region', e.target.value); } },
|
|
3856
|
-
h('option', { value: 'iad' }, 'Ashburn (iad)'),
|
|
3857
|
-
h('option', { value: 'ord' }, 'Chicago (ord)'),
|
|
3858
|
-
h('option', { value: '
|
|
3914
|
+
h('option', { value: 'iad' }, 'Ashburn, VA (iad)'),
|
|
3915
|
+
h('option', { value: 'ord' }, 'Chicago, IL (ord)'),
|
|
3916
|
+
h('option', { value: 'dfw' }, 'Dallas, TX (dfw)'),
|
|
3917
|
+
h('option', { value: 'lax' }, 'Los Angeles, CA (lax)'),
|
|
3918
|
+
h('option', { value: 'sea' }, 'Seattle, WA (sea)'),
|
|
3919
|
+
h('option', { value: 'sjc' }, 'San Jose, CA (sjc)'),
|
|
3920
|
+
h('option', { value: 'yyz' }, 'Toronto (yyz)'),
|
|
3859
3921
|
h('option', { value: 'lhr' }, 'London (lhr)'),
|
|
3860
3922
|
h('option', { value: 'ams' }, 'Amsterdam (ams)'),
|
|
3861
|
-
h('option', { value: '
|
|
3923
|
+
h('option', { value: 'fra' }, 'Frankfurt (fra)'),
|
|
3924
|
+
h('option', { value: 'cdg' }, 'Paris (cdg)'),
|
|
3925
|
+
h('option', { value: 'waw' }, 'Warsaw (waw)'),
|
|
3926
|
+
h('option', { value: 'nrt' }, 'Tokyo (nrt)'),
|
|
3927
|
+
h('option', { value: 'sin' }, 'Singapore (sin)'),
|
|
3928
|
+
h('option', { value: 'hkg' }, 'Hong Kong (hkg)'),
|
|
3929
|
+
h('option', { value: 'syd' }, 'Sydney (syd)'),
|
|
3930
|
+
h('option', { value: 'gru' }, 'São Paulo (gru)'),
|
|
3931
|
+
h('option', { value: 'jnb' }, 'Johannesburg (jnb)')
|
|
3862
3932
|
)
|
|
3863
3933
|
)
|
|
3864
3934
|
),
|
|
3935
|
+
|
|
3936
|
+
// ── Fly.io ──────────────────────────────────────────
|
|
3865
3937
|
deployForm.target === 'fly' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
3866
3938
|
h('div', { className: 'form-group' },
|
|
3867
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3939
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'API Token'),
|
|
3868
3940
|
h('input', { className: 'input', type: 'password', value: deployForm.flyApiToken, onChange: function(e) { setDf('flyApiToken', e.target.value); }, placeholder: 'fo1_...' }),
|
|
3869
3941
|
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 } }, 'From fly.io/user/personal_access_tokens')
|
|
3870
3942
|
),
|
|
3871
3943
|
h('div', { className: 'form-group' },
|
|
3872
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'App Name
|
|
3944
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'App Name'),
|
|
3873
3945
|
h('input', { className: 'input', value: deployForm.flyAppName, onChange: function(e) { setDf('flyAppName', e.target.value); }, placeholder: 'Auto-generated if empty' })
|
|
3946
|
+
),
|
|
3947
|
+
h('div', { className: 'form-group' },
|
|
3948
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Organization'),
|
|
3949
|
+
h('input', { className: 'input', value: deployForm.flyOrg, onChange: function(e) { setDf('flyOrg', e.target.value); }, placeholder: 'personal' })
|
|
3950
|
+
),
|
|
3951
|
+
h('div', { className: 'form-group' },
|
|
3952
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'VM Size'),
|
|
3953
|
+
h('select', { className: 'input', value: deployForm.flyVmSize, onChange: function(e) { setDf('flyVmSize', e.target.value); } },
|
|
3954
|
+
h('option', { value: 'shared-cpu-1x' }, 'Shared 1x (256MB) — $1.94/mo'),
|
|
3955
|
+
h('option', { value: 'shared-cpu-2x' }, 'Shared 2x (512MB) — $3.88/mo'),
|
|
3956
|
+
h('option', { value: 'shared-cpu-4x' }, 'Shared 4x (1GB) — $7.76/mo'),
|
|
3957
|
+
h('option', { value: 'shared-cpu-8x' }, 'Shared 8x (2GB) — $15.52/mo'),
|
|
3958
|
+
h('option', { value: 'performance-1x' }, 'Performance 1x (2GB) — $29.04/mo'),
|
|
3959
|
+
h('option', { value: 'performance-2x' }, 'Performance 2x (4GB) — $58.09/mo'),
|
|
3960
|
+
h('option', { value: 'performance-4x' }, 'Performance 4x (8GB) — $116.18/mo'),
|
|
3961
|
+
h('option', { value: 'performance-8x' }, 'Performance 8x (16GB) — $232.36/mo')
|
|
3962
|
+
)
|
|
3874
3963
|
)
|
|
3875
3964
|
),
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3965
|
+
|
|
3966
|
+
// ── AWS EC2 ─────────────────────────────────────────
|
|
3967
|
+
deployForm.target === 'aws' && h(Fragment, null,
|
|
3968
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
3969
|
+
h('div', { className: 'form-group' },
|
|
3970
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Access Key ID'),
|
|
3971
|
+
h('input', { className: 'input', type: 'password', value: deployForm.awsAccessKeyId, onChange: function(e) { setDf('awsAccessKeyId', e.target.value); }, placeholder: 'AKIA...' })
|
|
3972
|
+
),
|
|
3973
|
+
h('div', { className: 'form-group' },
|
|
3974
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Secret Access Key'),
|
|
3975
|
+
h('input', { className: 'input', type: 'password', value: deployForm.awsSecretAccessKey, onChange: function(e) { setDf('awsSecretAccessKey', e.target.value); }, placeholder: '••••••••' })
|
|
3976
|
+
)
|
|
3977
|
+
),
|
|
3978
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
3979
|
+
h('div', { className: 'form-group' },
|
|
3980
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
3981
|
+
h('select', { className: 'input', value: deployForm.awsRegion, onChange: function(e) { setDf('awsRegion', e.target.value); } },
|
|
3982
|
+
h('option', { value: 'us-east-1' }, 'US East (N. Virginia)'),
|
|
3983
|
+
h('option', { value: 'us-east-2' }, 'US East (Ohio)'),
|
|
3984
|
+
h('option', { value: 'us-west-1' }, 'US West (N. California)'),
|
|
3985
|
+
h('option', { value: 'us-west-2' }, 'US West (Oregon)'),
|
|
3986
|
+
h('option', { value: 'eu-west-1' }, 'EU (Ireland)'),
|
|
3987
|
+
h('option', { value: 'eu-west-2' }, 'EU (London)'),
|
|
3988
|
+
h('option', { value: 'eu-central-1' }, 'EU (Frankfurt)'),
|
|
3989
|
+
h('option', { value: 'ap-southeast-1' }, 'Asia Pacific (Singapore)'),
|
|
3990
|
+
h('option', { value: 'ap-northeast-1' }, 'Asia Pacific (Tokyo)'),
|
|
3991
|
+
h('option', { value: 'ap-south-1' }, 'Asia Pacific (Mumbai)'),
|
|
3992
|
+
h('option', { value: 'sa-east-1' }, 'South America (São Paulo)'),
|
|
3993
|
+
h('option', { value: 'af-south-1' }, 'Africa (Cape Town)')
|
|
3994
|
+
)
|
|
3995
|
+
),
|
|
3996
|
+
h('div', { className: 'form-group' },
|
|
3997
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Instance Type'),
|
|
3998
|
+
h('select', { className: 'input', value: deployForm.awsInstanceType, onChange: function(e) { setDf('awsInstanceType', e.target.value); } },
|
|
3999
|
+
h('option', { value: 't3.micro' }, 't3.micro (1 vCPU, 1GB) — ~$7.59/mo'),
|
|
4000
|
+
h('option', { value: 't3.small' }, 't3.small (2 vCPU, 2GB) — ~$15.18/mo'),
|
|
4001
|
+
h('option', { value: 't3.medium' }, 't3.medium (2 vCPU, 4GB) — ~$30.37/mo'),
|
|
4002
|
+
h('option', { value: 't3.large' }, 't3.large (2 vCPU, 8GB) — ~$60.74/mo'),
|
|
4003
|
+
h('option', { value: 'm5.large' }, 'm5.large (2 vCPU, 8GB) — ~$69.12/mo'),
|
|
4004
|
+
h('option', { value: 'm5.xlarge' }, 'm5.xlarge (4 vCPU, 16GB) — ~$138.24/mo'),
|
|
4005
|
+
h('option', { value: 'c5.large' }, 'c5.large (2 vCPU, 4GB) — ~$61.20/mo'),
|
|
4006
|
+
h('option', { value: 'c5.xlarge' }, 'c5.xlarge (4 vCPU, 8GB) — ~$122.40/mo')
|
|
4007
|
+
)
|
|
4008
|
+
),
|
|
4009
|
+
h('div', { className: 'form-group' },
|
|
4010
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Key Pair Name'),
|
|
4011
|
+
h('input', { className: 'input', value: deployForm.awsKeyPairName, onChange: function(e) { setDf('awsKeyPairName', e.target.value); }, placeholder: 'my-keypair' })
|
|
4012
|
+
)
|
|
4013
|
+
),
|
|
4014
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4015
|
+
h('div', { className: 'form-group' },
|
|
4016
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'AMI ID (optional)'),
|
|
4017
|
+
h('input', { className: 'input', value: deployForm.awsAmi, onChange: function(e) { setDf('awsAmi', e.target.value); }, placeholder: 'ami-... (default: Ubuntu 22.04)' })
|
|
4018
|
+
),
|
|
4019
|
+
h('div', { className: 'form-group' },
|
|
4020
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Subnet ID (optional)'),
|
|
4021
|
+
h('input', { className: 'input', value: deployForm.awsSubnetId, onChange: function(e) { setDf('awsSubnetId', e.target.value); }, placeholder: 'subnet-...' })
|
|
4022
|
+
),
|
|
4023
|
+
h('div', { className: 'form-group' },
|
|
4024
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Security Group (optional)'),
|
|
4025
|
+
h('input', { className: 'input', value: deployForm.awsSecurityGroupId, onChange: function(e) { setDf('awsSecurityGroupId', e.target.value); }, placeholder: 'sg-...' })
|
|
4026
|
+
)
|
|
4027
|
+
)
|
|
4028
|
+
),
|
|
4029
|
+
|
|
4030
|
+
// ── Google Cloud GCE ────────────────────────────────
|
|
4031
|
+
deployForm.target === 'gcp' && h(Fragment, null,
|
|
4032
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 } },
|
|
4033
|
+
h('div', { className: 'form-group' },
|
|
4034
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Project ID'),
|
|
4035
|
+
h('input', { className: 'input', value: deployForm.gcpProject, onChange: function(e) { setDf('gcpProject', e.target.value); }, placeholder: 'my-project-123' })
|
|
4036
|
+
),
|
|
4037
|
+
h('div', { className: 'form-group' },
|
|
4038
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Service Account Key (JSON)'),
|
|
4039
|
+
h('input', { className: 'input', type: 'password', value: deployForm.gcpServiceAccountKey, onChange: function(e) { setDf('gcpServiceAccountKey', e.target.value); }, placeholder: 'Paste JSON key or path' })
|
|
4040
|
+
)
|
|
3880
4041
|
),
|
|
4042
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4043
|
+
h('div', { className: 'form-group' },
|
|
4044
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
4045
|
+
h('select', { className: 'input', value: deployForm.gcpRegion, onChange: function(e) { setDf('gcpRegion', e.target.value); } },
|
|
4046
|
+
h('option', { value: 'us-central1' }, 'US Central (Iowa)'),
|
|
4047
|
+
h('option', { value: 'us-east1' }, 'US East (S. Carolina)'),
|
|
4048
|
+
h('option', { value: 'us-west1' }, 'US West (Oregon)'),
|
|
4049
|
+
h('option', { value: 'europe-west1' }, 'EU West (Belgium)'),
|
|
4050
|
+
h('option', { value: 'europe-west2' }, 'EU West (London)'),
|
|
4051
|
+
h('option', { value: 'europe-west3' }, 'EU West (Frankfurt)'),
|
|
4052
|
+
h('option', { value: 'asia-east1' }, 'Asia East (Taiwan)'),
|
|
4053
|
+
h('option', { value: 'asia-northeast1' }, 'Asia NE (Tokyo)'),
|
|
4054
|
+
h('option', { value: 'asia-southeast1' }, 'Asia SE (Singapore)'),
|
|
4055
|
+
h('option', { value: 'australia-southeast1' }, 'Australia (Sydney)'),
|
|
4056
|
+
h('option', { value: 'southamerica-east1' }, 'South America (São Paulo)')
|
|
4057
|
+
)
|
|
4058
|
+
),
|
|
4059
|
+
h('div', { className: 'form-group' },
|
|
4060
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Zone'),
|
|
4061
|
+
h('input', { className: 'input', value: deployForm.gcpZone, onChange: function(e) { setDf('gcpZone', e.target.value); }, placeholder: 'us-central1-a' })
|
|
4062
|
+
),
|
|
4063
|
+
h('div', { className: 'form-group' },
|
|
4064
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Machine Type'),
|
|
4065
|
+
h('select', { className: 'input', value: deployForm.gcpMachineType, onChange: function(e) { setDf('gcpMachineType', e.target.value); } },
|
|
4066
|
+
h('option', { value: 'e2-micro' }, 'e2-micro (0.25 vCPU, 1GB) — ~$6.11/mo'),
|
|
4067
|
+
h('option', { value: 'e2-small' }, 'e2-small (0.5 vCPU, 2GB) — ~$12.23/mo'),
|
|
4068
|
+
h('option', { value: 'e2-medium' }, 'e2-medium (1 vCPU, 4GB) — ~$24.46/mo'),
|
|
4069
|
+
h('option', { value: 'e2-standard-2' }, 'e2-standard-2 (2 vCPU, 8GB) — ~$48.92/mo'),
|
|
4070
|
+
h('option', { value: 'e2-standard-4' }, 'e2-standard-4 (4 vCPU, 16GB) — ~$97.83/mo'),
|
|
4071
|
+
h('option', { value: 'n2-standard-2' }, 'n2-standard-2 (2 vCPU, 8GB) — ~$56.52/mo'),
|
|
4072
|
+
h('option', { value: 'c2-standard-4' }, 'c2-standard-4 (4 vCPU, 16GB) — ~$124.49/mo')
|
|
4073
|
+
)
|
|
4074
|
+
)
|
|
4075
|
+
)
|
|
4076
|
+
),
|
|
4077
|
+
|
|
4078
|
+
// ── Microsoft Azure ─────────────────────────────────
|
|
4079
|
+
deployForm.target === 'azure' && h(Fragment, null,
|
|
4080
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
4081
|
+
h('div', { className: 'form-group' },
|
|
4082
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Subscription ID'),
|
|
4083
|
+
h('input', { className: 'input', value: deployForm.azureSubscriptionId, onChange: function(e) { setDf('azureSubscriptionId', e.target.value); }, placeholder: 'xxxxxxxx-xxxx-...' })
|
|
4084
|
+
),
|
|
4085
|
+
h('div', { className: 'form-group' },
|
|
4086
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Resource Group'),
|
|
4087
|
+
h('input', { className: 'input', value: deployForm.azureResourceGroup, onChange: function(e) { setDf('azureResourceGroup', e.target.value); }, placeholder: 'my-resource-group' })
|
|
4088
|
+
),
|
|
4089
|
+
h('div', { className: 'form-group' },
|
|
4090
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Region'),
|
|
4091
|
+
h('select', { className: 'input', value: deployForm.azureRegion, onChange: function(e) { setDf('azureRegion', e.target.value); } },
|
|
4092
|
+
h('option', { value: 'eastus' }, 'East US'),
|
|
4093
|
+
h('option', { value: 'eastus2' }, 'East US 2'),
|
|
4094
|
+
h('option', { value: 'westus2' }, 'West US 2'),
|
|
4095
|
+
h('option', { value: 'westus3' }, 'West US 3'),
|
|
4096
|
+
h('option', { value: 'centralus' }, 'Central US'),
|
|
4097
|
+
h('option', { value: 'northeurope' }, 'North Europe (Ireland)'),
|
|
4098
|
+
h('option', { value: 'westeurope' }, 'West Europe (Netherlands)'),
|
|
4099
|
+
h('option', { value: 'uksouth' }, 'UK South'),
|
|
4100
|
+
h('option', { value: 'germanywestcentral' }, 'Germany West Central'),
|
|
4101
|
+
h('option', { value: 'eastasia' }, 'East Asia (Hong Kong)'),
|
|
4102
|
+
h('option', { value: 'southeastasia' }, 'Southeast Asia (Singapore)'),
|
|
4103
|
+
h('option', { value: 'japaneast' }, 'Japan East'),
|
|
4104
|
+
h('option', { value: 'australiaeast' }, 'Australia East'),
|
|
4105
|
+
h('option', { value: 'brazilsouth' }, 'Brazil South'),
|
|
4106
|
+
h('option', { value: 'southafricanorth' }, 'South Africa North')
|
|
4107
|
+
)
|
|
4108
|
+
)
|
|
4109
|
+
),
|
|
4110
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4111
|
+
h('div', { className: 'form-group' },
|
|
4112
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'VM Size'),
|
|
4113
|
+
h('select', { className: 'input', value: deployForm.azureVmSize, onChange: function(e) { setDf('azureVmSize', e.target.value); } },
|
|
4114
|
+
h('option', { value: 'Standard_B1s' }, 'B1s (1 vCPU, 1GB) — ~$7.59/mo'),
|
|
4115
|
+
h('option', { value: 'Standard_B1ms' }, 'B1ms (1 vCPU, 2GB) — ~$15.11/mo'),
|
|
4116
|
+
h('option', { value: 'Standard_B2s' }, 'B2s (2 vCPU, 4GB) — ~$30.37/mo'),
|
|
4117
|
+
h('option', { value: 'Standard_B2ms' }, 'B2ms (2 vCPU, 8GB) — ~$60.74/mo'),
|
|
4118
|
+
h('option', { value: 'Standard_D2s_v5' }, 'D2s v5 (2 vCPU, 8GB) — ~$70.08/mo'),
|
|
4119
|
+
h('option', { value: 'Standard_D4s_v5' }, 'D4s v5 (4 vCPU, 16GB) — ~$140.16/mo'),
|
|
4120
|
+
h('option', { value: 'Standard_F2s_v2' }, 'F2s v2 (2 vCPU, 4GB) — ~$61.25/mo'),
|
|
4121
|
+
h('option', { value: 'Standard_E2s_v5' }, 'E2s v5 (2 vCPU, 16GB) — ~$91.98/mo')
|
|
4122
|
+
)
|
|
4123
|
+
),
|
|
4124
|
+
h('div', { className: 'form-group' },
|
|
4125
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Tenant ID (optional)'),
|
|
4126
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureTenantId, onChange: function(e) { setDf('azureTenantId', e.target.value); }, placeholder: 'For service principal auth' })
|
|
4127
|
+
)
|
|
4128
|
+
),
|
|
4129
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4130
|
+
h('div', { className: 'form-group' },
|
|
4131
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Client ID (optional)'),
|
|
4132
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureClientId, onChange: function(e) { setDf('azureClientId', e.target.value); }, placeholder: 'App registration client ID' })
|
|
4133
|
+
),
|
|
4134
|
+
h('div', { className: 'form-group' },
|
|
4135
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Client Secret (optional)'),
|
|
4136
|
+
h('input', { className: 'input', type: 'password', value: deployForm.azureClientSecret, onChange: function(e) { setDf('azureClientSecret', e.target.value); }, placeholder: '••••••••' })
|
|
4137
|
+
)
|
|
4138
|
+
)
|
|
4139
|
+
),
|
|
4140
|
+
|
|
4141
|
+
// ── Railway ─────────────────────────────────────────
|
|
4142
|
+
deployForm.target === 'railway' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
3881
4143
|
h('div', { className: 'form-group' },
|
|
3882
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3883
|
-
h('input', { className: 'input', value: deployForm.
|
|
4144
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'API Token'),
|
|
4145
|
+
h('input', { className: 'input', type: 'password', value: deployForm.railwayApiToken, onChange: function(e) { setDf('railwayApiToken', e.target.value); }, placeholder: 'railway_...' }),
|
|
4146
|
+
h('div', { style: { fontSize: 11, color: 'var(--text-muted)', marginTop: 2 } }, 'From railway.app/account/tokens')
|
|
3884
4147
|
),
|
|
3885
4148
|
h('div', { className: 'form-group' },
|
|
3886
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3887
|
-
h('input', { className: 'input', value: deployForm.
|
|
4149
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Project ID (optional)'),
|
|
4150
|
+
h('input', { className: 'input', value: deployForm.railwayProjectId, onChange: function(e) { setDf('railwayProjectId', e.target.value); }, placeholder: 'Auto-created if empty' })
|
|
3888
4151
|
),
|
|
3889
4152
|
h('div', { className: 'form-group' },
|
|
3890
|
-
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, '
|
|
3891
|
-
h('input', { className: 'input', value: deployForm.
|
|
4153
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Service Name'),
|
|
4154
|
+
h('input', { className: 'input', value: deployForm.railwayServiceName, onChange: function(e) { setDf('railwayServiceName', e.target.value); }, placeholder: 'agenticmail-agent' })
|
|
3892
4155
|
)
|
|
3893
4156
|
),
|
|
4157
|
+
|
|
4158
|
+
// ── Docker ──────────────────────────────────────────
|
|
4159
|
+
deployForm.target === 'docker' && h(Fragment, null,
|
|
4160
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
4161
|
+
h('div', { className: 'form-group' },
|
|
4162
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Image'),
|
|
4163
|
+
h('input', { className: 'input', value: deployForm.dockerImage, onChange: function(e) { setDf('dockerImage', e.target.value); }, placeholder: 'agenticmail/agent' })
|
|
4164
|
+
),
|
|
4165
|
+
h('div', { className: 'form-group' },
|
|
4166
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Tag'),
|
|
4167
|
+
h('input', { className: 'input', value: deployForm.dockerTag, onChange: function(e) { setDf('dockerTag', e.target.value); }, placeholder: 'latest' })
|
|
4168
|
+
),
|
|
4169
|
+
h('div', { className: 'form-group' },
|
|
4170
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Ports'),
|
|
4171
|
+
h('input', { className: 'input', value: deployForm.dockerPorts, onChange: function(e) { setDf('dockerPorts', e.target.value); }, placeholder: '3000' })
|
|
4172
|
+
)
|
|
4173
|
+
),
|
|
4174
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16, marginTop: 12 } },
|
|
4175
|
+
h('div', { className: 'form-group' },
|
|
4176
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Memory'),
|
|
4177
|
+
h('input', { className: 'input', value: deployForm.dockerMemory, onChange: function(e) { setDf('dockerMemory', e.target.value); }, placeholder: '512m' })
|
|
4178
|
+
),
|
|
4179
|
+
h('div', { className: 'form-group' },
|
|
4180
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'CPU'),
|
|
4181
|
+
h('input', { className: 'input', value: deployForm.dockerCpu, onChange: function(e) { setDf('dockerCpu', e.target.value); }, placeholder: '0.5' })
|
|
4182
|
+
),
|
|
4183
|
+
h('div', { className: 'form-group' },
|
|
4184
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Network'),
|
|
4185
|
+
h('input', { className: 'input', value: deployForm.dockerNetwork, onChange: function(e) { setDf('dockerNetwork', e.target.value); }, placeholder: 'bridge (default)' })
|
|
4186
|
+
),
|
|
4187
|
+
h('div', { className: 'form-group' },
|
|
4188
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Restart Policy'),
|
|
4189
|
+
h('select', { className: 'input', value: deployForm.dockerRestart, onChange: function(e) { setDf('dockerRestart', e.target.value); } },
|
|
4190
|
+
h('option', { value: 'unless-stopped' }, 'Unless Stopped'),
|
|
4191
|
+
h('option', { value: 'always' }, 'Always'),
|
|
4192
|
+
h('option', { value: 'on-failure' }, 'On Failure'),
|
|
4193
|
+
h('option', { value: 'no' }, 'Never')
|
|
4194
|
+
)
|
|
4195
|
+
)
|
|
4196
|
+
)
|
|
4197
|
+
),
|
|
4198
|
+
|
|
4199
|
+
// ── VPS / Bare Metal ────────────────────────────────
|
|
3894
4200
|
deployForm.target === 'vps' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 16 } },
|
|
3895
4201
|
h('div', { className: 'form-group' },
|
|
3896
4202
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Host'),
|
|
3897
|
-
h('input', { className: 'input', value: deployForm.vpsHost, onChange: function(e) { setDf('vpsHost', e.target.value); }, placeholder: '192.168.1.100' })
|
|
4203
|
+
h('input', { className: 'input', value: deployForm.vpsHost, onChange: function(e) { setDf('vpsHost', e.target.value); }, placeholder: '192.168.1.100 or hostname' })
|
|
4204
|
+
),
|
|
4205
|
+
h('div', { className: 'form-group' },
|
|
4206
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'SSH Port'),
|
|
4207
|
+
h('input', { className: 'input', type: 'number', value: deployForm.vpsPort, onChange: function(e) { setDf('vpsPort', e.target.value); }, placeholder: '22' })
|
|
3898
4208
|
),
|
|
3899
4209
|
h('div', { className: 'form-group' },
|
|
3900
4210
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'User'),
|
|
@@ -3903,7 +4213,16 @@ function DeploymentSection(props) {
|
|
|
3903
4213
|
h('div', { className: 'form-group' },
|
|
3904
4214
|
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'SSH Key Path'),
|
|
3905
4215
|
h('input', { className: 'input', value: deployForm.vpsKeyPath, onChange: function(e) { setDf('vpsKeyPath', e.target.value); }, placeholder: '~/.ssh/id_rsa' })
|
|
4216
|
+
),
|
|
4217
|
+
h('div', { className: 'form-group' },
|
|
4218
|
+
h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Work Directory'),
|
|
4219
|
+
h('input', { className: 'input', value: deployForm.vpsWorkDir, onChange: function(e) { setDf('vpsWorkDir', e.target.value); }, placeholder: '/opt/agenticmail' })
|
|
3906
4220
|
)
|
|
4221
|
+
),
|
|
4222
|
+
|
|
4223
|
+
// ── Local ───────────────────────────────────────────
|
|
4224
|
+
deployForm.target === 'local' && h('div', { style: { padding: 16, background: 'var(--bg-tertiary)', borderRadius: 8, fontSize: 13, color: 'var(--text-muted)' } },
|
|
4225
|
+
'Agent will run in-process on this server. No external deployment required. Best for development and testing.'
|
|
3907
4226
|
)
|
|
3908
4227
|
)
|
|
3909
4228
|
),
|