iron-edge 2.4.5 → 2.4.7

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 CHANGED
@@ -234,15 +234,16 @@ Converse com o Iron pelo dashboard ([iron-office.vercel.app](https://iron-office
234
234
  npx iron-edge office
235
235
  ```
236
236
 
237
- Antes, faça o **passo 4** do onboarding do Iron Office (ele salva a sua chave em `~/.claude/iron-office-api-key`).
237
+ Antes, faça o **passo 2** do onboarding do Iron Office (ele salva a sua chave em `~/.claude/iron-office-api-key`).
238
238
 
239
239
  O que esperar:
240
240
 
241
- 1. O comando confere a sua chave (formato `iok_…` e aceita pelo site) **antes** de abrir o Claude Code. Chave trocada ou fora do formato: ele para e manda refazer o passo 4, em vez de abrir uma sessão que nunca fica online.
241
+ 1. O comando confere a sua chave (formato `iok_…` e aceita pelo site) **antes** de abrir o Claude Code. Chave trocada ou fora do formato: ele para e manda refazer o passo 2, em vez de abrir uma sessão que nunca fica online.
242
242
  2. Instala (ou atualiza) o plugin de canal `iron-office` e abre o Claude Code com ele ligado.
243
243
  3. O Claude Code mostra um **aviso de tela cheia**: canais ainda são recurso em teste. Aceite.
244
244
  4. Abra a página **Iron** do dashboard. Em até 1 minuto aparece "Iron online". Escreva ali e o Iron responde ali.
245
245
  5. **Deixe essa aba do terminal aberta.** É ela que faz o Iron responder no site.
246
+ 6. **Pra fechar:** Ctrl+C duas vezes ou `/exit`, e o escritório anoitece em 1 a 2 segundos. No **Warp**, fechar a aba pelo X demora cerca de 1 minuto: o Warp guarda a aba fechada pra poder reabrir, e nesse tempo o canal ainda está vivo. Feche com Ctrl+C antes do X, ou desligue a reabertura de abas fechadas nas configurações do Warp.
246
247
 
247
248
  Por padrão a sessão do `office` roda **sem pedir licença** a cada ferramenta (é o que deixa o Iron trabalhar enquanto você está só no site). `npx iron-edge office --safe` abre pedindo licença a cada ferramenta. Qualquer outro argumento vai direto pro `claude`.
248
249
 
@@ -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('');
@@ -153,6 +180,7 @@ async function main(argv) {
153
180
  console.log('enquanto voce esta no site). Quer aprovar cada passo? Rode: npx iron-edge office --safe');
154
181
  }
155
182
  console.log('Deixe esta aba aberta: e ela que faz o Iron responder no site.');
183
+ console.log('Pra fechar: Ctrl+C duas vezes (no Warp, antes do X).');
156
184
  console.log('');
157
185
 
158
186
  const r = spawnSync(claude, buildClaudeArgs(argv), {
@@ -163,7 +191,7 @@ async function main(argv) {
163
191
  return r.status ?? 1;
164
192
  }
165
193
 
166
- module.exports = { buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
194
+ module.exports = { avisoPluginNovo, pluginVersion, buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
167
195
 
168
196
  if (require.main === module) {
169
197
  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.7",
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",