@borgee/agents-host 0.1.5 → 0.1.7
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.
- package/README.md +290 -49
- package/dist/agents-host-supervisor.d.ts +54 -0
- package/dist/agents-host-supervisor.js +313 -0
- package/dist/agents-host.d.ts +4 -4
- package/dist/agents-host.js +6 -4
- package/dist/cli-args.d.ts +35 -12
- package/dist/cli-args.js +225 -35
- package/dist/cli.d.ts +13 -1
- package/dist/cli.js +92 -26
- package/dist/config.d.ts +12 -7
- package/dist/config.js +80 -27
- package/dist/local-config.d.ts +51 -0
- package/dist/local-config.js +772 -0
- package/dist/providers/copilot/adapter.d.ts +1 -0
- package/dist/providers/copilot/adapter.js +3 -0
- package/dist/providers/copilot/cli-client.d.ts +55 -17
- package/dist/providers/copilot/cli-client.js +493 -50
- package/dist/providers/create-provider.js +3 -1
- package/dist/providers/provider-adapter.d.ts +1 -0
- package/dist/run.d.ts +27 -7
- package/dist/run.js +48 -10
- package/dist/types.d.ts +61 -5
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -1,41 +1,63 @@
|
|
|
1
1
|
# @borgee/agents-host
|
|
2
2
|
|
|
3
|
-
Minimal local runtime host
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Minimal local runtime host for Borgee agents.
|
|
4
|
+
|
|
5
|
+
- **Single-agent mode** keeps the existing one-process / one-agent flow.
|
|
6
|
+
- **Local-config mode** adds first-step multi-agent local hosting from a host
|
|
7
|
+
config file plus one config file per agent, with hot reload.
|
|
7
8
|
|
|
8
9
|
## What this is (and isn't)
|
|
9
10
|
|
|
10
|
-
This package
|
|
11
|
+
This package intentionally focuses on the smallest local-hosting loop:
|
|
11
12
|
|
|
12
|
-
```
|
|
13
|
+
```text
|
|
13
14
|
Borgee channel message
|
|
14
15
|
→ /ws/plugin (BPP)
|
|
15
16
|
→ @borgee/plugin-sdk
|
|
16
17
|
→ AgentsHost.handleMessage
|
|
17
|
-
→ local
|
|
18
|
+
→ local claude / copilot CLI subprocess
|
|
18
19
|
→ BPP reply
|
|
19
20
|
→ Borgee channel
|
|
20
21
|
```
|
|
21
22
|
|
|
22
|
-
**In scope:**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
**In scope:**
|
|
24
|
+
|
|
25
|
+
- single-agent env / CLI startup
|
|
26
|
+
- local-config multi-agent startup
|
|
27
|
+
- one isolated `AgentsHost` per effective agent key
|
|
28
|
+
- per-channel conversation memory via each provider's native session mechanism
|
|
29
|
+
- hot reload for host config and agent file add / update / remove
|
|
30
|
+
|
|
31
|
+
**Out of scope:**
|
|
32
|
+
|
|
33
|
+
- remote command execution / shell dispatch
|
|
34
|
+
- node provisioning
|
|
35
|
+
- systemd/service installation
|
|
36
|
+
- scheduled / periodic prompts
|
|
26
37
|
|
|
27
|
-
|
|
28
|
-
these): remote command execution / shell dispatch, node provisioning,
|
|
29
|
-
multi-agent discovery/sync, systemd service install, and scheduled/periodic
|
|
30
|
-
prompts. To run several agents, run several processes with different
|
|
31
|
-
`BORGEE_AGENT_API_KEY` values.
|
|
38
|
+
## Running
|
|
32
39
|
|
|
33
|
-
|
|
40
|
+
```bash
|
|
41
|
+
pnpm --filter @borgee/agents-host dev # tsx, env-var single-agent mode
|
|
42
|
+
pnpm --filter @borgee/agents-host build # tsc -> dist/
|
|
43
|
+
pnpm --filter @borgee/agents-host start # node dist/index.js, env-var single-agent mode
|
|
44
|
+
```
|
|
34
45
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
For the published CLI entry point:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
agents-host start <serverUrl> <apiKey> [options]
|
|
50
|
+
agents-host start --config <path-to-host-config>
|
|
51
|
+
agents-host validate --config <path-to-host-config>
|
|
52
|
+
agents-host print-layout --root <dir>
|
|
53
|
+
agents-host generate-config --root <dir> --stdin
|
|
54
|
+
agents-host generate-config --root <dir> --spec-json <json>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Single-agent mode
|
|
58
|
+
|
|
59
|
+
Use the existing env-var flow when you want exactly one hosted agent per
|
|
60
|
+
process.
|
|
39
61
|
|
|
40
62
|
```bash
|
|
41
63
|
BORGEE_BASE_URL=https://your-borgee-server \
|
|
@@ -45,46 +67,265 @@ RUNTIME_PROVIDER=claude \
|
|
|
45
67
|
pnpm --filter @borgee/agents-host dev
|
|
46
68
|
```
|
|
47
69
|
|
|
48
|
-
|
|
70
|
+
Or with the CLI:
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
| `BORGEE_AGENT_API_KEY` | yes | — | The agent's API key, revealed from the web UI |
|
|
54
|
-
| `BORGEE_AGENT_NAME` | no | `Assistant` | Display name used in prompts |
|
|
55
|
-
| `RUNTIME_PROVIDER` | no | `claude` | `claude` or `copilot` |
|
|
56
|
-
| `CLAUDE_COMMAND` / `CLAUDE_ARGS` | no | `claude` / `--print` | Local Claude CLI command + args |
|
|
57
|
-
| `COPILOT_COMMAND` / `COPILOT_ARGS` | no | `copilot` / `-s --no-color --allow-all-tools --output-format text` | Local Copilot CLI command + args |
|
|
72
|
+
```bash
|
|
73
|
+
agents-host start https://your-borgee-server bgr_xxxxxxxx --provider copilot
|
|
74
|
+
```
|
|
58
75
|
|
|
59
|
-
|
|
76
|
+
### Environment variables / equivalent single-agent CLI flags
|
|
60
77
|
|
|
61
|
-
|
|
62
|
-
|
|
78
|
+
| Variable | CLI flag | Required | Default | Description |
|
|
79
|
+
| ---------------------------------- | -------------------------------------- | -------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
80
|
+
| `BORGEE_BASE_URL` | positional `<serverUrl>` | yes | — | Borgee server base URL |
|
|
81
|
+
| `BORGEE_AGENT_API_KEY` | positional `<apiKey>` | yes | — | Agent API key from the web UI |
|
|
82
|
+
| `BORGEE_AGENT_NAME` | `--name` | no | `Assistant` | Display name used in prompts |
|
|
83
|
+
| `RUNTIME_PROVIDER` | `--provider` | no | `claude` | `claude` or `copilot` |
|
|
84
|
+
| `CLAUDE_COMMAND` / `CLAUDE_ARGS` | `--claude-command` / `--claude-args` | no | `claude` / `--print` | Local Claude CLI command + args |
|
|
85
|
+
| `COPILOT_COMMAND` / `COPILOT_ARGS` | `--copilot-command` / `--copilot-args` | no | `copilot` / parsed but ignored by ACP runtime | Local Copilot CLI command. The persistent Copilot ACP prototype always launches `copilot --acp`. |
|
|
86
|
+
| `COPILOT_SESSION_TTL_MINUTES` | `--copilot-session-ttl-minutes` | no | `2880` | Idle TTL for per-channel Copilot ACP sessions |
|
|
63
87
|
|
|
64
|
-
|
|
65
|
-
turn after uses `-r/--resume <uuid>` (Claude treats these as distinct
|
|
66
|
-
operations).
|
|
67
|
-
- **Copilot**: every turn uses `--session-id=<uuid>` — Copilot's CLI treats
|
|
68
|
-
that flag as create-or-resume for the same UUID.
|
|
88
|
+
## Local-config mode
|
|
69
89
|
|
|
70
|
-
|
|
71
|
-
process restarts, each channel starts a fresh CLI session (no session-id
|
|
72
|
-
persistence across restarts in this minimal version).
|
|
90
|
+
Run one supervisor process from a host config file:
|
|
73
91
|
|
|
74
|
-
|
|
92
|
+
```bash
|
|
93
|
+
agents-host start --config ./agents-host.yaml
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Validate the same local-config files without starting agents, the supervisor,
|
|
97
|
+
watchers, control-plane connections, or provider subprocesses:
|
|
75
98
|
|
|
76
99
|
```bash
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
agents-host validate --config ./agents-host.yaml
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`validate` supports local-config mode only and reuses the same
|
|
104
|
+
`loadLocalConfigSnapshot()` validation path as `start --config`.
|
|
105
|
+
|
|
106
|
+
Print the canonical default local-config layout for a root directory without
|
|
107
|
+
writing files or starting any runtime processes:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
agents-host print-layout --root ./runtime-root
|
|
80
111
|
```
|
|
81
112
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
`
|
|
113
|
+
This command prints JSON only. It describes the default bootstrap layout:
|
|
114
|
+
|
|
115
|
+
- host config file: `<root>/agents-host.yaml`
|
|
116
|
+
- agents directory: `<root>/agents`
|
|
117
|
+
|
|
118
|
+
It does **not** read an existing host config file, so it does **not** reflect a
|
|
119
|
+
custom `agentsDir` override from `agents-host.yaml`.
|
|
120
|
+
|
|
121
|
+
Materialize the canonical default local-config files under that root. Pass the
|
|
122
|
+
secret-bearing JSON spec on standard input so it is not exposed in process
|
|
123
|
+
arguments:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
printf '%s' '{"host":{"borgeeBaseUrl":"https://borgee.example.com"},"agents":[{"key":"cp1","name":"Copilot","apiKey":"bgr_xxx","provider":"copilot"}]}' \
|
|
127
|
+
| agents-host generate-config --root ./runtime-root --stdin
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`generate-config` is machine-oriented:
|
|
131
|
+
|
|
132
|
+
- it accepts one JSON spec object via `--stdin`; `--spec-json` remains only as
|
|
133
|
+
a compatibility input and exposes the JSON in process arguments
|
|
134
|
+
- it always writes the canonical default layout from `print-layout`
|
|
135
|
+
- it publishes a complete validated generation atomically; a failed generation
|
|
136
|
+
leaves the prior active set in place
|
|
137
|
+
- concurrent writers for the same managed root are serialized through a
|
|
138
|
+
root-local lock; a writer waits up to 10 seconds, then fails clearly if the
|
|
139
|
+
lock remains held
|
|
140
|
+
- it retains the active and immediately previous generations and reader-leased
|
|
141
|
+
generations, then removes older generated generations (including superseded API keys)
|
|
142
|
+
- if that post-publication pruning fails, the apply remains successful and its
|
|
143
|
+
JSON summary includes a `warnings` entry with code
|
|
144
|
+
`PRUNE_SUPERSEDED_GENERATIONS_FAILED`
|
|
145
|
+
- it uses a dedicated managed root: `<root>/agents-host.yaml` and
|
|
146
|
+
`<root>/agents` are stable links to the active private generation
|
|
147
|
+
- it replaces stale supported agent config files as part of that atomic
|
|
148
|
+
full-set publication, never by pruning the active set first
|
|
149
|
+
- it creates and normalizes the managed root and generation directories to
|
|
150
|
+
mode `0700`, and generated host and agent config files to mode `0600`
|
|
151
|
+
- it prints a JSON summary without echoing agent API keys
|
|
152
|
+
|
|
153
|
+
Use a new empty directory as the managed root. `generate-config` refuses a
|
|
154
|
+
root whose managed links or generation storage have been replaced with
|
|
155
|
+
unexpected file types or targets. Existing hand-managed local-config layouts
|
|
156
|
+
continue to work with `start --config` and `validate --config`; they are not
|
|
157
|
+
converted in place by this command.
|
|
158
|
+
|
|
159
|
+
The spec shape is:
|
|
160
|
+
|
|
161
|
+
```json
|
|
162
|
+
{
|
|
163
|
+
"host": {
|
|
164
|
+
"borgeeBaseUrl": "https://borgee.example.com",
|
|
165
|
+
"defaults": {
|
|
166
|
+
"claudeCommand": "claude",
|
|
167
|
+
"claudeArgs": ["--print"],
|
|
168
|
+
"copilotCommand": "copilot",
|
|
169
|
+
"copilotArgs": ["-s", "--no-color", "--allow-all-tools", "--output-format", "text"],
|
|
170
|
+
"copilotSessionTtlMinutes": 2880
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
"agents": [
|
|
174
|
+
{
|
|
175
|
+
"key": "cp1",
|
|
176
|
+
"name": "Copilot",
|
|
177
|
+
"apiKey": "bgr_xxx",
|
|
178
|
+
"provider": "copilot",
|
|
179
|
+
"enabled": true
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
`host.agentsDir` is intentionally **not** accepted here. Canonical generation
|
|
186
|
+
always targets `<root>/agents`, and validation is re-run after generation using
|
|
187
|
+
the same local-config loader as `start --config` / `validate --config`. Start
|
|
188
|
+
the generated layout with `agents-host start --config <root>/agents-host.yaml`;
|
|
189
|
+
that stable path follows the active atomically published generation.
|
|
190
|
+
The loader preserves that stable path for validation output and publication
|
|
191
|
+
watches, while pinning resolved host and agents-directory paths before reading.
|
|
192
|
+
Managed snapshots hold a short-lived reader lease until the read finishes, so
|
|
193
|
+
each snapshot uses one generation even if publication changes `current`
|
|
194
|
+
concurrently.
|
|
195
|
+
|
|
196
|
+
The supervisor loads:
|
|
197
|
+
|
|
198
|
+
- one **host config file**
|
|
199
|
+
- one **agent config file per discovered file** under the agents directory
|
|
200
|
+
- one isolated `AgentsHost` per enabled agent key
|
|
201
|
+
|
|
202
|
+
### Supported file types
|
|
203
|
+
|
|
204
|
+
Host and agent config files may be:
|
|
205
|
+
|
|
206
|
+
- `*.yaml`
|
|
207
|
+
- `*.yml`
|
|
208
|
+
- `*.json`
|
|
209
|
+
|
|
210
|
+
Parsing uses the `yaml` package for all supported file types.
|
|
211
|
+
|
|
212
|
+
### Recommended layout
|
|
213
|
+
|
|
214
|
+
```text
|
|
215
|
+
packages/agents-host/
|
|
216
|
+
agents-host.yaml
|
|
217
|
+
agents/
|
|
218
|
+
support.yaml
|
|
219
|
+
triage.json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Host config
|
|
223
|
+
|
|
224
|
+
`agentsDir` defaults to `./agents` relative to the host config file. Absolute
|
|
225
|
+
paths are also allowed.
|
|
226
|
+
|
|
227
|
+
```yaml
|
|
228
|
+
borgeeBaseUrl: https://borgee.example.com
|
|
229
|
+
agentsDir: ./agents
|
|
230
|
+
defaults:
|
|
231
|
+
claudeCommand: claude
|
|
232
|
+
claudeArgs:
|
|
233
|
+
- --print
|
|
234
|
+
copilotCommand: copilot
|
|
235
|
+
copilotArgs:
|
|
236
|
+
- -s
|
|
237
|
+
- --no-color
|
|
238
|
+
- --allow-all-tools
|
|
239
|
+
- --output-format
|
|
240
|
+
- text
|
|
241
|
+
copilotSessionTtlMinutes: 2880
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Host config fields:
|
|
245
|
+
|
|
246
|
+
- `borgeeBaseUrl` (**required**)
|
|
247
|
+
- `agentsDir` (optional, default `./agents` relative to the host config file)
|
|
248
|
+
- `defaults.claudeCommand`
|
|
249
|
+
- `defaults.claudeArgs`
|
|
250
|
+
- `defaults.copilotCommand`
|
|
251
|
+
- `defaults.copilotArgs`
|
|
252
|
+
- `defaults.copilotSessionTtlMinutes`
|
|
253
|
+
|
|
254
|
+
Absent host defaults fall back to the same code-level defaults used by the
|
|
255
|
+
single-agent env / CLI flow.
|
|
256
|
+
|
|
257
|
+
### Agent config
|
|
258
|
+
|
|
259
|
+
```yaml
|
|
260
|
+
key: support-bot
|
|
261
|
+
name: Support Bot
|
|
262
|
+
apiKey: bgr_support_xxxxxxxx
|
|
263
|
+
provider: claude
|
|
264
|
+
enabled: true
|
|
265
|
+
claudeArgs:
|
|
266
|
+
- --print
|
|
267
|
+
- --model
|
|
268
|
+
- sonnet
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Agent config fields:
|
|
272
|
+
|
|
273
|
+
- `key` (**required**): stable identity used for diffing and reload decisions
|
|
274
|
+
- `name` (**required**)
|
|
275
|
+
- `apiKey` (**required**)
|
|
276
|
+
- `provider` (**required**): `claude` or `copilot`
|
|
277
|
+
- `enabled` (optional, default `true`)
|
|
278
|
+
- optional overrides for `claudeCommand`, `claudeArgs`, `copilotCommand`,
|
|
279
|
+
`copilotArgs`, and `copilotSessionTtlMinutes`
|
|
280
|
+
|
|
281
|
+
Array overrides are **replacement**, not concatenation. For example, an agent
|
|
282
|
+
`claudeArgs` value replaces the host default `claudeArgs` entirely.
|
|
283
|
+
|
|
284
|
+
## Hot reload behavior
|
|
285
|
+
|
|
286
|
+
The supervisor watches:
|
|
287
|
+
|
|
288
|
+
- the stable host-config parent, so an atomic `current` publication triggers a reload
|
|
289
|
+
- the resolved host-config generation directory
|
|
290
|
+
- the resolved configured agents directory
|
|
291
|
+
|
|
292
|
+
Every `rename` / `change` event is treated as a reload trigger. Reloads are
|
|
293
|
+
serialized with initial startup and debounced by at least 300ms. Each reload
|
|
294
|
+
does a full rescan, validation pass, diff, and apply cycle.
|
|
295
|
+
|
|
296
|
+
Diff rules:
|
|
297
|
+
|
|
298
|
+
- `enabled: false` agents are excluded before diffing
|
|
299
|
+
- new `key` → start a new isolated `AgentsHost`
|
|
300
|
+
- removed `key` → stop that agent
|
|
301
|
+
- same `key` + same effective config → no-op
|
|
302
|
+
- same `key` + changed effective config → stop old runner, then start replacement
|
|
303
|
+
|
|
304
|
+
Changing an agent `key` is treated as **remove old + add new**, so provider-side
|
|
305
|
+
session state is not preserved across the key change.
|
|
306
|
+
|
|
307
|
+
If a reload candidate is invalid (malformed host config, malformed agent config,
|
|
308
|
+
or duplicate agent keys), the supervisor logs the error and keeps the last
|
|
309
|
+
successfully applied snapshot running.
|
|
310
|
+
|
|
311
|
+
## Conversation memory
|
|
312
|
+
|
|
313
|
+
Each Borgee channel is mapped 1:1 to a provider-native session while it stays
|
|
314
|
+
active:
|
|
315
|
+
|
|
316
|
+
- **Claude**: first turn for a channel uses `--session-id <uuid>`; every turn
|
|
317
|
+
after uses `-r/--resume <uuid>`.
|
|
318
|
+
- **Copilot**: one persistent `copilot --acp` subprocess is shared by a single
|
|
319
|
+
`AgentsHost`, with one ACP session per Borgee channel. Same-channel turns are
|
|
320
|
+
serialized; different channels keep isolated ACP sessions.
|
|
321
|
+
|
|
322
|
+
There is no separate history store on our side. If a runner restarts, that
|
|
323
|
+
agent's provider-side channel sessions start fresh.
|
|
85
324
|
|
|
86
325
|
## Testing
|
|
87
326
|
|
|
88
327
|
```bash
|
|
89
|
-
pnpm --filter @borgee/agents-host
|
|
328
|
+
pnpm --filter @borgee/agents-host exec vitest run --testTimeout=10000
|
|
329
|
+
pnpm --filter @borgee/agents-host typecheck
|
|
330
|
+
pnpm --filter @borgee/agents-host build
|
|
90
331
|
```
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AgentsHostConfig, LocalConfigSnapshot } from './types.js';
|
|
2
|
+
export interface HostRunner {
|
|
3
|
+
start(): Promise<void>;
|
|
4
|
+
stop(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface WatchHandle {
|
|
7
|
+
close(): void;
|
|
8
|
+
}
|
|
9
|
+
export interface WatchEventInfo {
|
|
10
|
+
eventType?: string;
|
|
11
|
+
filename?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface LoggerLike {
|
|
14
|
+
log(...args: unknown[]): void;
|
|
15
|
+
error(...args: unknown[]): void;
|
|
16
|
+
}
|
|
17
|
+
export interface AgentsHostSupervisorDeps {
|
|
18
|
+
createHost?: (config: AgentsHostConfig) => HostRunner;
|
|
19
|
+
loadSnapshot?: (configPath: string) => Promise<LocalConfigSnapshot>;
|
|
20
|
+
watchPath?: (path: string, onEvent: (event?: WatchEventInfo) => void) => WatchHandle;
|
|
21
|
+
logger?: LoggerLike;
|
|
22
|
+
}
|
|
23
|
+
export declare class AgentsHostSupervisor {
|
|
24
|
+
private readonly hostConfigPath;
|
|
25
|
+
private readonly createHost;
|
|
26
|
+
private readonly loadSnapshot;
|
|
27
|
+
private readonly watchPath;
|
|
28
|
+
private readonly logger;
|
|
29
|
+
private readonly activeHosts;
|
|
30
|
+
private readonly watchers;
|
|
31
|
+
private currentSnapshot;
|
|
32
|
+
private reloadTimer;
|
|
33
|
+
private reloadInFlight;
|
|
34
|
+
private pendingReload;
|
|
35
|
+
private runningReloadPromise;
|
|
36
|
+
private shuttingDown;
|
|
37
|
+
private started;
|
|
38
|
+
constructor(hostConfigPath: string, deps?: AgentsHostSupervisorDeps);
|
|
39
|
+
start(): Promise<void>;
|
|
40
|
+
stop(): Promise<void>;
|
|
41
|
+
private scheduleReload;
|
|
42
|
+
private clearReloadTimer;
|
|
43
|
+
private runReloadLoop;
|
|
44
|
+
private reloadOnce;
|
|
45
|
+
private refreshWatchers;
|
|
46
|
+
private getWatchPaths;
|
|
47
|
+
private handleWatchEvent;
|
|
48
|
+
private installStableWatcher;
|
|
49
|
+
private closeAllWatchers;
|
|
50
|
+
private cleanUpFailedStart;
|
|
51
|
+
private applySnapshot;
|
|
52
|
+
private startDesiredAgent;
|
|
53
|
+
private stopActiveHost;
|
|
54
|
+
}
|