@agenticmail/enterprise 0.5.94 → 0.5.97

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 || deployment.config?.cloud?.region || 'iad',
3751
- imageTag: (deployment.config?.docker?.tag) || deployment.imageTag || 'latest',
3752
- memory: (deployment.config?.docker?.memory) || deployment.memory || '512m',
3753
- cpu: (deployment.config?.docker?.cpu) || deployment.cpu || '0.5',
3754
- ports: (deployment.config?.docker?.ports || [3000]).join(', '),
3755
- flyApiToken: deployment.config?.cloud?.apiToken || '',
3756
- flyAppName: deployment.config?.cloud?.appName || '',
3757
- vpsHost: deployment.config?.vps?.host || '',
3758
- vpsUser: deployment.config?.vps?.user || 'root',
3759
- vpsKeyPath: deployment.config?.vps?.keyPath || '',
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 (deployForm.target === 'fly') {
3768
- deployConfig = { cloud: { provider: 'fly', region: deployForm.region || 'iad', apiToken: deployForm.flyApiToken || undefined, appName: deployForm.flyAppName || undefined } };
3769
- } else if (deployForm.target === 'docker') {
3770
- deployConfig = { docker: { image: 'agenticmail/agent', tag: deployForm.imageTag, ports: deployForm.ports.split(',').map(function(p) { return parseInt(p.trim()) || 3000; }), memory: deployForm.memory, cpu: deployForm.cpu, restart: 'unless-stopped' } };
3771
- } else if (deployForm.target === 'vps') {
3772
- deployConfig = { vps: { host: deployForm.vpsHost || '', user: deployForm.vpsUser || 'root', keyPath: deployForm.vpsKeyPath || '' } };
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: deployForm.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: 'docker' }, 'Docker'),
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: 'vps' }, 'VPS / Server'),
3850
- h('option', { value: 'local' }, 'Local')
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: 'lax' }, 'Los Angeles (lax)'),
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: 'nrt' }, 'Tokyo (nrt)')
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 } }, 'Fly.io API Token'),
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 (optional)'),
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
- deployForm.target === 'docker' && h('div', { style: { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr 1fr', gap: 16 } },
3877
- h('div', { className: 'form-group' },
3878
- h('label', { style: { display: 'block', fontSize: 12, fontWeight: 600, color: 'var(--text-secondary)', marginBottom: 4 } }, 'Image Tag'),
3879
- h('input', { className: 'input', value: deployForm.imageTag, onChange: function(e) { setDf('imageTag', e.target.value); } })
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 } }, 'Memory'),
3883
- h('input', { className: 'input', value: deployForm.memory, onChange: function(e) { setDf('memory', e.target.value); }, placeholder: '512m' })
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 } }, 'CPU'),
3887
- h('input', { className: 'input', value: deployForm.cpu, onChange: function(e) { setDf('cpu', e.target.value); }, placeholder: '0.5' })
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 } }, 'Ports'),
3891
- h('input', { className: 'input', value: deployForm.ports, onChange: function(e) { setDf('ports', e.target.value); }, placeholder: '3000' })
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
  ),
@@ -307,7 +307,7 @@ export class EngineDatabase {
307
307
  async upsertPermissionProfile(orgId: string, profile: AgentPermissionProfile): Promise<void> {
308
308
  await this.db.run(`
309
309
  INSERT INTO permission_profiles (id, org_id, name, description, config, is_preset, created_at, updated_at)
310
- VALUES (?, ?, ?, ?, ?, 0, ?, ?)
310
+ VALUES (?, ?, ?, ?, ?, false, ?, ?)
311
311
  ON CONFLICT(id) DO UPDATE SET
312
312
  name = excluded.name, description = excluded.description,
313
313
  config = excluded.config, updated_at = excluded.updated_at
@@ -137,6 +137,8 @@ export class AgentRuntime {
137
137
  agentId,
138
138
  workspaceDir: process.cwd(),
139
139
  agenticmailManager: this.config.agenticmailManager,
140
+ agentMemoryManager: this.config.agentMemoryManager,
141
+ orgId: 'default', // TODO: resolve from agent's org
140
142
  };
141
143
  if (this.config.getEmailConfig) {
142
144
  const ec = this.config.getEmailConfig(agentId);
@@ -258,7 +260,12 @@ export class AgentRuntime {
258
260
  // Build agent config
259
261
  var tools = opts.tools || await createAllTools(this.buildToolOptions(agentId));
260
262
 
261
- var systemPrompt = opts.systemPrompt || buildDefaultSystemPrompt(agentId);
263
+ // Inject persistent memory context into system prompt
264
+ var memoryContext = '';
265
+ if (this.config.agentMemoryManager) {
266
+ try { memoryContext = await this.config.agentMemoryManager.generateMemoryContext(agentId); } catch {}
267
+ }
268
+ var systemPrompt = opts.systemPrompt || buildDefaultSystemPrompt(agentId, memoryContext);
262
269
 
263
270
  var agentConfig: AgentConfig = {
264
271
  agentId,
@@ -300,11 +307,16 @@ export class AgentRuntime {
300
307
 
301
308
  var tools = await createAllTools(this.buildToolOptions(session.agentId));
302
309
 
310
+ var memoryContext = '';
311
+ if (this.config.agentMemoryManager) {
312
+ try { memoryContext = await this.config.agentMemoryManager.generateMemoryContext(session.agentId); } catch {}
313
+ }
314
+
303
315
  var agentConfig: AgentConfig = {
304
316
  agentId: session.agentId,
305
317
  orgId: session.orgId,
306
318
  model,
307
- systemPrompt: buildDefaultSystemPrompt(session.agentId),
319
+ systemPrompt: buildDefaultSystemPrompt(session.agentId, memoryContext),
308
320
  tools,
309
321
  };
310
322
 
@@ -591,11 +603,16 @@ export class AgentRuntime {
591
603
 
592
604
  var tools = await createAllTools(this.buildToolOptions(session.agentId));
593
605
 
606
+ var mc = '';
607
+ if (this.config.agentMemoryManager) {
608
+ try { mc = await this.config.agentMemoryManager.generateMemoryContext(session.agentId); } catch {}
609
+ }
610
+
594
611
  var agentConfig: AgentConfig = {
595
612
  agentId: session.agentId,
596
613
  orgId: session.orgId,
597
614
  model,
598
- systemPrompt: buildDefaultSystemPrompt(session.agentId),
615
+ systemPrompt: buildDefaultSystemPrompt(session.agentId, mc),
599
616
  tools,
600
617
  };
601
618
 
@@ -678,8 +695,8 @@ export function createAgentRuntime(config: RuntimeConfig): AgentRuntime {
678
695
 
679
696
  // ─── Default System Prompt ───────────────────────────────
680
697
 
681
- function buildDefaultSystemPrompt(agentId: string): string {
682
- return `You are an AI agent managed by AgenticMail Enterprise (agent: ${agentId}).
698
+ function buildDefaultSystemPrompt(agentId: string, memoryContext?: string): string {
699
+ var base = `You are an AI agent managed by AgenticMail Enterprise (agent: ${agentId}).
683
700
 
684
701
  You have access to a comprehensive set of tools for completing tasks. Use them effectively.
685
702
 
@@ -691,6 +708,15 @@ Guidelines:
691
708
  - Respect organization policies and permissions
692
709
  - Keep responses concise unless detail is requested
693
710
  - For long tasks, work systematically and report progress
711
+ - ACTIVELY USE YOUR MEMORY: After corrections, lessons, or insights, call memory_reflect to record them
712
+ - Before complex tasks, call memory_context to recall relevant knowledge
713
+ - Your memory persists across conversations — it's how you grow as an expert
694
714
 
695
715
  Current time: ${new Date().toISOString()}`;
716
+
717
+ if (memoryContext) {
718
+ base += '\n\n' + memoryContext;
719
+ }
720
+
721
+ return base;
696
722
  }
@@ -118,6 +118,8 @@ export interface RuntimeConfig {
118
118
  gatewayEnabled?: boolean;
119
119
  /** AgenticMail manager for org email access (optional — enables agenticmail_* tools) */
120
120
  agenticmailManager?: import('../agent-tools/tools/agenticmail.js').AgenticMailManagerRef;
121
+ /** Agent memory manager for persistent DB-backed memory (optional — enables enhanced memory tools) */
122
+ agentMemoryManager?: import('../engine/agent-memory.js').AgentMemoryManager;
121
123
  /** Get OAuth email config for an agent (enables Google/Microsoft Workspace tools) */
122
124
  getEmailConfig?: (agentId: string) => any;
123
125
  /** Callback to persist refreshed OAuth tokens */
package/src/server.ts CHANGED
@@ -268,8 +268,10 @@ export function createServer(config: ServerConfig): ServerInstance {
268
268
  // Import lifecycle for email config access
269
269
  let getEmailConfig: ((agentId: string) => any) | undefined;
270
270
  let onTokenRefresh: ((agentId: string, tokens: any) => void) | undefined;
271
+ let agentMemoryMgr: any;
271
272
  try {
272
- const { lifecycle: lc } = await import('./engine/routes.js');
273
+ const { lifecycle: lc, memoryManager: mm } = await import('./engine/routes.js');
274
+ agentMemoryMgr = mm;
273
275
  if (lc) {
274
276
  getEmailConfig = (agentId: string) => {
275
277
  const managed = lc.getAgent(agentId);
@@ -294,6 +296,7 @@ export function createServer(config: ServerConfig): ServerInstance {
294
296
  gatewayEnabled: true,
295
297
  getEmailConfig,
296
298
  onTokenRefresh,
299
+ agentMemoryManager: agentMemoryMgr,
297
300
  });
298
301
  await runtime.start();
299
302
  const runtimeApp = runtime.getApp();