diff --git a/.gitignore b/.gitignore
index 24fe21d..937f2fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,7 @@ obj/
*.user
*.suo
*.vs/
+Red Ink for Word/Red Ink for Word_TemporaryKey.pfx
+Red Ink for Excel/Red Ink for Excel_TemporaryKey.pfx
+Red Ink for Outlook/Red Ink for Outlook_TemporaryKey.pfx
diff --git a/Red Ink for Excel/Red Ink for Excel.vbproj b/Red Ink for Excel/Red Ink for Excel.vbproj
index 8353b14..aaef44a 100644
--- a/Red Ink for Excel/Red Ink for Excel.vbproj
+++ b/Red Ink for Excel/Red Ink for Excel.vbproj
@@ -1,4 +1,4 @@
-
+
@@ -448,4 +452,7 @@
-
\ No newline at end of file
+
+
+
+
diff --git a/Red Ink for Outlook/Ribbon1.Designer.vb b/Red Ink for Outlook/Ribbon1.Designer.vb
index a1d4b0d..196d398 100644
--- a/Red Ink for Outlook/Ribbon1.Designer.vb
+++ b/Red Ink for Outlook/Ribbon1.Designer.vb
@@ -112,6 +112,7 @@ Partial Class Ribbon1
Me.Menu1.Items.Add(Me.RI_Clipboard)
Me.Menu1.Items.Add(Me.RI_DefineMyStyle)
Me.Menu1.Items.Add(Me.RI_HelpMe)
+ Me.Menu1.Items.Add(Me.ModelsMenu)
Me.Menu1.Items.Add(Me.Settings)
Me.Menu1.KeyTip = "S"
Me.Menu1.Label = "Task"
@@ -380,6 +381,17 @@ Partial Class Ribbon1
Friend WithEvents RI_ApplyMyStyle As RibbonButton
Friend WithEvents RI_DefineMyStyle As RibbonButton
Friend WithEvents RI_HelpMe As RibbonButton
+ Friend WithEvents ModelsMenu As RibbonMenu
+ Friend WithEvents RI_Model1 As RibbonButton
+ Friend WithEvents RI_Model2 As RibbonButton
+ Friend WithEvents RI_Model3 As RibbonButton
+ Friend WithEvents RI_Model4 As RibbonButton
+ Friend WithEvents RI_Model5 As RibbonButton
+ Friend WithEvents RI_Model6 As RibbonButton
+ Friend WithEvents RI_Model7 As RibbonButton
+ Friend WithEvents RI_Model8 As RibbonButton
+ Friend WithEvents RI_Model9 As RibbonButton
+ Friend WithEvents RI_Model10 As RibbonButton
End Class
Partial Class ThisRibbonCollection
@@ -459,6 +471,17 @@ Partial Class Ribbon2
Me.RI_Clipboard = Me.Factory.CreateRibbonButton
Me.RI_DefineMyStyle = Me.Factory.CreateRibbonButton
Me.RI_HelpMe = Me.Factory.CreateRibbonButton
+ Me.ModelsMenu = Me.Factory.CreateRibbonMenu
+ Me.RI_Model1 = Me.Factory.CreateRibbonButton
+ Me.RI_Model2 = Me.Factory.CreateRibbonButton
+ Me.RI_Model3 = Me.Factory.CreateRibbonButton
+ Me.RI_Model4 = Me.Factory.CreateRibbonButton
+ Me.RI_Model5 = Me.Factory.CreateRibbonButton
+ Me.RI_Model6 = Me.Factory.CreateRibbonButton
+ Me.RI_Model7 = Me.Factory.CreateRibbonButton
+ Me.RI_Model8 = Me.Factory.CreateRibbonButton
+ Me.RI_Model9 = Me.Factory.CreateRibbonButton
+ Me.RI_Model10 = Me.Factory.CreateRibbonButton
Me.Settings = Me.Factory.CreateRibbonButton
Me.Group2 = Me.Factory.CreateRibbonGroup
Me.RI_PrimLang2 = Me.Factory.CreateRibbonButton
@@ -502,6 +525,7 @@ Partial Class Ribbon2
Me.Menu1.Items.Add(Me.RI_Clipboard)
Me.Menu1.Items.Add(Me.RI_DefineMyStyle)
Me.Menu1.Items.Add(Me.RI_HelpMe)
+ Me.Menu1.Items.Add(Me.ModelsMenu)
Me.Menu1.Items.Add(Me.Settings)
Me.Menu1.KeyTip = "S"
Me.Menu1.Label = "Task"
@@ -509,6 +533,82 @@ Partial Class Ribbon2
Me.Menu1.ShowImage = True
Me.Menu1.SuperTip = "Access other functions of Red Ink"
'
+ 'ModelsMenu
+ '
+ Me.ModelsMenu.Label = "Models"
+ Me.ModelsMenu.Name = "ModelsMenu"
+ Me.ModelsMenu.ShowImage = True
+ Me.ModelsMenu.Items.Add(Me.RI_Model1)
+ Me.ModelsMenu.Items.Add(Me.RI_Model2)
+ Me.ModelsMenu.Items.Add(Me.RI_Model3)
+ Me.ModelsMenu.Items.Add(Me.RI_Model4)
+ Me.ModelsMenu.Items.Add(Me.RI_Model5)
+ Me.ModelsMenu.Items.Add(Me.RI_Model6)
+ Me.ModelsMenu.Items.Add(Me.RI_Model7)
+ Me.ModelsMenu.Items.Add(Me.RI_Model8)
+ Me.ModelsMenu.Items.Add(Me.RI_Model9)
+ Me.ModelsMenu.Items.Add(Me.RI_Model10)
+ '
+ 'RI_Model1
+ '
+ Me.RI_Model1.Label = "Model 1"
+ Me.RI_Model1.Name = "RI_Model1"
+ Me.RI_Model1.Visible = False
+ '
+ 'RI_Model2
+ '
+ Me.RI_Model2.Label = "Model 2"
+ Me.RI_Model2.Name = "RI_Model2"
+ Me.RI_Model2.Visible = False
+ '
+ 'RI_Model3
+ '
+ Me.RI_Model3.Label = "Model 3"
+ Me.RI_Model3.Name = "RI_Model3"
+ Me.RI_Model3.Visible = False
+ '
+ 'RI_Model4
+ '
+ Me.RI_Model4.Label = "Model 4"
+ Me.RI_Model4.Name = "RI_Model4"
+ Me.RI_Model4.Visible = False
+ '
+ 'RI_Model5
+ '
+ Me.RI_Model5.Label = "Model 5"
+ Me.RI_Model5.Name = "RI_Model5"
+ Me.RI_Model5.Visible = False
+ '
+ 'RI_Model6
+ '
+ Me.RI_Model6.Label = "Model 6"
+ Me.RI_Model6.Name = "RI_Model6"
+ Me.RI_Model6.Visible = False
+ '
+ 'RI_Model7
+ '
+ Me.RI_Model7.Label = "Model 7"
+ Me.RI_Model7.Name = "RI_Model7"
+ Me.RI_Model7.Visible = False
+ '
+ 'RI_Model8
+ '
+ Me.RI_Model8.Label = "Model 8"
+ Me.RI_Model8.Name = "RI_Model8"
+ Me.RI_Model8.Visible = False
+ '
+ 'RI_Model9
+ '
+ Me.RI_Model9.Label = "Model 9"
+ Me.RI_Model9.Name = "RI_Model9"
+ Me.RI_Model9.Visible = False
+ '
+ 'RI_Model10
+ '
+ Me.RI_Model10.Label = "Model 10"
+ Me.RI_Model10.Name = "RI_Model10"
+ Me.RI_Model10.Visible = False
+ '
'RI_Primlang
'
Me.RI_Primlang.KeyTip = "E"
@@ -769,6 +869,17 @@ Partial Class Ribbon2
Friend WithEvents RI_ApplyMyStyle As RibbonButton
Friend WithEvents RI_DefineMyStyle As RibbonButton
Friend WithEvents RI_HelpMe As RibbonButton
+ Friend WithEvents ModelsMenu As RibbonMenu
+ Friend WithEvents RI_Model1 As RibbonButton
+ Friend WithEvents RI_Model2 As RibbonButton
+ Friend WithEvents RI_Model3 As RibbonButton
+ Friend WithEvents RI_Model4 As RibbonButton
+ Friend WithEvents RI_Model5 As RibbonButton
+ Friend WithEvents RI_Model6 As RibbonButton
+ Friend WithEvents RI_Model7 As RibbonButton
+ Friend WithEvents RI_Model8 As RibbonButton
+ Friend WithEvents RI_Model9 As RibbonButton
+ Friend WithEvents RI_Model10 As RibbonButton
End Class
Partial Class ThisRibbonCollection
diff --git a/Red Ink for Outlook/Ribbon1.vb b/Red Ink for Outlook/Ribbon1.vb
index 363666b..8a17bbe 100644
--- a/Red Ink for Outlook/Ribbon1.vb
+++ b/Red Ink for Outlook/Ribbon1.vb
@@ -3,6 +3,7 @@
Imports Microsoft.Office.Tools.Ribbon
Imports Microsoft.Win32
+Imports SharedLibrary.SharedLibrary
Public Class Ribbon1
Private Enum OfficeTheme
@@ -160,6 +161,84 @@ Public Class Ribbon1
Globals.ThisAddIn.HelpMeInky()
End Sub
+ Private Sub RI_Model1_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model1.Click
+ Globals.ThisAddIn.SelectModel(1)
+ End Sub
+
+ Private Sub RI_Model2_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model2.Click
+ Globals.ThisAddIn.SelectModel(2)
+ End Sub
+
+ Private Sub RI_Model3_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model3.Click
+ Globals.ThisAddIn.SelectModel(3)
+ End Sub
+
+ Private Sub RI_Model4_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model4.Click
+ Globals.ThisAddIn.SelectModel(4)
+ End Sub
+
+ Private Sub RI_Model5_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model5.Click
+ Globals.ThisAddIn.SelectModel(5)
+ End Sub
+
+ Private Sub RI_Model6_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model6.Click
+ Globals.ThisAddIn.SelectModel(6)
+ End Sub
+
+ Private Sub RI_Model7_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model7.Click
+ Globals.ThisAddIn.SelectModel(7)
+ End Sub
+
+ Private Sub RI_Model8_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model8.Click
+ Globals.ThisAddIn.SelectModel(8)
+ End Sub
+
+ Private Sub RI_Model9_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model9.Click
+ Globals.ThisAddIn.SelectModel(9)
+ End Sub
+
+ Private Sub RI_Model10_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model10.Click
+ Globals.ThisAddIn.SelectModel(10)
+ End Sub
+
+ Public Sub UpdateModelsMenu()
+ Try
+ Dim available = ModelConfigManager.GetAvailableModels()
+ Dim current = ModelConfigManager.GetCurrentModelNumber()
+
+ For i = 1 To 10
+ Dim btn = GetModelButton(i)
+ If btn Is Nothing Then Continue For
+
+ If available.Contains(i) Then
+ btn.Visible = True
+ Dim label = ModelConfigManager.GetModelDisplayName(i)
+ btn.Label = If(i = current, label & " *", label)
+ Else
+ btn.Visible = False
+ End If
+ Next
+ Catch
+ ' non-critical
+ End Try
+ End Sub
+
+ Private Function GetModelButton(i As Integer) As RibbonButton
+ Select Case i
+ Case 1 : Return RI_Model1
+ Case 2 : Return RI_Model2
+ Case 3 : Return RI_Model3
+ Case 4 : Return RI_Model4
+ Case 5 : Return RI_Model5
+ Case 6 : Return RI_Model6
+ Case 7 : Return RI_Model7
+ Case 8 : Return RI_Model8
+ Case 9 : Return RI_Model9
+ Case 10 : Return RI_Model10
+ End Select
+ Return Nothing
+ End Function
+
End Class
Public Class Ribbon2
diff --git a/Red Ink for Outlook/ThisAddIn.vb b/Red Ink for Outlook/ThisAddIn.vb
index c3cb2c7..c0fe161 100644
--- a/Red Ink for Outlook/ThisAddIn.vb
+++ b/Red Ink for Outlook/ThisAddIn.vb
@@ -48,6 +48,7 @@ Imports Microsoft.Office.Interop.Outlook
Imports Microsoft.Office.Interop.PowerPoint
Imports Microsoft.Office.Interop.Word
Imports SharedLibrary.SharedLibrary
+Imports SharedLibrary.SharedLibrary.SharedMethods
Partial Public Class ThisAddIn
@@ -576,6 +577,30 @@ Partial Public Class ThisAddIn
_context.InitialConfigFailed = False
_context.RDV = "Outlook (" & Version & ")"
SharedMethods.InitializeConfig(_context, FirstTime, Reload)
+ Try
+ If Globals.Ribbons.Ribbon1 IsNot Nothing Then
+ Globals.Ribbons.Ribbon1.UpdateModelsMenu()
+ End If
+ Catch
+ ' Ribbon may not be ready yet
+ End Try
+ End Sub
+ Public Shared Sub SelectModel(modelNumber As Integer)
+ Try
+ If ModelConfigManager.SelectModel(_context, modelNumber) Then
+ Try
+ If Globals.Ribbons.Ribbon1 IsNot Nothing Then
+ Globals.Ribbons.Ribbon1.UpdateModelsMenu()
+ End If
+ Catch
+ ' non-critical
+ End Try
+ Else
+ SharedMethods.ShowCustomMessageBox($"Model {modelNumber} is not configured.")
+ End If
+ Catch ex As System.Exception
+ SharedMethods.ShowCustomMessageBox($"Error switching model: {ex.Message}")
+ End Try
End Sub
'''
diff --git a/Red Ink for Word/Red Ink for Word.vbproj b/Red Ink for Word/Red Ink for Word.vbproj
index dd88f45..9fd61b9 100644
--- a/Red Ink for Word/Red Ink for Word.vbproj
+++ b/Red Ink for Word/Red Ink for Word.vbproj
@@ -1,4 +1,4 @@
-
+
@@ -48,21 +48,21 @@
3
- 1.0.0.700
+ 1.0.0.706
..\clickonce\apps\develop\word\
https://redink.ai/apps/develop/word/
Red Ink for Word %28Develop%29
Red Ink for Word %28Develop%29
- 1.0.0.201
+ 1.0.0.706
..\clickonce\apps\preview\word\
https://redink.ai/apps/preview/word/
Red Ink for Word %28Preview%29
Red Ink for Word %28Preview%29
- 1.0.0.1
+ 1.0.0.706
..\clickonce\apps\ga\word\
https://redink.ai/apps/ga/word/
Red Ink for Word
@@ -556,6 +556,7 @@
+
@@ -628,6 +629,7 @@
+
@@ -759,7 +761,7 @@
true
- 50229D23A3CA721BCA66C2ECC258074E6C6D6456
+ 5E40483CEA0314AAD471029E15CE26096544C430
http://timestamp.digicert.com
@@ -784,6 +786,9 @@
pdbonly
x64
+
+ Red Ink for Word_TemporaryKey.pfx
+
@@ -822,4 +827,9 @@
-
\ No newline at end of file
+
+
+
+
+
+
diff --git a/Red Ink for Word/Ribbon1.Designer.vb b/Red Ink for Word/Ribbon1.Designer.vb
index ad54705..389f337 100644
--- a/Red Ink for Word/Ribbon1.Designer.vb
+++ b/Red Ink for Word/Ribbon1.Designer.vb
@@ -85,6 +85,7 @@ Partial Class Ribbon1
Me.RI_ArgueAgainst = Me.Factory.CreateRibbonButton
Me.RI_SuggestTitles = Me.Factory.CreateRibbonButton
Me.RI_RevisionsSummary = Me.Factory.CreateRibbonButton
+ Me.RI_RevisionsSummary = Me.Factory.CreateRibbonButton
Me.RI_SpecialModel = Me.Factory.CreateRibbonButton
Me.RI_DocCheck = Me.Factory.CreateRibbonButton
Me.RI_FindClause = Me.Factory.CreateRibbonButton
@@ -113,6 +114,17 @@ Partial Class Ribbon1
Me.RI_Transcriptor = Me.Factory.CreateRibbonButton
Me.RI_DiscussInky = Me.Factory.CreateRibbonButton
Me.RI_HelpMe = Me.Factory.CreateRibbonButton
+ Me.ModelsMenu = Me.Factory.CreateRibbonMenu
+ Me.RI_Model1 = Me.Factory.CreateRibbonButton
+ Me.RI_Model2 = Me.Factory.CreateRibbonButton
+ Me.RI_Model3 = Me.Factory.CreateRibbonButton
+ Me.RI_Model4 = Me.Factory.CreateRibbonButton
+ Me.RI_Model5 = Me.Factory.CreateRibbonButton
+ Me.RI_Model6 = Me.Factory.CreateRibbonButton
+ Me.RI_Model7 = Me.Factory.CreateRibbonButton
+ Me.RI_Model8 = Me.Factory.CreateRibbonButton
+ Me.RI_Model9 = Me.Factory.CreateRibbonButton
+ Me.RI_Model10 = Me.Factory.CreateRibbonButton
Me.Settings = Me.Factory.CreateRibbonButton
Me.Group2 = Me.Factory.CreateRibbonGroup
Me.RI_PrimLang2 = Me.Factory.CreateRibbonButton
@@ -162,6 +174,7 @@ Partial Class Ribbon1
Me.Menu1.Items.Add(Me.RI_Transcriptor)
Me.Menu1.Items.Add(Me.RI_DiscussInky)
Me.Menu1.Items.Add(Me.RI_HelpMe)
+ Me.Menu1.Items.Add(Me.ModelsMenu)
Me.Menu1.Items.Add(Me.Settings)
Me.Menu1.KeyTip = "RI"
Me.Menu1.Label = "Task"
@@ -423,15 +436,6 @@ Partial Class Ribbon1
Me.RI_Explain.ScreenTip = "Explain in simple terms what the selected text means"
Me.RI_Explain.ShowImage = True
'
- 'RI_ArgueAgainst
- '
- Me.RI_ArgueAgainst.Label = "Argue Against"
- Me.RI_ArgueAgainst.Name = "RI_ArgueAgainst"
- Me.RI_ArgueAgainst.OfficeImageId = "SpeakStop"
- Me.RI_ArgueAgainst.ScreenTip = "This will let the AI argue against the selected text with at least the number of " &
- "words defined by you"
- Me.RI_ArgueAgainst.ShowImage = True
- '
'RI_SuggestTitles
'
Me.RI_SuggestTitles.Label = "Suggest Titles"
@@ -687,6 +691,82 @@ Partial Class Ribbon1
Me.RI_HelpMe.ScreenTip = "This will call up a chatbot that answers your questions about Red Ink"
Me.RI_HelpMe.ShowImage = True
'
+ 'ModelsMenu
+ '
+ Me.ModelsMenu.Items.Add(Me.RI_Model1)
+ Me.ModelsMenu.Items.Add(Me.RI_Model2)
+ Me.ModelsMenu.Items.Add(Me.RI_Model3)
+ Me.ModelsMenu.Items.Add(Me.RI_Model4)
+ Me.ModelsMenu.Items.Add(Me.RI_Model5)
+ Me.ModelsMenu.Items.Add(Me.RI_Model6)
+ Me.ModelsMenu.Items.Add(Me.RI_Model7)
+ Me.ModelsMenu.Items.Add(Me.RI_Model8)
+ Me.ModelsMenu.Items.Add(Me.RI_Model9)
+ Me.ModelsMenu.Items.Add(Me.RI_Model10)
+ Me.ModelsMenu.Label = "Models"
+ Me.ModelsMenu.Name = "ModelsMenu"
+ Me.ModelsMenu.ShowImage = True
+ '
+ 'RI_Model1
+ '
+ Me.RI_Model1.Label = ""
+ Me.RI_Model1.Name = "RI_Model1"
+ Me.RI_Model1.ShowImage = True
+ '
+ 'RI_Model2
+ '
+ Me.RI_Model2.Label = ""
+ Me.RI_Model2.Name = "RI_Model2"
+ Me.RI_Model2.ShowImage = True
+ '
+ 'RI_Model3
+ '
+ Me.RI_Model3.Label = ""
+ Me.RI_Model3.Name = "RI_Model3"
+ Me.RI_Model3.ShowImage = True
+ '
+ 'RI_Model4
+ '
+ Me.RI_Model4.Label = ""
+ Me.RI_Model4.Name = "RI_Model4"
+ Me.RI_Model4.ShowImage = True
+ '
+ 'RI_Model5
+ '
+ Me.RI_Model5.Label = ""
+ Me.RI_Model5.Name = "RI_Model5"
+ Me.RI_Model5.ShowImage = True
+ '
+ 'RI_Model6
+ '
+ Me.RI_Model6.Label = ""
+ Me.RI_Model6.Name = "RI_Model6"
+ Me.RI_Model6.ShowImage = True
+ '
+ 'RI_Model7
+ '
+ Me.RI_Model7.Label = ""
+ Me.RI_Model7.Name = "RI_Model7"
+ Me.RI_Model7.ShowImage = True
+ '
+ 'RI_Model8
+ '
+ Me.RI_Model8.Label = ""
+ Me.RI_Model8.Name = "RI_Model8"
+ Me.RI_Model8.ShowImage = True
+ '
+ 'RI_Model9
+ '
+ Me.RI_Model9.Label = ""
+ Me.RI_Model9.Name = "RI_Model9"
+ Me.RI_Model9.ShowImage = True
+ '
+ 'RI_Model10
+ '
+ Me.RI_Model10.Label = ""
+ Me.RI_Model10.Name = "RI_Model10"
+ Me.RI_Model10.ShowImage = True
+ '
'Settings
'
Me.Settings.Label = "Settings"
@@ -733,6 +813,15 @@ Partial Class Ribbon1
Me.RI_Chat.ScreenTip = "Will open a window where you can chat with the LLM"
Me.RI_Chat.ShowImage = True
'
+ 'RI_ArgueAgainst
+ '
+ Me.RI_ArgueAgainst.Label = "Argue Against"
+ Me.RI_ArgueAgainst.Name = "RI_ArgueAgainst"
+ Me.RI_ArgueAgainst.OfficeImageId = "SpeakStop"
+ Me.RI_ArgueAgainst.ScreenTip = "This will let the AI argue against the selected text with at least the number of " &
+ "words defined by you"
+ Me.RI_ArgueAgainst.ShowImage = True
+ '
'Ribbon1
'
Me.Name = "Ribbon1"
@@ -992,6 +1081,17 @@ Partial Class Ribbon1
Friend WithEvents RI_LiveCompare As RibbonButton
Friend WithEvents RI_RevisionsSummary As RibbonButton
Friend WithEvents RI_DiscussInky As RibbonButton
+ Friend WithEvents ModelsMenu As RibbonMenu
+ Friend WithEvents RI_Model1 As RibbonButton
+ Friend WithEvents RI_Model2 As RibbonButton
+ Friend WithEvents RI_Model3 As RibbonButton
+ Friend WithEvents RI_Model4 As RibbonButton
+ Friend WithEvents RI_Model5 As RibbonButton
+ Friend WithEvents RI_Model6 As RibbonButton
+ Friend WithEvents RI_Model7 As RibbonButton
+ Friend WithEvents RI_Model8 As RibbonButton
+ Friend WithEvents RI_Model9 As RibbonButton
+ Friend WithEvents RI_Model10 As RibbonButton
End Class
Partial Class ThisRibbonCollection
diff --git a/Red Ink for Word/Ribbon1.vb b/Red Ink for Word/Ribbon1.vb
index 85e0120..acd5f24 100644
--- a/Red Ink for Word/Ribbon1.vb
+++ b/Red Ink for Word/Ribbon1.vb
@@ -3,6 +3,7 @@
Imports Microsoft.Office.Tools.Ribbon
Imports Microsoft.Win32
+Imports SharedLibrary.SharedLibrary
Public Class Ribbon1
@@ -300,6 +301,84 @@ Public Class Ribbon1
Globals.ThisAddIn.ArgueAgainst()
End Sub
+ Private Sub RI_Model1_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model1.Click
+ Globals.ThisAddIn.SelectModel(1)
+ End Sub
+
+ Private Sub RI_Model2_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model2.Click
+ Globals.ThisAddIn.SelectModel(2)
+ End Sub
+
+ Private Sub RI_Model3_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model3.Click
+ Globals.ThisAddIn.SelectModel(3)
+ End Sub
+
+ Private Sub RI_Model4_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model4.Click
+ Globals.ThisAddIn.SelectModel(4)
+ End Sub
+
+ Private Sub RI_Model5_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model5.Click
+ Globals.ThisAddIn.SelectModel(5)
+ End Sub
+
+ Private Sub RI_Model6_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model6.Click
+ Globals.ThisAddIn.SelectModel(6)
+ End Sub
+
+ Private Sub RI_Model7_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model7.Click
+ Globals.ThisAddIn.SelectModel(7)
+ End Sub
+
+ Private Sub RI_Model8_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model8.Click
+ Globals.ThisAddIn.SelectModel(8)
+ End Sub
+
+ Private Sub RI_Model9_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model9.Click
+ Globals.ThisAddIn.SelectModel(9)
+ End Sub
+
+ Private Sub RI_Model10_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_Model10.Click
+ Globals.ThisAddIn.SelectModel(10)
+ End Sub
+
+ Public Sub UpdateModelsMenu()
+ Try
+ Dim available = ModelConfigManager.GetAvailableModels()
+ Dim current = ModelConfigManager.GetCurrentModelNumber()
+
+ For i = 1 To 10
+ Dim btn = GetModelButton(i)
+ If btn Is Nothing Then Continue For
+
+ If available.Contains(i) Then
+ btn.Visible = True
+ Dim label = ModelConfigManager.GetModelDisplayName(i)
+ btn.Label = If(i = current, $"{label} *", label)
+ Else
+ btn.Visible = False
+ End If
+ Next
+ Catch
+ ' non-critical
+ End Try
+ End Sub
+
+ Private Function GetModelButton(i As Integer) As RibbonButton
+ Select Case i
+ Case 1 : Return RI_Model1
+ Case 2 : Return RI_Model2
+ Case 3 : Return RI_Model3
+ Case 4 : Return RI_Model4
+ Case 5 : Return RI_Model5
+ Case 6 : Return RI_Model6
+ Case 7 : Return RI_Model7
+ Case 8 : Return RI_Model8
+ Case 9 : Return RI_Model9
+ Case 10 : Return RI_Model10
+ End Select
+ Return Nothing
+ End Function
+
Private Sub RI_LiveCompare_Click(sender As Object, e As RibbonControlEventArgs) Handles RI_LiveCompare.Click
Globals.ThisAddIn.CompareActiveDocWithOtherOpenDoc()
End Sub
diff --git a/Red Ink for Word/ThisAddIn.vb b/Red Ink for Word/ThisAddIn.vb
index 36b868b..f530b1e 100644
--- a/Red Ink for Word/ThisAddIn.vb
+++ b/Red Ink for Word/ThisAddIn.vb
@@ -41,6 +41,7 @@ Imports System.Threading
Imports System.Threading.Tasks
Imports System.Windows.Forms
Imports SharedLibrary.SharedLibrary
+Imports SharedLibrary.SharedLibrary.SharedMethods
Imports System.Globalization
Partial Public Class ThisAddIn
@@ -446,7 +447,39 @@ Partial Public Class ThisAddIn
_context.InitialConfigFailed = False
_context.RDV = "Word (" & Version & ")"
SharedMethods.InitializeConfig(_context, FirstTime, Reload)
+
+ ' Update the models menu if ribbon is loaded
+ Try
+ If Globals.Ribbons.Ribbon1 IsNot Nothing Then
+ Globals.Ribbons.Ribbon1.UpdateModelsMenu()
+ End If
+ Catch
+ ' Ribbon may not be loaded yet; ignore
+ End Try
+ End Sub
+
+ '''
+ ''' Selects a model by number and updates the primary configuration.
+ ''' Used by the ribbon \"Models\" menu.
+ '''
+ Public Shared Sub SelectModel(modelNumber As Integer)
+ Try
+ If ModelConfigManager.SelectModel(_context, modelNumber) Then
+ Try
+ If Globals.Ribbons.Ribbon1 IsNot Nothing Then
+ Globals.Ribbons.Ribbon1.UpdateModelsMenu()
+ End If
+ Catch
+ ' Non-critical UI update failure
+ End Try
+ Else
+ SharedMethods.ShowCustomMessageBox($"Model {modelNumber} is not configured.")
+ End If
+ Catch ex As Exception
+ SharedMethods.ShowCustomMessageBox($"Error switching model: {ex.Message}")
+ End Try
End Sub
+
Private Function INIValuesMissing() As Boolean
Return SharedMethods.INIValuesMissing(_context)
End Function
diff --git a/SharedLibrary/Code/Core/Config/ModelConfigManager.vb b/SharedLibrary/Code/Core/Config/ModelConfigManager.vb
new file mode 100644
index 0000000..67a13f8
--- /dev/null
+++ b/SharedLibrary/Code/Core/Config/ModelConfigManager.vb
@@ -0,0 +1,400 @@
+' Part of: Red Ink Shared Library by David Rosenthal
+' 2025-12-06 Modelmanager implemented by Roman Kost
+
+Option Strict On
+Option Explicit On
+
+Imports System.Collections.Generic
+Imports System.Diagnostics
+Imports System.Linq
+Imports System.Windows.Forms
+Imports SharedLibrary.SharedLibrary.SharedContext
+
+Namespace SharedLibrary
+
+ '''
+ ''' Manages multiple LLM model configurations loaded from redink.ini.
+ ''' - Detects numbered model variants (APIKey_1, Endpoint_1, Model_1, ...).
+ ''' - Stores them in memory.
+ ''' - Applies the selected model to the primary INI_* fields in the shared context.
+ ''' - Tracks the currently selected model number.
+ '''
+ ''' This class only manipulates PRIMARY fields (INI_APIKey, INI_Model, ...).
+ ''' It does NOT touch the secondary API slot (INI_*_2) used by SecondAPI / alternate models.
+ '''
+ Public Class ModelConfigManager
+
+ Private Const MultiModelPrefix As String = "MultiModel_"
+ Private Const MaxModelNumber As Integer = 100
+ ' Keep this aligned with SharedMethods.LoadConfig.INIValuesMissing to ensure both checks require the same core fields.
+ Private Shared ReadOnly RequiredModelKeys As String() = {"Endpoint", "Model", "APICall", "Response"}
+
+ ' Storage for all detected model configurations (per model number)
+ Private Shared ReadOnly _availableModels As New Dictionary(Of Integer, Dictionary(Of String, String))()
+
+ ' Currently selected model number (1-based), default 1
+ Private Shared _currentModelNumber As Integer = 1
+
+ ' Display names for each model (e.g. the Model_N value)
+ Private Shared ReadOnly _modelDisplayNames As New Dictionary(Of Integer, String)()
+
+ '''
+ ''' Detects and stores all model configurations from the parsed INI dictionary.
+ '''
+ Public Shared Sub DetectAndStoreModels(configDict As Dictionary(Of String, String))
+ _availableModels.Clear()
+ _modelDisplayNames.Clear()
+
+ ' Preferred format: MultiModel__
+ Dim perModel = ExtractPrefixedModels(configDict)
+
+ ' Validate each detected model
+ For Each n In perModel.Keys.OrderBy(Function(x) x)
+ Dim mc = perModel(n)
+ If ValidateModel(mc, $"#{n}") Then
+ _availableModels(n) = mc
+ _modelDisplayNames(n) = GetModelDisplayNameForConfig(mc, n)
+ End If
+ Next
+
+ ' Backward compatibility: if no numbered models, extract a "primary" model as Model 1
+ If _availableModels.Count = 0 Then
+ Dim primary = ExtractPrimaryModelConfig(configDict)
+ If ValidateModel(primary, "primary (no suffix)") Then
+ _availableModels(1) = primary
+ _modelDisplayNames(1) = GetModelDisplayNameForConfig(primary, 1)
+ End If
+ End If
+
+ ' If previous current model is no longer available, fall back to 1
+ If _availableModels.Count > 0 Then
+ If Not _availableModels.ContainsKey(_currentModelNumber) Then
+ _currentModelNumber = 1
+ End If
+ Else
+ _currentModelNumber = 1
+ End If
+ End Sub
+
+ '''
+ ''' Returns the list of available model numbers.
+ '''
+ Public Shared Function GetAvailableModels() As List(Of Integer)
+ Return _availableModels.Keys.OrderBy(Function(n) n).ToList()
+ End Function
+
+ '''
+ ''' Returns a user-friendly display name for a model.
+ '''
+ Public Shared Function GetModelDisplayName(modelNumber As Integer) As String
+ If _modelDisplayNames.ContainsKey(modelNumber) Then
+ Return _modelDisplayNames(modelNumber)
+ End If
+ Return $"Model {modelNumber}"
+ End Function
+
+ '''
+ ''' Returns the currently selected model number (1-based).
+ '''
+ Public Shared Function GetCurrentModelNumber() As Integer
+ Return _currentModelNumber
+ End Function
+
+ '''
+ ''' Selects a model by copying its configuration into the primary INI_* fields.
+ ''' Returns False if the model number is not available or if an error occurs.
+ '''
+ Public Shared Function SelectModel(context As ISharedContext, modelNumber As Integer) As Boolean
+ If context Is Nothing Then Return False
+ If Not _availableModels.ContainsKey(modelNumber) Then Return False
+
+ Dim mc = _availableModels(modelNumber)
+
+ Try
+ CopyPropertiesToContext(context, mc)
+ UpdateDecodedAPI(context)
+
+ _currentModelNumber = modelNumber
+
+ ' Persist selection to settings; ignore failures
+ Try
+ My.Settings.SelectedModelNumber = modelNumber
+ My.Settings.Save()
+ Catch
+ End Try
+
+ Return True
+ Catch ex As Exception
+ Return False
+ End Try
+ End Function
+
+ '''
+ ''' Loads the saved model selection from settings.
+ ''' Returns 1 if not found or invalid.
+ '''
+ Public Shared Function LoadSavedModelNumber() As Integer
+ Try
+ Dim n = My.Settings.SelectedModelNumber
+ If n > 0 Then Return n
+ Catch
+ End Try
+ Return 1
+ End Function
+
+ ' -----------------------
+ ' Internal helpers
+ ' -----------------------
+
+ Private Shared Function ExtractPrefixedModels(configDict As Dictionary(Of String, String)) As Dictionary(Of Integer, Dictionary(Of String, String))
+ Dim perModel As New Dictionary(Of Integer, Dictionary(Of String, String))()
+
+ For Each kvp In configDict
+ Dim key = kvp.Key
+ If Not key.StartsWith(MultiModelPrefix, StringComparison.OrdinalIgnoreCase) Then Continue For
+
+ Dim remainder = key.Substring(MultiModelPrefix.Length)
+ Dim idx = remainder.LastIndexOf("_"c)
+ If idx <= 0 OrElse idx = remainder.Length - 1 Then Continue For
+
+ Dim baseKey = remainder.Substring(0, idx)
+ Dim suffix = remainder.Substring(idx + 1)
+
+ Dim n As Integer
+ If Integer.TryParse(suffix, n) AndAlso n > 0 AndAlso n <= MaxModelNumber Then
+ If Not perModel.ContainsKey(n) Then
+ perModel(n) = New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
+ End If
+
+ perModel(n)(baseKey) = kvp.Value
+ End If
+ Next
+
+ Return perModel
+ End Function
+ Private Shared Function ExtractPrimaryModelConfig(configDict As Dictionary(Of String, String)) As Dictionary(Of String, String)
+ Dim result As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
+
+ For Each kvp In configDict
+ Dim key = kvp.Key
+ ' skip keys that clearly belong to numbered or secondary models
+ Dim idx = key.LastIndexOf("_"c)
+ Dim numericSuffix As Integer
+ If idx > 0 AndAlso Integer.TryParse(key.Substring(idx + 1), numericSuffix) AndAlso numericSuffix > 0 AndAlso numericSuffix <= MaxModelNumber Then
+ ' belongs to model N, handled elsewhere
+ Continue For
+ End If
+ result(key) = kvp.Value
+ Next
+
+ Return result
+ End Function
+
+ Private Shared Function ValidateModel(config As Dictionary(Of String, String), modelLabel As String) As Boolean
+ If config Is Nothing OrElse config.Count = 0 Then
+ Dim emptyMessage = BuildMissingKeyMessage(modelLabel, Nothing, True, config)
+ Debug.WriteLine($"[ModelConfigManager] {emptyMessage}")
+ MessageBox.Show(emptyMessage,
+ "Model configuration invalid",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Warning)
+ Return False
+ End If
+
+ Dim missing As New List(Of String)()
+
+ For Each key In RequiredModelKeys
+ If Not config.ContainsKey(key) OrElse String.IsNullOrWhiteSpace(config(key)) Then
+ missing.Add(key)
+ End If
+ Next
+
+ If missing.Count > 0 Then
+ Dim detailedMsg = BuildMissingKeyMessage(modelLabel, missing, False, config)
+ Debug.WriteLine($"[ModelConfigManager] {detailedMsg}")
+ MessageBox.Show(detailedMsg,
+ "Model configuration invalid",
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Warning)
+ Return False
+ End If
+
+ Return True
+ End Function
+
+ Private Shared Function BuildMissingKeyMessage(modelLabel As String,
+ missingKeys As List(Of String),
+ noEntries As Boolean,
+ modelConfig As Dictionary(Of String, String)) As String
+ Dim prefix As String
+ Dim fixHints As New List(Of String)()
+
+ Dim labelNumber As Integer
+ Dim hasNumericLabel As Boolean = False
+
+ If Not String.IsNullOrWhiteSpace(modelLabel) AndAlso modelLabel.StartsWith("#", StringComparison.Ordinal) Then
+ Dim suffix = modelLabel.TrimStart("#"c)
+ If Integer.TryParse(suffix, labelNumber) Then
+ hasNumericLabel = True
+ End If
+ End If
+
+ If hasNumericLabel Then
+ Dim identifierSuffix As String = ""
+ prefix = $"Model #{labelNumber}"
+ If missingKeys IsNot Nothing Then
+ For Each key In missingKeys
+ fixHints.Add($"MultiModel_{key}_{labelNumber}")
+ Next
+ Else
+ fixHints.Add($"MultiModel__{labelNumber}")
+ End If
+
+ Dim itemNameExists As Boolean = modelConfig IsNot Nothing AndAlso modelConfig.ContainsKey("ItemName") AndAlso Not String.IsNullOrWhiteSpace(modelConfig("ItemName"))
+ Dim modelNameExists As Boolean = modelConfig IsNot Nothing AndAlso modelConfig.ContainsKey("Model") AndAlso Not String.IsNullOrWhiteSpace(modelConfig("Model"))
+
+ If itemNameExists Then
+ identifierSuffix = $"MultiModel_ItemName_{labelNumber} = '{modelConfig("ItemName")}'"
+ ElseIf modelNameExists Then
+ identifierSuffix = $"MultiModel_Model_{labelNumber} = '{modelConfig("Model")}'"
+ Else
+ identifierSuffix = $"MultiModel suffix #{labelNumber}"
+ End If
+
+ prefix = $"{prefix} ({identifierSuffix})"
+ Else
+ prefix = $"Model {modelLabel}"
+ If missingKeys IsNot Nothing Then
+ fixHints.AddRange(missingKeys)
+ Else
+ fixHints.Add("base INI keys (e.g., Endpoint, Model, APICall, Response)")
+ End If
+
+ If modelConfig IsNot Nothing Then
+ Dim primaryName As String = ""
+ If modelConfig.ContainsKey("ItemName") AndAlso Not String.IsNullOrWhiteSpace(modelConfig("ItemName")) Then
+ primaryName = $"ItemName = '{modelConfig("ItemName")}'"
+ ElseIf modelConfig.ContainsKey("Model") AndAlso Not String.IsNullOrWhiteSpace(modelConfig("Model")) Then
+ primaryName = $"Model = '{modelConfig("Model")}'"
+ End If
+
+ If Not String.IsNullOrWhiteSpace(primaryName) Then
+ prefix = $"{prefix} ({primaryName})"
+ End If
+ End If
+ End If
+
+ Dim baseMessage As String
+ If noEntries Then
+ baseMessage = $"{prefix} did not contain any configuration entries."
+ Else
+ baseMessage = $"{prefix} is missing required fields: {String.Join(", ", missingKeys)}."
+ End If
+
+ Dim hintText = $"Please set the following INI keys: {String.Join(", ", fixHints.Distinct())}"
+ Return $"{baseMessage}{Environment.NewLine}{hintText}"
+ End Function
+
+ Private Shared Function GetModelDisplayNameForConfig(config As Dictionary(Of String, String), n As Integer) As String
+ If config.ContainsKey("ItemName") AndAlso Not String.IsNullOrWhiteSpace(config("ItemName")) Then
+ Return config("ItemName")
+ End If
+ If config.ContainsKey("Model") AndAlso Not String.IsNullOrWhiteSpace(config("Model")) Then
+ Return config("Model")
+ End If
+ Return $"Model {n}"
+ End Function
+
+ Private Shared Sub CopyPropertiesToContext(context As ISharedContext,
+ model As Dictionary(Of String, String))
+ ' Strings
+ context.INI_APIKey = GetValue(model, "APIKey", "")
+ context.INI_APIKeyBack = context.INI_APIKey
+ context.INI_APIKeyPrefix = GetValue(model, "APIKeyPrefix", "")
+ context.INI_Endpoint = GetValue(model, "Endpoint", "")
+ context.INI_Model = GetValue(model, "Model", "")
+ context.INI_Temperature = GetValue(model, "Temperature", "")
+ context.INI_HeaderA = GetValue(model, "HeaderA", "")
+ context.INI_HeaderB = GetValue(model, "HeaderB", "")
+ context.INI_Response = GetValue(model, "Response", "")
+ context.INI_APICall = GetValue(model, "APICall", "")
+ context.INI_APICall_Object = GetValue(model, "APICall_Object", "")
+ context.INI_Anon = GetValue(model, "Anon", "")
+ context.INI_TokenCount = GetValue(model, "TokenCount", "")
+ context.INI_PreCorrection = GetValue(model, "PreCorrection", "")
+ context.INI_PostCorrection = GetValue(model, "PostCorrection", "")
+ context.INI_OAuth2ClientMail = GetValue(model, "OAuth2ClientMail", "")
+ context.INI_OAuth2Scopes = GetValue(model, "OAuth2Scopes", "")
+ context.INI_OAuth2Endpoint = GetValue(model, "OAuth2Endpoint", "")
+
+ ' Numerics
+ context.INI_Timeout = GetLongValue(model, "Timeout", 0)
+ context.INI_MaxOutputToken = GetIntValue(model, "MaxOutputToken", 0)
+ context.INI_OAuth2ATExpiry = GetLongValue(model, "OAuth2ATExpiry", 3600)
+
+ ' Booleans
+ context.INI_APIEncrypted = GetBoolValue(model, "APIKeyEncrypted", False)
+ context.INI_DoubleS = GetBoolValue(model, "DoubleS", False)
+ context.INI_Clean = GetBoolValue(model, "Clean", False)
+ context.INI_NoDash = GetBoolValue(model, "NoEmDash", False)
+ context.INI_OAuth2 = GetBoolValue(model, "OAuth2", False)
+ End Sub
+
+ Private Shared Sub UpdateDecodedAPI(context As ISharedContext)
+ ' Mirrors logic from InitializeConfig for primary API
+ If context.INI_OAuth2 Then
+ context.INI_APIKey = Trim(SharedMethods.RealAPIKey(context.INI_APIKey, False, True, context)).Replace(vbLf, "").Replace(vbCr, "")
+ ' If something goes wrong, RealAPIKey will already have shown an error via SharedMethods
+ Else
+ context.DecodedAPI = SharedMethods.RealAPIKey(context.INI_APIKey, False, False, context)
+ End If
+ End Sub
+
+ Private Shared Function GetValue(config As Dictionary(Of String, String),
+ key As String,
+ defaultValue As String) As String
+ If config.ContainsKey(key) Then
+ Return config(key)
+ End If
+ Return defaultValue
+ End Function
+
+ Private Shared Function GetLongValue(config As Dictionary(Of String, String),
+ key As String,
+ defaultValue As Long) As Long
+ If config.ContainsKey(key) Then
+ Dim v As Long
+ If Long.TryParse(config(key), v) Then
+ Return v
+ End If
+ End If
+ Return defaultValue
+ End Function
+
+ Private Shared Function GetIntValue(config As Dictionary(Of String, String),
+ key As String,
+ defaultValue As Integer) As Integer
+ If config.ContainsKey(key) Then
+ Dim v As Integer
+ If Integer.TryParse(config(key), v) Then
+ Return v
+ End If
+ End If
+ Return defaultValue
+ End Function
+
+ Private Shared Function GetBoolValue(config As Dictionary(Of String, String),
+ key As String,
+ defaultValue As Boolean) As Boolean
+ If config.ContainsKey(key) Then
+ Dim raw = config(key).Trim().ToLowerInvariant()
+ Return raw = "yes" OrElse raw = "true" OrElse raw = "ja" OrElse raw = "wahr" OrElse raw = "1"
+ End If
+ Return defaultValue
+ End Function
+
+ End Class
+
+End Namespace
+
+
diff --git a/SharedLibrary/Code/Core/Config/SharedMethods.LoadConfig.vb b/SharedLibrary/Code/Core/Config/SharedMethods.LoadConfig.vb
index 91d126d..26cb6fd 100644
--- a/SharedLibrary/Code/Core/Config/SharedMethods.LoadConfig.vb
+++ b/SharedLibrary/Code/Core/Config/SharedMethods.LoadConfig.vb
@@ -78,11 +78,24 @@ Namespace SharedLibrary
If Not String.IsNullOrEmpty(trimmedLine) AndAlso Not trimmedLine.StartsWith(";") Then ' Skip comments and empty lines
Dim keyValue = trimmedLine.Split(New Char() {"="c}, 2)
If keyValue.Length = 2 Then
- configDict(keyValue(0).Trim()) = keyValue(1).Trim()
+ Dim key = keyValue(0).Trim()
+ Dim value = keyValue(1).Trim()
+
+ If Not configDict.ContainsKey(key) Then
+ configDict(key) = value
+ ElseIf Not String.IsNullOrWhiteSpace(value) Then
+ ' Prefer non-empty overrides; ignore blank defaults that would wipe earlier values
+ configDict(key) = value
+ End If
End If
End If
Next
+ ' Detect available models using ModelConfigManager.
+ ' "Primary" = the original top-level INI_* keys (no suffix) that will be treated as Model 1 when no MultiModel_*_ keys exist.
+ ' New configs should prefer the MultiModel__ naming convention introduced by ModelConfigManager.
+ ModelConfigManager.DetectAndStoreModels(configDict)
+
' Assign and validate configuration values
context.INI_APIKey = If(configDict.ContainsKey("APIKey"), configDict("APIKey"), "")
context.INI_Endpoint = If(configDict.ContainsKey("Endpoint"), configDict("Endpoint"), "")
@@ -334,6 +347,16 @@ Namespace SharedLibrary
Return
End If
+ ' Apply selected model to primary fields if multi-model configuration is present.
+ Dim availableModels = ModelConfigManager.GetAvailableModels()
+ If availableModels.Count > 0 Then
+ Dim modelToSelect As Integer = ModelConfigManager.LoadSavedModelNumber()
+ If Not availableModels.Contains(modelToSelect) Then
+ modelToSelect = 1
+ End If
+ ModelConfigManager.SelectModel(context, modelToSelect)
+ End If
+
' Additional configurations for OAuth2
context.TokenExpiry = Microsoft.VisualBasic.DateAndTime.DateAdd(Microsoft.VisualBasic.DateInterval.Year, -1, DateTime.Now)
context.DecodedAPI = ""
diff --git a/SharedLibrary/My Project/Settings.Designer.vb b/SharedLibrary/My Project/Settings.Designer.vb
index 4e4acf1..a245387 100644
--- a/SharedLibrary/My Project/Settings.Designer.vb
+++ b/SharedLibrary/My Project/Settings.Designer.vb
@@ -431,6 +431,18 @@ Namespace My
Me("LicenseWarningStartCount") = value
End Set
End Property
+
+ _
+ Public Property SelectedModelNumber() As Integer
+ Get
+ Return CType(Me("SelectedModelNumber"),Integer)
+ End Get
+ Set
+ Me("SelectedModelNumber") = value
+ End Set
+ End Property
End Class
End Namespace
diff --git a/SharedLibrary/My Project/Settings.settings b/SharedLibrary/My Project/Settings.settings
index d151a5c..8c83c7f 100644
--- a/SharedLibrary/My Project/Settings.settings
+++ b/SharedLibrary/My Project/Settings.settings
@@ -98,5 +98,8 @@
0
+
+ 1
+
\ No newline at end of file
diff --git a/SharedLibrary/SharedLibrary.vbproj b/SharedLibrary/SharedLibrary.vbproj
index a8ae4d1..6e3d54e 100644
--- a/SharedLibrary/SharedLibrary.vbproj
+++ b/SharedLibrary/SharedLibrary.vbproj
@@ -333,6 +333,7 @@
+