@fabioforest/openclaw 3.4.1 → 3.5.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/README.md +200 -2
- package/bin/openclaw.js +2 -0
- package/lib/cli/uninstall.js +194 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,7 @@ npx @fabioforest/openclaw ide install --apply
|
|
|
44
44
|
|----------|---------|-----------|
|
|
45
45
|
| Primeira vez no projeto | `init --apply` | Cria `.agent/` com templates |
|
|
46
46
|
| Atualizar skills/rules | `update --apply` | Atualiza preservando customizações |
|
|
47
|
+
| Desinstalar do projeto | `uninstall --apply` | Remove `.agent/` com backup |
|
|
47
48
|
| Ver o que está instalado | `status` | Lista componentes e config |
|
|
48
49
|
| Algo não funciona | `doctor` | Diagnóstico completo |
|
|
49
50
|
| Quero entender meu ambiente | `inspect` | Análise 100% read-only |
|
|
@@ -113,6 +114,54 @@ npx @fabioforest/openclaw update --apply --merge
|
|
|
113
114
|
|
|
114
115
|
---
|
|
115
116
|
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### `openclaw uninstall` — Desinstalar do projeto
|
|
120
|
+
|
|
121
|
+
**Quando usar:** Quando quiser remover completamente o OpenClaw de um projeto.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# 1. Simula a remoção (mostra o que seria deletado)
|
|
125
|
+
npx @fabioforest/openclaw uninstall
|
|
126
|
+
# → Mostra tree de .agent/ e openclaw.json
|
|
127
|
+
# → Alerta sobre audit logs e state que seriam perdidos
|
|
128
|
+
# → Nenhum arquivo é removido
|
|
129
|
+
|
|
130
|
+
# 2. Aplica a remoção (com backup automático)
|
|
131
|
+
npx @fabioforest/openclaw uninstall --apply
|
|
132
|
+
# → Pede para digitar "UNINSTALL" como confirmação
|
|
133
|
+
# → Oferece fazer backup (.agent.backup-<timestamp>/)
|
|
134
|
+
# → Remove .agent/ e openclaw.json
|
|
135
|
+
# → Salva log de auditoria no diretório
|
|
136
|
+
|
|
137
|
+
# 3. Remoção forçada (sem backup, com --yes pula confirmação)
|
|
138
|
+
npx @fabioforest/openclaw uninstall --apply --force --yes
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Saída de exemplo (modo PLAN):**
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
🗑️ OpenClaw Uninstall
|
|
145
|
+
|
|
146
|
+
📂 Diretório: /home/user/meu-projeto
|
|
147
|
+
|
|
148
|
+
🔴 REMOVER .agent/ (25 arquivos)
|
|
149
|
+
📁 agents (3 arquivos)
|
|
150
|
+
📁 audit (1 arquivos)
|
|
151
|
+
📁 hooks (1 arquivos)
|
|
152
|
+
📁 rules (5 arquivos)
|
|
153
|
+
📁 skills (11 arquivos)
|
|
154
|
+
📁 workflows (7 arquivos)
|
|
155
|
+
🔴 REMOVER openclaw.json
|
|
156
|
+
|
|
157
|
+
⚠️ 1 log(s) de auditoria serão perdidos!
|
|
158
|
+
|
|
159
|
+
🔒 Modo PLAN (Read-Only). Nenhuma alteração feita.
|
|
160
|
+
Para desinstalar, rode: npx @fabioforest/openclaw uninstall --apply
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
116
165
|
### `openclaw inspect` — Analisar ambiente (read-only)
|
|
117
166
|
|
|
118
167
|
**Quando usar:** Antes de qualquer ação, para entender o contexto. 100% read-only — nunca altera nada.
|
|
@@ -419,6 +468,155 @@ npx @fabioforest/openclaw assist
|
|
|
419
468
|
|
|
420
469
|
---
|
|
421
470
|
|
|
471
|
+
## 💬 Exemplo Real: Usando o OpenClaw na IDE (Chat)
|
|
472
|
+
|
|
473
|
+
O OpenClaw funciona como agente via chat na IDE. Aqui está uma simulação de como seria o fluxo real:
|
|
474
|
+
|
|
475
|
+
### Exemplo 1: Otimizar perfil do LinkedIn
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
👤 Você (chat na IDE):
|
|
479
|
+
"Quero otimizar meu perfil do LinkedIn para vagas de AI Engineer"
|
|
480
|
+
|
|
481
|
+
🤖 Agente (openclaw-router detecta: linkedin-optimizer):
|
|
482
|
+
📋 INSPECT ─ Coletando contexto:
|
|
483
|
+
• Objetivo: otimizar perfil LinkedIn para AI Engineer
|
|
484
|
+
• Idioma: pt-BR
|
|
485
|
+
• Skills instaladas: linkedin-optimizer ✅
|
|
486
|
+
|
|
487
|
+
📝 PLAN ─ Proposta de ações:
|
|
488
|
+
1. Analisar headline atual e propor 2 versões A/B
|
|
489
|
+
2. Reescrever seção "Sobre" com keywords de AI/MLOps
|
|
490
|
+
3. Sugerir ajustes nas experiências com métricas
|
|
491
|
+
4. Gerar checklist de publicação
|
|
492
|
+
|
|
493
|
+
⚠️ RESTRIÇÃO: LinkedIn proíbe automação. Todo conteúdo
|
|
494
|
+
será gerado como rascunho para aplicação manual.
|
|
495
|
+
|
|
496
|
+
Deseja prosseguir? (S/n)
|
|
497
|
+
|
|
498
|
+
👤 Você: "S"
|
|
499
|
+
|
|
500
|
+
🤖 Agente:
|
|
501
|
+
✅ APPLY ─ Rascunhos salvos em .agent/state/linkedin/drafts.md
|
|
502
|
+
|
|
503
|
+
## Headline (opção A)
|
|
504
|
+
"AI Engineer | MLOps | Python | RAG & LLMs | Open Source"
|
|
505
|
+
|
|
506
|
+
## Headline (opção B)
|
|
507
|
+
"Engenheiro de IA | Construindo pipelines de ML em produção"
|
|
508
|
+
|
|
509
|
+
📝 AUDIT ─ log salvo em .agent/audit/
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
### Exemplo 2: Testar performance de um site
|
|
513
|
+
|
|
514
|
+
```
|
|
515
|
+
👤 Você:
|
|
516
|
+
"Testa a performance do meu site https://meu-portfolio.dev"
|
|
517
|
+
|
|
518
|
+
🤖 Agente (openclaw-router detecta: site-tester):
|
|
519
|
+
📋 INSPECT:
|
|
520
|
+
• URL: https://meu-portfolio.dev
|
|
521
|
+
• robots.txt: verificado ✅
|
|
522
|
+
• Ferramentas disponíveis: PageSpeed Insights API
|
|
523
|
+
|
|
524
|
+
📝 PLAN:
|
|
525
|
+
1. Rodar Lighthouse via PageSpeed Insights (sem infra local)
|
|
526
|
+
2. Coletar métricas: Performance, SEO, Acessibilidade, PWA
|
|
527
|
+
3. Listar as 5 principais oportunidades de melhoria
|
|
528
|
+
4. Salvar relatório em .agent/state/site-tests/
|
|
529
|
+
|
|
530
|
+
Confirmar execução?
|
|
531
|
+
|
|
532
|
+
👤 Você: "sim"
|
|
533
|
+
|
|
534
|
+
🤖 Agente:
|
|
535
|
+
✅ Resultados:
|
|
536
|
+
• Performance: 87 → otimizar imagens (ganho estimado: +8pts)
|
|
537
|
+
• SEO: 95 ✅
|
|
538
|
+
• Acessibilidade: 72 → falta alt em 3 imagens + contraste baixo
|
|
539
|
+
• PWA: 60 → falta manifest.json e service worker
|
|
540
|
+
|
|
541
|
+
📊 Relatório salvo em .agent/state/site-tests/2026-02-19.json
|
|
542
|
+
📝 Audit salvo
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Exemplo 3: Atualizar skills após nova versão
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
👤 Você:
|
|
549
|
+
"Saiu versão nova do OpenClaw, como atualizo?"
|
|
550
|
+
|
|
551
|
+
🤖 Agente (openclaw-router detecta: assist):
|
|
552
|
+
Recomendo o seguinte fluxo:
|
|
553
|
+
|
|
554
|
+
1. Primeiro, veja o que mudaria (modo PLAN, seguro):
|
|
555
|
+
$ npx @fabioforest/openclaw update
|
|
556
|
+
|
|
557
|
+
2. Se estiver tudo OK, aplique:
|
|
558
|
+
$ npx @fabioforest/openclaw update --apply
|
|
559
|
+
|
|
560
|
+
3. Para preservar customizações:
|
|
561
|
+
$ npx @fabioforest/openclaw update --apply --merge
|
|
562
|
+
|
|
563
|
+
O update faz backup automático de arquivos customizados
|
|
564
|
+
antes de sobrescrever, e copia novos templates.
|
|
565
|
+
|
|
566
|
+
Quer que eu execute o passo 1 agora?
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Exemplo 4: Desinstalar o OpenClaw de um projeto
|
|
570
|
+
|
|
571
|
+
```
|
|
572
|
+
👤 Você:
|
|
573
|
+
"Quero remover o OpenClaw deste projeto"
|
|
574
|
+
|
|
575
|
+
🤖 Agente:
|
|
576
|
+
Vou simular a remoção primeiro (modo PLAN, seguro):
|
|
577
|
+
|
|
578
|
+
$ npx @fabioforest/openclaw uninstall
|
|
579
|
+
|
|
580
|
+
🗑️ PLAN — Seria removido:
|
|
581
|
+
.agent/ (25 arquivos, 15 skills, 5 rules)
|
|
582
|
+
openclaw.json
|
|
583
|
+
⚠️ 3 logs de auditoria seriam perdidos
|
|
584
|
+
|
|
585
|
+
Para aplicar de fato:
|
|
586
|
+
$ npx @fabioforest/openclaw uninstall --apply
|
|
587
|
+
|
|
588
|
+
O sistema vai pedir que você digite "UNINSTALL"
|
|
589
|
+
e oferecerá fazer backup antes de remover.
|
|
590
|
+
|
|
591
|
+
Quer que eu execute?
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## 🔄 Ciclo de Vida Completo
|
|
597
|
+
|
|
598
|
+
```
|
|
599
|
+
📦 INSTALAR → npx @fabioforest/openclaw init --apply
|
|
600
|
+
ou: npx @fabioforest/openclaw ide install --apply
|
|
601
|
+
|
|
602
|
+
🔍 INSPECIONAR → npx @fabioforest/openclaw inspect
|
|
603
|
+
npx @fabioforest/openclaw status
|
|
604
|
+
|
|
605
|
+
🛠️ USAR → Chat na IDE (skills + router fazem o resto)
|
|
606
|
+
ou: npx @fabioforest/openclaw assist
|
|
607
|
+
|
|
608
|
+
🔄 ATUALIZAR → npx @fabioforest/openclaw update --apply
|
|
609
|
+
(preserva customizações com --merge)
|
|
610
|
+
|
|
611
|
+
🏥 DIAGNOSTICAR → npx @fabioforest/openclaw doctor
|
|
612
|
+
npx @fabioforest/openclaw debug
|
|
613
|
+
|
|
614
|
+
🗑️ DESINSTALAR → npx @fabioforest/openclaw uninstall --apply
|
|
615
|
+
(backup automático + confirmação forte)
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
422
620
|
## 🛠️ Desenvolvimento
|
|
423
621
|
|
|
424
622
|
```bash
|
|
@@ -445,8 +643,8 @@ Todas as flags funcionam com qualquer comando:
|
|
|
445
643
|
|------|-----------|--------|
|
|
446
644
|
| `--plan` | Modo simulação (read-only) | **Sim** |
|
|
447
645
|
| `--apply` | Modo execução (aplica alterações) | Não |
|
|
448
|
-
| `--yes, -y` | Pula confirmações | Não |
|
|
449
|
-
| `--force, -f` | Permite operações destrutivas | Não |
|
|
646
|
+
| `--yes, -y` | Pula confirmações interativas | Não |
|
|
647
|
+
| `--force, -f` | Permite operações destrutivas (sem backup no uninstall) | Não |
|
|
450
648
|
| `--path, -p <dir>` | Diretório alvo | `./` |
|
|
451
649
|
| `--quiet, -q` | Saída mínima | Não |
|
|
452
650
|
| `--no-audit` | Desabilita logs de auditoria | Não |
|
package/bin/openclaw.js
CHANGED
|
@@ -24,6 +24,7 @@ const pkg = require("../package.json");
|
|
|
24
24
|
const COMMANDS = {
|
|
25
25
|
init: "../lib/cli/init",
|
|
26
26
|
update: "../lib/cli/update",
|
|
27
|
+
uninstall: "../lib/cli/uninstall",
|
|
27
28
|
status: "../lib/cli/status",
|
|
28
29
|
doctor: "../lib/cli/doctor",
|
|
29
30
|
debug: "../lib/cli/debug",
|
|
@@ -92,6 +93,7 @@ function showHelp() {
|
|
|
92
93
|
Comandos:
|
|
93
94
|
init Instala templates .agent/ no projeto atual
|
|
94
95
|
update Atualiza templates preservando customizações
|
|
96
|
+
uninstall Remove .agent/ e openclaw.json (com backup)
|
|
95
97
|
status Mostra status da instalação
|
|
96
98
|
doctor Healthcheck automatizado do ambiente
|
|
97
99
|
setup Roda wizard interativo de configuração
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Comando CLI: uninstall
|
|
5
|
+
*
|
|
6
|
+
* Remove a instalação do OpenClaw (.agent/) de um projeto.
|
|
7
|
+
* Segue o protocolo consent-first:
|
|
8
|
+
* - Modo PLAN por padrão (mostra o que seria removido)
|
|
9
|
+
* - Exige --apply para executar
|
|
10
|
+
* - Exige confirmação forte (digitar frase)
|
|
11
|
+
* - Backup opcional antes de remover
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require("fs");
|
|
15
|
+
const path = require("path");
|
|
16
|
+
const readline = require("readline");
|
|
17
|
+
const { detectContext, getAuditHeader } = require("../context");
|
|
18
|
+
|
|
19
|
+
function ask(q) {
|
|
20
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
21
|
+
return new Promise((res) => rl.question(q, (ans) => { rl.close(); res(ans.trim()); }));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Conta arquivos recursivamente em um diretório.
|
|
26
|
+
*/
|
|
27
|
+
function countFiles(dir) {
|
|
28
|
+
let count = 0;
|
|
29
|
+
if (!fs.existsSync(dir)) return 0;
|
|
30
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
31
|
+
if (entry.isDirectory()) {
|
|
32
|
+
count += countFiles(path.join(dir, entry.name));
|
|
33
|
+
} else {
|
|
34
|
+
count++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return count;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Lista o conteúdo de um diretório de forma visual (tree).
|
|
42
|
+
*/
|
|
43
|
+
function listTree(dir, prefix = "") {
|
|
44
|
+
const lines = [];
|
|
45
|
+
if (!fs.existsSync(dir)) return lines;
|
|
46
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
47
|
+
entries.forEach((entry, i) => {
|
|
48
|
+
const isLast = i === entries.length - 1;
|
|
49
|
+
const connector = isLast ? "└── " : "├── ";
|
|
50
|
+
const icon = entry.isDirectory() ? "📁" : "📄";
|
|
51
|
+
lines.push(`${prefix}${connector}${icon} ${entry.name}`);
|
|
52
|
+
if (entry.isDirectory()) {
|
|
53
|
+
const childPrefix = prefix + (isLast ? " " : "│ ");
|
|
54
|
+
lines.push(...listTree(path.join(dir, entry.name), childPrefix));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return lines;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Executa o comando uninstall.
|
|
62
|
+
* @param {object} options
|
|
63
|
+
* @param {string} options.targetPath — diretório alvo
|
|
64
|
+
* @param {object} options.flags — flags do CLI
|
|
65
|
+
*/
|
|
66
|
+
async function run({ targetPath, flags }) {
|
|
67
|
+
const agentDir = path.join(targetPath, ".agent");
|
|
68
|
+
const configFile = path.join(targetPath, "openclaw.json");
|
|
69
|
+
const planMode = !flags.apply;
|
|
70
|
+
const ctx = detectContext(targetPath);
|
|
71
|
+
|
|
72
|
+
console.log("\n🗑️ OpenClaw Uninstall\n");
|
|
73
|
+
|
|
74
|
+
// Verificar se existe instalação
|
|
75
|
+
if (!fs.existsSync(agentDir) && !fs.existsSync(configFile)) {
|
|
76
|
+
console.log("ℹ️ Nenhuma instalação do OpenClaw encontrada neste diretório.");
|
|
77
|
+
console.log(` Path: ${targetPath}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Mostrar o que será removido
|
|
82
|
+
console.log(` 📂 Diretório: ${targetPath}`);
|
|
83
|
+
console.log("");
|
|
84
|
+
|
|
85
|
+
const toRemove = [];
|
|
86
|
+
|
|
87
|
+
if (fs.existsSync(agentDir)) {
|
|
88
|
+
const fileCount = countFiles(agentDir);
|
|
89
|
+
toRemove.push({ path: agentDir, label: ".agent/", files: fileCount, isDir: true });
|
|
90
|
+
console.log(` 🔴 REMOVER .agent/ (${fileCount} arquivos)`);
|
|
91
|
+
|
|
92
|
+
// Mostrar tree resumido (primeiro nível)
|
|
93
|
+
const entries = fs.readdirSync(agentDir, { withFileTypes: true });
|
|
94
|
+
entries.forEach(e => {
|
|
95
|
+
const icon = e.isDirectory() ? "📁" : "📄";
|
|
96
|
+
const subCount = e.isDirectory() ? ` (${countFiles(path.join(agentDir, e.name))} arquivos)` : "";
|
|
97
|
+
console.log(` ${icon} ${e.name}${subCount}`);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (fs.existsSync(configFile)) {
|
|
102
|
+
toRemove.push({ path: configFile, label: "openclaw.json", isDir: false });
|
|
103
|
+
console.log(` 🔴 REMOVER openclaw.json`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Verificar audit logs que seriam perdidos
|
|
107
|
+
const auditDir = path.join(agentDir, "audit");
|
|
108
|
+
if (fs.existsSync(auditDir)) {
|
|
109
|
+
const auditCount = countFiles(auditDir);
|
|
110
|
+
if (auditCount > 0) {
|
|
111
|
+
console.log(`\n ⚠️ ${auditCount} log(s) de auditoria serão perdidos!`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Verificar state que seria perdido
|
|
116
|
+
const stateDir = path.join(agentDir, "state");
|
|
117
|
+
if (fs.existsSync(stateDir)) {
|
|
118
|
+
const stateCount = countFiles(stateDir);
|
|
119
|
+
if (stateCount > 0) {
|
|
120
|
+
console.log(` ⚠️ ${stateCount} arquivo(s) de estado serão perdidos (mission_control, MEMORY)!`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Modo PLAN: não faz nada
|
|
125
|
+
if (planMode) {
|
|
126
|
+
console.log("\n🔒 Modo PLAN (Read-Only). Nenhuma alteração feita.");
|
|
127
|
+
console.log(" Para desinstalar, rode: npx @fabioforest/openclaw uninstall --apply");
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Modo APPLY: pedir confirmação forte
|
|
132
|
+
console.log("");
|
|
133
|
+
if (!flags.yes) {
|
|
134
|
+
const confirm = await ask("⚠️ Digite 'UNINSTALL' para confirmar a remoção: ");
|
|
135
|
+
if (confirm !== "UNINSTALL") {
|
|
136
|
+
console.log("⏹️ Cancelado. Nada foi removido.");
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Backup opcional
|
|
142
|
+
if (!flags.force) {
|
|
143
|
+
const doBackup = flags.yes ? "s" : await ask("💾 Fazer backup antes de remover? (S/n): ");
|
|
144
|
+
if (doBackup.toLowerCase() !== "n") {
|
|
145
|
+
const backupName = `.agent.backup-${Date.now()}`;
|
|
146
|
+
const backupPath = path.join(targetPath, backupName);
|
|
147
|
+
try {
|
|
148
|
+
fs.cpSync(agentDir, backupPath, { recursive: true });
|
|
149
|
+
console.log(` ✅ Backup criado: ${backupName}/`);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error(` ⚠️ Falha no backup: ${err.message}`);
|
|
152
|
+
const cont = await ask(" Continuar sem backup? (y/N): ");
|
|
153
|
+
if (cont.toLowerCase() !== "y") {
|
|
154
|
+
console.log("⏹️ Cancelado.");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Executar remoção
|
|
162
|
+
const audit = [getAuditHeader(ctx, "uninstall", flags)];
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
for (const item of toRemove) {
|
|
166
|
+
if (item.isDir) {
|
|
167
|
+
fs.rmSync(item.path, { recursive: true, force: true });
|
|
168
|
+
} else {
|
|
169
|
+
fs.unlinkSync(item.path);
|
|
170
|
+
}
|
|
171
|
+
console.log(` ✅ Removido: ${item.label}`);
|
|
172
|
+
audit.push(`- ACT: REMOVED ${item.label}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log("\n✨ OpenClaw desinstalado com sucesso!");
|
|
176
|
+
console.log(" Para reinstalar: npx @fabioforest/openclaw init --apply\n");
|
|
177
|
+
|
|
178
|
+
// Gravar audit no diretório pai (já que .agent/ foi removido)
|
|
179
|
+
if (flags.audit !== false) {
|
|
180
|
+
const filename = `openclaw-uninstall-${new Date().toISOString().replace(/[:.]/g, "-")}.md`;
|
|
181
|
+
const auditPath = path.join(targetPath, filename);
|
|
182
|
+
try {
|
|
183
|
+
fs.writeFileSync(auditPath, audit.join("\n") + "\n", "utf8");
|
|
184
|
+
console.log(` 📝 Log de auditoria: ${filename}`);
|
|
185
|
+
} catch (e) { /* silencioso */ }
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
} catch (err) {
|
|
189
|
+
console.error(`\n❌ Falha: ${err.message}`);
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = { run };
|