@hellolynk-ai/workbuddy-mcp 0.0.0-stage → 0.3.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.
Files changed (176) hide show
  1. package/LICENSE +92 -0
  2. package/README.md +103 -2
  3. package/bin/hellolynk-client-setup.mjs +2748 -0
  4. package/bin/hellolynk-mcp-config-shape.mjs +23 -0
  5. package/clients/core/hellolynk-client-account.mjs +180 -0
  6. package/clients/core/hellolynk-client-core.mjs +770 -0
  7. package/clients/core/hellolynk-client-profile.mjs +191 -0
  8. package/clients/core/hellolynk-client-update-entry.mjs +31 -0
  9. package/clients/core/hellolynk-client-update-runtime.mjs +600 -0
  10. package/clients/core/hellolynk-client-update.mjs +453 -0
  11. package/clients/core/hellolynk-contact-request-e2ee.mjs +867 -0
  12. package/clients/core/hellolynk-device-enrollment.mjs +435 -0
  13. package/clients/core/hellolynk-direct-text-e2ee-client.mjs +1964 -0
  14. package/clients/core/hellolynk-direct-text-e2ee.mjs +1207 -0
  15. package/clients/core/hellolynk-host-auth.mjs +347 -0
  16. package/clients/core/hellolynk-host-protected-store.mjs +2721 -0
  17. package/clients/core/hellolynk-host-transport-client.mjs +946 -0
  18. package/clients/core/hellolynk-host.mjs +2374 -0
  19. package/clients/core/hellolynk-human-confirmation-ledger.mjs +256 -0
  20. package/clients/core/hellolynk-human-relationship-controller.mjs +1234 -0
  21. package/clients/core/hellolynk-inbox-read-state.mjs +11 -0
  22. package/clients/core/hellolynk-indexed-message-store.mjs +1558 -0
  23. package/clients/core/hellolynk-instance-conversation.mjs +185 -0
  24. package/clients/core/hellolynk-local-contact-requests.mjs +1733 -0
  25. package/clients/core/hellolynk-local-contacts.mjs +1228 -0
  26. package/clients/core/hellolynk-local-data-migration.mjs +766 -0
  27. package/clients/core/hellolynk-local-data-protection.mjs +747 -0
  28. package/clients/core/hellolynk-local-identity-trust.mjs +274 -0
  29. package/clients/core/hellolynk-local-messaging.mjs +3043 -0
  30. package/clients/core/hellolynk-local-peer-transport.mjs +103 -0
  31. package/clients/core/hellolynk-local-process-lock.mjs +157 -0
  32. package/clients/core/hellolynk-model-inbox.mjs +230 -0
  33. package/clients/core/hellolynk-model-notices.cjs +60 -0
  34. package/clients/core/hellolynk-native-addressing-tools.cjs +231 -0
  35. package/clients/core/hellolynk-native-conversations.mjs +280 -0
  36. package/clients/core/hellolynk-native-human-confirmation-broker.mjs +1036 -0
  37. package/clients/core/hellolynk-native-inbox-runtime.mjs +553 -0
  38. package/clients/core/hellolynk-native-notice.mjs +50 -0
  39. package/clients/core/hellolynk-native-reply-routes.mjs +96 -0
  40. package/clients/core/hellolynk-native-task-index.cjs +305 -0
  41. package/clients/core/hellolynk-native-worker-lease.mjs +84 -0
  42. package/clients/core/hellolynk-neutral-host-assembly.mjs +955 -0
  43. package/clients/core/hellolynk-neutral-host-installation-store.mjs +765 -0
  44. package/clients/core/hellolynk-neutral-host-launcher.mjs +665 -0
  45. package/clients/core/hellolynk-neutral-host-process.mjs +4374 -0
  46. package/clients/core/hellolynk-neutral-host-store-adapters.mjs +548 -0
  47. package/clients/core/hellolynk-neutral-host-workbench-read-model.mjs +1365 -0
  48. package/clients/core/hellolynk-platform-credential-store.mjs +773 -0
  49. package/clients/core/hellolynk-relay-client-cli.mjs +232 -0
  50. package/clients/core/hellolynk-release-retention.mjs +277 -0
  51. package/clients/core/hellolynk-runtime-safety.cjs +471 -0
  52. package/clients/core/hellolynk-workbench-action-grants.mjs +457 -0
  53. package/clients/core/hellolynk-workbench-connection.mjs +234 -0
  54. package/clients/platform/windows/credential-store.ps1 +844 -0
  55. package/clients/platform/windows/hellolynk-host-protected-store.ps1 +2866 -0
  56. package/clients/platform/windows/hellolynk-human-confirmation-ledger.ps1 +155 -0
  57. package/clients/platform/windows/hellolynk-local-data-key.ps1 +300 -0
  58. package/clients/platform/windows/hellolynk-native-human-confirmation-broker.ps1 +216 -0
  59. package/clients/workbench/contract.mjs +1314 -0
  60. package/clients/workbench/service.mjs +485 -0
  61. package/hellolynk-client-pack-manifest.json +884 -0
  62. package/hellolynk-client-pack-pin.json +4 -0
  63. package/integrations/workbuddy/package.json +15 -0
  64. package/integrations/workbuddy/server/host-lifecycle.mjs +249 -0
  65. package/integrations/workbuddy/server/mcp-proxy.mjs +258 -0
  66. package/integrations/workbuddy/server/mcp-server.mjs +357 -0
  67. package/integrations/workbuddy/server/model-call-origin.mjs +87 -0
  68. package/integrations/workbuddy/server/native-task-cdp.mjs +175 -0
  69. package/integrations/workbuddy/server/native-task-debug-startup.mjs +117 -0
  70. package/integrations/workbuddy/server/native-task-debug-startup.ps1 +40 -0
  71. package/integrations/workbuddy/server/native-task-mcp-registration.mjs +30 -0
  72. package/integrations/workbuddy/server/native-task-service-registration.mjs +115 -0
  73. package/integrations/workbuddy/server/native-task-worker.mjs +127 -0
  74. package/integrations/workbuddy/server/neutral-host-adapter.mjs +639 -0
  75. package/integrations/workbuddy/server/origin-hook.mjs +111 -0
  76. package/integrations/workbuddy/server/origin-routes.mjs +211 -0
  77. package/integrations/workbuddy/server/package-bootstrap.mjs +111 -0
  78. package/integrations/workbuddy/server/workbench-candidate.mjs +202 -0
  79. package/integrations/workbuddy/server/workbench-hidden-launcher.vbs +46 -0
  80. package/integrations/workbuddy/server/workbench-process.mjs +373 -0
  81. package/integrations/workbuddy/server/workbench-task.ps1 +196 -0
  82. package/integrations/workbuddy/skills/hellolynk-inbox/SKILL.md +9 -0
  83. package/integrations/workbuddy/skills/hellolynk-inbox/workbuddy.json +6 -0
  84. package/package.json +65 -4
  85. package/runtime/connect-activate.mjs +837 -0
  86. package/runtime/core/hellolynk-agent-configurator.mjs +701 -0
  87. package/runtime/core/hellolynk-client-account.mjs +180 -0
  88. package/runtime/core/hellolynk-client-core.mjs +770 -0
  89. package/runtime/core/hellolynk-client-profile.mjs +191 -0
  90. package/runtime/core/hellolynk-client-update-entry.mjs +31 -0
  91. package/runtime/core/hellolynk-client-update-runtime.mjs +600 -0
  92. package/runtime/core/hellolynk-client-update.mjs +453 -0
  93. package/runtime/core/hellolynk-contact-request-e2ee.mjs +867 -0
  94. package/runtime/core/hellolynk-device-enrollment.mjs +435 -0
  95. package/runtime/core/hellolynk-direct-text-e2ee-client.mjs +1964 -0
  96. package/runtime/core/hellolynk-direct-text-e2ee.mjs +1207 -0
  97. package/runtime/core/hellolynk-host-auth.mjs +347 -0
  98. package/runtime/core/hellolynk-host-protected-store.mjs +2721 -0
  99. package/runtime/core/hellolynk-host-transport-client.mjs +946 -0
  100. package/runtime/core/hellolynk-host.mjs +2374 -0
  101. package/runtime/core/hellolynk-human-confirmation-ledger.mjs +256 -0
  102. package/runtime/core/hellolynk-human-relationship-controller.mjs +1234 -0
  103. package/runtime/core/hellolynk-inbox-read-state.mjs +11 -0
  104. package/runtime/core/hellolynk-indexed-message-store.mjs +1558 -0
  105. package/runtime/core/hellolynk-instance-conversation.mjs +185 -0
  106. package/runtime/core/hellolynk-local-contact-requests.mjs +1733 -0
  107. package/runtime/core/hellolynk-local-contacts.mjs +1228 -0
  108. package/runtime/core/hellolynk-local-data-migration.mjs +766 -0
  109. package/runtime/core/hellolynk-local-data-protection.mjs +747 -0
  110. package/runtime/core/hellolynk-local-identity-trust.mjs +274 -0
  111. package/runtime/core/hellolynk-local-messaging.mjs +3043 -0
  112. package/runtime/core/hellolynk-local-peer-transport.mjs +103 -0
  113. package/runtime/core/hellolynk-local-process-lock.mjs +157 -0
  114. package/runtime/core/hellolynk-model-inbox.mjs +230 -0
  115. package/runtime/core/hellolynk-model-notices.cjs +60 -0
  116. package/runtime/core/hellolynk-native-addressing-tools.cjs +231 -0
  117. package/runtime/core/hellolynk-native-conversations.mjs +280 -0
  118. package/runtime/core/hellolynk-native-human-confirmation-broker.mjs +1036 -0
  119. package/runtime/core/hellolynk-native-inbox-runtime.mjs +553 -0
  120. package/runtime/core/hellolynk-native-notice.mjs +50 -0
  121. package/runtime/core/hellolynk-native-reply-routes.mjs +96 -0
  122. package/runtime/core/hellolynk-native-worker-lease.mjs +84 -0
  123. package/runtime/core/hellolynk-neutral-host-assembly.mjs +955 -0
  124. package/runtime/core/hellolynk-neutral-host-installation-store.mjs +765 -0
  125. package/runtime/core/hellolynk-neutral-host-launcher.mjs +665 -0
  126. package/runtime/core/hellolynk-neutral-host-process.mjs +4374 -0
  127. package/runtime/core/hellolynk-neutral-host-store-adapters.mjs +548 -0
  128. package/runtime/core/hellolynk-neutral-host-workbench-read-model.mjs +1365 -0
  129. package/runtime/core/hellolynk-platform-credential-store.mjs +773 -0
  130. package/runtime/core/hellolynk-relay-client-cli.mjs +232 -0
  131. package/runtime/core/hellolynk-release-retention.mjs +277 -0
  132. package/runtime/core/hellolynk-runtime-safety.cjs +471 -0
  133. package/runtime/core/hellolynk-workbench-action-grants.mjs +457 -0
  134. package/runtime/core/hellolynk-workbench-connection.mjs +234 -0
  135. package/runtime/neutral-host-bootstrap.mjs +57 -0
  136. package/runtime/neutral-host-release-entry.mjs +81 -0
  137. package/runtime/neutral-host-release-loader.mjs +156 -0
  138. package/runtime/neutral-host-release-manifest.json +302 -0
  139. package/runtime/neutral-host-release-pin.json +4 -0
  140. package/runtime/platform/windows/configure-agent.ps1 +281 -0
  141. package/runtime/platform/windows/credential-store.ps1 +844 -0
  142. package/runtime/platform/windows/hellolynk-host-protected-store.ps1 +2866 -0
  143. package/runtime/platform/windows/hellolynk-human-confirmation-ledger.ps1 +155 -0
  144. package/runtime/platform/windows/hellolynk-local-data-key.ps1 +300 -0
  145. package/runtime/platform/windows/hellolynk-native-human-confirmation-broker.ps1 +216 -0
  146. package/runtime/workbench/candidate-bootstrap.mjs +54 -0
  147. package/runtime/workbench/contract.mjs +1314 -0
  148. package/runtime/workbench/hellolynk-workbench-build.json +215 -0
  149. package/runtime/workbench/host-capabilities.mjs +80 -0
  150. package/runtime/workbench/i18n.mjs +1127 -0
  151. package/runtime/workbench/loopback-surface.mjs +740 -0
  152. package/runtime/workbench/mcp-app-bundle.mjs +97 -0
  153. package/runtime/workbench/service.mjs +485 -0
  154. package/runtime/workbench/state.mjs +421 -0
  155. package/runtime/workbench/transports.mjs +171 -0
  156. package/runtime/workbench/ui/app.mjs +6120 -0
  157. package/runtime/workbench/ui/connection-form.mjs +155 -0
  158. package/runtime/workbench/ui/hellolynk-mark.png +0 -0
  159. package/runtime/workbench/ui/http-transport.mjs +247 -0
  160. package/runtime/workbench/ui/icons/arrow-left.svg +3 -0
  161. package/runtime/workbench/ui/icons/close.svg +3 -0
  162. package/runtime/workbench/ui/icons/contacts.svg +3 -0
  163. package/runtime/workbench/ui/icons/inbox.svg +3 -0
  164. package/runtime/workbench/ui/icons/refresh.svg +3 -0
  165. package/runtime/workbench/ui/icons/search.svg +3 -0
  166. package/runtime/workbench/ui/icons/security.svg +3 -0
  167. package/runtime/workbench/ui/icons/settings.svg +3 -0
  168. package/runtime/workbench/ui/index.html +139 -0
  169. package/runtime/workbench/ui/loopback-entry.mjs +26 -0
  170. package/runtime/workbench/ui/mcp-app-client.mjs +151 -0
  171. package/runtime/workbench/ui/mcp-app-entry.mjs +452 -0
  172. package/runtime/workbench/ui/styles.css +686 -0
  173. package/tools/hellolynk-activate-neutral-host-clients.mjs +837 -0
  174. package/tools/hellolynk-install-client-skills.mjs +1211 -0
  175. package/workbuddy-package-manifest.json +1 -0
  176. package/workbuddy-package-pin.json +1 -0
@@ -0,0 +1,281 @@
1
+ param(
2
+ [ValidateSet("OpenClaw")]
3
+ [string]$Client = "OpenClaw",
4
+
5
+ [string]$OpenClawConfig = (Join-Path $env:USERPROFILE ".openclaw\openclaw.json"),
6
+
7
+ [switch]$WaitForUser,
8
+
9
+ [switch]$AtomicReplace
10
+ )
11
+
12
+ $ErrorActionPreference = "Stop"
13
+ [Console]::SetIn([IO.StreamReader]::new([Console]::OpenStandardInput(), [Text.UTF8Encoding]::new($false, $true)))
14
+
15
+ function Write-AtomicResult([string]$Code, [int]$ExitCode) {
16
+ [Console]::Out.Write($Code)
17
+ exit $ExitCode
18
+ }
19
+
20
+ function Assert-PlainPath([string]$Candidate, [string]$ExpectedParent = "") {
21
+ $absolute = [IO.Path]::GetFullPath($Candidate)
22
+ if ($ExpectedParent -and -not [StringComparer]::OrdinalIgnoreCase.Equals([IO.Path]::GetDirectoryName($absolute), $ExpectedParent)) {
23
+ throw "agent_setup_config_path_invalid"
24
+ }
25
+ $cursor = if ([IO.File]::Exists($absolute)) { $absolute } else { [IO.Path]::GetDirectoryName($absolute) }
26
+ while ($cursor) {
27
+ if (([IO.File]::GetAttributes($cursor) -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
28
+ throw "agent_setup_config_reparse_rejected"
29
+ }
30
+ $parent = [IO.Path]::GetDirectoryName($cursor)
31
+ if (-not $parent -or $parent -eq $cursor) { break }
32
+ $cursor = $parent
33
+ }
34
+ return $absolute
35
+ }
36
+
37
+ function Initialize-NativeFileIdentity {
38
+ if ("HelloLynk.NativeFileIdentity" -as [type]) { return }
39
+ Add-Type -TypeDefinition @'
40
+ using System;
41
+ using System.ComponentModel;
42
+ using System.Runtime.InteropServices;
43
+ using Microsoft.Win32.SafeHandles;
44
+
45
+ namespace HelloLynk {
46
+ public static class NativeFileIdentity {
47
+ [StructLayout(LayoutKind.Sequential)]
48
+ private struct ByHandleFileInformation {
49
+ public uint FileAttributes;
50
+ public System.Runtime.InteropServices.ComTypes.FILETIME CreationTime;
51
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
52
+ public System.Runtime.InteropServices.ComTypes.FILETIME LastWriteTime;
53
+ public uint VolumeSerialNumber;
54
+ public uint FileSizeHigh;
55
+ public uint FileSizeLow;
56
+ public uint NumberOfLinks;
57
+ public uint FileIndexHigh;
58
+ public uint FileIndexLow;
59
+ }
60
+
61
+ [DllImport("kernel32.dll", SetLastError = true)]
62
+ private static extern bool GetFileInformationByHandle(
63
+ SafeFileHandle handle,
64
+ out ByHandleFileInformation information
65
+ );
66
+
67
+ public static string Get(SafeFileHandle handle, out uint attributes) {
68
+ ByHandleFileInformation information;
69
+ if (!GetFileInformationByHandle(handle, out information)) {
70
+ throw new Win32Exception(Marshal.GetLastWin32Error());
71
+ }
72
+ attributes = information.FileAttributes;
73
+ return String.Format("{0:X8}:{1:X8}{2:X8}",
74
+ information.VolumeSerialNumber,
75
+ information.FileIndexHigh,
76
+ information.FileIndexLow);
77
+ }
78
+ }
79
+ }
80
+ '@
81
+ }
82
+
83
+ function Get-FileSnapshot([string]$Candidate) {
84
+ Initialize-NativeFileIdentity
85
+ $stream = [IO.File]::Open($Candidate, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)
86
+ try {
87
+ [uint32]$attributes = 0
88
+ $identity = [HelloLynk.NativeFileIdentity]::Get($stream.SafeFileHandle, [ref]$attributes)
89
+ if (($attributes -band [uint32][IO.FileAttributes]::ReparsePoint) -ne 0) {
90
+ throw "agent_setup_config_reparse_rejected"
91
+ }
92
+ $hasher = [Security.Cryptography.SHA256]::Create()
93
+ try { $hash = [Convert]::ToHexString($hasher.ComputeHash($stream)) } finally { $hasher.Dispose() }
94
+ $security = [IO.FileSystemAclExtensions]::GetAccessControl($stream)
95
+ return [pscustomobject]@{
96
+ Identity = $identity
97
+ Hash = $hash
98
+ Dacl = $security.GetSecurityDescriptorSddlForm([Security.AccessControl.AccessControlSections]::Access)
99
+ Owner = $security.GetOwner([Security.Principal.SecurityIdentifier]).Value
100
+ Group = $security.GetGroup([Security.Principal.SecurityIdentifier]).Value
101
+ Security = $security.GetSecurityDescriptorSddlForm(
102
+ [Security.AccessControl.AccessControlSections]::Access -bor
103
+ [Security.AccessControl.AccessControlSections]::Owner -bor
104
+ [Security.AccessControl.AccessControlSections]::Group
105
+ )
106
+ }
107
+ } finally { $stream.Dispose() }
108
+ }
109
+
110
+ function Set-Dacl([string]$Candidate, [Security.AccessControl.FileSecurity]$Security, [string]$ExpectedHash) {
111
+ $snapshot = Get-FileSnapshot $Candidate
112
+ if (-not [StringComparer]::OrdinalIgnoreCase.Equals($snapshot.Hash, $ExpectedHash)) {
113
+ throw "agent_setup_config_changed"
114
+ }
115
+ [IO.FileSystemAclExtensions]::SetAccessControl([IO.FileInfo]::new($Candidate), $Security)
116
+ }
117
+
118
+ function Restore-FileSecurity([string]$Candidate, [string]$ExpectedHash, [string]$ExpectedSecurity) {
119
+ $snapshot = Get-FileSnapshot $Candidate
120
+ if ($snapshot.Hash -ne $ExpectedHash) { throw "agent_setup_config_rollback_failed" }
121
+ $security = [Security.AccessControl.FileSecurity]::new()
122
+ $security.SetSecurityDescriptorSddlForm(
123
+ $ExpectedSecurity,
124
+ [Security.AccessControl.AccessControlSections]::Access -bor
125
+ [Security.AccessControl.AccessControlSections]::Owner -bor
126
+ [Security.AccessControl.AccessControlSections]::Group
127
+ )
128
+ [IO.FileSystemAclExtensions]::SetAccessControl([IO.FileInfo]::new($Candidate), $security)
129
+ }
130
+
131
+ function Invoke-AtomicReplace {
132
+ try {
133
+ $controlText = [Console]::In.ReadToEnd()
134
+ if (-not $controlText -or $controlText.Length -gt 32768) { throw "agent_setup_config_control_invalid" }
135
+ $control = $controlText | ConvertFrom-Json -ErrorAction Stop
136
+ if (@($control.psobject.Properties.Name).Count -ne 4 -or
137
+ -not $control.configPath -or -not $control.temporary -or
138
+ $control.expectedSha256 -notmatch '^[A-Fa-f0-9]{64}$' -or
139
+ $control.replacementSha256 -notmatch '^[A-Fa-f0-9]{64}$') {
140
+ throw "agent_setup_config_control_invalid"
141
+ }
142
+
143
+ $target = Assert-PlainPath ([string]$control.configPath)
144
+ $parent = [IO.Path]::GetDirectoryName($target)
145
+ $temporary = Assert-PlainPath ([string]$control.temporary) $parent
146
+ if (-not [IO.File]::Exists($temporary) -or [IO.Directory]::Exists($temporary)) {
147
+ throw "agent_setup_config_temporary_invalid"
148
+ }
149
+
150
+ if (-not [IO.File]::Exists($target)) {
151
+ $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
152
+ $security = [Security.AccessControl.FileSecurity]::new()
153
+ $security.SetOwner($identity.User)
154
+ $security.SetAccessRuleProtection($true, $false)
155
+ $rule = [Security.AccessControl.FileSystemAccessRule]::new(
156
+ $identity.User,
157
+ [Security.AccessControl.FileSystemRights]::FullControl,
158
+ [Security.AccessControl.AccessControlType]::Allow
159
+ )
160
+ $security.AddAccessRule($rule)
161
+ Set-Dacl $temporary $security ([string]$control.replacementSha256)
162
+ $securedTemporary = Get-FileSnapshot $temporary
163
+ [IO.File]::Move($temporary, $target, $false)
164
+ $newSnapshot = Get-FileSnapshot $target
165
+ if ($newSnapshot.Hash -ne [string]$control.replacementSha256 -or
166
+ $newSnapshot.Dacl -ne $securedTemporary.Dacl -or
167
+ $newSnapshot.Owner -ne $securedTemporary.Owner -or
168
+ $newSnapshot.Group -ne $securedTemporary.Group) {
169
+ throw "agent_setup_config_acl_unsafe"
170
+ }
171
+ Write-AtomicResult "agent_setup_config_replace_ok" 0
172
+ }
173
+
174
+ if ([IO.Directory]::Exists($target)) { throw "agent_setup_config_invalid" }
175
+ $before = Get-FileSnapshot $target
176
+ if (-not [StringComparer]::OrdinalIgnoreCase.Equals($before.Hash, [string]$control.expectedSha256)) {
177
+ throw "agent_setup_config_changed"
178
+ }
179
+ $replacement = Get-FileSnapshot $temporary
180
+ if ($replacement.Hash -ne [string]$control.replacementSha256) {
181
+ throw "agent_setup_config_temporary_changed"
182
+ }
183
+ # ReplaceFileW can retain the temporary file's owner and add an explicit ACE
184
+ # for the original owner. Give it the exact original security first; do not
185
+ # weaken the post-replace comparison to accept that metadata change.
186
+ $replacementSecurity = [Security.AccessControl.FileSecurity]::new()
187
+ $replacementSecurity.SetSecurityDescriptorSddlForm(
188
+ $before.Security,
189
+ [Security.AccessControl.AccessControlSections]::Access -bor
190
+ [Security.AccessControl.AccessControlSections]::Owner -bor
191
+ [Security.AccessControl.AccessControlSections]::Group
192
+ )
193
+ Set-Dacl $temporary $replacementSecurity ([string]$control.replacementSha256)
194
+ # HELLOLYNK_TEST_PRE_REPLACE_IDENTITY_INJECTION_POINT
195
+ # A second snapshot narrows the unavoidable path-based ReplaceFileW window. A process
196
+ # already running as this Windows account remains outside this configurator's trust boundary.
197
+ $target = Assert-PlainPath $target
198
+ $immediate = Get-FileSnapshot $target
199
+ if ($immediate.Identity -ne $before.Identity -or
200
+ $immediate.Hash -ne $before.Hash -or
201
+ $immediate.Dacl -ne $before.Dacl -or
202
+ $immediate.Owner -ne $before.Owner -or
203
+ $immediate.Group -ne $before.Group) {
204
+ throw "agent_setup_config_changed"
205
+ }
206
+ $securedReplacement = Get-FileSnapshot $temporary
207
+ if ($securedReplacement.Identity -ne $replacement.Identity -or
208
+ $securedReplacement.Hash -ne [string]$control.replacementSha256 -or
209
+ $securedReplacement.Dacl -ne $before.Dacl -or
210
+ $securedReplacement.Owner -ne $before.Owner -or
211
+ $securedReplacement.Group -ne $before.Group) {
212
+ throw "agent_setup_config_temporary_changed"
213
+ }
214
+
215
+ $backup = Join-Path $parent (".{0}.{1}.bak" -f [IO.Path]::GetFileName($target), [guid]::NewGuid().ToString("N"))
216
+ [IO.File]::Replace($temporary, $target, $backup, $true)
217
+ # HELLOLYNK_TEST_POST_REPLACE_ACL_INJECTION_POINT
218
+ try {
219
+ $after = Get-FileSnapshot $target
220
+ if ($after.Hash -ne [string]$control.replacementSha256 -or
221
+ $after.Dacl -ne $before.Dacl -or
222
+ $after.Owner -ne $before.Owner -or
223
+ $after.Group -ne $before.Group) {
224
+ throw "agent_setup_config_acl_unsafe"
225
+ }
226
+ [IO.File]::Delete($backup)
227
+ } catch {
228
+ $failureCode = [string]$_.Exception.Message
229
+ try {
230
+ if (-not [IO.File]::Exists($backup)) { throw "agent_setup_config_rollback_failed" }
231
+ [IO.File]::Replace($backup, $target, $temporary, $true)
232
+ Restore-FileSecurity $target $before.Hash $before.Security
233
+ $restored = Get-FileSnapshot $target
234
+ if ($restored.Hash -ne $before.Hash -or $restored.Dacl -ne $before.Dacl -or
235
+ $restored.Owner -ne $before.Owner -or $restored.Group -ne $before.Group) {
236
+ throw "agent_setup_config_rollback_failed"
237
+ }
238
+ if ([IO.File]::Exists($temporary)) { [IO.File]::Delete($temporary) }
239
+ if ([IO.File]::Exists($temporary) -or [IO.File]::Exists($backup)) {
240
+ throw "agent_setup_config_rollback_failed"
241
+ }
242
+ } catch {
243
+ throw "agent_setup_config_rollback_failed"
244
+ }
245
+ throw $failureCode
246
+ }
247
+ Write-AtomicResult "agent_setup_config_replace_ok" 0
248
+ } catch {
249
+ $code = [string]$_.Exception.Message
250
+ if ($code -notmatch '^[a-z][a-z0-9_]{0,127}$') { $code = "agent_setup_config_replace_failed" }
251
+ Write-AtomicResult $code 1
252
+ }
253
+ }
254
+
255
+ if ($AtomicReplace) { Invoke-AtomicReplace }
256
+
257
+ $projectRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot "..\..\.."))
258
+ $configurator = Join-Path $projectRoot "clients\core\hellolynk-agent-configurator.mjs"
259
+ $pluginPath = Join-Path $projectRoot "integrations\openclaw-channel"
260
+ $nodePath = (Get-Command node -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source
261
+
262
+ if (-not (Test-Path -LiteralPath $configurator -PathType Leaf)) { throw "hellolynk_agent_configurator_missing" }
263
+ if (-not (Test-Path -LiteralPath (Join-Path $pluginPath "openclaw.plugin.json") -PathType Leaf)) { throw "hellolynk_openclaw_plugin_missing" }
264
+ if (-not (Test-Path -LiteralPath $OpenClawConfig -PathType Leaf)) { throw "openclaw_config_missing" }
265
+
266
+ try {
267
+ Write-Host "HelloLynk 正在为 OpenClaw(开放爪)配置本机中立 Host 表面。" -ForegroundColor Cyan
268
+ Write-Host "本步骤不读取旧 profile、不输入 KEY、不写入设备凭据。"
269
+ Write-Host "OpenClaw 的受保护 capability binding 必须已由 HelloLynk Host 安全配置;若缺失将安全停止。"
270
+
271
+ $configureOutput = & $nodePath $configurator openclaw `
272
+ --config-path $OpenClawConfig `
273
+ --plugin-path $pluginPath
274
+ if ($LASTEXITCODE -ne 0) { throw "openclaw_neutral_configuration_failed" }
275
+
276
+ Write-Host "配置完成:OpenClaw 将仅通过本机 HelloLynk Host 受限表面工作。" -ForegroundColor Green
277
+ Write-Host "请先关闭本窗口,再由人类重启 OpenClaw;配置程序不会自行启停 Host 或 OpenClaw。" -ForegroundColor Yellow
278
+ Write-Output '{"ok":true,"client":"openclaw","mode":"neutral","bindingRef":"protected-store:openclaw","secretRead":false,"secretPrinted":false,"restartRequired":true}'
279
+ } finally {
280
+ if ($WaitForUser) { Read-Host "按回车关闭此窗口" | Out-Null }
281
+ }