iron-edge 2.8.0 → 2.8.1

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
@@ -239,7 +239,7 @@ O que esperar:
239
239
 
240
240
  0. **Na primeira vez** (ou quando o texto mudar), ele mostra em poucas linhas o que o canal faz, o que sai da máquina e o que atualiza sozinho, e pergunta `Continuar?`. Não (ou sem terminal interativo) = nada é ligado, nem as flags `--sem-feed`/`--com-feed`. O aceite fica em `~/.iron/office-consent.json`.
241
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
- 2. Instala (ou atualiza) o plugin de canal `iron-office` e liga o conector oficial do **Meta Ads** (`claude mcp add --scope user --transport http meta-ads https://mcp.facebook.com/ads`; desde a 2.5.0, melhor-esforço: se falhar, o Iron abre normal). O login na Meta é seu: no Iron, digite `/mcp`, escolha `meta-ads` e entre com o seu Facebook. Depois abre o Claude Code com o canal ligado, **dentro do seu cofre** (desde a 2.8.0): o caminho vem do `vault_path` do `~/.iron/config.yaml` (ou `obsidian_vault_path` / `obsidian.vault_path`, de instalações antigas); se ele aponta pra uma pasta dentro do cofre, o Iron sobe até a raiz (a pasta com `.obsidian`). Sem cofre, abre onde você estava e avisa: `npx iron-edge install --cofre`.
242
+ 2. Instala (ou atualiza) o plugin de canal `iron-office` e liga o conector oficial do **Meta Ads** (`claude mcp add --scope user --transport http meta-ads https://mcp.facebook.com/ads`; desde a 2.5.0, melhor-esforço: se falhar, o Iron abre normal). O login na Meta é seu: no Iron, digite `/mcp`, escolha `meta-ads` e entre com o seu Facebook. Depois abre o Claude Code com o canal ligado, **dentro do seu cofre** (desde a 2.8.1): o caminho vem do `vault_path` do `~/.iron/config.yaml` (ou `obsidian_vault_path` / `obsidian.vault_path`, de instalações antigas); se ele aponta pra uma pasta dentro do cofre, o Iron sobe até a raiz (a pasta com `.obsidian`). Sem cofre, abre onde você estava e avisa: `npx iron-edge install --cofre`.
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. **Ficha da loja** (skill `loja`, desde a 2.8.0): no site, "Começar com a loja X" (ou diga "monta a ficha"). O Iron lê a Shopify da loja, aponta o que está errado, pergunta só o que falta e grava `Projetos/<loja>/PROJETO.md` e `brand.json` no seu cofre; pro site vai só um resumo de até 600 caracteres (sem sócio, fornecedor, conta de anúncio nem pedido). Daí em diante todo pedido daquela loja chega com a ficha.
@@ -155,19 +155,40 @@ function buildClaudeArgs(argv) {
155
155
  return args.concat(extra);
156
156
  }
157
157
 
158
+ // Le um campo escalar do config.yaml SEM biblioteca: o pacote publicado nao tem dependencias (o js-yaml e' so'
159
+ // de desenvolvimento; usado aqui, faltava no npx e o erro engolido fazia abrir fora do cofre, 2.8.0).
160
+ // Topo (`vault_path: ...`) ou dentro de um bloco (`obsidian:` + linhas recuadas). Aspas duplas, simples ou sem aspas.
161
+ function campoYaml(txt, nome, bloco) {
162
+ const linhas = String(txt || '').replace(/^\uFEFF/, '').split(/\r?\n/);
163
+ let dentro = !bloco;
164
+ for (const l of linhas) {
165
+ if (/^\s*(#|$)/.test(l)) continue;
166
+ if (bloco) {
167
+ if (/^\S/.test(l)) { dentro = new RegExp('^' + bloco + ':\\s*(#.*)?$').test(l); continue; }
168
+ if (!dentro) continue;
169
+ } else if (/^\s/.test(l)) continue;
170
+ const m = l.match(new RegExp('^\\s*' + nome + ':\\s*(.*)$'));
171
+ if (!m) continue;
172
+ const v = m[1].trim();
173
+ if (v.startsWith('"')) { const q = v.match(/^"((?:[^"\\]|\\.)*)"/); return q ? q[1].replace(/\\(["\\])/g, '$1') : ''; }
174
+ if (v.startsWith("'")) { const q = v.match(/^'((?:[^']|'')*)'/); return q ? q[1].replace(/''/g, "'") : ''; }
175
+ return v.replace(/\s+#.*$/, '').trim();
176
+ }
177
+ return '';
178
+ }
179
+
158
180
  // Onda 26b: a pasta do cofre, lida do ~/.iron/config.yaml (vault_path -> obsidian_vault_path ->
159
181
  // obsidian.vault_path; `~` expandido). Caminho apontado pra dentro do cofre (ex.: uma pasta de projeto) sobe
160
182
  // ate a raiz, marcada pela pasta .obsidian. Devolve { cwd, configured }: cwd undefined = nao achou (abre
161
183
  // onde o aluno estava, como antes); configured = o caminho do config (pro aviso), ou '' sem campo.
162
184
  function resolveCwd(home) {
163
185
  const h = home || os.homedir();
164
- let cfg = null;
165
- try { cfg = require('js-yaml').load(fs.readFileSync(path.join(h, '.iron', 'config.yaml'), 'utf8')); } catch (_) { cfg = null; }
166
- const str = (v) => (typeof v === 'string' && v.trim() && v.trim() !== '~' ? v.trim() : '');
167
- let raw = '';
168
- if (cfg && typeof cfg === 'object') {
169
- raw = str(cfg.vault_path) || str(cfg.obsidian_vault_path) || str(cfg.obsidian && cfg.obsidian.vault_path);
170
- }
186
+ let txt = '';
187
+ try { txt = fs.readFileSync(path.join(h, '.iron', 'config.yaml'), 'utf8'); } catch (_) { txt = ''; }
188
+ // `~`, `null` e vazio = sem cofre (o js-yaml da 2.8.0 lia `null` como nulo; aqui viraria HOME/null)
189
+ const str = (v) => (typeof v === 'string' && v.trim() && !/^(~|null)$/i.test(v.trim()) ? v.trim() : '');
190
+ const raw = str(campoYaml(txt, 'vault_path')) || str(campoYaml(txt, 'obsidian_vault_path'))
191
+ || str(campoYaml(txt, 'vault_path', 'obsidian'));
171
192
  if (!raw) return { cwd: undefined, configured: '' };
172
193
  // ~ e caminho relativo contam a partir da HOME (nunca da pasta onde o aluno digitou o comando)
173
194
  const abs = path.resolve(h, raw.replace(/^~(?=$|[\\/])/, h));
@@ -329,7 +350,7 @@ async function main(argv) {
329
350
  return r.status ?? 1;
330
351
  }
331
352
 
332
- module.exports = { resolveCwd, CONSENT_VERSION, CONSENT_TEXT, consentPath, consentimentoOk, pedirConsentimento, aplicarFlagsFeed, metaAds, META_ADS_MCP, avisoPluginNovo, pluginVersion, buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
353
+ module.exports = { resolveCwd, campoYaml, CONSENT_VERSION, CONSENT_TEXT, consentPath, consentimentoOk, pedirConsentimento, aplicarFlagsFeed, metaAds, META_ADS_MCP, avisoPluginNovo, pluginVersion, buildClaudeArgs, keyPath, readKey, keyFileExists, isValidKey, ping, resolveClaude, CHANNEL, PLUGIN, MARKETPLACE_REPO, KEY_RE };
333
354
 
334
355
  if (require.main === module) {
335
356
  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.8.0",
3
+ "version": "2.8.1",
4
4
  "description": "Ecossistema de agentes para Claude Code: 44 agentes de topo, 18 squads e 16 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",