@ansible-flow/node 0.0.0-stage → 0.86.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 +9 -2
- package/dist/ai/agents.d.ts +34 -0
- package/dist/ai/agents.js +16 -0
- package/dist/ai/agents.js.map +7 -0
- package/dist/ai/hostConfig.d.ts +44 -0
- package/dist/ai/hostConfig.js +120 -0
- package/dist/ai/hostConfig.js.map +7 -0
- package/dist/ai/hosts.d.ts +28 -0
- package/dist/ai/hosts.js +9 -0
- package/dist/ai/hosts.js.map +7 -0
- package/dist/ai/writers.d.ts +124 -0
- package/dist/ai/writers.js +75 -0
- package/dist/ai/writers.js.map +7 -0
- package/dist/autoLayout.d.ts +38 -0
- package/dist/autoLayout.js +145 -0
- package/dist/autoLayout.js.map +7 -0
- package/dist/awx/awxWorkflow.d.ts +47 -0
- package/dist/awx/awxWorkflow.js +17 -0
- package/dist/awx/awxWorkflow.js.map +7 -0
- package/dist/awx/client.d.ts +77 -0
- package/dist/awx/client.js +22 -0
- package/dist/awx/client.js.map +7 -0
- package/dist/catalog/bindingCheck.d.ts +4 -0
- package/dist/catalog/bindingCheck.js +69 -0
- package/dist/catalog/bindingCheck.js.map +7 -0
- package/dist/catalog/catalogIndex.d.ts +52 -0
- package/dist/catalog/catalogIndex.js +13 -0
- package/dist/catalog/catalogIndex.js.map +7 -0
- package/dist/catalog/catalogWorker.d.ts +17 -0
- package/dist/catalog/catalogWorker.js +38 -0
- package/dist/catalog/catalogWorker.js.map +7 -0
- package/dist/catalog/dumpFiles.d.ts +3 -0
- package/dist/catalog/dumpFiles.js +19 -0
- package/dist/catalog/dumpFiles.js.map +7 -0
- package/dist/chunks/chunk-2MZQHIXP.js +614 -0
- package/dist/chunks/chunk-2MZQHIXP.js.map +7 -0
- package/dist/chunks/chunk-4FHPTGI4.js +52 -0
- package/dist/chunks/chunk-4FHPTGI4.js.map +7 -0
- package/dist/chunks/chunk-A2NMQGQE.js +189 -0
- package/dist/chunks/chunk-A2NMQGQE.js.map +7 -0
- package/dist/chunks/chunk-EPJKJBNW.js +181 -0
- package/dist/chunks/chunk-EPJKJBNW.js.map +7 -0
- package/dist/chunks/chunk-FG53MLUX.js +136 -0
- package/dist/chunks/chunk-FG53MLUX.js.map +7 -0
- package/dist/chunks/chunk-GAL5LW6Y.js +269 -0
- package/dist/chunks/chunk-GAL5LW6Y.js.map +7 -0
- package/dist/chunks/chunk-HPVT6I36.js +371 -0
- package/dist/chunks/chunk-HPVT6I36.js.map +7 -0
- package/dist/chunks/chunk-I6FIOP7G.js +48 -0
- package/dist/chunks/chunk-I6FIOP7G.js.map +7 -0
- package/dist/chunks/chunk-IIFP6UQR.js +44 -0
- package/dist/chunks/chunk-IIFP6UQR.js.map +7 -0
- package/dist/chunks/chunk-JDPN3LTT.js +18 -0
- package/dist/chunks/chunk-JDPN3LTT.js.map +7 -0
- package/dist/chunks/chunk-LGUG2Q7Z.js +191 -0
- package/dist/chunks/chunk-LGUG2Q7Z.js.map +7 -0
- package/dist/chunks/chunk-NTZRNEZM.js +25 -0
- package/dist/chunks/chunk-NTZRNEZM.js.map +7 -0
- package/dist/chunks/chunk-RETJPSKL.js +123 -0
- package/dist/chunks/chunk-RETJPSKL.js.map +7 -0
- package/dist/chunks/chunk-SSZNBJZQ.js +52 -0
- package/dist/chunks/chunk-SSZNBJZQ.js.map +7 -0
- package/dist/chunks/chunk-SUV3VHKR.js +52 -0
- package/dist/chunks/chunk-SUV3VHKR.js.map +7 -0
- package/dist/chunks/chunk-THNSGAKN.js +133 -0
- package/dist/chunks/chunk-THNSGAKN.js.map +7 -0
- package/dist/chunks/chunk-UNCR5JOZ.js +85 -0
- package/dist/chunks/chunk-UNCR5JOZ.js.map +7 -0
- package/dist/env/probeClient.d.ts +77 -0
- package/dist/env/probeClient.js +244 -0
- package/dist/env/probeClient.js.map +7 -0
- package/dist/env/userSettings.d.ts +33 -0
- package/dist/env/userSettings.js +101 -0
- package/dist/env/userSettings.js.map +7 -0
- package/dist/flowMerge.d.ts +35 -0
- package/dist/flowMerge.js +74 -0
- package/dist/flowMerge.js.map +7 -0
- package/dist/run/audit.d.ts +2 -0
- package/dist/run/audit.js +10 -0
- package/dist/run/audit.js.map +7 -0
- package/dist/run/exec.d.ts +14 -0
- package/dist/run/exec.js +7 -0
- package/dist/run/exec.js.map +7 -0
- package/dist/run/facts.d.ts +39 -0
- package/dist/run/facts.js +96 -0
- package/dist/run/facts.js.map +7 -0
- package/dist/run/ids.d.ts +2 -0
- package/dist/run/ids.js +8 -0
- package/dist/run/ids.js.map +7 -0
- package/dist/run/pastRuns.d.ts +9 -0
- package/dist/run/pastRuns.js +13 -0
- package/dist/run/pastRuns.js.map +7 -0
- package/dist/run/runFlow.d.ts +78 -0
- package/dist/run/runFlow.js +20 -0
- package/dist/run/runFlow.js.map +7 -0
- package/dist/run/segments.d.ts +43 -0
- package/dist/run/segments.js +157 -0
- package/dist/run/segments.js.map +7 -0
- package/dist/run/stop.d.ts +3 -0
- package/dist/run/stop.js +7 -0
- package/dist/run/stop.js.map +7 -0
- package/dist/run/storage.d.ts +16 -0
- package/dist/run/storage.js +15 -0
- package/dist/run/storage.js.map +7 -0
- package/dist/run/tail.d.ts +5 -0
- package/dist/run/tail.js +7 -0
- package/dist/run/tail.js.map +7 -0
- package/dist/runner/client.d.ts +149 -0
- package/dist/runner/client.js +168 -0
- package/dist/runner/client.js.map +7 -0
- package/dist/runner/devBundle.d.ts +14 -0
- package/dist/runner/devBundle.js +78 -0
- package/dist/runner/devBundle.js.map +7 -0
- package/dist/scenario/cli.d.ts +39 -0
- package/dist/scenario/cli.js +125 -0
- package/dist/scenario/cli.js.map +7 -0
- package/dist/scenario/runner.d.ts +50 -0
- package/dist/scenario/runner.js +185 -0
- package/dist/scenario/runner.js.map +7 -0
- package/dist/sharedRefs.d.ts +22 -0
- package/dist/sharedRefs.js +114 -0
- package/dist/sharedRefs.js.map +7 -0
- package/dist/ssh/exec.d.ts +39 -0
- package/dist/ssh/exec.js +13 -0
- package/dist/ssh/exec.js.map +7 -0
- package/dist/ssh/remote.d.ts +40 -0
- package/dist/ssh/remote.js +25 -0
- package/dist/ssh/remote.js.map +7 -0
- package/dist/ssh/sshRun.d.ts +1 -0
- package/dist/ssh/sshRun.js +24 -0
- package/dist/ssh/sshRun.js.map +7 -0
- package/dist/ssh/sync.d.ts +22 -0
- package/dist/ssh/sync.js +12 -0
- package/dist/ssh/sync.js.map +7 -0
- package/dist/timeouts.d.ts +38 -0
- package/dist/timeouts.js +7 -0
- package/dist/timeouts.js.map +7 -0
- package/package.json +35 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sergei Chistokhin
|
|
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
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @ansible-flow/node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Ansible Flow Designer for Node hosts: layout, the probe client, runs, the AWX client, the module catalog and SSH.
|
|
4
|
+
|
|
5
|
+
Built from [Ansible Flow Designer](https://github.com/ChistokhinSV/ansible-flow-designer) 0.86.0
|
|
6
|
+
and released with it. Modules are imported by their path in the source tree, for example
|
|
7
|
+
`@ansible-flow/node/ai/agents`.
|
|
8
|
+
|
|
9
|
+
What is in the package, which entry points are documented and what may change:
|
|
10
|
+
[docs/packages.md](https://github.com/ChistokhinSV/ansible-flow-designer/blob/main/docs/packages.md).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Agent, type Launch } from './writers';
|
|
2
|
+
export interface AgentInfo {
|
|
3
|
+
id: Agent;
|
|
4
|
+
label: string;
|
|
5
|
+
/** Where the skill and the tools go, for the pick list. */
|
|
6
|
+
detail: string;
|
|
7
|
+
bins: string[];
|
|
8
|
+
/** Paths under the home folder that only this agent creates. */
|
|
9
|
+
markers: string[];
|
|
10
|
+
/** Installed apps: under %LOCALAPPDATA% on Windows, absolute on macOS. */
|
|
11
|
+
apps: {
|
|
12
|
+
win?: string;
|
|
13
|
+
mac?: string;
|
|
14
|
+
};
|
|
15
|
+
/** VS Code extension IDs (lowercase). */
|
|
16
|
+
extensions: string[];
|
|
17
|
+
}
|
|
18
|
+
export declare const AGENT_INFO: AgentInfo[];
|
|
19
|
+
export declare const agentLabel: (id: Agent) => string;
|
|
20
|
+
export interface Probe {
|
|
21
|
+
home: string;
|
|
22
|
+
/** %LOCALAPPDATA% on Windows. */
|
|
23
|
+
localAppData?: string;
|
|
24
|
+
platform: NodeJS.Platform;
|
|
25
|
+
onPath(name: string): Promise<string | undefined>;
|
|
26
|
+
/** Installed VS Code extension IDs, lowercase. */
|
|
27
|
+
extensions: string[];
|
|
28
|
+
}
|
|
29
|
+
/** The known agents on this machine, each with why it was found. */
|
|
30
|
+
export declare function findAgents(probe: Probe): Promise<Map<Agent, string>>;
|
|
31
|
+
/** The MCP entry most agents take (an "mcpServers" object). */
|
|
32
|
+
export declare function mcpJson(launch: Launch): string;
|
|
33
|
+
/** A guide for agents setup does not know: where the skill and the tools go, with this machine's command. */
|
|
34
|
+
export declare function otherAgentGuide(launch: Launch): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AGENT_INFO,
|
|
3
|
+
agentLabel,
|
|
4
|
+
findAgents,
|
|
5
|
+
mcpJson,
|
|
6
|
+
otherAgentGuide
|
|
7
|
+
} from "../chunks/chunk-EPJKJBNW.js";
|
|
8
|
+
import "../chunks/chunk-2MZQHIXP.js";
|
|
9
|
+
export {
|
|
10
|
+
AGENT_INFO,
|
|
11
|
+
agentLabel,
|
|
12
|
+
findAgents,
|
|
13
|
+
mcpJson,
|
|
14
|
+
otherAgentGuide
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type HostEnv, type HostId } from './hosts';
|
|
2
|
+
import { type Env, type Registration } from './writers';
|
|
3
|
+
/** AFD-195: the mcp.js our entry starts, and whether it is there. */
|
|
4
|
+
export interface ServerFile {
|
|
5
|
+
path: string;
|
|
6
|
+
exists: boolean;
|
|
7
|
+
}
|
|
8
|
+
export interface McpFileState {
|
|
9
|
+
path: string;
|
|
10
|
+
exists: boolean;
|
|
11
|
+
/** Server names in it (mcpServers or servers). */
|
|
12
|
+
servers: string[];
|
|
13
|
+
/** Not JSON (with comments) the agent could read. */
|
|
14
|
+
broken?: boolean;
|
|
15
|
+
/** What our entry starts, when it starts an mcp.js. */
|
|
16
|
+
ours?: ServerFile;
|
|
17
|
+
}
|
|
18
|
+
export interface FolderState {
|
|
19
|
+
path: string;
|
|
20
|
+
exists: boolean;
|
|
21
|
+
/** Entries in it: skill or plugin folder names. */
|
|
22
|
+
entries: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface HostConfig {
|
|
25
|
+
host: HostId;
|
|
26
|
+
mcp: McpFileState[];
|
|
27
|
+
skills: FolderState[];
|
|
28
|
+
plugins?: FolderState;
|
|
29
|
+
}
|
|
30
|
+
/** Each fork's MCP files, skill folders and plugin folder as they are now. */
|
|
31
|
+
export declare function hostConfigs(env: HostEnv, hosts?: HostId[]): Promise<HostConfig[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Markdown lines for one editor's configuration; ours is marked, with the server file it starts.
|
|
34
|
+
* `server`: this extension's installed copy, to tell another extension ID's copy.
|
|
35
|
+
*/
|
|
36
|
+
export declare function configLines(c: HostConfig, server?: string): string[];
|
|
37
|
+
/** AFD-195: each agent's ansible-flow entry as Set Up AI Assistants wrote it, and what it starts. */
|
|
38
|
+
export declare function agentRegistrations(env: Env): Promise<{
|
|
39
|
+
registration: Registration | undefined;
|
|
40
|
+
file?: ServerFile;
|
|
41
|
+
agent: string;
|
|
42
|
+
}[]>;
|
|
43
|
+
/** Markdown lines for agentRegistrations; `server` is this extension's installed copy. */
|
|
44
|
+
export declare function registrationLines(found: Awaited<ReturnType<typeof agentRegistrations>>, server: string): string[];
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import {
|
|
2
|
+
agentLabel
|
|
3
|
+
} from "../chunks/chunk-EPJKJBNW.js";
|
|
4
|
+
import {
|
|
5
|
+
HOSTS
|
|
6
|
+
} from "../chunks/chunk-UNCR5JOZ.js";
|
|
7
|
+
import {
|
|
8
|
+
AGENTS,
|
|
9
|
+
SERVER_NAME,
|
|
10
|
+
SKILL_NAME,
|
|
11
|
+
entryServer,
|
|
12
|
+
registration,
|
|
13
|
+
storageId
|
|
14
|
+
} from "../chunks/chunk-2MZQHIXP.js";
|
|
15
|
+
|
|
16
|
+
// src/node/ai/hostConfig.ts
|
|
17
|
+
import { promises as fs } from "node:fs";
|
|
18
|
+
import { parse } from "jsonc-parser";
|
|
19
|
+
var fileExists = (path) => fs.stat(path).then(
|
|
20
|
+
() => true,
|
|
21
|
+
() => false
|
|
22
|
+
);
|
|
23
|
+
async function serverFile(server) {
|
|
24
|
+
return server ? { path: server, exists: await fileExists(server) } : void 0;
|
|
25
|
+
}
|
|
26
|
+
async function mcpFile(path) {
|
|
27
|
+
let text;
|
|
28
|
+
try {
|
|
29
|
+
text = await fs.readFile(path, "utf8");
|
|
30
|
+
} catch {
|
|
31
|
+
return { path, exists: false, servers: [] };
|
|
32
|
+
}
|
|
33
|
+
if (!text.trim()) return { path, exists: true, servers: [] };
|
|
34
|
+
const errors = [];
|
|
35
|
+
const data = parse(text, errors, { allowTrailingComma: true });
|
|
36
|
+
if (errors.length > 0 || !data || typeof data !== "object")
|
|
37
|
+
return { path, exists: true, servers: [], broken: true };
|
|
38
|
+
const table = data.mcpServers ?? data.servers;
|
|
39
|
+
const ours = await serverFile(entryServer(table?.[SERVER_NAME]).server);
|
|
40
|
+
return {
|
|
41
|
+
path,
|
|
42
|
+
exists: true,
|
|
43
|
+
servers: table && typeof table === "object" ? Object.keys(table).sort() : [],
|
|
44
|
+
...ours ? { ours } : {}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function serverText(s, server) {
|
|
48
|
+
const id = storageId(s.path);
|
|
49
|
+
const other = id && server && storageId(server) && id !== storageId(server);
|
|
50
|
+
return `starts \`${s.path}\`: ${s.exists ? other ? `there, but another extension ID's copy (${id})` : "there" : "**missing**"}`;
|
|
51
|
+
}
|
|
52
|
+
async function folder(path) {
|
|
53
|
+
try {
|
|
54
|
+
const entries = await fs.readdir(path, { withFileTypes: true });
|
|
55
|
+
return {
|
|
56
|
+
path,
|
|
57
|
+
exists: true,
|
|
58
|
+
entries: entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name).sort()
|
|
59
|
+
};
|
|
60
|
+
} catch {
|
|
61
|
+
return { path, exists: false, entries: [] };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function hostConfigs(env, hosts = ["cursor", "antigravity", "windsurf", "kiro"]) {
|
|
65
|
+
return Promise.all(
|
|
66
|
+
hosts.map(async (id) => {
|
|
67
|
+
const info = HOSTS[id];
|
|
68
|
+
const plugins = info.plugins?.(env);
|
|
69
|
+
return {
|
|
70
|
+
host: id,
|
|
71
|
+
mcp: await Promise.all(info.mcp(env).map(mcpFile)),
|
|
72
|
+
skills: await Promise.all(info.skills(env).map(folder)),
|
|
73
|
+
...plugins ? { plugins: await folder(plugins) } : {}
|
|
74
|
+
};
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function configLines(c, server) {
|
|
79
|
+
const mark = (name) => name === SERVER_NAME || name === SKILL_NAME ? `**${name}**` : name;
|
|
80
|
+
const lines = [`### ${HOSTS[c.host].label} (${HOSTS[c.host].agent})`, ""];
|
|
81
|
+
for (const f of c.mcp)
|
|
82
|
+
lines.push(
|
|
83
|
+
`- MCP \`${f.path}\`: ${!f.exists ? "none" : f.broken ? "not valid JSON" : f.servers.length ? f.servers.map(mark).join(", ") : "no servers"}${f.ours ? `; ${SERVER_NAME} ${serverText(f.ours, server)}` : ""}`
|
|
84
|
+
);
|
|
85
|
+
for (const s of c.skills)
|
|
86
|
+
lines.push(
|
|
87
|
+
`- Skills \`${s.path}\`: ${!s.exists ? "none" : s.entries.map(mark).join(", ") || "empty"}`
|
|
88
|
+
);
|
|
89
|
+
if (c.plugins)
|
|
90
|
+
lines.push(
|
|
91
|
+
`- Plugins \`${c.plugins.path}\`: ${!c.plugins.exists ? "none" : c.plugins.entries.join(", ") || "empty"}`
|
|
92
|
+
);
|
|
93
|
+
lines.push(`- Note: ${HOSTS[c.host].note}`, "");
|
|
94
|
+
return lines;
|
|
95
|
+
}
|
|
96
|
+
async function agentRegistrations(env) {
|
|
97
|
+
return Promise.all(
|
|
98
|
+
AGENTS.map(async (agent) => {
|
|
99
|
+
const r = await registration(agent, env);
|
|
100
|
+
const file = await serverFile(r?.server);
|
|
101
|
+
return { agent: agentLabel(agent), registration: r, ...file ? { file } : {} };
|
|
102
|
+
})
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
function registrationLines(found, server) {
|
|
106
|
+
return found.map(({ agent, registration: r, file }) => {
|
|
107
|
+
if (!r) return `- ${agent}: not registered`;
|
|
108
|
+
const where = `- ${agent} \`${r.file}\``;
|
|
109
|
+
if (r.hand) return `${where}: written by hand; Set Up leaves it as it is`;
|
|
110
|
+
if (!file) return `${where}: starts \`${r.command ?? "?"}\`, not an mcp.js`;
|
|
111
|
+
return `${where}: ${serverText(file, server)}`;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
agentRegistrations,
|
|
116
|
+
configLines,
|
|
117
|
+
hostConfigs,
|
|
118
|
+
registrationLines
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=hostConfig.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/node/ai/hostConfig.ts"],
|
|
4
|
+
"sourcesContent": ["// What each editor's agent is configured with on this machine (AFD-172): MCP servers by name, the\n// skills in its folders and its plugin bundles. Read-only, names only: a server entry's command,\n// arguments and environment (tokens) are never read out, except where ours starts (AFD-195).\nimport { promises as fs } from 'node:fs';\nimport { type ParseError, parse } from 'jsonc-parser';\nimport { agentLabel } from './agents';\nimport { HOSTS, type HostEnv, type HostId } from './hosts';\nimport {\n AGENTS,\n type Env,\n entryServer,\n type Registration,\n registration,\n SERVER_NAME,\n SKILL_NAME,\n storageId,\n} from './writers';\n\n/** AFD-195: the mcp.js our entry starts, and whether it is there. */\nexport interface ServerFile {\n path: string;\n exists: boolean;\n}\n\nconst fileExists = (path: string) =>\n fs.stat(path).then(\n () => true,\n () => false,\n );\n\nasync function serverFile(server: string | undefined): Promise<ServerFile | undefined> {\n return server ? { path: server, exists: await fileExists(server) } : undefined;\n}\n\nexport interface McpFileState {\n path: string;\n exists: boolean;\n /** Server names in it (mcpServers or servers). */\n servers: string[];\n /** Not JSON (with comments) the agent could read. */\n broken?: boolean;\n /** What our entry starts, when it starts an mcp.js. */\n ours?: ServerFile;\n}\n\nexport interface FolderState {\n path: string;\n exists: boolean;\n /** Entries in it: skill or plugin folder names. */\n entries: string[];\n}\n\nexport interface HostConfig {\n host: HostId;\n mcp: McpFileState[];\n skills: FolderState[];\n plugins?: FolderState;\n}\n\nasync function mcpFile(path: string): Promise<McpFileState> {\n let text: string;\n try {\n text = await fs.readFile(path, 'utf8');\n } catch {\n return { path, exists: false, servers: [] };\n }\n if (!text.trim()) return { path, exists: true, servers: [] };\n const errors: ParseError[] = [];\n const data = parse(text, errors, { allowTrailingComma: true }) as Record<string, unknown> | null;\n if (errors.length > 0 || !data || typeof data !== 'object')\n return { path, exists: true, servers: [], broken: true };\n const table = (data.mcpServers ?? data.servers) as Record<string, unknown> | undefined;\n const ours = await serverFile(entryServer(table?.[SERVER_NAME]).server);\n return {\n path,\n exists: true,\n servers: table && typeof table === 'object' ? Object.keys(table).sort() : [],\n ...(ours ? { ours } : {}),\n };\n}\n\n/** How a registered server file reads in the report. */\nfunction serverText(s: ServerFile, server?: string): string {\n const id = storageId(s.path);\n const other = id && server && storageId(server) && id !== storageId(server);\n return `starts \\`${s.path}\\`: ${s.exists ? (other ? `there, but another extension ID's copy (${id})` : 'there') : '**missing**'}`;\n}\n\nasync function folder(path: string): Promise<FolderState> {\n try {\n const entries = await fs.readdir(path, { withFileTypes: true });\n return {\n path,\n exists: true,\n entries: entries\n .filter((e) => e.isDirectory() || e.isSymbolicLink())\n .map((e) => e.name)\n .sort(),\n };\n } catch {\n return { path, exists: false, entries: [] };\n }\n}\n\n/** Each fork's MCP files, skill folders and plugin folder as they are now. */\nexport async function hostConfigs(\n env: HostEnv,\n hosts: HostId[] = ['cursor', 'antigravity', 'windsurf', 'kiro'],\n): Promise<HostConfig[]> {\n return Promise.all(\n hosts.map(async (id) => {\n const info = HOSTS[id];\n const plugins = info.plugins?.(env);\n return {\n host: id,\n mcp: await Promise.all(info.mcp(env).map(mcpFile)),\n skills: await Promise.all(info.skills(env).map(folder)),\n ...(plugins ? { plugins: await folder(plugins) } : {}),\n };\n }),\n );\n}\n\n/**\n * Markdown lines for one editor's configuration; ours is marked, with the server file it starts.\n * `server`: this extension's installed copy, to tell another extension ID's copy.\n */\nexport function configLines(c: HostConfig, server?: string): string[] {\n const mark = (name: string) =>\n name === SERVER_NAME || name === SKILL_NAME ? `**${name}**` : name;\n const lines = [`### ${HOSTS[c.host].label} (${HOSTS[c.host].agent})`, ''];\n for (const f of c.mcp)\n lines.push(\n `- MCP \\`${f.path}\\`: ${\n !f.exists\n ? 'none'\n : f.broken\n ? 'not valid JSON'\n : f.servers.length\n ? f.servers.map(mark).join(', ')\n : 'no servers'\n }${f.ours ? `; ${SERVER_NAME} ${serverText(f.ours, server)}` : ''}`,\n );\n for (const s of c.skills)\n lines.push(\n `- Skills \\`${s.path}\\`: ${!s.exists ? 'none' : s.entries.map(mark).join(', ') || 'empty'}`,\n );\n if (c.plugins)\n lines.push(\n `- Plugins \\`${c.plugins.path}\\`: ${!c.plugins.exists ? 'none' : c.plugins.entries.join(', ') || 'empty'}`,\n );\n lines.push(`- Note: ${HOSTS[c.host].note}`, '');\n return lines;\n}\n\n/** AFD-195: each agent's ansible-flow entry as Set Up AI Assistants wrote it, and what it starts. */\nexport async function agentRegistrations(\n env: Env,\n): Promise<{ registration: Registration | undefined; file?: ServerFile; agent: string }[]> {\n return Promise.all(\n AGENTS.map(async (agent) => {\n const r = await registration(agent, env);\n const file = await serverFile(r?.server);\n return { agent: agentLabel(agent), registration: r, ...(file ? { file } : {}) };\n }),\n );\n}\n\n/** Markdown lines for agentRegistrations; `server` is this extension's installed copy. */\nexport function registrationLines(\n found: Awaited<ReturnType<typeof agentRegistrations>>,\n server: string,\n): string[] {\n return found.map(({ agent, registration: r, file }) => {\n if (!r) return `- ${agent}: not registered`;\n const where = `- ${agent} \\`${r.file}\\``;\n if (r.hand) return `${where}: written by hand; Set Up leaves it as it is`;\n if (!file) return `${where}: starts \\`${r.command ?? '?'}\\`, not an mcp.js`;\n return `${where}: ${serverText(file, server)}`;\n });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type HostId = 'vscode' | 'cursor' | 'antigravity' | 'windsurf' | 'kiro' | 'other';
|
|
2
|
+
export interface HostEnv {
|
|
3
|
+
home: string;
|
|
4
|
+
platform: NodeJS.Platform;
|
|
5
|
+
/** XDG_CONFIG_HOME, which Devin honours outside Windows. */
|
|
6
|
+
xdgConfig?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface HostInfo {
|
|
9
|
+
id: HostId;
|
|
10
|
+
/** The editor, as people call it. */
|
|
11
|
+
label: string;
|
|
12
|
+
/** Its built-in agent. */
|
|
13
|
+
agent: string;
|
|
14
|
+
/** User-level MCP files the agent reads; the first is where an entry goes. */
|
|
15
|
+
mcp(env: HostEnv): string[];
|
|
16
|
+
/** User-level skill folders the agent reads (each holds one folder per skill). */
|
|
17
|
+
skills(env: HostEnv): string[];
|
|
18
|
+
/** Where plugin bundles go (plugin.json, MCP file, skills/), if the agent loads them. */
|
|
19
|
+
plugins?(env: HostEnv): string;
|
|
20
|
+
/** What is known and what is still to be probed. */
|
|
21
|
+
note: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const HOSTS: Record<HostId, HostInfo>;
|
|
24
|
+
/** Which editor this is, from vscode.env.appName and uriScheme (the scheme is the surer of the two). */
|
|
25
|
+
export declare function detectHost(app: {
|
|
26
|
+
appName: string;
|
|
27
|
+
uriScheme: string;
|
|
28
|
+
}): HostId;
|
package/dist/ai/hosts.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
export declare const AGENTS: readonly ['claude', 'codex', 'gemini', 'opencode', 'zcode', 'copilot', 'cursor', 'kiro', 'antigravity', 'devin'];
|
|
2
|
+
export type Agent = (typeof AGENTS)[number];
|
|
3
|
+
export type Scope = 'repo' | 'user';
|
|
4
|
+
export declare const SERVER_NAME = "ansible-flow";
|
|
5
|
+
export declare const SKILL_NAME = "ansible-flow";
|
|
6
|
+
/** How agents start the MCP server. */
|
|
7
|
+
export interface Launch {
|
|
8
|
+
command: string;
|
|
9
|
+
args: string[];
|
|
10
|
+
env?: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export interface Item {
|
|
13
|
+
agent: Agent;
|
|
14
|
+
what: 'skill' | 'mcp';
|
|
15
|
+
/** File or folder, or the command for Claude's registration. */
|
|
16
|
+
target: string;
|
|
17
|
+
action: 'create' | 'update' | 'unchanged' | 'skip' | 'remove';
|
|
18
|
+
/** Why an item is skipped, or what the user must do. */
|
|
19
|
+
note?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface Env {
|
|
22
|
+
home: string;
|
|
23
|
+
/** Where Devin keeps its MCP file depends on it (default: this process's platform). */
|
|
24
|
+
platform?: NodeJS.Platform;
|
|
25
|
+
/** XDG_CONFIG_HOME, which Devin honours outside Windows. */
|
|
26
|
+
xdgConfig?: string;
|
|
27
|
+
/** The repository (workspace folder) for repo-scope skill copies. */
|
|
28
|
+
repo?: string;
|
|
29
|
+
/** Runs the claude CLI; undefined when it is not installed. */
|
|
30
|
+
claude?: (args: string[]) => Promise<{
|
|
31
|
+
code: number;
|
|
32
|
+
out: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
export interface SkillFiles {
|
|
36
|
+
version: string;
|
|
37
|
+
/** Relative path (posix) -> text. */
|
|
38
|
+
files: Record<string, string>;
|
|
39
|
+
}
|
|
40
|
+
/** Folders an agent reads the skill from, per scope. */
|
|
41
|
+
export declare function skillDirs(agent: Agent, scope: Scope, env: Env): string[];
|
|
42
|
+
export interface SkillState {
|
|
43
|
+
dir: string;
|
|
44
|
+
/** Not ours: the folder exists without our manifest. */
|
|
45
|
+
foreign: boolean;
|
|
46
|
+
version?: string;
|
|
47
|
+
/** Files of ours the user changed since they were written. */
|
|
48
|
+
edited: string[];
|
|
49
|
+
}
|
|
50
|
+
export declare function skillState(dir: string): Promise<SkillState | undefined>;
|
|
51
|
+
/** a > b for versions like 0.75.0 (non-numeric parts count as 0). */
|
|
52
|
+
export declare function newerVersion(a: string, b: string): boolean;
|
|
53
|
+
export declare function planSkill(dir: string, skill: SkillFiles): Promise<Item['action']>;
|
|
54
|
+
export declare function writeSkill(dir: string, skill: SkillFiles): Promise<void>;
|
|
55
|
+
/** Removes our files (and the folder when nothing else is left in it); foreign folders stay. */
|
|
56
|
+
export declare function removeSkill(dir: string): Promise<boolean>;
|
|
57
|
+
export declare const codexConfig: (env: Env) => string;
|
|
58
|
+
export declare function codexBlock(launch: Launch): string;
|
|
59
|
+
export declare function planCodex(env: Env, launch: Launch): Promise<Item>;
|
|
60
|
+
export declare function writeCodex(env: Env, launch: Launch): Promise<void>;
|
|
61
|
+
export declare function removeCodex(env: Env): Promise<boolean>;
|
|
62
|
+
type JsonAgent = Exclude<Agent, 'claude' | 'codex'>;
|
|
63
|
+
/** Cursor's variable for the open folder, resolved by Cursor when it starts the server. */
|
|
64
|
+
export declare const CURSOR_WORKSPACE = "${workspaceFolder}";
|
|
65
|
+
/**
|
|
66
|
+
* Devin Desktop's MCP file, as its own code builds it: %USERPROFILE%\AppData\Roaming\devin on
|
|
67
|
+
* Windows, else $XDG_CONFIG_HOME/devin or ~/.config/devin. (It reads Windsurf's
|
|
68
|
+
* ~/.codeium/windsurf/mcp_config.json too, and Claude Code's and Cursor's entries.)
|
|
69
|
+
*/
|
|
70
|
+
export declare function devinMcpFile(env: Env): string;
|
|
71
|
+
/** The config file an agent's registration goes in (Claude's is managed by its CLI). */
|
|
72
|
+
export declare function mcpTarget(agent: Agent, env: Env, launch?: Launch): Promise<string>;
|
|
73
|
+
export declare function planJson(agent: JsonAgent, env: Env, launch: Launch): Promise<Item>;
|
|
74
|
+
export declare function writeJson(agent: JsonAgent, env: Env, launch: Launch): Promise<void>;
|
|
75
|
+
export declare function removeJson(agent: JsonAgent, env: Env): Promise<boolean>;
|
|
76
|
+
export declare function claudeAddArgs(launch: Launch): string[];
|
|
77
|
+
/** The command a user runs when the claude CLI cannot be run from here. */
|
|
78
|
+
export declare function claudeCommandLine(launch: Launch): string;
|
|
79
|
+
export declare function planClaude(env: Env, launch: Launch): Promise<Item>;
|
|
80
|
+
export declare function writeClaude(env: Env, launch: Launch): Promise<void>;
|
|
81
|
+
export declare function removeClaude(env: Env): Promise<boolean>;
|
|
82
|
+
/** Runs the claude CLI found at this path (a .cmd shim needs the shell, with quoted arguments). */
|
|
83
|
+
export declare function claudeRunner(path: string): Env['claude'];
|
|
84
|
+
/** The registration of the flow tools for one agent (no skill). */
|
|
85
|
+
export declare function planMcp(agent: Agent, env: Env, launch: Launch): Promise<Item>;
|
|
86
|
+
export declare function planSetup(agents: Agent[], scope: Scope, env: Env, launch: Launch, skill: SkillFiles): Promise<Item[]>;
|
|
87
|
+
export declare function applySetup(items: Item[], env: Env, launch: Launch, skill: SkillFiles): Promise<void>;
|
|
88
|
+
/** Removes skill copies (both scopes) and registrations of these agents; returns what went. */
|
|
89
|
+
export declare function removeSetup(agents: Agent[], env: Env): Promise<Item[]>;
|
|
90
|
+
/** Claude Code's user-scope servers, read from the file: `claude mcp get` starts the server. */
|
|
91
|
+
export declare const claudeConfig: (env: Env) => string;
|
|
92
|
+
/** What an agent's ansible-flow entry starts, read from its config file (never by running it). */
|
|
93
|
+
export interface Registration {
|
|
94
|
+
agent: Agent;
|
|
95
|
+
/** The config file the entry is in. */
|
|
96
|
+
file: string;
|
|
97
|
+
command?: string;
|
|
98
|
+
/** The mcp.js it starts; none when it starts something else (npx, a script of the user's). */
|
|
99
|
+
server?: string;
|
|
100
|
+
/** Codex: a table the user wrote outside our block, which Set Up never changes. */
|
|
101
|
+
hand?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** The command and the mcp.js of an MCP entry: stdio (command, args) or OpenCode's command list. */
|
|
104
|
+
export declare function entryServer(entry: unknown): {
|
|
105
|
+
command?: string;
|
|
106
|
+
server?: string;
|
|
107
|
+
};
|
|
108
|
+
export declare function registration(agent: Agent, env: Env): Promise<Registration | undefined>;
|
|
109
|
+
/** The extension ID of a server copied into an editor's storage: …/globalStorage/<id>/mcp/mcp.js. */
|
|
110
|
+
export declare function storageId(server: string): string | undefined;
|
|
111
|
+
export interface StaleRegistration extends Registration {
|
|
112
|
+
server: string;
|
|
113
|
+
/** missing: the mcp.js is gone; elsewhere: another extension ID's copy (an older publisher). */
|
|
114
|
+
why: 'missing' | 'elsewhere';
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Entries of ours that no longer start this server (`server`, this extension's installed copy):
|
|
118
|
+
* the mcp.js they name is gone, as when the publisher ID changed and the old ID's storage went
|
|
119
|
+
* with it, or it is another extension ID's copy. Only an entry that starts an mcp.js in an
|
|
120
|
+
* editor's global storage is ours: one the user wrote (a Codex table outside our block, a path of
|
|
121
|
+
* their own) is never reported. Another editor's copy under the same ID is not stale.
|
|
122
|
+
*/
|
|
123
|
+
export declare function staleRegistrations(agents: readonly Agent[], env: Env, server: string): Promise<StaleRegistration[]>;
|
|
124
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AGENTS,
|
|
3
|
+
CURSOR_WORKSPACE,
|
|
4
|
+
SERVER_NAME,
|
|
5
|
+
SKILL_NAME,
|
|
6
|
+
applySetup,
|
|
7
|
+
claudeAddArgs,
|
|
8
|
+
claudeCommandLine,
|
|
9
|
+
claudeConfig,
|
|
10
|
+
claudeRunner,
|
|
11
|
+
codexBlock,
|
|
12
|
+
codexConfig,
|
|
13
|
+
devinMcpFile,
|
|
14
|
+
entryServer,
|
|
15
|
+
mcpTarget,
|
|
16
|
+
newerVersion,
|
|
17
|
+
planClaude,
|
|
18
|
+
planCodex,
|
|
19
|
+
planJson,
|
|
20
|
+
planMcp,
|
|
21
|
+
planSetup,
|
|
22
|
+
planSkill,
|
|
23
|
+
registration,
|
|
24
|
+
removeClaude,
|
|
25
|
+
removeCodex,
|
|
26
|
+
removeJson,
|
|
27
|
+
removeSetup,
|
|
28
|
+
removeSkill,
|
|
29
|
+
skillDirs,
|
|
30
|
+
skillState,
|
|
31
|
+
staleRegistrations,
|
|
32
|
+
storageId,
|
|
33
|
+
writeClaude,
|
|
34
|
+
writeCodex,
|
|
35
|
+
writeJson,
|
|
36
|
+
writeSkill
|
|
37
|
+
} from "../chunks/chunk-2MZQHIXP.js";
|
|
38
|
+
export {
|
|
39
|
+
AGENTS,
|
|
40
|
+
CURSOR_WORKSPACE,
|
|
41
|
+
SERVER_NAME,
|
|
42
|
+
SKILL_NAME,
|
|
43
|
+
applySetup,
|
|
44
|
+
claudeAddArgs,
|
|
45
|
+
claudeCommandLine,
|
|
46
|
+
claudeConfig,
|
|
47
|
+
claudeRunner,
|
|
48
|
+
codexBlock,
|
|
49
|
+
codexConfig,
|
|
50
|
+
devinMcpFile,
|
|
51
|
+
entryServer,
|
|
52
|
+
mcpTarget,
|
|
53
|
+
newerVersion,
|
|
54
|
+
planClaude,
|
|
55
|
+
planCodex,
|
|
56
|
+
planJson,
|
|
57
|
+
planMcp,
|
|
58
|
+
planSetup,
|
|
59
|
+
planSkill,
|
|
60
|
+
registration,
|
|
61
|
+
removeClaude,
|
|
62
|
+
removeCodex,
|
|
63
|
+
removeJson,
|
|
64
|
+
removeSetup,
|
|
65
|
+
removeSkill,
|
|
66
|
+
skillDirs,
|
|
67
|
+
skillState,
|
|
68
|
+
staleRegistrations,
|
|
69
|
+
storageId,
|
|
70
|
+
writeClaude,
|
|
71
|
+
writeCodex,
|
|
72
|
+
writeJson,
|
|
73
|
+
writeSkill
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=writers.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type FlowModel, type Level } from '@ansible-flow/core/flow/model';
|
|
2
|
+
import type { FlowDocument, Layout, Position, Ulid } from '@ansible-flow/core/flow/types';
|
|
3
|
+
/** Top to bottom (the default) or left to right: the user setting `afd.canvas.direction` (AFD-42). */
|
|
4
|
+
export type LayoutDirection = 'TB' | 'LR';
|
|
5
|
+
/**
|
|
6
|
+
* Positions for every node of a level. Wires run port to port. Model order
|
|
7
|
+
* (`considerModelOrder`) and straightness priority on main outputs were tried for AFD-192: both
|
|
8
|
+
* gave more crossings on the fixtures, so ELK orders the layers by crossings alone.
|
|
9
|
+
*/
|
|
10
|
+
export declare function layoutLevel(level: Level, direction?: LayoutDirection): Promise<Record<Ulid, Position>>;
|
|
11
|
+
/** ELK positions for every level of a new document, in the one flat layout map (ADR-0002). */
|
|
12
|
+
export declare function layoutAll(doc: FlowDocument): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* In-memory positions for nodes the layout block does not place (ADR-0002). With no stored
|
|
15
|
+
* positions at all the level gets a full ELK layout. Otherwise (AFD-23) the missing nodes keep
|
|
16
|
+
* ELK's shape around the placed ones: each goes where ELK puts it relative to a placed neighbour
|
|
17
|
+
* (its predecessor first), else by the placed nodes' median shift, and moves right while it would
|
|
18
|
+
* overlap a node. Before, each missing node went straight below its predecessor, so a flow with
|
|
19
|
+
* only Start and Done placed (the New Flow template) and everything else added by an AI agent
|
|
20
|
+
* stood in one column, siblings on top of each other.
|
|
21
|
+
*/
|
|
22
|
+
export declare function autoPositions(level: Level, layout: Layout | undefined, direction?: LayoutDirection): Promise<Record<Ulid, Position>>;
|
|
23
|
+
/**
|
|
24
|
+
* The layout the canvas shows (AFD-23): the stored one, except that a level whose only positions
|
|
25
|
+
* are the New Flow template's (Start at 0,0 and Done at 36,160), while it has other nodes, is shown
|
|
26
|
+
* with a full auto-layout. Flows made before AFD-23 and then filled by an AI agent look like that.
|
|
27
|
+
* The shown positions are written on the first move or Tidy up, like any auto position.
|
|
28
|
+
*/
|
|
29
|
+
export declare function shownLayout(model: FlowModel): Layout | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Where the canvas shows every node (AFD-24), for the AI tools: `stored` positions (the old
|
|
32
|
+
* template's dropped, as in the view) and `auto` positions for the rest, on every level. Pass the
|
|
33
|
+
* canvas direction (`afd.canvas.direction`) so the layout check sees what the canvas shows (AFD-192).
|
|
34
|
+
*/
|
|
35
|
+
export declare function shownPositions(model: FlowModel, direction?: LayoutDirection): Promise<{
|
|
36
|
+
stored: Layout;
|
|
37
|
+
auto: Record<Ulid, Position>;
|
|
38
|
+
}>;
|