@ericsanchezok/meta-synergy 1.1.26 → 1.2.17
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 +47 -0
- package/install +444 -0
- package/package.json +7 -6
- package/script/build.ts +93 -0
- package/src/cli-backend.ts +118 -16
- package/src/cli.ts +178 -33
- package/src/control/schema.ts +25 -0
- package/src/display.ts +70 -0
- package/src/exec/process-registry.ts +14 -5
- package/src/holos/auth.ts +183 -0
- package/src/holos/login.ts +148 -8
- package/src/inbound/handler.ts +20 -9
- package/src/index.ts +1 -0
- package/src/migration/index.ts +22 -0
- package/src/migration/types.ts +5 -0
- package/src/owner-registry.ts +162 -0
- package/src/runtime.ts +283 -33
- package/src/service.ts +169 -77
- package/src/state/migration.ts +19 -0
- package/src/state/store.ts +53 -7
- package/src/types.ts +8 -0
- package/test/cli-backend-auth.test.ts +86 -0
- package/test/cli-backend-mode.test.ts +49 -0
- package/test/control-socket.test.ts +123 -0
- package/test/holos-auth.test.ts +117 -0
- package/test/migration.test.ts +58 -0
- package/test/runtime-managed-mode.test.ts +111 -0
- package/script/publish.ts +0 -38
package/src/cli-backend.ts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { MetaSynergyControlClient } from "./control/client"
|
|
2
|
+
import { MetaSynergyHolosAuth, type MetaSynergyHolosAuthSource } from "./holos/auth"
|
|
2
3
|
import { MetaSynergyHolosLogin } from "./holos/login"
|
|
3
4
|
import { MetaSynergyService } from "./service"
|
|
4
5
|
import {
|
|
5
6
|
MetaSynergyStore,
|
|
6
7
|
type MetaSynergyApprovalMode,
|
|
8
|
+
type MetaSynergyAuthState,
|
|
7
9
|
type MetaSynergyPendingRequest,
|
|
8
10
|
type MetaSynergyState,
|
|
9
11
|
} from "./state/store"
|
|
12
|
+
import { MetaSynergyDisplay, type MetaSynergyHiddenReason } from "./display"
|
|
13
|
+
import { MetaSynergyOwnerRegistry } from "./owner-registry"
|
|
10
14
|
|
|
11
15
|
export type MetaSynergyTrustSubject = "agent" | "user"
|
|
12
16
|
|
|
@@ -30,8 +34,61 @@ export namespace MetaSynergyCLIBackend {
|
|
|
30
34
|
return await loadSnapshot()
|
|
31
35
|
}
|
|
32
36
|
|
|
33
|
-
export async function
|
|
34
|
-
|
|
37
|
+
export async function mode() {
|
|
38
|
+
if (await MetaSynergyControlClient.isAvailable()) {
|
|
39
|
+
return await MetaSynergyControlClient.request({ action: "runtime.mode" })
|
|
40
|
+
}
|
|
41
|
+
const state = await MetaSynergyStore.loadState()
|
|
42
|
+
return {
|
|
43
|
+
mode: state.runtimeMode,
|
|
44
|
+
ownership: MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry),
|
|
45
|
+
connectionStatus: state.connectionStatus,
|
|
46
|
+
service: await MetaSynergyService.status(),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function enterManagedMode() {
|
|
51
|
+
if (await MetaSynergyControlClient.isAvailable()) {
|
|
52
|
+
return await MetaSynergyControlClient.request({ action: "runtime.enter_managed" })
|
|
53
|
+
}
|
|
54
|
+
const state = await MetaSynergyStore.loadState()
|
|
55
|
+
state.runtimeMode = "managed"
|
|
56
|
+
MetaSynergyOwnerRegistry.declareLocalOwner(state.ownerRegistry, state.envID ?? `local:${crypto.randomUUID()}`)
|
|
57
|
+
state.connectionStatus = "disconnected"
|
|
58
|
+
await MetaSynergyStore.saveState(state)
|
|
59
|
+
return {
|
|
60
|
+
mode: state.runtimeMode,
|
|
61
|
+
ownership: MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry),
|
|
62
|
+
connectionStatus: state.connectionStatus,
|
|
63
|
+
service: await MetaSynergyService.status(),
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export async function enterStandaloneMode() {
|
|
68
|
+
if (await MetaSynergyControlClient.isAvailable()) {
|
|
69
|
+
return await MetaSynergyControlClient.request({ action: "runtime.set_mode", mode: "standalone" })
|
|
70
|
+
}
|
|
71
|
+
const state = await MetaSynergyStore.loadState()
|
|
72
|
+
state.runtimeMode = "standalone"
|
|
73
|
+
MetaSynergyOwnerRegistry.releaseLocalOwner(state.ownerRegistry)
|
|
74
|
+
state.connectionStatus = "disconnected"
|
|
75
|
+
await MetaSynergyStore.saveState(state)
|
|
76
|
+
return {
|
|
77
|
+
mode: state.runtimeMode,
|
|
78
|
+
ownership: MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry),
|
|
79
|
+
connectionStatus: state.connectionStatus,
|
|
80
|
+
service: await MetaSynergyService.status(),
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function login(options?: { agentID?: string; agentSecret?: string }) {
|
|
85
|
+
const result =
|
|
86
|
+
options?.agentID && options?.agentSecret
|
|
87
|
+
? await MetaSynergyHolosLogin.loginWithExistingCredentials({
|
|
88
|
+
agentID: options.agentID,
|
|
89
|
+
agentSecret: options.agentSecret,
|
|
90
|
+
})
|
|
91
|
+
: await MetaSynergyHolosLogin.login()
|
|
35
92
|
return {
|
|
36
93
|
agentID: result.agentID,
|
|
37
94
|
service: await MetaSynergyService.status(),
|
|
@@ -48,17 +105,23 @@ export namespace MetaSynergyCLIBackend {
|
|
|
48
105
|
state.service.pid = undefined
|
|
49
106
|
state.service.stoppedAt = Date.now()
|
|
50
107
|
await MetaSynergyStore.saveState(state)
|
|
51
|
-
|
|
108
|
+
if (state.runtimeMode !== "managed") {
|
|
109
|
+
await MetaSynergyHolosAuth.clear()
|
|
110
|
+
}
|
|
52
111
|
return {
|
|
53
112
|
service,
|
|
54
|
-
authCleared:
|
|
113
|
+
authCleared: state.runtimeMode !== "managed",
|
|
55
114
|
}
|
|
56
115
|
}
|
|
57
116
|
|
|
58
117
|
export async function whoami() {
|
|
59
118
|
const snapshot = await loadSnapshot()
|
|
119
|
+
const storedAuth = await MetaSynergyHolosAuth.inspect()
|
|
60
120
|
return {
|
|
61
|
-
auth:
|
|
121
|
+
auth: sanitizeAuth(storedAuth.auth, storedAuth.source),
|
|
122
|
+
mode: snapshot.mode,
|
|
123
|
+
ownership: snapshot.ownership,
|
|
124
|
+
envID: snapshot.state.envID ?? null,
|
|
62
125
|
label: snapshot.state.label ?? null,
|
|
63
126
|
service: snapshot.service,
|
|
64
127
|
}
|
|
@@ -76,19 +139,38 @@ export namespace MetaSynergyCLIBackend {
|
|
|
76
139
|
}
|
|
77
140
|
|
|
78
141
|
export async function doctor() {
|
|
79
|
-
const auth = await MetaSynergyStore.loadAuth()
|
|
80
142
|
const state = await MetaSynergyStore.loadState()
|
|
81
143
|
const service = await MetaSynergyService.status()
|
|
144
|
+
const managed = state.runtimeMode === "managed"
|
|
145
|
+
const authInfo = await MetaSynergyHolosAuth.inspect()
|
|
146
|
+
const auth = authInfo.auth
|
|
147
|
+
const ownership = MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry)
|
|
82
148
|
const checks = [
|
|
83
149
|
{
|
|
84
150
|
name: "config_dir",
|
|
85
151
|
ok: true,
|
|
86
152
|
detail: MetaSynergyStore.root(),
|
|
87
153
|
},
|
|
154
|
+
{
|
|
155
|
+
name: "mode",
|
|
156
|
+
ok: true,
|
|
157
|
+
detail: state.runtimeMode,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: "local_owner",
|
|
161
|
+
ok: ownership.local.owned,
|
|
162
|
+
detail: ownership.local.activeOwnerID ?? "No local owner declared",
|
|
163
|
+
},
|
|
88
164
|
{
|
|
89
165
|
name: "auth",
|
|
90
|
-
ok: Boolean(auth),
|
|
91
|
-
detail:
|
|
166
|
+
ok: managed ? true : Boolean(auth),
|
|
167
|
+
detail: managed
|
|
168
|
+
? auth
|
|
169
|
+
? `Stored agent ${MetaSynergyDisplay.identifier(auth.agentID, { hiddenReason: "managed" })} (${authInfo.source}) — not required in managed mode`
|
|
170
|
+
: "Managed mode does not require Holos auth"
|
|
171
|
+
: auth
|
|
172
|
+
? `agent ${auth.agentID} (${authInfo.source})`
|
|
173
|
+
: "No Holos credentials found",
|
|
92
174
|
},
|
|
93
175
|
{
|
|
94
176
|
name: "service",
|
|
@@ -97,12 +179,12 @@ export namespace MetaSynergyCLIBackend {
|
|
|
97
179
|
},
|
|
98
180
|
{
|
|
99
181
|
name: "connection",
|
|
100
|
-
ok: state.connectionStatus === "connected",
|
|
182
|
+
ok: managed ? state.connectionStatus === "disconnected" : state.connectionStatus === "connected",
|
|
101
183
|
detail: state.connectionStatus,
|
|
102
184
|
},
|
|
103
185
|
]
|
|
104
186
|
|
|
105
|
-
if (auth) {
|
|
187
|
+
if (auth && !managed) {
|
|
106
188
|
const verification = await MetaSynergyHolosLogin.verifySecret(auth.agentSecret)
|
|
107
189
|
checks.push({
|
|
108
190
|
name: "holos_secret",
|
|
@@ -115,8 +197,12 @@ export namespace MetaSynergyCLIBackend {
|
|
|
115
197
|
ok: checks.every((check) => check.ok),
|
|
116
198
|
checks,
|
|
117
199
|
service,
|
|
200
|
+
mode: state.runtimeMode,
|
|
201
|
+
ownership,
|
|
118
202
|
state: sanitizeState(state),
|
|
119
|
-
auth: sanitizeAuth(auth
|
|
203
|
+
auth: sanitizeAuth(auth, authInfo.source, {
|
|
204
|
+
hiddenReason: managed ? "managed" : null,
|
|
205
|
+
}),
|
|
120
206
|
}
|
|
121
207
|
}
|
|
122
208
|
|
|
@@ -352,14 +438,18 @@ async function decideRequestOffline(requestID: string, status: "approved" | "den
|
|
|
352
438
|
}
|
|
353
439
|
|
|
354
440
|
async function loadSnapshot() {
|
|
355
|
-
const [
|
|
356
|
-
MetaSynergyStore.loadAuth(),
|
|
441
|
+
const [state, service, authInfo] = await Promise.all([
|
|
357
442
|
MetaSynergyStore.loadState(),
|
|
358
443
|
MetaSynergyService.status(),
|
|
444
|
+
MetaSynergyHolosAuth.inspect(),
|
|
359
445
|
])
|
|
360
446
|
|
|
361
447
|
return {
|
|
362
|
-
auth: sanitizeAuth(auth
|
|
448
|
+
auth: sanitizeAuth(authInfo.auth, authInfo.source, {
|
|
449
|
+
hiddenReason: state.runtimeMode === "managed" ? "managed" : null,
|
|
450
|
+
}),
|
|
451
|
+
mode: state.runtimeMode,
|
|
452
|
+
ownership: MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry),
|
|
363
453
|
state: sanitizeState(state),
|
|
364
454
|
host: {
|
|
365
455
|
envID: state.envID ?? null,
|
|
@@ -370,20 +460,32 @@ async function loadSnapshot() {
|
|
|
370
460
|
}
|
|
371
461
|
}
|
|
372
462
|
|
|
373
|
-
function sanitizeAuth(
|
|
463
|
+
function sanitizeAuth(
|
|
464
|
+
auth: { agentID: string; agentSecret: string } | undefined,
|
|
465
|
+
source: MetaSynergyHolosAuthSource | null,
|
|
466
|
+
options?: { hiddenReason?: MetaSynergyHiddenReason | null },
|
|
467
|
+
) {
|
|
374
468
|
return auth
|
|
375
469
|
? {
|
|
376
470
|
loggedIn: true,
|
|
377
|
-
agentID: auth.agentID,
|
|
471
|
+
agentID: MetaSynergyDisplay.identifier(auth.agentID, {
|
|
472
|
+
hiddenReason: options?.hiddenReason,
|
|
473
|
+
}),
|
|
474
|
+
source,
|
|
475
|
+
hiddenReason: options?.hiddenReason ?? null,
|
|
378
476
|
}
|
|
379
477
|
: {
|
|
380
478
|
loggedIn: false,
|
|
381
479
|
agentID: null,
|
|
480
|
+
source: null,
|
|
481
|
+
hiddenReason: null,
|
|
382
482
|
}
|
|
383
483
|
}
|
|
384
484
|
|
|
385
485
|
function sanitizeState(state: MetaSynergyState) {
|
|
386
486
|
return {
|
|
487
|
+
runtimeMode: state.runtimeMode,
|
|
488
|
+
ownerRegistry: MetaSynergyOwnerRegistry.snapshot(state.ownerRegistry),
|
|
387
489
|
collaborationEnabled: state.collaborationEnabled,
|
|
388
490
|
approvalMode: state.approvalMode,
|
|
389
491
|
trusted: {
|
package/src/cli.ts
CHANGED
|
@@ -4,13 +4,25 @@ import { MetaSynergyCLIBackend, type MetaSynergyTrustSubject } from "./cli-backe
|
|
|
4
4
|
import type { MetaSynergyApprovalMode } from "./state/store"
|
|
5
5
|
import { MetaSynergyRuntime } from "./runtime"
|
|
6
6
|
import { MetaSynergyService } from "./service"
|
|
7
|
+
import { MetaSynergyHolosLogin } from "./holos/login"
|
|
8
|
+
import { MetaSynergyDisplay } from "./display"
|
|
7
9
|
|
|
8
10
|
interface CLIContext {
|
|
9
11
|
json: boolean
|
|
10
12
|
printLogs: boolean
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
invocationEntry?: string
|
|
14
|
+
launcherPath: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface GlobalFlags {
|
|
18
|
+
help: boolean
|
|
19
|
+
json: boolean
|
|
20
|
+
printLogs: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface MetaSynergyLoginOptions {
|
|
24
|
+
agentID?: string
|
|
25
|
+
agentSecret?: string
|
|
14
26
|
}
|
|
15
27
|
|
|
16
28
|
interface CommandSuccess {
|
|
@@ -36,19 +48,18 @@ async function main() {
|
|
|
36
48
|
renderFailure(parsed.error, {
|
|
37
49
|
json: false,
|
|
38
50
|
printLogs: false,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
execPath: process.execPath,
|
|
51
|
+
invocationEntry: process.argv[1],
|
|
52
|
+
launcherPath: process.execPath,
|
|
42
53
|
})
|
|
54
|
+
|
|
43
55
|
process.exit(parsed.error.exitCode ?? 1)
|
|
44
56
|
}
|
|
45
57
|
|
|
46
58
|
const context: CLIContext = {
|
|
47
59
|
json: parsed.flags.json,
|
|
48
60
|
printLogs: parsed.flags.printLogs,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
execPath: process.execPath,
|
|
61
|
+
invocationEntry: process.argv[1],
|
|
62
|
+
launcherPath: process.execPath,
|
|
52
63
|
}
|
|
53
64
|
|
|
54
65
|
if (parsed.flags.help || parsed.command.length === 0) {
|
|
@@ -102,6 +113,8 @@ async function dispatch(command: string[], context: CLIContext): Promise<Command
|
|
|
102
113
|
return reconnect(rest)
|
|
103
114
|
case "doctor":
|
|
104
115
|
return doctor(rest)
|
|
116
|
+
case "mode":
|
|
117
|
+
return handleMode(rest)
|
|
105
118
|
case "collaboration":
|
|
106
119
|
return handleCollaboration(rest)
|
|
107
120
|
case "requests":
|
|
@@ -148,8 +161,8 @@ async function startService(args: string[], context: CLIContext): Promise<Comman
|
|
|
148
161
|
return invalidUsage("Usage: meta-synergy start")
|
|
149
162
|
}
|
|
150
163
|
const service = await MetaSynergyService.start({
|
|
151
|
-
|
|
152
|
-
|
|
164
|
+
launcherPath: context.launcherPath,
|
|
165
|
+
invocationEntry: context.invocationEntry,
|
|
153
166
|
printLogs: false,
|
|
154
167
|
})
|
|
155
168
|
if (!service.running) {
|
|
@@ -183,8 +196,8 @@ async function restartService(args: string[], context: CLIContext): Promise<Comm
|
|
|
183
196
|
return invalidUsage("Usage: meta-synergy restart")
|
|
184
197
|
}
|
|
185
198
|
const result = await MetaSynergyService.restart({
|
|
186
|
-
|
|
187
|
-
|
|
199
|
+
launcherPath: context.launcherPath,
|
|
200
|
+
invocationEntry: context.invocationEntry,
|
|
188
201
|
printLogs: false,
|
|
189
202
|
})
|
|
190
203
|
if (!result.started.running) {
|
|
@@ -246,9 +259,52 @@ async function showLogs(args: string[], context: CLIContext): Promise<CommandRes
|
|
|
246
259
|
}
|
|
247
260
|
|
|
248
261
|
async function login(args: string[]): Promise<CommandResult> {
|
|
249
|
-
|
|
250
|
-
|
|
262
|
+
const parsed = parseLoginArgs(args)
|
|
263
|
+
if (!parsed.ok) {
|
|
264
|
+
return invalidUsage(parsed.usage)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (parsed.options.agentID || parsed.options.agentSecret) {
|
|
268
|
+
if (!parsed.options.agentID || !parsed.options.agentSecret) {
|
|
269
|
+
return {
|
|
270
|
+
ok: false,
|
|
271
|
+
message: "`--agent-id` and `--agent-secret` must be provided together.",
|
|
272
|
+
usage: loginUsage(),
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const result = await MetaSynergyCLIBackend.login({
|
|
277
|
+
agentID: parsed.options.agentID,
|
|
278
|
+
agentSecret: parsed.options.agentSecret,
|
|
279
|
+
})
|
|
280
|
+
return {
|
|
281
|
+
ok: true,
|
|
282
|
+
message: `Logged in as ${result.agentID}.`,
|
|
283
|
+
data: result,
|
|
284
|
+
}
|
|
251
285
|
}
|
|
286
|
+
|
|
287
|
+
if (process.stdin.isTTY && process.stdout.isTTY) {
|
|
288
|
+
const mode = await MetaSynergyHolosLogin.promptLoginMode()
|
|
289
|
+
if (mode === "existing") {
|
|
290
|
+
const credentials = await MetaSynergyHolosLogin.promptForExistingCredentials()
|
|
291
|
+
if (!credentials) {
|
|
292
|
+
return {
|
|
293
|
+
ok: false,
|
|
294
|
+
message: "Login cancelled.",
|
|
295
|
+
exitCode: 1,
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const result = await MetaSynergyCLIBackend.login(credentials)
|
|
300
|
+
return {
|
|
301
|
+
ok: true,
|
|
302
|
+
message: `Logged in as ${result.agentID}.`,
|
|
303
|
+
data: result,
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
252
308
|
const result = await MetaSynergyCLIBackend.login()
|
|
253
309
|
return {
|
|
254
310
|
ok: true,
|
|
@@ -304,6 +360,37 @@ async function doctor(args: string[]): Promise<CommandResult> {
|
|
|
304
360
|
}
|
|
305
361
|
}
|
|
306
362
|
|
|
363
|
+
async function handleMode(args: string[]): Promise<CommandResult> {
|
|
364
|
+
const [action, ...rest] = args
|
|
365
|
+
if (!action || action === "help") {
|
|
366
|
+
return invalidUsage("Usage: meta-synergy mode <status|managed|standalone>")
|
|
367
|
+
}
|
|
368
|
+
if (rest.length > 0) {
|
|
369
|
+
return invalidUsage("Usage: meta-synergy mode <status|managed|standalone>")
|
|
370
|
+
}
|
|
371
|
+
if (action === "status") {
|
|
372
|
+
return {
|
|
373
|
+
ok: true,
|
|
374
|
+
data: await MetaSynergyCLIBackend.mode(),
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
if (action === "managed") {
|
|
378
|
+
return {
|
|
379
|
+
ok: true,
|
|
380
|
+
message: "Managed mode enabled.",
|
|
381
|
+
data: await MetaSynergyCLIBackend.enterManagedMode(),
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
if (action === "standalone") {
|
|
385
|
+
return {
|
|
386
|
+
ok: true,
|
|
387
|
+
message: "Standalone mode enabled.",
|
|
388
|
+
data: await MetaSynergyCLIBackend.enterStandaloneMode(),
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return invalidUsage("Usage: meta-synergy mode <status|managed|standalone>")
|
|
392
|
+
}
|
|
393
|
+
|
|
307
394
|
async function handleCollaboration(args: string[]): Promise<CommandResult> {
|
|
308
395
|
const [action, ...rest] = args
|
|
309
396
|
if (!action || action === "help") {
|
|
@@ -511,7 +598,7 @@ function parseArgv(
|
|
|
511
598
|
continue
|
|
512
599
|
}
|
|
513
600
|
if (token.startsWith("-")) {
|
|
514
|
-
if (command[0] === "logs") {
|
|
601
|
+
if (command[0] === "logs" || command[0] === "login") {
|
|
515
602
|
command.push(token)
|
|
516
603
|
continue
|
|
517
604
|
}
|
|
@@ -607,7 +694,8 @@ function rootUsage() {
|
|
|
607
694
|
"Commands:",
|
|
608
695
|
" server [--print-logs]",
|
|
609
696
|
" start | stop | restart | status | logs",
|
|
610
|
-
" login | logout | whoami | reconnect | doctor",
|
|
697
|
+
" login [--agent-id ID --agent-secret SECRET] | logout | whoami | reconnect | doctor",
|
|
698
|
+
" mode <status|managed|standalone>",
|
|
611
699
|
" collaboration <enable|disable|status>",
|
|
612
700
|
" requests <list|show|approve|deny>",
|
|
613
701
|
" session <status|kick|block>",
|
|
@@ -629,11 +717,12 @@ function usageMap(): Record<string, string> {
|
|
|
629
717
|
restart: "Usage: meta-synergy restart",
|
|
630
718
|
status: "Usage: meta-synergy status",
|
|
631
719
|
logs: "Usage: meta-synergy logs [-f] [--tail N] [--since DURATION]",
|
|
632
|
-
login:
|
|
720
|
+
login: loginUsage(),
|
|
633
721
|
logout: "Usage: meta-synergy logout",
|
|
634
722
|
whoami: "Usage: meta-synergy whoami",
|
|
635
723
|
reconnect: "Usage: meta-synergy reconnect",
|
|
636
724
|
doctor: "Usage: meta-synergy doctor",
|
|
725
|
+
mode: "Usage: meta-synergy mode <status|managed|standalone>",
|
|
637
726
|
collaboration: "Usage: meta-synergy collaboration <enable|disable|status>",
|
|
638
727
|
requests: "Usage: meta-synergy requests <list|show|approve|deny> [request-id]",
|
|
639
728
|
session: "Usage: meta-synergy session <status|kick|block>",
|
|
@@ -722,7 +811,10 @@ function isStatusResult(value: unknown): value is {
|
|
|
722
811
|
}
|
|
723
812
|
|
|
724
813
|
function isWhoamiResult(value: unknown): value is {
|
|
725
|
-
auth: { loggedIn: boolean; agentID: string | null }
|
|
814
|
+
auth: { loggedIn: boolean; agentID: string | null; source?: string | null }
|
|
815
|
+
mode?: string
|
|
816
|
+
ownership?: { local?: { activeOwnerID?: string | null; owned?: boolean } }
|
|
817
|
+
envID?: string | null
|
|
726
818
|
label: string | null
|
|
727
819
|
service: { running: boolean }
|
|
728
820
|
} {
|
|
@@ -782,10 +874,19 @@ function formatStatus(value: { auth: unknown; state: Record<string, unknown>; se
|
|
|
782
874
|
const state = value.state
|
|
783
875
|
const service = value.service
|
|
784
876
|
const currentSession = isObject(state.currentSession) ? state.currentSession : null
|
|
877
|
+
const ownerRegistry = isObject(state.ownerRegistry) ? state.ownerRegistry : undefined
|
|
878
|
+
const localOwnership = ownerRegistry && isObject(ownerRegistry.local) ? ownerRegistry.local : undefined
|
|
879
|
+
const sessionSummary = currentSession
|
|
880
|
+
? `${MetaSynergyDisplay.maybeIdentifier(currentSession.remoteAgentID, { unknown: "unknown" })} (${MetaSynergyDisplay.maybeIdentifier(currentSession.sessionID, { unknown: "unknown", hiddenReason: "policy" })})`
|
|
881
|
+
: "idle"
|
|
882
|
+
|
|
785
883
|
return [
|
|
884
|
+
`Mode: ${typeof state.runtimeMode === "string" ? state.runtimeMode : typeof (value as { mode?: unknown }).mode === "string" ? String((value as { mode?: unknown }).mode) : "unknown"}`,
|
|
885
|
+
`Local owner: ${MetaSynergyDisplay.maybeIdentifier(localOwnership?.activeOwnerID, { hiddenReason: "policy" })}`,
|
|
786
886
|
`Logged in: ${auth.loggedIn === true ? "yes" : "no"}`,
|
|
787
|
-
`Agent ID: ${
|
|
788
|
-
`
|
|
887
|
+
`Agent ID: ${MetaSynergyDisplay.maybeIdentifier(auth.agentID)}`,
|
|
888
|
+
`Auth source: ${typeof auth.source === "string" ? auth.source : "none"}`,
|
|
889
|
+
`Env ID: ${MetaSynergyDisplay.maybeIdentifier(state.envID, { hiddenReason: "policy" })}`,
|
|
789
890
|
`Label: ${typeof state.label === "string" ? state.label : "none"}`,
|
|
790
891
|
`Service: ${service.running === true ? "running" : "stopped"}`,
|
|
791
892
|
`PID: ${typeof service.pid === "number" ? String(service.pid) : "none"}`,
|
|
@@ -793,18 +894,25 @@ function formatStatus(value: { auth: unknown; state: Record<string, unknown>; se
|
|
|
793
894
|
`Collaboration: ${state.collaborationEnabled === true ? "enabled" : "disabled"}`,
|
|
794
895
|
`Approval: ${typeof state.approvalMode === "string" ? state.approvalMode : "unknown"}`,
|
|
795
896
|
`Pending requests: ${Array.isArray(state.pendingRequests) ? state.pendingRequests.filter((request) => isObject(request) && request.status === "pending").length : 0}`,
|
|
796
|
-
`Session: ${
|
|
897
|
+
`Session: ${sessionSummary}`,
|
|
797
898
|
].join("\n")
|
|
798
899
|
}
|
|
799
900
|
|
|
800
901
|
function formatWhoami(value: {
|
|
801
|
-
auth: { loggedIn: boolean; agentID: string | null }
|
|
902
|
+
auth: { loggedIn: boolean; agentID: string | null; source?: string | null }
|
|
903
|
+
mode?: string
|
|
904
|
+
ownership?: { local?: { activeOwnerID?: string | null } }
|
|
905
|
+
envID?: string | null
|
|
802
906
|
label: string | null
|
|
803
907
|
service: { running: boolean }
|
|
804
908
|
}) {
|
|
805
909
|
return [
|
|
910
|
+
`Mode: ${value.mode ?? "unknown"}`,
|
|
911
|
+
`Local owner: ${MetaSynergyDisplay.maybeIdentifier(value.ownership?.local?.activeOwnerID, { hiddenReason: "policy" })}`,
|
|
806
912
|
`Logged in: ${value.auth.loggedIn ? "yes" : "no"}`,
|
|
807
|
-
`Agent ID: ${value.auth.agentID
|
|
913
|
+
`Agent ID: ${MetaSynergyDisplay.maybeIdentifier(value.auth.agentID)}`,
|
|
914
|
+
`Env ID: ${MetaSynergyDisplay.maybeIdentifier(value.envID)}`,
|
|
915
|
+
`Auth source: ${value.auth.source ?? "none"}`,
|
|
808
916
|
`Label: ${value.label ?? "none"}`,
|
|
809
917
|
`Service: ${value.service.running ? "running" : "stopped"}`,
|
|
810
918
|
].join("\n")
|
|
@@ -817,9 +925,9 @@ function formatRequests(requests: Array<Record<string, unknown>>) {
|
|
|
817
925
|
|
|
818
926
|
function formatRequest(request: Record<string, unknown>) {
|
|
819
927
|
return [
|
|
820
|
-
`Request ID: ${
|
|
821
|
-
`Caller: ${
|
|
822
|
-
`Owner User: ${
|
|
928
|
+
`Request ID: ${MetaSynergyDisplay.maybeIdentifier(request.id, { unknown: "unknown", hiddenReason: "policy" })}`,
|
|
929
|
+
`Caller: ${MetaSynergyDisplay.maybeIdentifier(request.callerAgentID, { unknown: "unknown", hiddenReason: "policy" })}`,
|
|
930
|
+
`Owner User: ${request.callerOwnerUserID == null ? "none" : String(request.callerOwnerUserID)}`,
|
|
823
931
|
`Label: ${typeof request.label === "string" ? request.label : "none"}`,
|
|
824
932
|
`Status: ${String(request.status ?? "unknown")}`,
|
|
825
933
|
`Count: ${String(request.requestCount ?? 1)}`,
|
|
@@ -828,9 +936,9 @@ function formatRequest(request: Record<string, unknown>) {
|
|
|
828
936
|
|
|
829
937
|
function formatTrust(value: { agents: string[]; users: number[]; blockedAgents?: string[] }) {
|
|
830
938
|
return [
|
|
831
|
-
`Trusted agents: ${
|
|
939
|
+
`Trusted agents: ${MetaSynergyDisplay.identifierList(value.agents, { hiddenReason: "policy" })}`,
|
|
832
940
|
`Trusted users: ${value.users.length > 0 ? value.users.join(", ") : "none"}`,
|
|
833
|
-
`Blocked agents: ${
|
|
941
|
+
`Blocked agents: ${MetaSynergyDisplay.identifierList(value.blockedAgents, { hiddenReason: "policy" })}`,
|
|
834
942
|
].join("\n")
|
|
835
943
|
}
|
|
836
944
|
|
|
@@ -840,9 +948,9 @@ function formatSessionStatus(value: {
|
|
|
840
948
|
service: Record<string, unknown>
|
|
841
949
|
}) {
|
|
842
950
|
return [
|
|
843
|
-
`Session: ${value.session ?
|
|
844
|
-
`Remote agent: ${value.session ?
|
|
845
|
-
`Blocked agents: ${
|
|
951
|
+
`Session: ${value.session ? MetaSynergyDisplay.maybeIdentifier(value.session.sessionID, { unknown: "unknown", hiddenReason: "policy" }) : "idle"}`,
|
|
952
|
+
`Remote agent: ${value.session ? MetaSynergyDisplay.maybeIdentifier(value.session.remoteAgentID, { unknown: "unknown", hiddenReason: "policy" }) : "none"}`,
|
|
953
|
+
`Blocked agents: ${MetaSynergyDisplay.identifierList(value.blockedAgentIDs, { hiddenReason: "policy" })}`,
|
|
846
954
|
`Service: ${value.service.running === true ? "running" : "stopped"}`,
|
|
847
955
|
].join("\n")
|
|
848
956
|
}
|
|
@@ -857,7 +965,7 @@ function formatCollaborationStatus(value: {
|
|
|
857
965
|
`Enabled: ${value.enabled ? "yes" : "no"}`,
|
|
858
966
|
`Approval: ${value.approvalMode}`,
|
|
859
967
|
`Pending requests: ${value.pendingRequestCount}`,
|
|
860
|
-
`Session: ${value.session ?
|
|
968
|
+
`Session: ${value.session ? MetaSynergyDisplay.maybeIdentifier(value.session.remoteAgentID ?? value.session.sessionID, { unknown: "busy", hiddenReason: "policy" }) : "idle"}`,
|
|
861
969
|
].join("\n")
|
|
862
970
|
}
|
|
863
971
|
|
|
@@ -868,6 +976,43 @@ function formatDoctor(value: { ok: boolean; checks: Array<{ name: string; ok: bo
|
|
|
868
976
|
].join("\n")
|
|
869
977
|
}
|
|
870
978
|
|
|
979
|
+
function loginUsage() {
|
|
980
|
+
return [
|
|
981
|
+
"Usage: meta-synergy login [--agent-id ID --agent-secret SECRET]",
|
|
982
|
+
"",
|
|
983
|
+
"Without flags, interactive TTY sessions let you choose browser login or importing existing credentials.",
|
|
984
|
+
].join("\n")
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
function parseLoginArgs(args: string[]): { ok: true; options: MetaSynergyLoginOptions } | { ok: false; usage: string } {
|
|
988
|
+
const options: MetaSynergyLoginOptions = {}
|
|
989
|
+
|
|
990
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
991
|
+
const token = args[index]
|
|
992
|
+
if (token === "--agent-id") {
|
|
993
|
+
const next = args[index + 1]
|
|
994
|
+
if (!next || next.startsWith("-")) {
|
|
995
|
+
return { ok: false, usage: loginUsage() }
|
|
996
|
+
}
|
|
997
|
+
options.agentID = next
|
|
998
|
+
index += 1
|
|
999
|
+
continue
|
|
1000
|
+
}
|
|
1001
|
+
if (token === "--agent-secret") {
|
|
1002
|
+
const next = args[index + 1]
|
|
1003
|
+
if (!next || next.startsWith("-")) {
|
|
1004
|
+
return { ok: false, usage: loginUsage() }
|
|
1005
|
+
}
|
|
1006
|
+
options.agentSecret = next
|
|
1007
|
+
index += 1
|
|
1008
|
+
continue
|
|
1009
|
+
}
|
|
1010
|
+
return { ok: false, usage: loginUsage() }
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
return { ok: true, options }
|
|
1014
|
+
}
|
|
1015
|
+
|
|
871
1016
|
function parseLogsArgs(
|
|
872
1017
|
args: string[],
|
|
873
1018
|
): { ok: true; follow: boolean; tailLines?: number; since?: string } | { ok: false; usage: string } {
|
package/src/control/schema.ts
CHANGED
|
@@ -23,6 +23,26 @@ export const ControlRequestSchema = z.discriminatedUnion("action", [
|
|
|
23
23
|
z.object({ action: z.literal("service.status") }),
|
|
24
24
|
z.object({ action: z.literal("service.stop") }),
|
|
25
25
|
z.object({ action: z.literal("runtime.status") }),
|
|
26
|
+
z.object({ action: z.literal("runtime.mode") }),
|
|
27
|
+
z.object({ action: z.literal("runtime.enter_managed") }),
|
|
28
|
+
z.object({
|
|
29
|
+
action: z.literal("runtime.enter_managed_mode"),
|
|
30
|
+
owner: z.string().optional(),
|
|
31
|
+
ownerAgentId: z.string().optional(),
|
|
32
|
+
phase: z.number().optional(),
|
|
33
|
+
}),
|
|
34
|
+
z.object({
|
|
35
|
+
action: z.literal("runtime.set_mode"),
|
|
36
|
+
mode: z.enum(["managed", "standalone"]),
|
|
37
|
+
owner: z.string().optional(),
|
|
38
|
+
ownerAgentId: z.string().optional(),
|
|
39
|
+
leaseExpiresAt: z.number().optional(),
|
|
40
|
+
}),
|
|
41
|
+
z.object({
|
|
42
|
+
action: z.literal("runtime.release_managed"),
|
|
43
|
+
owner: z.string().optional(),
|
|
44
|
+
ownerAgentId: z.string().optional(),
|
|
45
|
+
}),
|
|
26
46
|
z.object({ action: z.literal("runtime.reconnect") }),
|
|
27
47
|
z.object({ action: z.literal("collaboration.status") }),
|
|
28
48
|
z.object({ action: z.literal("collaboration.set"), enabled: z.boolean() }),
|
|
@@ -32,6 +52,11 @@ export const ControlRequestSchema = z.discriminatedUnion("action", [
|
|
|
32
52
|
z.object({ action: z.literal("requests.deny"), requestID: z.string() }),
|
|
33
53
|
z.object({ action: z.literal("session.status") }),
|
|
34
54
|
z.object({ action: z.literal("session.kick"), block: z.boolean().optional() }),
|
|
55
|
+
z.object({
|
|
56
|
+
action: z.literal("meta.execute"),
|
|
57
|
+
caller: z.unknown(),
|
|
58
|
+
body: z.unknown(),
|
|
59
|
+
}),
|
|
35
60
|
z.object({ action: z.literal("approval.get") }),
|
|
36
61
|
z.object({ action: z.literal("approval.set"), mode: z.enum(["auto", "manual", "trusted-only"]) }),
|
|
37
62
|
z.object({ action: z.literal("trust.list") }),
|