@fazer-ai/agents 1.0.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/dist/agents/claude.js +152 -0
  4. package/dist/agents/codex.js +155 -0
  5. package/dist/agents/detect.js +15 -0
  6. package/dist/agents/handoff.js +22 -0
  7. package/dist/agents/hermes-skills.js +177 -0
  8. package/dist/agents/hermes.js +474 -0
  9. package/dist/agents/index.js +57 -0
  10. package/dist/agents/manual.js +22 -0
  11. package/dist/agents/other.js +39 -0
  12. package/dist/agents/shell.js +15 -0
  13. package/dist/agents/types.js +2 -0
  14. package/dist/config.js +48 -0
  15. package/dist/exec.js +279 -0
  16. package/dist/hostinger.js +75 -0
  17. package/dist/hub-command.js +144 -0
  18. package/dist/index.js +726 -0
  19. package/dist/licenses.js +93 -0
  20. package/dist/mcp.js +100 -0
  21. package/dist/oauth.js +578 -0
  22. package/dist/onboarding-marker.js +48 -0
  23. package/dist/preferences.js +40 -0
  24. package/dist/skills/agents-dev/SKILL.md +37 -0
  25. package/dist/skills/agents-dev/gotchas.md +6 -0
  26. package/dist/skills/agents-dev/guardrails.md +6 -0
  27. package/dist/skills/agents-dev/references/00-get-the-code.md +28 -0
  28. package/dist/skills/agents-dev/references/01-layout-and-bun-check.md +29 -0
  29. package/dist/skills/agents-dev/references/02-free-full-and-invariants.md +7 -0
  30. package/dist/skills/agents-dev/references/03-implement.md +9 -0
  31. package/dist/skills/agents-dev/references/04-own-image-and-deploy.md +13 -0
  32. package/dist/skills/agents-onboarding/SKILL.md +80 -0
  33. package/dist/skills/agents-onboarding/gotchas.md +157 -0
  34. package/dist/skills/agents-onboarding/guardrails.md +65 -0
  35. package/dist/skills/agents-onboarding/references/00-prereqs-and-access.md +37 -0
  36. package/dist/skills/agents-onboarding/references/01-vps-dns-ssh.md +67 -0
  37. package/dist/skills/agents-onboarding/references/01b-brownfield.md +70 -0
  38. package/dist/skills/agents-onboarding/references/01c-pick-tier.md +61 -0
  39. package/dist/skills/agents-onboarding/references/02-coolify.md +109 -0
  40. package/dist/skills/agents-onboarding/references/03-chatwoot-pro.md +61 -0
  41. package/dist/skills/agents-onboarding/references/04-agents-image.md +46 -0
  42. package/dist/skills/agents-onboarding/references/05-langfuse.md +45 -0
  43. package/dist/skills/agents-onboarding/references/06-setup-and-mcp.md +47 -0
  44. package/dist/skills/agents-onboarding/references/08-agent-import.md +55 -0
  45. package/dist/skills/agents-onboarding/references/09-chatwoot-bind.md +41 -0
  46. package/dist/skills/agents-onboarding/references/10-validate-e2e.md +34 -0
  47. package/dist/skills/agents-onboarding/references/agent-features.md +61 -0
  48. package/dist/skills/agents-onboarding/references/chatwoot-hub-register.md +69 -0
  49. package/dist/skills/agents-onboarding/references/deploy-b-portainer.md +138 -0
  50. package/dist/skills/agents-onboarding/references/deploy-c-compose.md +64 -0
  51. package/dist/skills/agents-onboarding/samples/agents/README.md +23 -0
  52. package/dist/skills/agents-onboarding/samples/agents/maria-clinica-moreira.json +313 -0
  53. package/dist/skills/agents-onboarding/scripts/chatwoot-admin.py +248 -0
  54. package/dist/skills/agents-onboarding/scripts/coolify.py +552 -0
  55. package/dist/skills/agents-onboarding/scripts/docker-status.py +129 -0
  56. package/dist/skills/agents-onboarding/scripts/gen-onboarding-env.ts +187 -0
  57. package/dist/skills/agents-onboarding/scripts/harbor-login.py +118 -0
  58. package/dist/skills/agents-onboarding/scripts/langfuse-verify.py +118 -0
  59. package/dist/skills/agents-onboarding/scripts/portainer-brownfield.py +115 -0
  60. package/dist/skills/agents-onboarding/scripts/remote.py +198 -0
  61. package/dist/skills/agents-onboarding/scripts/sshkey.py +140 -0
  62. package/dist/skills/agents-onboarding/templates/chatwoot/.env.example +30 -0
  63. package/dist/skills/agents-onboarding/templates/chatwoot/README.md +65 -0
  64. package/dist/skills/agents-onboarding/templates/chatwoot/docker-compose.coolify.yml +136 -0
  65. package/dist/skills/agents-onboarding/templates/chatwoot/docker-compose.yml +139 -0
  66. package/dist/skills/agents-onboarding/templates/docker-compose.coolify.yml +73 -0
  67. package/dist/skills/agents-onboarding/templates/docker-compose.portainer.yml +132 -0
  68. package/dist/skills/agents-onboarding/templates/docker-compose.prod.yml +85 -0
  69. package/dist/skills/agents-onboarding/templates/langfuse/.env.example +59 -0
  70. package/dist/skills/agents-onboarding/templates/langfuse/README.md +132 -0
  71. package/dist/skills/agents-onboarding/templates/langfuse/docker-compose.coolify.yml +189 -0
  72. package/dist/skills/agents-onboarding/templates/langfuse/docker-compose.yml +185 -0
  73. package/dist/skills/agents-operation/SKILL.md +42 -0
  74. package/dist/skills/agents-operation/gotchas.md +61 -0
  75. package/dist/skills/agents-operation/guardrails.md +26 -0
  76. package/dist/skills/agents-operation/references/00-production-safety.md +24 -0
  77. package/dist/skills/agents-operation/references/01-diagnose.md +34 -0
  78. package/dist/skills/agents-operation/references/02-reproduce.md +22 -0
  79. package/dist/skills/agents-operation/references/03-adjust.md +36 -0
  80. package/dist/skills/agents-operation/references/04-validate-and-apply.md +31 -0
  81. package/dist/ui-select.js +279 -0
  82. package/dist/ui.js +167 -0
  83. package/package.json +53 -0
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isUsable = isUsable;
4
+ exports.isAvailable = isAvailable;
5
+ exports.kanbanLicenses = kanbanLicenses;
6
+ exports.hasCommunityAccess = hasCommunityAccess;
7
+ exports.licenseLabel = licenseLabel;
8
+ exports.instanceLabel = instanceLabel;
9
+ exports.parseLicenseChoice = parseLicenseChoice;
10
+ exports.buildLicenseMenu = buildLicenseMenu;
11
+ // Status que tornam a licença utilizável pra ligar o Pro (os demais: past_due,
12
+ // canceled, unpaid, paused, incomplete, não habilitam).
13
+ const USABLE_STATUS = new Set(["ACTIVE", "TRIALING"]);
14
+ function isUsable(l) {
15
+ return USABLE_STATUS.has(l.status.toUpperCase());
16
+ }
17
+ // Disponível = utilizável E ainda não atachada a uma instância.
18
+ function isAvailable(l) {
19
+ return isUsable(l) && l.instance === null;
20
+ }
21
+ // Filtra as licenças Kanban/Chatwoot do conjunto cru do `list_licenses`.
22
+ function kanbanLicenses(all) {
23
+ return all.filter((l) => l.feature?.toUpperCase() === "KANBAN" &&
24
+ l.instanceType?.toUpperCase() === "CHATWOOT");
25
+ }
26
+ // Acesso à edição Pro da fazer.ai agents = membership da comunidade (`isCommunityGrant`)
27
+ // com status utilizável. Difere do Kanban avulso: o projeto `agents` no Harbor é
28
+ // liberado só pra membros da comunidade (robot per-user, gating no hub). Uma licença
29
+ // Chatwoot Pro avulsa (isCommunityGrant=false) NÃO desbloqueia o fazer.ai agents Pro.
30
+ function hasCommunityAccess(all) {
31
+ return all.some((l) => l.isCommunityGrant && isUsable(l));
32
+ }
33
+ // Rótulo curto e estável de uma licença pro seletor.
34
+ function licenseLabel(l) {
35
+ const grant = l.isCommunityGrant ? " · comunidade" : "";
36
+ return `Licença #${l.number}${grant}`;
37
+ }
38
+ // Rótulo legível da instância atachada: nome amigável → host → UUID de instalação.
39
+ // O `identifier` cru é um UUID, ilegível como "em uso por"; é o último recurso.
40
+ function instanceLabel(instance) {
41
+ if (!instance)
42
+ return "outra instância";
43
+ return instance.name?.trim() || instance.host?.trim() || instance.identifier;
44
+ }
45
+ // Decodifica o value escolhido no seletor (`lic:<id>` / `attached:<id>` / ação).
46
+ function parseLicenseChoice(value) {
47
+ if (value.startsWith("lic:"))
48
+ return { kind: "available", id: value.slice(4) };
49
+ if (value.startsWith("attached:")) {
50
+ return { kind: "attached", id: value.slice("attached:".length) };
51
+ }
52
+ return { kind: "action", action: value };
53
+ }
54
+ // Monta o menu de licença, ciente do estado:
55
+ // - **empty** (0 licenças): "Atualizar lista" + "Ainda não tenho licença" (única
56
+ // porta pro fluxo da comunidade, só faz sentido quando não há NENHUMA).
57
+ // - **none-available** (só consumidas) / **has-available**: as licenças primeiro
58
+ // (disponíveis selecionáveis = `lic:`, consumidas selecionáveis = `attached:`
59
+ // pra desvincular), depois "Adquirir nova licença" + "Seguir sem o Chatwoot
60
+ // Pro". `defaultIndex` cai na última usada se ainda disponível, senão na 1ª opção.
61
+ function buildLicenseMenu(kanban, lastUsedId) {
62
+ const available = kanban.filter(isAvailable);
63
+ const consumed = kanban.filter((l) => isUsable(l) && l.instance !== null);
64
+ const options = [];
65
+ for (const l of available) {
66
+ options.push({ value: `lic:${l.id}`, label: licenseLabel(l) });
67
+ }
68
+ for (const l of consumed) {
69
+ options.push({
70
+ value: `attached:${l.id}`,
71
+ label: licenseLabel(l),
72
+ hint: `em uso por ${instanceLabel(l.instance)}`,
73
+ });
74
+ }
75
+ let state;
76
+ if (available.length + consumed.length === 0) {
77
+ state = "empty";
78
+ options.push({ value: "refresh", label: "Atualizar lista" });
79
+ options.push({ value: "community", label: "Ainda não tenho licença" });
80
+ }
81
+ else {
82
+ state = available.length > 0 ? "has-available" : "none-available";
83
+ options.push({ value: "acquire", label: "Adquirir nova licença" });
84
+ options.push({
85
+ value: "skip",
86
+ label: "Seguir sem o Chatwoot Pro (OSS, sem Kanban)",
87
+ });
88
+ }
89
+ const lastIdx = lastUsedId
90
+ ? available.findIndex((l) => l.id === lastUsedId)
91
+ : -1;
92
+ return { options, defaultIndex: lastIdx >= 0 ? lastIdx : 0, state };
93
+ }
package/dist/mcp.js ADDED
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hostingerEntryPath = hostingerEntryPath;
4
+ exports.installHostingerMcp = installHostingerMcp;
5
+ exports.hasHostingerSpecs = hasHostingerSpecs;
6
+ exports.bootstrapMcpSpecs = bootstrapMcpSpecs;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const exec_1 = require("./exec");
11
+ // NOTE: Pacote único oficial (hostinger-api-mcp) que expõe 3 servidores por módulo
12
+ // (DNS, VPS, domains). Instalamos LOCAL (~/.fazer-ai/mcp) e apontamos o MCP pro
13
+ // entry .js via o runtime atual (`process.execPath`), em vez de `npx … @latest`: o npx tem startup
14
+ // variável (resolução + checagem de registro do @latest) que estoura os timeouts
15
+ // de conexão do agente (Hermes ~10s) → "Connection closed". O entry via runtime sobe
16
+ // em <1s, conecta de forma confiável nos 3 agentes e é cross-platform (o shim do
17
+ // `.bin/` viraria `.cmd`/`.ps1` no Windows). Token: no execute gravamos o LITERAL (vindo do
18
+ // ~/.fazer-ai/hostinger.json que já mantemos) no config de MCP do agente, pra o
19
+ // conector funcionar também ao REABRIR o agente fora do handoff, sem depender do
20
+ // env vivo nem da expansão de ${VAR} (que só confirmamos no Hermes). No preview do
21
+ // plan usamos a REFERÊNCIA ${HOSTINGER_API_TOKEN} e a marca como segredo, então o
22
+ // literal nunca aparece em saída/preview.
23
+ const HOSTINGER_PACKAGE = "hostinger-api-mcp@latest";
24
+ const HOSTINGER_MODULES = ["dns", "vps", "domains"];
25
+ const HOSTINGER_MCP_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), ".fazer-ai", "mcp");
26
+ // Caminho do ENTRY .js do servidor MCP de um módulo (o `bin` do pacote aponta
27
+ // pra src/servers/<mod>.js). Lançamos via o runtime atual (`process.execPath`) em vez do shim do
28
+ // `.bin/`: no Windows o shim vira `.cmd`/`.ps1` (que o agente não consegue lançar
29
+ // como stdio sem shell), enquanto o runtime é um caminho absoluto sempre resolvível. É o que o
30
+ // shim faz por baixo, só que cross-platform.
31
+ function hostingerEntryPath(mod) {
32
+ return (0, node_path_1.join)(HOSTINGER_MCP_DIR, "node_modules", "hostinger-api-mcp", "src", "servers", `${mod}.js`);
33
+ }
34
+ // Instala o pacote localmente (idempotente: pula se o binário já existe). Robusto a PATH mínimo, na
35
+ // ordem: bun → npm → heal+retry. O instalador instala o bun pra rodar o CLI, então o bun é garantido;
36
+ // sob `bunx` o próprio process.execPath JÁ é o bun (caminho absoluto, sem depender do PATH), o que cobre
37
+ // até o caso bun-only (sem node/npm). O heal do PATH (registro) só entra como último recurso, antes de
38
+ // retentar o npm.
39
+ async function installHostingerMcp(log) {
40
+ if ((0, node_fs_1.existsSync)(hostingerEntryPath("dns")))
41
+ return;
42
+ log?.("Instalando o conector da Hostinger...");
43
+ (0, node_fs_1.mkdirSync)(HOSTINGER_MCP_DIR, { recursive: true });
44
+ const bun = process.versions.bun
45
+ ? process.execPath
46
+ : (await (0, exec_1.capture)("bun", ["--version"])).code === 0
47
+ ? "bun"
48
+ : undefined;
49
+ if (bun) {
50
+ await (0, exec_1.run)(bun, ["add", `--cwd=${HOSTINGER_MCP_DIR}`, HOSTINGER_PACKAGE], {
51
+ quiet: true,
52
+ });
53
+ return;
54
+ }
55
+ const npmArgs = [
56
+ "install",
57
+ "--no-fund",
58
+ "--no-audit",
59
+ "--prefix",
60
+ HOSTINGER_MCP_DIR,
61
+ HOSTINGER_PACKAGE,
62
+ ];
63
+ try {
64
+ await (0, exec_1.run)("npm", npmArgs, { quiet: true });
65
+ }
66
+ catch {
67
+ await (0, exec_1.healPath)();
68
+ await (0, exec_1.run)("npm", npmArgs, { quiet: true });
69
+ }
70
+ }
71
+ // Algum spec é dos MCPs da Hostinger? (gateia o install no execute do agente.)
72
+ function hasHostingerSpecs(specs) {
73
+ return specs.some((s) => s.name.startsWith("hostinger-"));
74
+ }
75
+ function bootstrapMcpSpecs(opts) {
76
+ // Provider "other": sem MCP de provisionamento. O agente instrui DNS/VPS com
77
+ // base no conhecimento do provider que o usuário indicar (ver o skill).
78
+ // Hostinger só entra com token (index.ts captura/seta antes); sem token,
79
+ // conectar falharia, então pula em vez de injetar MCPs quebrados.
80
+ const literalToken = typeof opts.hostingerToken === "string" && opts.hostingerToken.length > 0
81
+ ? opts.hostingerToken
82
+ : undefined;
83
+ const specs = opts.provider === "hostinger" && opts.hostingerTokenProvided
84
+ ? HOSTINGER_MODULES.map((mod) => ({
85
+ name: `hostinger-${mod}`,
86
+ transport: "stdio",
87
+ command: process.execPath,
88
+ args: [hostingerEntryPath(mod)],
89
+ env: { HOSTINGER_API_TOKEN: literalToken ?? "${HOSTINGER_API_TOKEN}" },
90
+ // Só marca como segredo quando é o token literal (execute): o preview
91
+ // redige. A referência de env (plan) não é segredo e pode aparecer.
92
+ ...(literalToken ? { secretEnvKeys: ["HOSTINGER_API_TOKEN"] } : {}),
93
+ note: `Hostinger ${mod}.`,
94
+ }))
95
+ : [];
96
+ // NOTE: o hub NÃO é injetado como MCP no agente. As ops do hub que o onboarding precisa saem pelo
97
+ // proxy `agents hub <op>` (hub-command.ts): menos privilégio (sem token mcp:admin na sessão do
98
+ // agente) e resolve o timing (o agente chama attach-license quando já sabe o host da instância).
99
+ return specs;
100
+ }