sensorium-mcp 3.0.4 → 3.0.6

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.
Files changed (120) hide show
  1. package/Install-Sensorium.ps1 +102 -209
  2. package/dist/dashboard/routes/data.d.ts.map +1 -1
  3. package/dist/dashboard/routes/data.js +2 -1
  4. package/dist/dashboard/routes/data.js.map +1 -1
  5. package/dist/dashboard/routes/threads.js +1 -1
  6. package/dist/dashboard/routes/threads.js.map +1 -1
  7. package/dist/dashboard/routes.d.ts.map +1 -1
  8. package/dist/dashboard/routes.js +1 -3
  9. package/dist/dashboard/routes.js.map +1 -1
  10. package/dist/data/memory/migration-runner.d.ts +1 -1
  11. package/dist/data/memory/migration-runner.d.ts.map +1 -1
  12. package/dist/data/memory/migration-runner.js +59 -3
  13. package/dist/data/memory/migration-runner.js.map +1 -1
  14. package/dist/data/memory/narrative.d.ts.map +1 -1
  15. package/dist/data/memory/narrative.js +43 -6
  16. package/dist/data/memory/narrative.js.map +1 -1
  17. package/dist/data/memory/reflection.d.ts +24 -0
  18. package/dist/data/memory/reflection.d.ts.map +1 -1
  19. package/dist/data/memory/reflection.js +65 -1
  20. package/dist/data/memory/reflection.js.map +1 -1
  21. package/dist/data/memory/schema-ddl.d.ts +1 -1
  22. package/dist/data/memory/schema-ddl.d.ts.map +1 -1
  23. package/dist/data/memory/schema-ddl.js +2 -1
  24. package/dist/data/memory/schema-ddl.js.map +1 -1
  25. package/dist/data/memory/thread-registry.js +1 -1
  26. package/dist/data/memory/thread-registry.js.map +1 -1
  27. package/dist/http-server.d.ts.map +1 -1
  28. package/dist/http-server.js +1 -9
  29. package/dist/http-server.js.map +1 -1
  30. package/dist/index.js +3 -6
  31. package/dist/index.js.map +1 -1
  32. package/dist/server/factory.js +1 -1
  33. package/dist/server/factory.js.map +1 -1
  34. package/dist/services/agent-spawn.service.d.ts +7 -1
  35. package/dist/services/agent-spawn.service.d.ts.map +1 -1
  36. package/dist/services/agent-spawn.service.js +69 -45
  37. package/dist/services/agent-spawn.service.js.map +1 -1
  38. package/dist/services/consolidation.service.d.ts.map +1 -1
  39. package/dist/services/consolidation.service.js +88 -35
  40. package/dist/services/consolidation.service.js.map +1 -1
  41. package/dist/services/keeper.service.d.ts +21 -0
  42. package/dist/services/keeper.service.d.ts.map +1 -0
  43. package/dist/services/keeper.service.js +195 -0
  44. package/dist/services/keeper.service.js.map +1 -0
  45. package/dist/services/maintenance-signal.d.ts +2 -0
  46. package/dist/services/maintenance-signal.d.ts.map +1 -1
  47. package/dist/services/maintenance-signal.js +7 -1
  48. package/dist/services/maintenance-signal.js.map +1 -1
  49. package/dist/services/memory-briefing.service.d.ts.map +1 -1
  50. package/dist/services/memory-briefing.service.js +17 -1
  51. package/dist/services/memory-briefing.service.js.map +1 -1
  52. package/dist/services/process.service.d.ts +19 -2
  53. package/dist/services/process.service.d.ts.map +1 -1
  54. package/dist/services/process.service.js +104 -10
  55. package/dist/services/process.service.js.map +1 -1
  56. package/dist/services/thread-lifecycle.service.d.ts +5 -0
  57. package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
  58. package/dist/services/thread-lifecycle.service.js +33 -8
  59. package/dist/services/thread-lifecycle.service.js.map +1 -1
  60. package/dist/services/worker-cleanup.service.d.ts +14 -1
  61. package/dist/services/worker-cleanup.service.d.ts.map +1 -1
  62. package/dist/services/worker-cleanup.service.js +36 -38
  63. package/dist/services/worker-cleanup.service.js.map +1 -1
  64. package/dist/sessions.d.ts +0 -5
  65. package/dist/sessions.d.ts.map +1 -1
  66. package/dist/sessions.js +0 -7
  67. package/dist/sessions.js.map +1 -1
  68. package/dist/stdio-server.d.ts.map +1 -1
  69. package/dist/stdio-server.js +1 -7
  70. package/dist/stdio-server.js.map +1 -1
  71. package/dist/tools/delegate-tool.d.ts.map +1 -1
  72. package/dist/tools/delegate-tool.js +2 -2
  73. package/dist/tools/delegate-tool.js.map +1 -1
  74. package/dist/tools/session-tools.js +1 -1
  75. package/dist/tools/session-tools.js.map +1 -1
  76. package/dist/tools/start-session-tool.d.ts.map +1 -1
  77. package/dist/tools/start-session-tool.js +8 -9
  78. package/dist/tools/start-session-tool.js.map +1 -1
  79. package/dist/tools/wait/message-processing.d.ts.map +1 -1
  80. package/dist/tools/wait/message-processing.js +28 -0
  81. package/dist/tools/wait/message-processing.js.map +1 -1
  82. package/dist/tools/wait/poll-loop.js +1 -1
  83. package/dist/tools/wait/poll-loop.js.map +1 -1
  84. package/package.json +1 -1
  85. package/dist/tools/thread-lifecycle.d.ts +0 -6
  86. package/dist/tools/thread-lifecycle.d.ts.map +0 -1
  87. package/dist/tools/thread-lifecycle.js +0 -6
  88. package/dist/tools/thread-lifecycle.js.map +0 -1
  89. package/supervisor/config.go +0 -253
  90. package/supervisor/config_test.go +0 -78
  91. package/supervisor/go.mod +0 -15
  92. package/supervisor/go.sum +0 -20
  93. package/supervisor/health.go +0 -433
  94. package/supervisor/health_test.go +0 -93
  95. package/supervisor/keeper.go +0 -309
  96. package/supervisor/keeper_test.go +0 -27
  97. package/supervisor/lock.go +0 -57
  98. package/supervisor/lock_test.go +0 -54
  99. package/supervisor/log.go +0 -195
  100. package/supervisor/log_test.go +0 -125
  101. package/supervisor/main.go +0 -475
  102. package/supervisor/main_test.go +0 -130
  103. package/supervisor/notify.go +0 -53
  104. package/supervisor/process.go +0 -294
  105. package/supervisor/process_test.go +0 -108
  106. package/supervisor/process_unix.go +0 -14
  107. package/supervisor/process_windows.go +0 -15
  108. package/supervisor/secrets.go +0 -95
  109. package/supervisor/secrets_securevault_test.go +0 -98
  110. package/supervisor/secrets_test.go +0 -119
  111. package/supervisor/self_update.go +0 -282
  112. package/supervisor/self_update_test.go +0 -177
  113. package/supervisor/service_restart_stub.go +0 -9
  114. package/supervisor/service_restart_windows.go +0 -63
  115. package/supervisor/service_stub.go +0 -15
  116. package/supervisor/service_windows.go +0 -194
  117. package/supervisor/update_state.go +0 -264
  118. package/supervisor/update_state_test.go +0 -306
  119. package/supervisor/updater.go +0 -613
  120. package/supervisor/updater_test.go +0 -64
@@ -1,253 +0,0 @@
1
- package main
2
-
3
- import (
4
- "errors"
5
- "fmt"
6
- "os"
7
- "path/filepath"
8
- "regexp"
9
- "strconv"
10
- "strings"
11
- "time"
12
-
13
- sv "github.com/andriyshevchenko/SecureVault/securevault-go"
14
- )
15
-
16
- // Config holds all supervisor configuration, sourced from environment variables
17
- // with sensible defaults matching the TypeScript watcher-service.ts CONFIG object.
18
- type Config struct {
19
- // Watcher
20
- Mode string
21
- PollAtHour int
22
- PollInterval time.Duration
23
- GracePeriod time.Duration
24
- MinUptime time.Duration
25
- MCPStartCommand string
26
- HostMode string
27
- DataDir string
28
- KeyringService string
29
- SecureVaultProfile string
30
- SecureVaultBaseDir string
31
- MCPHttpPort int
32
- MCPHttpSecret string
33
- TelegramToken string
34
- TelegramChatID string
35
- HealthFailThresh int
36
- ResolvedProfileEnv map[string]string
37
-
38
- // Keeper defaults
39
- KeeperBaseBackoff time.Duration
40
- KeeperMaxBackoff time.Duration
41
- KeeperHealthCheckInterval time.Duration
42
- KeeperMaxRetries int
43
- KeeperCooldown time.Duration
44
- KeeperReadyPollInterval time.Duration
45
- KeeperReadyTimeout time.Duration
46
- FastExitThreshold time.Duration
47
- FastExitMaxCount int
48
- FastExitBaseCooldown time.Duration
49
- FastExitMaxCooldown time.Duration
50
- StuckThreshold time.Duration
51
-
52
- // Derived paths
53
- Paths Paths
54
- }
55
-
56
- // Paths holds all filesystem paths derived from DataDir.
57
- type Paths struct {
58
- BinaryDir string
59
- MaintenanceFlag string
60
- VersionFile string
61
- SupervisorVersion string
62
- UpdateState string
63
- UpdateApplyLock string
64
- PendingBinary string
65
- PendingVersion string
66
- LastActivity string
67
- MCPStderrLog string
68
- ServerPID string
69
- WatcherLock string
70
- WatcherLog string
71
- PIDsDir string
72
- HeartbeatsDir string
73
- }
74
-
75
- func LoadConfig(runningAsService bool) Config {
76
- dataDir := filepath.Join(homeDir(), ".remote-copilot-mcp")
77
-
78
- mode := envOr("WATCHER_MODE", "development")
79
- graceDef := 300
80
- if mode == "development" {
81
- graceDef = 10
82
- }
83
-
84
- c := Config{
85
- Mode: mode,
86
- PollAtHour: envInt("WATCHER_POLL_HOUR", 4),
87
- PollInterval: time.Duration(envInt("WATCHER_POLL_INTERVAL", 60)) * time.Second,
88
- GracePeriod: time.Duration(envInt("WATCHER_GRACE_PERIOD", graceDef)) * time.Second,
89
- MinUptime: 600 * time.Second,
90
- MCPStartCommand: envOr("MCP_START_COMMAND", "npx -y sensorium-mcp@latest"),
91
- HostMode: parseHostMode(os.Getenv("HOST_MODE"), runningAsService),
92
- DataDir: dataDir,
93
- KeyringService: envOr("SUPERVISOR_KEYRING_SERVICE", defaultKeyringService),
94
- SecureVaultProfile: os.Getenv("SUPERVISOR_SECUREVAULT_PROFILE"),
95
- SecureVaultBaseDir: os.Getenv("SUPERVISOR_SECUREVAULT_BASEDIR"),
96
- HealthFailThresh: 3,
97
-
98
- KeeperBaseBackoff: 5 * time.Second,
99
- KeeperMaxBackoff: 5 * time.Minute,
100
- KeeperHealthCheckInterval: 2 * time.Minute,
101
- KeeperMaxRetries: 5,
102
- KeeperCooldown: 5 * time.Minute,
103
- KeeperReadyPollInterval: 3 * time.Second,
104
- KeeperReadyTimeout: 2 * time.Minute,
105
- FastExitThreshold: 60 * time.Second,
106
- FastExitMaxCount: 3,
107
- FastExitBaseCooldown: 10 * time.Minute,
108
- FastExitMaxCooldown: 4 * time.Hour,
109
- StuckThreshold: time.Duration(envInt("KEEPER_STUCK_THRESHOLD_MIN", 30)) * time.Minute,
110
-
111
- Paths: Paths{
112
- BinaryDir: filepath.Join(dataDir, "bin"),
113
- MaintenanceFlag: filepath.Join(dataDir, "maintenance.flag"),
114
- VersionFile: filepath.Join(dataDir, "current-version.txt"),
115
- SupervisorVersion: filepath.Join(dataDir, "supervisor-version.txt"),
116
- UpdateState: filepath.Join(dataDir, "update-state.json"),
117
- UpdateApplyLock: filepath.Join(dataDir, "update-apply.lock"),
118
- PendingBinary: filepath.Join(dataDir, "bin", "sensorium-supervisor.new.exe"),
119
- PendingVersion: filepath.Join(dataDir, "bin", "sensorium-supervisor.new.exe.version"),
120
- LastActivity: filepath.Join(dataDir, "last-activity.txt"),
121
- MCPStderrLog: filepath.Join(dataDir, "mcp-stderr.log"),
122
- ServerPID: filepath.Join(dataDir, "server.pid"),
123
- WatcherLock: filepath.Join(dataDir, "watcher.lock"),
124
- WatcherLog: filepath.Join(dataDir, "watcher.log"),
125
- PIDsDir: filepath.Join(dataDir, "pids"),
126
- HeartbeatsDir: filepath.Join(dataDir, "heartbeats"),
127
- },
128
- }
129
-
130
- // Use the full chain (env → SecureVault → keyring) when a profile is configured;
131
- // otherwise fall back to the plain env → keyring path.
132
- if c.SecureVaultProfile != "" {
133
- c.ResolvedProfileEnv = resolveProfileEnv(c.SecureVaultProfile, c.SecureVaultBaseDir)
134
- c.MCPHttpPort = resolveIntChain("MCP_HTTP_PORT", c.SecureVaultProfile, c.SecureVaultBaseDir, c.KeyringService, 0)
135
- c.MCPHttpSecret = resolveStringChain("MCP_HTTP_SECRET", c.SecureVaultProfile, c.SecureVaultBaseDir, c.KeyringService)
136
- c.TelegramToken = resolveStringChain("TELEGRAM_TOKEN", c.SecureVaultProfile, c.SecureVaultBaseDir, c.KeyringService)
137
- c.TelegramChatID = resolveStringChain("TELEGRAM_CHAT_ID", c.SecureVaultProfile, c.SecureVaultBaseDir, c.KeyringService)
138
- } else {
139
- c.ResolvedProfileEnv = map[string]string{}
140
- c.MCPHttpPort = resolveIntWithKeyring("MCP_HTTP_PORT", c.KeyringService, 0)
141
- c.MCPHttpSecret = resolveSecretWithKeyring("MCP_HTTP_SECRET", c.KeyringService)
142
- c.TelegramToken = resolveSecretWithKeyring("TELEGRAM_TOKEN", c.KeyringService)
143
- c.TelegramChatID = resolveSecretWithKeyring("TELEGRAM_CHAT_ID", c.KeyringService)
144
- }
145
-
146
- return c
147
- }
148
-
149
- func homeDir() string {
150
- h, err := os.UserHomeDir()
151
- if err != nil {
152
- fmt.Fprintf(os.Stderr, "FATAL: cannot determine home directory: %v\n", err)
153
- os.Exit(1)
154
- }
155
- return h
156
- }
157
-
158
- func envOr(key, fallback string) string {
159
- if v := os.Getenv(key); v != "" {
160
- return v
161
- }
162
- return fallback
163
- }
164
-
165
- func envInt(key string, fallback int) int {
166
- s := os.Getenv(key)
167
- if s == "" {
168
- return fallback
169
- }
170
- v, err := strconv.Atoi(s)
171
- if err != nil {
172
- return fallback
173
- }
174
- return v
175
- }
176
-
177
- func parseHostMode(value string, runningAsService bool) string {
178
- normalized := strings.ToLower(strings.TrimSpace(value))
179
- if runningAsService {
180
- if normalized == "" || normalized == "service" {
181
- return "service"
182
- }
183
- if normalized == "task" {
184
- fmt.Fprintf(os.Stderr, "WARN: HOST_MODE=%q ignored because process is running as a Windows service; forcing \"service\"\n", value)
185
- } else {
186
- fmt.Fprintf(os.Stderr, "WARN: invalid HOST_MODE=%q ignored because process is running as a Windows service; forcing \"service\" (allowed: task|service)\n", value)
187
- }
188
- return "service"
189
- }
190
-
191
- if normalized == "" {
192
- return "task"
193
- }
194
-
195
- switch normalized {
196
- case "task", "service":
197
- return normalized
198
- default:
199
- fmt.Fprintf(os.Stderr, "WARN: invalid HOST_MODE=%q (allowed: task|service); using default \"task\"\n", value)
200
- return "task"
201
- }
202
- }
203
-
204
- func resolveProfileEnv(profileName, baseDir string) map[string]string {
205
- resolved := map[string]string{}
206
- if strings.TrimSpace(profileName) == "" {
207
- return resolved
208
- }
209
-
210
- store := sv.NewStore(baseDir)
211
- vals, err := store.ResolveProfile(profileName)
212
- if err != nil {
213
- if errors.Is(err, sv.ErrNotFound) || errors.Is(err, sv.ErrUnsupportedPlatform) {
214
- return resolved
215
- }
216
- fmt.Fprintf(os.Stderr, "WARN: failed to resolve SecureVault profile %q: %v\n", profileName, err)
217
- return resolved
218
- }
219
-
220
- for k, v := range vals {
221
- if !isAllowedProfileEnvKey(k) {
222
- fmt.Fprintf(os.Stderr, "WARN: skipping unsafe profile env key %q\n", k)
223
- continue
224
- }
225
- if envVal := os.Getenv(k); envVal != "" {
226
- resolved[k] = envVal
227
- continue
228
- }
229
- resolved[k] = v
230
- }
231
-
232
- return resolved
233
- }
234
-
235
- var profileEnvKeyPattern = regexp.MustCompile(`^[A-Z_][A-Z0-9_]*$`)
236
-
237
- var deniedProfileEnvKeys = map[string]struct{}{
238
- "PATH": {},
239
- "PATHEXT": {},
240
- "COMSPEC": {},
241
- "SYSTEMROOT": {},
242
- "WINDIR": {},
243
- "NODE_OPTIONS": {},
244
- }
245
-
246
- func isAllowedProfileEnvKey(key string) bool {
247
- trimmed := strings.TrimSpace(key)
248
- if !profileEnvKeyPattern.MatchString(trimmed) {
249
- return false
250
- }
251
- _, denied := deniedProfileEnvKeys[trimmed]
252
- return !denied
253
- }
@@ -1,78 +0,0 @@
1
- package main
2
-
3
- import "testing"
4
-
5
- func TestParseHostMode_DefaultsAndValidation(t *testing.T) {
6
- tests := []struct {
7
- name string
8
- value string
9
- runningAsService bool
10
- want string
11
- }{
12
- {
13
- name: "empty defaults to service when running as service",
14
- value: "",
15
- runningAsService: true,
16
- want: "service",
17
- },
18
- {
19
- name: "empty defaults to task when not running as service",
20
- value: "",
21
- runningAsService: false,
22
- want: "task",
23
- },
24
- {
25
- name: "invalid falls back to service default for service mode",
26
- value: "invalid",
27
- runningAsService: true,
28
- want: "service",
29
- },
30
- {
31
- name: "invalid falls back to task default for task mode",
32
- value: "invalid",
33
- runningAsService: false,
34
- want: "task",
35
- },
36
- {
37
- name: "valid task accepted",
38
- value: "task",
39
- runningAsService: true,
40
- want: "service",
41
- },
42
- {
43
- name: "valid service accepted",
44
- value: "service",
45
- runningAsService: false,
46
- want: "service",
47
- },
48
- }
49
-
50
- for _, tc := range tests {
51
- t.Run(tc.name, func(t *testing.T) {
52
- got := parseHostMode(tc.value, tc.runningAsService)
53
- if got != tc.want {
54
- t.Fatalf("parseHostMode(%q, runningAsService=%v) = %q, want %q", tc.value, tc.runningAsService, got, tc.want)
55
- }
56
- })
57
- }
58
- }
59
-
60
- func TestIsAllowedProfileEnvKey(t *testing.T) {
61
- tests := []struct {
62
- key string
63
- want bool
64
- }{
65
- {key: "TELEGRAM_TOKEN", want: true},
66
- {key: "MCP_HTTP_PORT", want: true},
67
- {key: "PATH", want: false},
68
- {key: "NODE_OPTIONS", want: false},
69
- {key: "bad-key", want: false},
70
- {key: "1BAD", want: false},
71
- }
72
-
73
- for _, tc := range tests {
74
- if got := isAllowedProfileEnvKey(tc.key); got != tc.want {
75
- t.Fatalf("isAllowedProfileEnvKey(%q) = %v, want %v", tc.key, got, tc.want)
76
- }
77
- }
78
- }
package/supervisor/go.mod DELETED
@@ -1,15 +0,0 @@
1
- module github.com/andriyshevchenko/sensorium-supervisor
2
-
3
- go 1.22
4
-
5
- require (
6
- github.com/zalando/go-keyring v0.2.8
7
- golang.org/x/sys v0.30.0
8
- )
9
-
10
- require github.com/andriyshevchenko/SecureVault/securevault-go v0.1.2
11
-
12
- require (
13
- github.com/danieljoos/wincred v1.2.3 // indirect
14
- github.com/godbus/dbus/v5 v5.2.2 // indirect
15
- )
package/supervisor/go.sum DELETED
@@ -1,20 +0,0 @@
1
- github.com/andriyshevchenko/SecureVault/securevault-go v0.1.2 h1:4PyakSOgHmBnN0Oqapoh3/Ik92fvmR8R2ksE5qCXXOE=
2
- github.com/andriyshevchenko/SecureVault/securevault-go v0.1.2/go.mod h1:oEb5uTPCvex+efofFySxxbe55z13LbAO3JSaxcjVq2Q=
3
- github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ=
4
- github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs=
5
- github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6
- github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7
- github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
8
- github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
9
- github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
10
- github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
11
- github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
12
- github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
13
- github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
14
- github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
15
- github.com/zalando/go-keyring v0.2.8 h1:6sD/Ucpl7jNq10rM2pgqTs0sZ9V3qMrqfIIy5YPccHs=
16
- github.com/zalando/go-keyring v0.2.8/go.mod h1:tsMo+VpRq5NGyKfxoBVjCuMrG47yj8cmakZDO5QGii0=
17
- golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
18
- golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
19
- gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
20
- gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=