iron-edge 2.4.5 → 2.4.6

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.
@@ -5,7 +5,8 @@
5
5
  *
6
6
  * Regras:
7
7
  * - Windows: nao faz nada (o PowerShell nao le .zshrc/.bashrc). O aluno usa `npx iron-edge office`.
8
- * - escolhe ~/.zshrc se existir, senao ~/.bashrc se existir, senao cria ~/.zshrc (padrao do Mac).
8
+ * - Mac: sempre ~/.zshrc (o shell padrao do Mac le so ele; um alias no .bashrc nunca carregaria).
9
+ * Linux: ~/.zshrc se existir, senao ~/.bashrc se existir, senao cria ~/.zshrc.
9
10
  * - se o arquivo ja tem `alias ironoffice=`, nao mexe: nunca duplica.
10
11
  * - so' ACRESCENTA no fim. Nunca remove nem edita linha existente: o arquivo e' do aluno.
11
12
  * - escrita atomica: grava ao lado e renomeia por cima. Se o .zshrc e' um link (dotfiles),
@@ -26,7 +27,8 @@ const LINHA = 'alias ironoffice="npx iron-edge office"';
26
27
  const BLOCO = '\n# Iron Edge: atalho do canal do Iron Office\n' + LINHA + '\n';
27
28
  const JA_TEM = /^\s*alias\s+ironoffice=/m;
28
29
 
29
- function arquivoDoShell(home) {
30
+ function arquivoDoShell(home, platform) {
31
+ if (platform === 'darwin') return path.join(home, '.zshrc');
30
32
  for (const nome of ['.zshrc', '.bashrc']) {
31
33
  const p = path.join(home, nome);
32
34
  if (fs.existsSync(p)) return p;
@@ -42,7 +44,7 @@ function criarAtalho(opts) {
42
44
  if (o.semAtalho) return { pulado: 'sem-atalho' };
43
45
  if (platform === 'win32') return { pulado: 'windows' };
44
46
  const home = o.HOME || os.homedir();
45
- const rc = arquivoDoShell(home);
47
+ const rc = arquivoDoShell(home, platform);
46
48
  let link = false;
47
49
  try { link = fs.lstatSync(rc).isSymbolicLink(); } catch (_) { /* nao existe */ }
48
50
  let real = rc;
@@ -94,11 +94,17 @@ function checkPlugin(claudeBin) {
94
94
  // alias ironoffice (installer/atalho.js): no Windows nao existe, entao conta como ok
95
95
  function checkAtalho(home) {
96
96
  if (IS_WIN) return item(true, 'não se aplica (Windows: npx iron-edge office)');
97
+ // nao existe = segue procurando; existe e nao abre = diz isso (o update tambem nao conseguiria)
98
+ let semLeitura = '';
97
99
  for (const nome of ['.zshrc', '.bashrc']) {
98
100
  let txt = '';
99
- try { txt = fs.readFileSync(path.join(home, nome), 'utf8'); } catch (_) { continue; }
101
+ try { txt = fs.readFileSync(path.join(home, nome), 'latin1'); } catch (e) {
102
+ if (!semLeitura && e && e.code !== 'ENOENT') semLeitura = nome;
103
+ continue;
104
+ }
100
105
  if (/^\s*alias\s+ironoffice=/m.test(txt)) return item(true, 'ironoffice em ~/' + nome);
101
106
  }
107
+ if (semLeitura) return item(false, 'não consegui ler ~/' + semLeitura);
102
108
  return item(false, 'ausente: rode npx iron-edge update');
103
109
  }
104
110
 
@@ -94,6 +94,32 @@ function resolveClaude() {
94
94
  return null;
95
95
  }
96
96
 
97
+ // Versao do plugin instalado, lida do `claude plugin list` ("Version: x.y.z" logo abaixo do nome).
98
+ // Timeout de 5 s: um `claude plugin list` travado nao pode segurar a abertura do canal (estourou = sem aviso).
99
+ function pluginVersion(claude) {
100
+ const r = run(claude, ['plugin', 'list'], { timeout: 5000 });
101
+ if (r.error) return '';
102
+ const out = (r.stdout || '') + (r.stderr || '');
103
+ const i = out.indexOf(PLUGIN);
104
+ if (i < 0) return '';
105
+ const m = out.slice(i).match(/Version:\s*([0-9][\w.-]*)/);
106
+ return m ? m[1] : '';
107
+ }
108
+
109
+ // Plugin mudou desde a ultima abertura do canal: sessoes do Claude abertas antes rodam o hook velho,
110
+ // que o painel nao aceita mais (onda 10). Avisa uma vez por versao; guarda a ultima em ~/.iron.
111
+ // Primeira abertura (sem registro anterior): grava calado, porque quem acabou de instalar nao tem sessao velha.
112
+ function avisoPluginNovo(claude, home) {
113
+ const atual = pluginVersion(claude);
114
+ if (!atual) return;
115
+ const arq = path.join(home || os.homedir(), '.iron', 'office-plugin-version');
116
+ let anterior = '';
117
+ try { anterior = fs.readFileSync(arq, 'utf8').trim(); } catch (_) { /* primeira vez */ }
118
+ if (anterior === atual) return;
119
+ if (anterior) console.log(' [aviso] Plugin atualizado: sessoes do Claude abertas antes disso nao aparecem mais no painel; abra o canal de novo.');
120
+ try { fs.mkdirSync(path.dirname(arq), { recursive: true }); fs.writeFileSync(arq, atual + '\n'); } catch (_) { /* aviso de novo na proxima */ }
121
+ }
122
+
97
123
  function step(claude, label, args, okPatterns) {
98
124
  const r = run(claude, args);
99
125
  const out = ((r.stdout || '') + (r.stderr || '')).trim();
@@ -143,6 +169,7 @@ async function main(argv) {
143
169
  }
144
170
  // atualizar e' melhor-esforco: sem internet no meio, segue com a versao ja instalada
145
171
  step(claude, 'atualizacao do plugin', ['plugin', 'update', PLUGIN], [/already|up.to.date|latest/i]);
172
+ avisoPluginNovo(claude);
146
173
 
147
174
  const safe = argv.includes('--safe');
148
175
  console.log('');
@@ -163,7 +190,7 @@ async function main(argv) {
163
190
  return r.status ?? 1;
164
191
  }
165
192
 
166
- module.exports = { buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
193
+ module.exports = { avisoPluginNovo, pluginVersion, buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
167
194
 
168
195
  if (require.main === module) {
169
196
  main(process.argv.slice(2)).then(code => process.exit(code), err => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iron-edge",
3
- "version": "2.4.5",
3
+ "version": "2.4.6",
4
4
  "description": "Ecossistema de agentes para Claude Code: 44 agentes de topo, 18 squads e 14 skills, com quality gate, memoria, instalador que nunca sobrescreve o comando office (chat do Iron Office no dashboard; confere a chave com o site antes de abrir o Claude) e o doctor (mede a maquina e acende o Setup do site).",
5
5
  "keywords": [
6
6
  "claude",