@a5c-ai/agent-mux-adapters 0.2.0
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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/adapter-install.d.ts +21 -0
- package/dist/adapter-install.d.ts.map +1 -0
- package/dist/adapter-install.js +114 -0
- package/dist/adapter-install.js.map +1 -0
- package/dist/agent-mux-remote-adapter.d.ts +66 -0
- package/dist/agent-mux-remote-adapter.d.ts.map +1 -0
- package/dist/agent-mux-remote-adapter.js +283 -0
- package/dist/agent-mux-remote-adapter.js.map +1 -0
- package/dist/auth-config.d.ts +14 -0
- package/dist/auth-config.d.ts.map +1 -0
- package/dist/auth-config.js +52 -0
- package/dist/auth-config.js.map +1 -0
- package/dist/base-adapter.d.ts +150 -0
- package/dist/base-adapter.d.ts.map +1 -0
- package/dist/base-adapter.js +458 -0
- package/dist/base-adapter.js.map +1 -0
- package/dist/claude-adapter.d.ts +52 -0
- package/dist/claude-adapter.d.ts.map +1 -0
- package/dist/claude-adapter.js +375 -0
- package/dist/claude-adapter.js.map +1 -0
- package/dist/codex-adapter.d.ts +26 -0
- package/dist/codex-adapter.d.ts.map +1 -0
- package/dist/codex-adapter.js +243 -0
- package/dist/codex-adapter.js.map +1 -0
- package/dist/copilot-adapter.d.ts +26 -0
- package/dist/copilot-adapter.d.ts.map +1 -0
- package/dist/copilot-adapter.js +199 -0
- package/dist/copilot-adapter.js.map +1 -0
- package/dist/cursor-adapter.d.ts +39 -0
- package/dist/cursor-adapter.d.ts.map +1 -0
- package/dist/cursor-adapter.js +247 -0
- package/dist/cursor-adapter.js.map +1 -0
- package/dist/gemini-adapter.d.ts +36 -0
- package/dist/gemini-adapter.d.ts.map +1 -0
- package/dist/gemini-adapter.js +287 -0
- package/dist/gemini-adapter.js.map +1 -0
- package/dist/hermes-adapter.d.ts +33 -0
- package/dist/hermes-adapter.d.ts.map +1 -0
- package/dist/hermes-adapter.js +269 -0
- package/dist/hermes-adapter.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp-plugins.d.ts +13 -0
- package/dist/mcp-plugins.d.ts.map +1 -0
- package/dist/mcp-plugins.js +63 -0
- package/dist/mcp-plugins.js.map +1 -0
- package/dist/omp-adapter.d.ts +26 -0
- package/dist/omp-adapter.d.ts.map +1 -0
- package/dist/omp-adapter.js +195 -0
- package/dist/omp-adapter.js.map +1 -0
- package/dist/openclaw-adapter.d.ts +30 -0
- package/dist/openclaw-adapter.d.ts.map +1 -0
- package/dist/openclaw-adapter.js +212 -0
- package/dist/openclaw-adapter.js.map +1 -0
- package/dist/opencode-adapter.d.ts +30 -0
- package/dist/opencode-adapter.d.ts.map +1 -0
- package/dist/opencode-adapter.js +231 -0
- package/dist/opencode-adapter.js.map +1 -0
- package/dist/pi-adapter.d.ts +26 -0
- package/dist/pi-adapter.d.ts.map +1 -0
- package/dist/pi-adapter.js +196 -0
- package/dist/pi-adapter.js.map +1 -0
- package/dist/qwen-adapter.d.ts +36 -0
- package/dist/qwen-adapter.d.ts.map +1 -0
- package/dist/qwen-adapter.js +257 -0
- package/dist/qwen-adapter.js.map +1 -0
- package/dist/session-fs.d.ts +83 -0
- package/dist/session-fs.d.ts.map +1 -0
- package/dist/session-fs.js +255 -0
- package/dist/session-fs.js.map +1 -0
- package/package.json +56 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 a5c-ai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @a5c-ai/agent-mux-adapters
|
|
2
|
+
|
|
3
|
+
Built-in agent adapters for [agent-mux](https://github.com/a5c-ai/agent-mux): `claude-code`, `codex`, `gemini`, `copilot`, `cursor`, `opencode`, `pi`, `omp`, `openclaw`, `hermes`, plus a remote `agent-mux` adapter.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @a5c-ai/agent-mux-adapters @a5c-ai/agent-mux-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Requires Node.js >= 20.9.0. ESM-only.
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { registerBuiltinAdapters } from '@a5c-ai/agent-mux-adapters';
|
|
17
|
+
import { defaultRegistry } from '@a5c-ai/agent-mux-core';
|
|
18
|
+
|
|
19
|
+
registerBuiltinAdapters(defaultRegistry);
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
See the [repository README](https://github.com/a5c-ai/agent-mux#readme) for full documentation.
|
|
23
|
+
|
|
24
|
+
## License
|
|
25
|
+
|
|
26
|
+
MIT © a5c-ai
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install/update helpers for BaseAgentAdapter.
|
|
3
|
+
*
|
|
4
|
+
* The install and update flows share the "pick method → resolve command →
|
|
5
|
+
* spawn → re-detect" skeleton. Extracted here so the base class stays
|
|
6
|
+
* small; no behavior change.
|
|
7
|
+
*/
|
|
8
|
+
import type { AdapterInstallOptions, AdapterUpdateOptions, DetectInstallationResult, InstallMethod, InstallResult, Spawner } from '@a5c-ai/agent-mux-core';
|
|
9
|
+
/** Collaborators the helpers need from the adapter. */
|
|
10
|
+
export interface InstallContext {
|
|
11
|
+
readonly cliCommand: string;
|
|
12
|
+
readonly displayName: string;
|
|
13
|
+
readonly spawner: Spawner;
|
|
14
|
+
detectInstallation(): Promise<DetectInstallationResult>;
|
|
15
|
+
pickInstallMethod(): InstallMethod | undefined;
|
|
16
|
+
applyVersionToCommand(method: InstallMethod, version?: string): string;
|
|
17
|
+
deriveUpdateCommand(method: InstallMethod): string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function runInstall(ctx: InstallContext, opts: AdapterInstallOptions): Promise<InstallResult>;
|
|
20
|
+
export declare function runUpdate(ctx: InstallContext, opts: AdapterUpdateOptions): Promise<InstallResult>;
|
|
21
|
+
//# sourceMappingURL=adapter-install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-install.d.ts","sourceRoot":"","sources":["../src/adapter-install.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,aAAa,EACb,aAAa,EACb,OAAO,EACR,MAAM,wBAAwB,CAAC;AAEhC,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,kBAAkB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IACxD,iBAAiB,IAAI,aAAa,GAAG,SAAS,CAAC;IAC/C,qBAAqB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvE,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAAC;CAC3D;AAuCD,wBAAsB,UAAU,CAC9B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,aAAa,CAAC,CA8CxB;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,aAAa,CAAC,CA+BxB"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install/update helpers for BaseAgentAdapter.
|
|
3
|
+
*
|
|
4
|
+
* The install and update flows share the "pick method → resolve command →
|
|
5
|
+
* spawn → re-detect" skeleton. Extracted here so the base class stays
|
|
6
|
+
* small; no behavior change.
|
|
7
|
+
*/
|
|
8
|
+
import * as os from 'node:os';
|
|
9
|
+
async function executeCommand(ctx, method, command) {
|
|
10
|
+
const parts = command.split(/\s+/).filter(Boolean);
|
|
11
|
+
const [cmd, ...argv] = parts;
|
|
12
|
+
let runResult;
|
|
13
|
+
try {
|
|
14
|
+
runResult = await ctx.spawner(cmd, argv);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
return {
|
|
18
|
+
ok: false,
|
|
19
|
+
method: method.type,
|
|
20
|
+
command,
|
|
21
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
const ok = runResult.code === 0;
|
|
25
|
+
let installedVersion;
|
|
26
|
+
if (ok) {
|
|
27
|
+
const det = await ctx.detectInstallation().catch(() => null);
|
|
28
|
+
if (det?.version)
|
|
29
|
+
installedVersion = det.version;
|
|
30
|
+
}
|
|
31
|
+
const result = {
|
|
32
|
+
ok,
|
|
33
|
+
method: method.type,
|
|
34
|
+
command,
|
|
35
|
+
stdout: runResult.stdout,
|
|
36
|
+
stderr: runResult.stderr,
|
|
37
|
+
};
|
|
38
|
+
if (installedVersion)
|
|
39
|
+
result.installedVersion = installedVersion;
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
export async function runInstall(ctx, opts) {
|
|
43
|
+
if (!opts.force && !opts.dryRun) {
|
|
44
|
+
const existing = await ctx.detectInstallation();
|
|
45
|
+
if (existing.installed) {
|
|
46
|
+
const r = {
|
|
47
|
+
ok: true,
|
|
48
|
+
method: 'already-installed',
|
|
49
|
+
command: '',
|
|
50
|
+
message: `${ctx.cliCommand} is already installed${existing.version ? ` (${existing.version})` : ''}`,
|
|
51
|
+
};
|
|
52
|
+
if (existing.version)
|
|
53
|
+
r.installedVersion = existing.version;
|
|
54
|
+
return r;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const method = ctx.pickInstallMethod();
|
|
58
|
+
if (!method) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
method: 'none',
|
|
62
|
+
command: '',
|
|
63
|
+
message: `No compatible install method for platform ${os.platform()}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (method.type === 'manual') {
|
|
67
|
+
return {
|
|
68
|
+
ok: false,
|
|
69
|
+
method: 'manual',
|
|
70
|
+
command: method.command,
|
|
71
|
+
message: `${ctx.displayName} must be installed manually: ${method.command}`,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
const command = ctx.applyVersionToCommand(method, opts.version);
|
|
75
|
+
if (opts.dryRun) {
|
|
76
|
+
return {
|
|
77
|
+
ok: true,
|
|
78
|
+
method: method.type,
|
|
79
|
+
command,
|
|
80
|
+
message: `[dry-run] would execute: ${command}`,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return executeCommand(ctx, method, command);
|
|
84
|
+
}
|
|
85
|
+
export async function runUpdate(ctx, opts) {
|
|
86
|
+
const method = ctx.pickInstallMethod();
|
|
87
|
+
if (!method) {
|
|
88
|
+
return {
|
|
89
|
+
ok: false,
|
|
90
|
+
method: 'none',
|
|
91
|
+
command: '',
|
|
92
|
+
message: `No compatible update method for platform ${os.platform()}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const command = ctx.deriveUpdateCommand(method);
|
|
96
|
+
if (!command) {
|
|
97
|
+
return {
|
|
98
|
+
ok: false,
|
|
99
|
+
method: method.type,
|
|
100
|
+
command: method.command,
|
|
101
|
+
message: `Update not supported for method "${method.type}". Install command: ${method.command}`,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
if (opts.dryRun) {
|
|
105
|
+
return {
|
|
106
|
+
ok: true,
|
|
107
|
+
method: method.type,
|
|
108
|
+
command,
|
|
109
|
+
message: `[dry-run] would execute: ${command}`,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return executeCommand(ctx, method, command);
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=adapter-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter-install.js","sourceRoot":"","sources":["../src/adapter-install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentMuxRemoteAdapter — pass-through adapter that delegates to another
|
|
3
|
+
* `amux` CLI installation. Transport is out of scope: this adapter emits
|
|
4
|
+
* plain `amux run ...` spawn args, and the caller wraps them with the
|
|
5
|
+
* desired invocation mode (local/docker/ssh/k8s) via
|
|
6
|
+
* `buildInvocationCommand()`.
|
|
7
|
+
*
|
|
8
|
+
* This lets agent-mux nest: a local amux invocation dispatches to a second
|
|
9
|
+
* amux executing in a docker container, on a remote SSH host, or in a k8s
|
|
10
|
+
* pod. All structured events are forwarded verbatim — the remote `amux run`
|
|
11
|
+
* emits JSONL which we pass through unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Configuration is read from RunOptions.env:
|
|
14
|
+
* AMUX_REMOTE_AGENT — agent name to invoke on the remote (default: claude)
|
|
15
|
+
*
|
|
16
|
+
* The transport-specific bits (host, identity file, docker image, ...) live
|
|
17
|
+
* on `RunOptions.invocation` — not on this adapter.
|
|
18
|
+
*/
|
|
19
|
+
import type { AgentCapabilities, ModelCapabilities, AgentConfigSchema, AuthState, AuthSetupGuidance, Session, SpawnArgs, ParseContext, RunOptions, AgentEvent, AgentConfig } from '@a5c-ai/agent-mux-core';
|
|
20
|
+
import { BaseAgentAdapter } from './base-adapter.js';
|
|
21
|
+
export declare class AgentMuxRemoteAdapter extends BaseAgentAdapter {
|
|
22
|
+
readonly agent: "agent-mux-remote";
|
|
23
|
+
readonly displayName = "agent-mux (remote via invocation mode)";
|
|
24
|
+
readonly cliCommand = "amux";
|
|
25
|
+
readonly minVersion = "0.1.0";
|
|
26
|
+
readonly hostEnvSignals: readonly [];
|
|
27
|
+
readonly capabilities: AgentCapabilities;
|
|
28
|
+
readonly models: ModelCapabilities[];
|
|
29
|
+
readonly defaultModelId: undefined;
|
|
30
|
+
readonly configSchema: AgentConfigSchema;
|
|
31
|
+
/** Resolve the remote agent name (which agent to invoke inside the nested amux). */
|
|
32
|
+
private resolveRemoteAgent;
|
|
33
|
+
/**
|
|
34
|
+
* Emit `amux run --json --agent <agent> --prompt <...>` args.
|
|
35
|
+
*
|
|
36
|
+
* The caller is responsible for wrapping these with an invocation mode
|
|
37
|
+
* (ssh/docker/k8s) via `buildInvocationCommand()`. This keeps the adapter
|
|
38
|
+
* transport-agnostic so the same binary can be used inside a docker
|
|
39
|
+
* container, on a remote SSH host, or in a k8s pod.
|
|
40
|
+
*/
|
|
41
|
+
buildSpawnArgs(options: RunOptions): SpawnArgs;
|
|
42
|
+
parseEvent(line: string, context: ParseContext): AgentEvent | AgentEvent[] | null;
|
|
43
|
+
/** Detect version via the local spawner running plain `amux --version`. */
|
|
44
|
+
detectVersion(): Promise<string | null>;
|
|
45
|
+
protected detectVersionFromCli(): Promise<string | null>;
|
|
46
|
+
detectAuth(): Promise<AuthState>;
|
|
47
|
+
getAuthGuidance(): AuthSetupGuidance;
|
|
48
|
+
sessionDir(_cwd?: string): string;
|
|
49
|
+
parseSessionFile(_filePath: string): Promise<Session>;
|
|
50
|
+
/** List remote sessions via plain `amux sessions list --json` (transport is external). */
|
|
51
|
+
listSessionFiles(_cwd?: string): Promise<string[]>;
|
|
52
|
+
readConfig(_cwd?: string): Promise<AgentConfig>;
|
|
53
|
+
writeConfig(_config: Partial<AgentConfig>, _cwd?: string): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Detect whether `amux` is available at the current spawner scope (local or
|
|
56
|
+
* wrapped). The wrapper — docker/ssh/k8s — is applied externally.
|
|
57
|
+
*/
|
|
58
|
+
detectInstallation(): Promise<import('@a5c-ai/agent-mux-core').DetectInstallationResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Install amux via `npm install -g @a5c-ai/agent-mux-cli`.
|
|
61
|
+
* Transport wrapping (ssh/docker/k8s) is the caller's responsibility.
|
|
62
|
+
*/
|
|
63
|
+
install(opts?: import('@a5c-ai/agent-mux-core').AdapterInstallOptions): Promise<import('@a5c-ai/agent-mux-core').InstallResult>;
|
|
64
|
+
update(opts?: import('@a5c-ai/agent-mux-core').AdapterUpdateOptions): Promise<import('@a5c-ai/agent-mux-core').InstallResult>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=agent-mux-remote-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-mux-remote-adapter.d.ts","sourceRoot":"","sources":["../src/agent-mux-remote-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,SAAS,EACT,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACZ,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,qBAAa,qBAAsB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,KAAK,EAAG,kBAAkB,CAAU;IAC7C,QAAQ,CAAC,WAAW,4CAA4C;IAChE,QAAQ,CAAC,UAAU,UAAU;IAC7B,QAAQ,CAAC,UAAU,WAAW;IAC9B,QAAQ,CAAC,cAAc,cAAe;IAEtC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CA0CtC;IAEF,QAAQ,CAAC,MAAM,EAAE,iBAAiB,EAAE,CAAM;IAC1C,QAAQ,CAAC,cAAc,YAAa;IAEpC,QAAQ,CAAC,YAAY,EAAE,iBAAiB,CAOtC;IAEF,oFAAoF;IACpF,OAAO,CAAC,kBAAkB;IAK1B;;;;;;;OAOG;IACH,cAAc,CAAC,OAAO,EAAE,UAAU,GAAG,SAAS;IAsB9C,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI;IAajF,2EAA2E;IACrE,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;cAWpB,oBAAoB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIjE,UAAU,IAAI,OAAO,CAAC,SAAS,CAAC;IAQtC,eAAe,IAAI,iBAAiB;IAiBpC,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM;IAI3B,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3D,0FAA0F;IACpF,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAqBlD,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAI/C,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9E;;;OAGG;IACY,kBAAkB,IAAI,OAAO,CAAC,OAAO,wBAAwB,EAAE,wBAAwB,CAAC;IAqBvG;;;OAGG;IACY,OAAO,CACpB,IAAI,GAAE,OAAO,wBAAwB,EAAE,qBAA0B,GAChE,OAAO,CAAC,OAAO,wBAAwB,EAAE,aAAa,CAAC;IAwB3C,MAAM,CACnB,IAAI,GAAE,OAAO,wBAAwB,EAAE,oBAAyB,GAC/D,OAAO,CAAC,OAAO,wBAAwB,EAAE,aAAa,CAAC;CAuB3D"}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentMuxRemoteAdapter — pass-through adapter that delegates to another
|
|
3
|
+
* `amux` CLI installation. Transport is out of scope: this adapter emits
|
|
4
|
+
* plain `amux run ...` spawn args, and the caller wraps them with the
|
|
5
|
+
* desired invocation mode (local/docker/ssh/k8s) via
|
|
6
|
+
* `buildInvocationCommand()`.
|
|
7
|
+
*
|
|
8
|
+
* This lets agent-mux nest: a local amux invocation dispatches to a second
|
|
9
|
+
* amux executing in a docker container, on a remote SSH host, or in a k8s
|
|
10
|
+
* pod. All structured events are forwarded verbatim — the remote `amux run`
|
|
11
|
+
* emits JSONL which we pass through unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Configuration is read from RunOptions.env:
|
|
14
|
+
* AMUX_REMOTE_AGENT — agent name to invoke on the remote (default: claude)
|
|
15
|
+
*
|
|
16
|
+
* The transport-specific bits (host, identity file, docker image, ...) live
|
|
17
|
+
* on `RunOptions.invocation` — not on this adapter.
|
|
18
|
+
*/
|
|
19
|
+
import { BaseAgentAdapter } from './base-adapter.js';
|
|
20
|
+
export class AgentMuxRemoteAdapter extends BaseAgentAdapter {
|
|
21
|
+
agent = 'agent-mux-remote';
|
|
22
|
+
displayName = 'agent-mux (remote via invocation mode)';
|
|
23
|
+
cliCommand = 'amux';
|
|
24
|
+
minVersion = '0.1.0';
|
|
25
|
+
hostEnvSignals = [];
|
|
26
|
+
capabilities = {
|
|
27
|
+
agent: 'agent-mux-remote',
|
|
28
|
+
canResume: true,
|
|
29
|
+
canFork: false,
|
|
30
|
+
supportsMultiTurn: true,
|
|
31
|
+
sessionPersistence: 'none',
|
|
32
|
+
supportsTextStreaming: true,
|
|
33
|
+
supportsToolCallStreaming: true,
|
|
34
|
+
supportsThinkingStreaming: true,
|
|
35
|
+
supportsNativeTools: true,
|
|
36
|
+
supportsMCP: false,
|
|
37
|
+
supportsParallelToolCalls: true,
|
|
38
|
+
requiresToolApproval: false,
|
|
39
|
+
approvalModes: ['yolo', 'prompt', 'deny'],
|
|
40
|
+
supportsThinking: true,
|
|
41
|
+
thinkingEffortLevels: ['low', 'medium', 'high'],
|
|
42
|
+
supportsThinkingBudgetTokens: true,
|
|
43
|
+
supportsJsonMode: true,
|
|
44
|
+
supportsStructuredOutput: true,
|
|
45
|
+
supportsSkills: false,
|
|
46
|
+
supportsAgentsMd: false,
|
|
47
|
+
skillsFormat: null,
|
|
48
|
+
supportsSubagentDispatch: true,
|
|
49
|
+
supportsParallelExecution: true,
|
|
50
|
+
supportsInteractiveMode: false,
|
|
51
|
+
supportsStdinInjection: true,
|
|
52
|
+
supportsImageInput: false,
|
|
53
|
+
supportsImageOutput: false,
|
|
54
|
+
supportsFileAttachments: false,
|
|
55
|
+
supportsPlugins: false,
|
|
56
|
+
pluginFormats: [],
|
|
57
|
+
pluginRegistries: [],
|
|
58
|
+
supportedPlatforms: ['darwin', 'linux', 'win32'],
|
|
59
|
+
requiresGitRepo: false,
|
|
60
|
+
requiresPty: false,
|
|
61
|
+
authMethods: [
|
|
62
|
+
{ type: 'api_key', name: 'Transport', description: 'Handled by invocation mode (local/docker/ssh/k8s).' },
|
|
63
|
+
],
|
|
64
|
+
authFiles: [],
|
|
65
|
+
installMethods: [
|
|
66
|
+
{ platform: 'all', type: 'manual', command: 'Install amux on the target (see `amux remote install <host>`).' },
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
models = [];
|
|
70
|
+
defaultModelId = undefined;
|
|
71
|
+
configSchema = {
|
|
72
|
+
agent: 'agent-mux-remote',
|
|
73
|
+
version: 1,
|
|
74
|
+
fields: [],
|
|
75
|
+
configFilePaths: [],
|
|
76
|
+
configFormat: 'json',
|
|
77
|
+
supportsProjectConfig: false,
|
|
78
|
+
};
|
|
79
|
+
/** Resolve the remote agent name (which agent to invoke inside the nested amux). */
|
|
80
|
+
resolveRemoteAgent(options) {
|
|
81
|
+
const env = options.env ?? {};
|
|
82
|
+
return env['AMUX_REMOTE_AGENT'] ?? process.env['AMUX_REMOTE_AGENT'] ?? 'claude';
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Emit `amux run --json --agent <agent> --prompt <...>` args.
|
|
86
|
+
*
|
|
87
|
+
* The caller is responsible for wrapping these with an invocation mode
|
|
88
|
+
* (ssh/docker/k8s) via `buildInvocationCommand()`. This keeps the adapter
|
|
89
|
+
* transport-agnostic so the same binary can be used inside a docker
|
|
90
|
+
* container, on a remote SSH host, or in a k8s pod.
|
|
91
|
+
*/
|
|
92
|
+
buildSpawnArgs(options) {
|
|
93
|
+
const remoteAgent = this.resolveRemoteAgent(options);
|
|
94
|
+
const prompt = Array.isArray(options.prompt) ? options.prompt.join('\n') : options.prompt;
|
|
95
|
+
const args = ['run', '--json', '--agent', remoteAgent, '--prompt', prompt];
|
|
96
|
+
if (options.model)
|
|
97
|
+
args.push('--model', options.model);
|
|
98
|
+
if (options.sessionId)
|
|
99
|
+
args.push('--session', options.sessionId);
|
|
100
|
+
if (options.approvalMode === 'yolo')
|
|
101
|
+
args.push('--yolo');
|
|
102
|
+
if (options.approvalMode === 'deny')
|
|
103
|
+
args.push('--deny');
|
|
104
|
+
return {
|
|
105
|
+
command: this.cliCommand,
|
|
106
|
+
args,
|
|
107
|
+
env: this.buildEnvFromOptions(options),
|
|
108
|
+
cwd: options.cwd ?? process.cwd(),
|
|
109
|
+
usePty: false,
|
|
110
|
+
timeout: options.timeout,
|
|
111
|
+
inactivityTimeout: options.inactivityTimeout,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
parseEvent(line, context) {
|
|
115
|
+
const parsed = this.parseJsonLine(line);
|
|
116
|
+
if (parsed == null || typeof parsed !== 'object')
|
|
117
|
+
return null;
|
|
118
|
+
const obj = parsed;
|
|
119
|
+
const event = { ...obj };
|
|
120
|
+
if (typeof event['runId'] !== 'string')
|
|
121
|
+
event['runId'] = context.runId;
|
|
122
|
+
if (typeof event['timestamp'] !== 'number')
|
|
123
|
+
event['timestamp'] = Date.now();
|
|
124
|
+
event['agent'] = this.agent;
|
|
125
|
+
if (typeof event['type'] !== 'string')
|
|
126
|
+
return null;
|
|
127
|
+
return event;
|
|
128
|
+
}
|
|
129
|
+
/** Detect version via the local spawner running plain `amux --version`. */
|
|
130
|
+
async detectVersion() {
|
|
131
|
+
try {
|
|
132
|
+
const res = await this._spawner('amux', ['--version']);
|
|
133
|
+
if (res.code !== 0)
|
|
134
|
+
return null;
|
|
135
|
+
const match = (res.stdout + '\n' + res.stderr).match(/\d+\.\d+\.\d+(?:-[\w.]+)?/);
|
|
136
|
+
return match ? match[0] : null;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async detectVersionFromCli() {
|
|
143
|
+
return this.detectVersion();
|
|
144
|
+
}
|
|
145
|
+
async detectAuth() {
|
|
146
|
+
return {
|
|
147
|
+
status: 'authenticated',
|
|
148
|
+
method: 'transport',
|
|
149
|
+
identity: 'handled by invocation mode',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
getAuthGuidance() {
|
|
153
|
+
return {
|
|
154
|
+
agent: 'agent-mux-remote',
|
|
155
|
+
providerName: 'agent-mux (remote)',
|
|
156
|
+
steps: [
|
|
157
|
+
{ step: 1, description: 'Install amux on the target (local, remote SSH host, docker image, or k8s pod).' },
|
|
158
|
+
{ step: 2, description: 'Set RunOptions.invocation to select the transport (ssh/docker/k8s).' },
|
|
159
|
+
{ step: 3, description: 'Optionally set AMUX_REMOTE_AGENT to choose which agent the nested amux invokes.' },
|
|
160
|
+
],
|
|
161
|
+
envVars: [
|
|
162
|
+
{ name: 'AMUX_REMOTE_AGENT', description: 'Agent to invoke on the remote (default: claude)', required: false },
|
|
163
|
+
],
|
|
164
|
+
documentationUrls: [],
|
|
165
|
+
verifyCommand: 'amux --version',
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
sessionDir(_cwd) {
|
|
169
|
+
return '';
|
|
170
|
+
}
|
|
171
|
+
async parseSessionFile(_filePath) {
|
|
172
|
+
throw new Error('agent-mux-remote does not store sessions locally; use `amux sessions list` on the remote.');
|
|
173
|
+
}
|
|
174
|
+
/** List remote sessions via plain `amux sessions list --json` (transport is external). */
|
|
175
|
+
async listSessionFiles(_cwd) {
|
|
176
|
+
try {
|
|
177
|
+
const res = await this._spawner('amux', ['sessions', 'list', '--json']);
|
|
178
|
+
if (res.code !== 0)
|
|
179
|
+
return [];
|
|
180
|
+
const parsed = JSON.parse(res.stdout);
|
|
181
|
+
const data = Array.isArray(parsed) ? parsed : (parsed?.data ?? []);
|
|
182
|
+
if (!Array.isArray(data))
|
|
183
|
+
return [];
|
|
184
|
+
return data
|
|
185
|
+
.map((s) => {
|
|
186
|
+
if (s && typeof s === 'object') {
|
|
187
|
+
const sid = s['sessionId'] ?? s['id'];
|
|
188
|
+
return typeof sid === 'string' ? sid : null;
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
})
|
|
192
|
+
.filter((s) => typeof s === 'string');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async readConfig(_cwd) {
|
|
199
|
+
return { agent: 'agent-mux-remote', source: 'global' };
|
|
200
|
+
}
|
|
201
|
+
async writeConfig(_config, _cwd) {
|
|
202
|
+
/* No local config to write. */
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Detect whether `amux` is available at the current spawner scope (local or
|
|
206
|
+
* wrapped). The wrapper — docker/ssh/k8s — is applied externally.
|
|
207
|
+
*/
|
|
208
|
+
async detectInstallation() {
|
|
209
|
+
try {
|
|
210
|
+
const res = await this._spawner('amux', ['--version']);
|
|
211
|
+
if (res.code !== 0) {
|
|
212
|
+
return { installed: false, notes: `amux probe failed (code ${res.code})` };
|
|
213
|
+
}
|
|
214
|
+
const version = this.parseVersionOutput(res.stdout + '\n' + res.stderr);
|
|
215
|
+
const out = {
|
|
216
|
+
installed: true,
|
|
217
|
+
path: 'amux',
|
|
218
|
+
};
|
|
219
|
+
if (version)
|
|
220
|
+
out.version = version;
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
return {
|
|
225
|
+
installed: false,
|
|
226
|
+
notes: err instanceof Error ? `amux probe error: ${err.message}` : 'amux probe error',
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Install amux via `npm install -g @a5c-ai/agent-mux-cli`.
|
|
232
|
+
* Transport wrapping (ssh/docker/k8s) is the caller's responsibility.
|
|
233
|
+
*/
|
|
234
|
+
async install(opts = {}) {
|
|
235
|
+
const command = 'npm install -g @a5c-ai/agent-mux-cli';
|
|
236
|
+
if (opts.dryRun) {
|
|
237
|
+
return { ok: true, method: 'npm', command, message: `[dry-run] would execute: ${command}` };
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const res = await this._spawner('npm', ['install', '-g', '@a5c-ai/agent-mux-cli']);
|
|
241
|
+
return {
|
|
242
|
+
ok: res.code === 0,
|
|
243
|
+
method: 'npm',
|
|
244
|
+
command,
|
|
245
|
+
stdout: res.stdout,
|
|
246
|
+
stderr: res.stderr,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
return {
|
|
251
|
+
ok: false,
|
|
252
|
+
method: 'npm',
|
|
253
|
+
command,
|
|
254
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async update(opts = {}) {
|
|
259
|
+
const command = 'npm update -g @a5c-ai/agent-mux-cli';
|
|
260
|
+
if (opts.dryRun) {
|
|
261
|
+
return { ok: true, method: 'npm', command, message: `[dry-run] would execute: ${command}` };
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
const res = await this._spawner('npm', ['update', '-g', '@a5c-ai/agent-mux-cli']);
|
|
265
|
+
return {
|
|
266
|
+
ok: res.code === 0,
|
|
267
|
+
method: 'npm',
|
|
268
|
+
command,
|
|
269
|
+
stdout: res.stdout,
|
|
270
|
+
stderr: res.stderr,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
catch (err) {
|
|
274
|
+
return {
|
|
275
|
+
ok: false,
|
|
276
|
+
method: 'npm',
|
|
277
|
+
command,
|
|
278
|
+
stderr: err instanceof Error ? err.message : String(err),
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=agent-mux-remote-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-mux-remote-adapter.js","sourceRoot":"","sources":["../src/agent-mux-remote-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a set of candidate paths (supports `~/` prefix) against the user's
|
|
3
|
+
* home directory and return the first one that exists.
|
|
4
|
+
*/
|
|
5
|
+
export declare function findExistingAuthFile(candidates: string[]): Promise<string | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Read an agent auth config file (if present) and attempt to extract a
|
|
8
|
+
* recognizable token/email identity. Returns null if no candidate exists.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readAuthConfigIdentity(candidates: string[], tokenKeys?: string[]): Promise<{
|
|
11
|
+
filePath: string;
|
|
12
|
+
identity: string;
|
|
13
|
+
} | null>;
|
|
14
|
+
//# sourceMappingURL=auth-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-config.d.ts","sourceRoot":"","sources":["../src/auth-config.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcvF;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,UAAU,EAAE,MAAM,EAAE,EACpB,SAAS,GAAE,MAAM,EAAoF,GACpG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmBxD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as os from 'node:os';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { promises as fsp } from 'node:fs';
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a set of candidate paths (supports `~/` prefix) against the user's
|
|
6
|
+
* home directory and return the first one that exists.
|
|
7
|
+
*/
|
|
8
|
+
export async function findExistingAuthFile(candidates) {
|
|
9
|
+
const home = os.homedir();
|
|
10
|
+
for (const raw of candidates) {
|
|
11
|
+
const abs = raw.startsWith('~')
|
|
12
|
+
? path.join(home, raw.slice(raw.startsWith('~/') ? 2 : 1))
|
|
13
|
+
: raw;
|
|
14
|
+
try {
|
|
15
|
+
const st = await fsp.stat(abs);
|
|
16
|
+
if (st.isFile())
|
|
17
|
+
return abs;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// keep looking
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Read an agent auth config file (if present) and attempt to extract a
|
|
27
|
+
* recognizable token/email identity. Returns null if no candidate exists.
|
|
28
|
+
*/
|
|
29
|
+
export async function readAuthConfigIdentity(candidates, tokenKeys = ['apiKey', 'api_key', 'OPENAI_API_KEY', 'token', 'accessToken', 'access_token']) {
|
|
30
|
+
const filePath = await findExistingAuthFile(candidates);
|
|
31
|
+
if (!filePath)
|
|
32
|
+
return null;
|
|
33
|
+
let identity = path.basename(filePath);
|
|
34
|
+
try {
|
|
35
|
+
const raw = await fsp.readFile(filePath, 'utf8');
|
|
36
|
+
const parsed = JSON.parse(raw);
|
|
37
|
+
for (const k of tokenKeys) {
|
|
38
|
+
const v = parsed[k];
|
|
39
|
+
if (typeof v === 'string' && v.length > 4) {
|
|
40
|
+
identity = `...${v.slice(-4)}`;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (typeof parsed['email'] === 'string')
|
|
45
|
+
identity = parsed['email'];
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// opaque file; keep the basename identity
|
|
49
|
+
}
|
|
50
|
+
return { filePath, identity };
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=auth-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-config.js","sourceRoot":"","sources":["../src/auth-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,IAAI,GAAG,EAAE,MAAM,SAAS,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,UAAoB;IAC7D,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;YAC7B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1D,CAAC,CAAC,GAAG,CAAC;QACR,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC/B,IAAI,EAAE,CAAC,MAAM,EAAE;gBAAE,OAAO,GAAG,CAAC;QAC9B,CAAC;QAAC,MAAM,CAAC;YACP,eAAe;QACjB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAoB,EACpB,YAAsB,CAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,CAAC;IAErG,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACxD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA4B,CAAC;QAC1D,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1C,QAAQ,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/B,MAAM;YACR,CAAC;QACH,CAAC;QACD,IAAI,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,QAAQ;YAAE,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAW,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,0CAA0C;IAC5C,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAChC,CAAC"}
|