@neetru/cli 2.8.0 → 2.9.3
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/CHANGELOG.md +128 -0
- package/dist/commands/admin/sdk-credential.d.ts +19 -0
- package/dist/commands/admin/sdk-credential.js +169 -0
- package/dist/commands/admin/sdk-credential.js.map +1 -0
- package/dist/commands/bug.d.ts +87 -0
- package/dist/commands/bug.js +419 -0
- package/dist/commands/bug.js.map +1 -0
- package/dist/commands/customers.d.ts +17 -0
- package/dist/commands/customers.js +160 -0
- package/dist/commands/customers.js.map +1 -0
- package/dist/commands/db.d.ts +4 -0
- package/dist/commands/db.js +380 -64
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/docs.d.ts +4 -0
- package/dist/commands/docs.js +99 -7
- package/dist/commands/docs.js.map +1 -1
- package/dist/commands/doctor.js +4 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/marketplace.d.ts +36 -0
- package/dist/commands/marketplace.js +584 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/new.js +196 -37
- package/dist/commands/new.js.map +1 -1
- package/dist/commands/open.d.ts +8 -0
- package/dist/commands/open.js +61 -13
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/products.d.ts +23 -0
- package/dist/commands/products.js +39 -1
- package/dist/commands/products.js.map +1 -1
- package/dist/commands/tenants.js +24 -2
- package/dist/commands/tenants.js.map +1 -1
- package/dist/commands/ui.d.ts +1 -1
- package/dist/commands/ui.js +172 -2
- package/dist/commands/ui.js.map +1 -1
- package/dist/commands/workspaces.d.ts +10 -1
- package/dist/commands/workspaces.js +145 -23
- package/dist/commands/workspaces.js.map +1 -1
- package/dist/index.js +327 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/config-schema.d.ts +10 -10
- package/dist/lib/pickers.d.ts +25 -0
- package/dist/lib/pickers.js +75 -1
- package/dist/lib/pickers.js.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { log } from './utils/logger.js';
|
|
4
4
|
import { CLI_VERSION } from './version.js';
|
|
5
|
+
// pdv #6 fix: fecha stdin antes de qualquer process.exit() para evitar a
|
|
6
|
+
// asserção libuv "!(handle->flags & UV_HANDLE_CLOSING)" no Windows.
|
|
7
|
+
// stdin fica aberto como handle libuv quando inquirer/ora o pegam; destruir
|
|
8
|
+
// antes do exit garante que o loop de eventos drene limpo.
|
|
9
|
+
process.on('exit', () => {
|
|
10
|
+
try {
|
|
11
|
+
process.stdin.destroy();
|
|
12
|
+
}
|
|
13
|
+
catch { /* silencioso — handle pode já estar fechado */ }
|
|
14
|
+
});
|
|
5
15
|
const program = new Command();
|
|
6
16
|
program
|
|
7
17
|
.name('neetru')
|
|
@@ -239,6 +249,47 @@ program
|
|
|
239
249
|
const { runSurfaceStatus } = await import('./commands/surface-status.js');
|
|
240
250
|
await runSurfaceStatus({ clientId: opts.clientId, json: !!opts.json });
|
|
241
251
|
});
|
|
252
|
+
// ── neetru customers ──────────────────────────────────────────────────
|
|
253
|
+
// pdv #2 fix: operadores podem criar customers pelo CLI sem abrir o painel.
|
|
254
|
+
// Customer = empresa/PJ que paga (CRM comercial).
|
|
255
|
+
// Tenant = instância do produto para esse customer.
|
|
256
|
+
const customersCmd = program
|
|
257
|
+
.command('customers')
|
|
258
|
+
.description('Gerenciar customers (empresa/PJ que paga o serviço Neetru)');
|
|
259
|
+
customersCmd
|
|
260
|
+
.command('list')
|
|
261
|
+
.description('Listar customers')
|
|
262
|
+
.option('--status <status>', 'ativo | em prospecção | suspenso | arquivado')
|
|
263
|
+
.option('--search <texto>', 'busca por nome, email ou CNPJ')
|
|
264
|
+
.option('--json', 'saída em JSON')
|
|
265
|
+
.action(async (opts) => {
|
|
266
|
+
const { runCustomersList } = await import('./commands/customers.js');
|
|
267
|
+
await runCustomersList({ status: opts.status, search: opts.search, json: !!opts.json });
|
|
268
|
+
});
|
|
269
|
+
customersCmd
|
|
270
|
+
.command('get <id>')
|
|
271
|
+
.description('Mostrar detalhes de um customer')
|
|
272
|
+
.option('--json', 'saída em JSON')
|
|
273
|
+
.action(async (id, opts) => {
|
|
274
|
+
const { runCustomersGet } = await import('./commands/customers.js');
|
|
275
|
+
await runCustomersGet(id, { json: !!opts.json });
|
|
276
|
+
});
|
|
277
|
+
customersCmd
|
|
278
|
+
.command('create')
|
|
279
|
+
.description('Criar customer (empresa/PJ) — necessário antes de criar workspace')
|
|
280
|
+
.option('--name <nome>', 'nome do customer (razão social ou nome comercial)')
|
|
281
|
+
.option('--email <email>', 'email de contato')
|
|
282
|
+
.option('--tax-id <cnpj>', 'CNPJ ou CPF (opcional)')
|
|
283
|
+
.option('--json', 'saída em JSON')
|
|
284
|
+
.action(async (opts) => {
|
|
285
|
+
const { runCustomersCreate } = await import('./commands/customers.js');
|
|
286
|
+
await runCustomersCreate({
|
|
287
|
+
name: opts.name,
|
|
288
|
+
email: opts.email,
|
|
289
|
+
taxId: opts.taxId,
|
|
290
|
+
json: !!opts.json,
|
|
291
|
+
});
|
|
292
|
+
});
|
|
242
293
|
// ── neetru tenants ────────────────────────────────────────────────────
|
|
243
294
|
const tenantsCmd = program
|
|
244
295
|
.command('tenants')
|
|
@@ -269,7 +320,10 @@ tenantsCmd
|
|
|
269
320
|
});
|
|
270
321
|
tenantsCmd
|
|
271
322
|
.command('create')
|
|
272
|
-
.description('Criar tenant
|
|
323
|
+
.description('[STAFF-ONLY] Criar tenant sem OAuth client/secret.\n' +
|
|
324
|
+
'DEPRECATED: para uso normal (ambiente completo com OAuth), use:\n' +
|
|
325
|
+
' neetru workspaces create\n' +
|
|
326
|
+
'Este comando permanece para casos staff-only (registro de tenant pré-existente).')
|
|
273
327
|
.option('--name <name>', 'nome do tenant')
|
|
274
328
|
.option('--slug <slug>', 'slug do tenant')
|
|
275
329
|
.option('--customer <customerId>', 'id do customer')
|
|
@@ -450,6 +504,8 @@ workspacesCmd
|
|
|
450
504
|
.option('--env <env>', 'dev | staging | prod (default: dev)')
|
|
451
505
|
.option('--tier <tier>', 'dev | standard | enterprise (default: standard)')
|
|
452
506
|
.option('--name <name>', 'label do workspace')
|
|
507
|
+
.option('--bind-config', 'grava tenantId retornado no neetru.config.json do cwd')
|
|
508
|
+
.option('--force-duplicate', 'cria mesmo que já exista ambiente ativo para produto+env')
|
|
453
509
|
.option('--json', 'saída em JSON')
|
|
454
510
|
.action(async (opts) => {
|
|
455
511
|
const { runWorkspacesCreate } = await import('./commands/workspaces.js');
|
|
@@ -459,6 +515,8 @@ workspacesCmd
|
|
|
459
515
|
env: opts.env,
|
|
460
516
|
tier: opts.tier,
|
|
461
517
|
name: opts.name,
|
|
518
|
+
bindConfig: !!opts.bindConfig,
|
|
519
|
+
forceDuplicate: !!opts.forceDuplicate,
|
|
462
520
|
json: !!opts.json,
|
|
463
521
|
});
|
|
464
522
|
});
|
|
@@ -811,6 +869,15 @@ adminDatabaseCmd
|
|
|
811
869
|
const { runDbGet } = await import('./commands/products-db.js');
|
|
812
870
|
await runDbGet(id, { json: !!opts.json });
|
|
813
871
|
});
|
|
872
|
+
// gestovendas #12 fix: alias `status` → `get` (skill /neetru documenta como `status`).
|
|
873
|
+
adminDatabaseCmd
|
|
874
|
+
.command('status [id]')
|
|
875
|
+
.description('[Staff] Alias de `get` — mostrar detalhes e status de um banco')
|
|
876
|
+
.option('--json')
|
|
877
|
+
.action(async (id, opts) => {
|
|
878
|
+
const { runDbGet } = await import('./commands/products-db.js');
|
|
879
|
+
await runDbGet(id, { json: !!opts.json });
|
|
880
|
+
});
|
|
814
881
|
// D-2: `set-status` é ESCRITA explícita. `status` era ambíguo com o READ em `neetru db status`.
|
|
815
882
|
adminDatabaseCmd
|
|
816
883
|
.command('set-status [id] [status]')
|
|
@@ -845,6 +912,57 @@ adminDatabaseCmd
|
|
|
845
912
|
const { runDbDelete } = await import('./commands/products-db.js');
|
|
846
913
|
await runDbDelete(id, { json: !!opts.json });
|
|
847
914
|
});
|
|
915
|
+
// ── neetru admin sdk-credential ────────────────────────────────────────────
|
|
916
|
+
// Gerencia credenciais OIDC (SDK) por produto — create / list / revoke.
|
|
917
|
+
// Resolve bug_599d2f033e024bc194aa07639cd26c84: bootstrap CI/IaC desbloqueado.
|
|
918
|
+
// Internamente usa `oidc_clients/{clientId}` no Core (canônico pós-devkit).
|
|
919
|
+
const adminSdkCredentialCmd = adminCmd
|
|
920
|
+
.command('sdk-credential')
|
|
921
|
+
.description('Gerenciar credenciais OIDC (SDK) de produtos — create / list / revoke');
|
|
922
|
+
adminSdkCredentialCmd
|
|
923
|
+
.command('create')
|
|
924
|
+
.description('[Staff] Criar credencial OIDC para produto — exibe clientSecret ONE-TIME')
|
|
925
|
+
.requiredOption('--product-id <id>', 'ID do produto')
|
|
926
|
+
.requiredOption('--name <label>', 'nome/label da credencial (ex: "Backend Prod")')
|
|
927
|
+
.option('--scopes <escopos>', 'escopos separados por vírgula (ex: "entitlements.read,usage.write")')
|
|
928
|
+
.option('--mfa-token <code>', 'código TOTP para step-up MFA (se exigido pelo servidor)')
|
|
929
|
+
.option('--json', 'saída em JSON (machine-readable)')
|
|
930
|
+
.action(async (opts) => {
|
|
931
|
+
const { runSdkCredentialCreate } = await import('./commands/admin/sdk-credential.js');
|
|
932
|
+
await runSdkCredentialCreate({
|
|
933
|
+
productId: opts.productId,
|
|
934
|
+
name: opts.name,
|
|
935
|
+
scopes: opts.scopes,
|
|
936
|
+
mfaToken: opts.mfaToken,
|
|
937
|
+
json: !!opts.json,
|
|
938
|
+
});
|
|
939
|
+
});
|
|
940
|
+
adminSdkCredentialCmd
|
|
941
|
+
.command('list')
|
|
942
|
+
.description('[Staff] Listar credenciais OIDC de um produto')
|
|
943
|
+
.requiredOption('--product-id <id>', 'ID do produto')
|
|
944
|
+
.option('--json', 'saída em JSON')
|
|
945
|
+
.action(async (opts) => {
|
|
946
|
+
const { runSdkCredentialList } = await import('./commands/admin/sdk-credential.js');
|
|
947
|
+
await runSdkCredentialList({
|
|
948
|
+
productId: opts.productId,
|
|
949
|
+
json: !!opts.json,
|
|
950
|
+
});
|
|
951
|
+
});
|
|
952
|
+
adminSdkCredentialCmd
|
|
953
|
+
.command('revoke <clientId>')
|
|
954
|
+
.description('[Staff] Revogar credencial OIDC (status → desativado, irreversível)')
|
|
955
|
+
.requiredOption('--product-id <id>', 'ID do produto dono da credencial')
|
|
956
|
+
.option('--mfa-token <code>', 'código TOTP para step-up MFA')
|
|
957
|
+
.option('--json', 'saída em JSON')
|
|
958
|
+
.action(async (clientId, opts) => {
|
|
959
|
+
const { runSdkCredentialRevoke } = await import('./commands/admin/sdk-credential.js');
|
|
960
|
+
await runSdkCredentialRevoke(clientId, {
|
|
961
|
+
productId: opts.productId,
|
|
962
|
+
mfaToken: opts.mfaToken,
|
|
963
|
+
json: !!opts.json,
|
|
964
|
+
});
|
|
965
|
+
});
|
|
848
966
|
// ── neetru products db (alias de remoção — D-1) ────────────────────────────
|
|
849
967
|
// Emite aviso informando o novo caminho. Mantém subcomandos funcionais por
|
|
850
968
|
// compatibilidade temporária mas deixa claro que foi renomeado.
|
|
@@ -855,16 +973,27 @@ const productsDbCmd = productsCmd
|
|
|
855
973
|
process.stderr.write('\nAviso: `neetru products db` foi renomeado para `neetru admin database`.\n' +
|
|
856
974
|
'Por favor, atualize seus scripts. Este alias será removido em breve.\n\n');
|
|
857
975
|
});
|
|
976
|
+
// gestovendas #2 / pdv #5 fix: alias `list` aceita --product (slug legado) OU
|
|
977
|
+
// --product-id (novo). Se slug recebido, passa como productId para o Core.
|
|
978
|
+
// O Core tenta resolver slug → id server-side (fallback); se o Core não suportar,
|
|
979
|
+
// o operador vê mensagem específica do servidor e não um erro de sintaxe.
|
|
858
980
|
productsDbCmd
|
|
859
981
|
.command('list')
|
|
860
982
|
.description('[RENOMEADO — use: neetru admin database list]')
|
|
861
|
-
.option('--product-id <id>')
|
|
983
|
+
.option('--product-id <id>', 'ID do produto (novo)')
|
|
984
|
+
.option('--product <slugOrId>', 'slug ou ID do produto (legado — use --product-id)')
|
|
862
985
|
.option('--engine <engine>')
|
|
863
986
|
.option('--status <status>')
|
|
864
987
|
.option('--json')
|
|
865
988
|
.action(async (opts) => {
|
|
989
|
+
// Tradução de flag: --product (legado) → productId (novo).
|
|
990
|
+
const productId = opts.productId ?? opts.product;
|
|
991
|
+
if (opts.product && !opts.productId) {
|
|
992
|
+
process.stderr.write(`[DEPRECATED] Use --product-id em vez de --product.\n` +
|
|
993
|
+
` Próxima major remove o suporte a --product neste alias.\n`);
|
|
994
|
+
}
|
|
866
995
|
const { runDbList } = await import('./commands/products-db.js');
|
|
867
|
-
await runDbList({ productId
|
|
996
|
+
await runDbList({ productId, engine: opts.engine, status: opts.status, json: !!opts.json });
|
|
868
997
|
});
|
|
869
998
|
productsDbCmd
|
|
870
999
|
.command('engines')
|
|
@@ -1025,6 +1154,74 @@ program
|
|
|
1025
1154
|
ctaLabel: opts.ctaLabel,
|
|
1026
1155
|
});
|
|
1027
1156
|
});
|
|
1157
|
+
// ── neetru marketplace ────────────────────────────────────────────────
|
|
1158
|
+
const marketplaceCmd = program
|
|
1159
|
+
.command('marketplace')
|
|
1160
|
+
.description('Central de artefatos do ecossistema Neetru (skills, SDK, templates)');
|
|
1161
|
+
const marketplaceSkillsCmd = marketplaceCmd
|
|
1162
|
+
.command('skills')
|
|
1163
|
+
.description('Gerenciar Skills do Claude Code');
|
|
1164
|
+
marketplaceSkillsCmd
|
|
1165
|
+
.command('install')
|
|
1166
|
+
.description('Clonar neetru-libs e instalar skills em ~/.claude/skills/')
|
|
1167
|
+
.action(async () => {
|
|
1168
|
+
const { runSkillsInstall } = await import('./commands/marketplace.js');
|
|
1169
|
+
await runSkillsInstall();
|
|
1170
|
+
});
|
|
1171
|
+
marketplaceSkillsCmd
|
|
1172
|
+
.command('update')
|
|
1173
|
+
.description('Atualizar cache neetru-libs (git pull) e re-copiar skills instaladas')
|
|
1174
|
+
.action(async () => {
|
|
1175
|
+
const { runSkillsUpdate } = await import('./commands/marketplace.js');
|
|
1176
|
+
await runSkillsUpdate();
|
|
1177
|
+
});
|
|
1178
|
+
marketplaceSkillsCmd
|
|
1179
|
+
.command('list')
|
|
1180
|
+
.description('Listar skills disponíveis no cache local')
|
|
1181
|
+
.action(async () => {
|
|
1182
|
+
const { runSkillsList } = await import('./commands/marketplace.js');
|
|
1183
|
+
await runSkillsList();
|
|
1184
|
+
});
|
|
1185
|
+
marketplaceSkillsCmd
|
|
1186
|
+
.command('uninstall')
|
|
1187
|
+
.description('Remover skills de ~/.claude/skills/ (pede confirmação)')
|
|
1188
|
+
.option('--yes', 'pular confirmação interativa')
|
|
1189
|
+
.action(async (opts) => {
|
|
1190
|
+
const { runSkillsUninstall } = await import('./commands/marketplace.js');
|
|
1191
|
+
await runSkillsUninstall({ yes: !!opts.yes });
|
|
1192
|
+
});
|
|
1193
|
+
const marketplaceSdkCmd = marketplaceCmd
|
|
1194
|
+
.command('sdk')
|
|
1195
|
+
.description('Gerenciar @neetru/sdk no projeto atual');
|
|
1196
|
+
marketplaceSdkCmd
|
|
1197
|
+
.command('init')
|
|
1198
|
+
.description('Adicionar @neetru/sdk ao package.json e criar src/neetru.ts')
|
|
1199
|
+
.action(async () => {
|
|
1200
|
+
const { runSdkInit } = await import('./commands/marketplace.js');
|
|
1201
|
+
await runSdkInit();
|
|
1202
|
+
});
|
|
1203
|
+
marketplaceSdkCmd
|
|
1204
|
+
.command('templates')
|
|
1205
|
+
.description('Listar templates de feature disponíveis (auth, billing, usage…)')
|
|
1206
|
+
.action(async () => {
|
|
1207
|
+
const { runSdkTemplates } = await import('./commands/marketplace.js');
|
|
1208
|
+
await runSdkTemplates();
|
|
1209
|
+
});
|
|
1210
|
+
marketplaceSdkCmd
|
|
1211
|
+
.command('add <template>')
|
|
1212
|
+
.description('Copiar template de feature pra src/ do projeto atual')
|
|
1213
|
+
.option('--force', 'sobrescrever arquivos existentes')
|
|
1214
|
+
.action(async (template, opts) => {
|
|
1215
|
+
const { runSdkAddTemplate } = await import('./commands/marketplace.js');
|
|
1216
|
+
await runSdkAddTemplate(template, { force: !!opts.force });
|
|
1217
|
+
});
|
|
1218
|
+
marketplaceCmd
|
|
1219
|
+
.command('browse')
|
|
1220
|
+
.description('Abrir https://github.com/Neetru/neetru-libs no browser')
|
|
1221
|
+
.action(async () => {
|
|
1222
|
+
const { runMarketplaceBrowse } = await import('./commands/marketplace.js');
|
|
1223
|
+
await runMarketplaceBrowse();
|
|
1224
|
+
});
|
|
1028
1225
|
// ── neetru add ────────────────────────────────────────────────────────
|
|
1029
1226
|
program
|
|
1030
1227
|
.command('add <feature>')
|
|
@@ -1124,6 +1321,7 @@ dbCmd
|
|
|
1124
1321
|
.option('--env <env>', 'ambiente: dev-local (padrão) | staging | production')
|
|
1125
1322
|
.option('--product-id <id>', 'override do productId (default: slug do neetru.config.json)')
|
|
1126
1323
|
.option('-y, --yes', 'modo não-interativo (usa defaults)')
|
|
1324
|
+
.option('--json', 'saída em JSON estruturado')
|
|
1127
1325
|
.action(async (opts) => {
|
|
1128
1326
|
const { runDbInit } = await import('./commands/db.js');
|
|
1129
1327
|
await runDbInit({
|
|
@@ -1132,6 +1330,7 @@ dbCmd
|
|
|
1132
1330
|
env: opts.env,
|
|
1133
1331
|
productId: opts.productId,
|
|
1134
1332
|
yes: !!opts.yes,
|
|
1333
|
+
json: !!opts.json,
|
|
1135
1334
|
});
|
|
1136
1335
|
});
|
|
1137
1336
|
// ── neetru db apply ───────────────────────────────────────────────────
|
|
@@ -1144,6 +1343,7 @@ dbCmd
|
|
|
1144
1343
|
.option('--schema <path>', 'caminho do schema (default: db/schema.ts)')
|
|
1145
1344
|
.option('--dry-run', 'calcula o diff mas NÃO envia ao Core')
|
|
1146
1345
|
.option('-y, --yes', 'pula a confirmação interativa')
|
|
1346
|
+
.option('--json', 'saída em JSON estruturado')
|
|
1147
1347
|
.action(async (opts) => {
|
|
1148
1348
|
const { runDbApply } = await import('./commands/db.js');
|
|
1149
1349
|
await runDbApply({
|
|
@@ -1152,6 +1352,7 @@ dbCmd
|
|
|
1152
1352
|
schemaPath: opts.schema,
|
|
1153
1353
|
dryRun: !!opts.dryRun,
|
|
1154
1354
|
yes: !!opts.yes,
|
|
1355
|
+
json: !!opts.json,
|
|
1155
1356
|
});
|
|
1156
1357
|
});
|
|
1157
1358
|
// ── neetru db migrations ──────────────────────────────────────────────
|
|
@@ -1436,6 +1637,117 @@ supportTicketsCmd
|
|
|
1436
1637
|
const { runSupportTicketsStatus } = await import('./commands/support.js');
|
|
1437
1638
|
await runSupportTicketsStatus(id, { to: opts.to, json: !!opts.json });
|
|
1438
1639
|
});
|
|
1640
|
+
// ── neetru bug ───────────────────────────────────────────────────────
|
|
1641
|
+
/**
|
|
1642
|
+
* neetru bug — bugs e ocorrências reportados pela CLI, agentes Claude e staff.
|
|
1643
|
+
*
|
|
1644
|
+
* Subcomandos:
|
|
1645
|
+
* report — reportar novo bug (interativo ou one-shot via flags)
|
|
1646
|
+
* list — listar bugs abertos (ou com filtros)
|
|
1647
|
+
* show <id> — detalhe completo
|
|
1648
|
+
* claim <id> — assumir investigação
|
|
1649
|
+
* resolve <id> — encerrar (resolved/wont_fix/duplicate)
|
|
1650
|
+
* comment <id> — adicionar comentário na thread
|
|
1651
|
+
*
|
|
1652
|
+
* Exemplo rápido (agentes Claude):
|
|
1653
|
+
* neetru bug report --title "X trava" --body "Stack trace…" --category cli --severity high --actor-type agent_claude --json
|
|
1654
|
+
* neetru bug list --status open --json
|
|
1655
|
+
*/
|
|
1656
|
+
const bugCmd = program
|
|
1657
|
+
.command('bug')
|
|
1658
|
+
.description('Reportar, listar e resolver bugs e ocorrências da plataforma');
|
|
1659
|
+
bugCmd
|
|
1660
|
+
.command('report')
|
|
1661
|
+
.description('Reportar novo bug (interativo ou flags --title/--body para agentes)')
|
|
1662
|
+
.option('--title <text>', 'título curto do bug')
|
|
1663
|
+
.option('--body <text>', 'descrição detalhada')
|
|
1664
|
+
.option('--category <cat>', 'cli | sdk | core | agent | libs | docs | infra | other', 'other')
|
|
1665
|
+
.option('--severity <sev>', 'critical | high | medium | low', 'medium')
|
|
1666
|
+
.option('--product <id>', 'productId afetado (opcional)')
|
|
1667
|
+
.option('--steps <text>', 'passos para reproduzir (opcional)')
|
|
1668
|
+
.option('--expected <text>', 'comportamento esperado (opcional)')
|
|
1669
|
+
.option('--actual <text>', 'comportamento atual (opcional)')
|
|
1670
|
+
.option('--actor-type <type>', 'cli_principal | agent_claude | staff_session', 'cli_principal')
|
|
1671
|
+
.option('--json', 'saída em JSON (modo não-interativo)')
|
|
1672
|
+
.action(async (opts) => {
|
|
1673
|
+
const { runBugReport } = await import('./commands/bug.js');
|
|
1674
|
+
await runBugReport({
|
|
1675
|
+
title: opts.title,
|
|
1676
|
+
body: opts.body,
|
|
1677
|
+
category: opts.category,
|
|
1678
|
+
severity: opts.severity,
|
|
1679
|
+
product: opts.product,
|
|
1680
|
+
steps: opts.steps,
|
|
1681
|
+
expected: opts.expected,
|
|
1682
|
+
actual: opts.actual,
|
|
1683
|
+
actorType: opts.actorType,
|
|
1684
|
+
json: !!opts.json,
|
|
1685
|
+
});
|
|
1686
|
+
});
|
|
1687
|
+
bugCmd
|
|
1688
|
+
.command('list')
|
|
1689
|
+
.description('Listar bugs e ocorrências')
|
|
1690
|
+
.option('--status <s>', 'open | triaged | in_progress | resolved | wont_fix | duplicate')
|
|
1691
|
+
.option('--category <cat>', 'cli | sdk | core | agent | libs | docs | infra | other')
|
|
1692
|
+
.option('--assigned-to <uid>', 'filtrar por responsável (uid ou session id)')
|
|
1693
|
+
.option('--product <id>', 'filtrar por productId')
|
|
1694
|
+
.option('--limit <n>', 'máximo de resultados (default 20, max 200)')
|
|
1695
|
+
.option('--json', 'saída em JSON')
|
|
1696
|
+
.action(async (opts) => {
|
|
1697
|
+
const { runBugList } = await import('./commands/bug.js');
|
|
1698
|
+
await runBugList({
|
|
1699
|
+
status: opts.status,
|
|
1700
|
+
category: opts.category,
|
|
1701
|
+
assignedTo: opts.assignedTo,
|
|
1702
|
+
product: opts.product,
|
|
1703
|
+
limit: opts.limit,
|
|
1704
|
+
json: !!opts.json,
|
|
1705
|
+
});
|
|
1706
|
+
});
|
|
1707
|
+
bugCmd
|
|
1708
|
+
.command('show <id>')
|
|
1709
|
+
.description('Mostrar detalhe completo de um bug')
|
|
1710
|
+
.option('--json', 'saída em JSON')
|
|
1711
|
+
.action(async (id, opts) => {
|
|
1712
|
+
const { runBugShow } = await import('./commands/bug.js');
|
|
1713
|
+
await runBugShow(id, { json: !!opts.json });
|
|
1714
|
+
});
|
|
1715
|
+
bugCmd
|
|
1716
|
+
.command('claim <id>')
|
|
1717
|
+
.description('Assumir investigação de um bug')
|
|
1718
|
+
.option('--assigned-to <uid>', 'uid ou session id (default: caller)')
|
|
1719
|
+
.option('--json', 'saída em JSON')
|
|
1720
|
+
.action(async (id, opts) => {
|
|
1721
|
+
const { runBugClaim } = await import('./commands/bug.js');
|
|
1722
|
+
await runBugClaim(id, { assignedTo: opts.assignedTo, json: !!opts.json });
|
|
1723
|
+
});
|
|
1724
|
+
bugCmd
|
|
1725
|
+
.command('resolve <id>')
|
|
1726
|
+
.description('Encerrar um bug como resolvido, wont_fix ou duplicate')
|
|
1727
|
+
.option('--summary <text>', 'resumo do que foi feito / por que não corrigir')
|
|
1728
|
+
.option('--commit <sha>', 'commit SHA que corrige o bug (opcional)')
|
|
1729
|
+
.option('--status <s>', 'resolved | wont_fix | duplicate (default: resolved)', 'resolved')
|
|
1730
|
+
.option('--duplicate-of <id>', 'ID do bug original (obrigatório quando --status duplicate)')
|
|
1731
|
+
.option('--json', 'saída em JSON (modo não-interativo)')
|
|
1732
|
+
.action(async (id, opts) => {
|
|
1733
|
+
const { runBugResolve } = await import('./commands/bug.js');
|
|
1734
|
+
await runBugResolve(id, {
|
|
1735
|
+
summary: opts.summary,
|
|
1736
|
+
commit: opts.commit,
|
|
1737
|
+
status: opts.status,
|
|
1738
|
+
duplicateOf: opts.duplicateOf,
|
|
1739
|
+
json: !!opts.json,
|
|
1740
|
+
});
|
|
1741
|
+
});
|
|
1742
|
+
bugCmd
|
|
1743
|
+
.command('comment <id>')
|
|
1744
|
+
.description('Adicionar comentário na thread de um bug')
|
|
1745
|
+
.option('--body <text>', 'corpo do comentário')
|
|
1746
|
+
.option('--json', 'saída em JSON (modo não-interativo)')
|
|
1747
|
+
.action(async (id, opts) => {
|
|
1748
|
+
const { runBugComment } = await import('./commands/bug.js');
|
|
1749
|
+
await runBugComment(id, { body: opts.body, json: !!opts.json });
|
|
1750
|
+
});
|
|
1439
1751
|
// ── neetru dns ───────────────────────────────────────────────────────
|
|
1440
1752
|
const dnsCmd = program
|
|
1441
1753
|
.command('dns')
|
|
@@ -1572,9 +1884,20 @@ drCmd
|
|
|
1572
1884
|
// Frente B — docs em GCS + Firestore registry. Desacopla conteúdo de docs
|
|
1573
1885
|
// do deploy do Core (owner edita markdown direto pelo bucket OU via CLI,
|
|
1574
1886
|
// sem rebuild).
|
|
1887
|
+
//
|
|
1888
|
+
// `neetru docs open [topic]` abre documentação no browser. É o ponto de
|
|
1889
|
+
// entrada pra quem quer LER docs, não publicar.
|
|
1575
1890
|
const docsCmd = program
|
|
1576
1891
|
.command('docs')
|
|
1577
|
-
.description('
|
|
1892
|
+
.description('Documentação + registry de docs publicados em gs://neetru-docs');
|
|
1893
|
+
docsCmd
|
|
1894
|
+
.command('open [topic]')
|
|
1895
|
+
.description('Abrir documentação no browser (ex: sdk, cli, db, webhooks, auth)')
|
|
1896
|
+
.option('--json', 'saída em JSON (imprime URL sem abrir browser)')
|
|
1897
|
+
.action(async (topic, opts) => {
|
|
1898
|
+
const { runDocsOpen } = await import('./commands/docs.js');
|
|
1899
|
+
await runDocsOpen(topic, { json: !!opts.json });
|
|
1900
|
+
});
|
|
1578
1901
|
docsCmd
|
|
1579
1902
|
.command('publish <file>')
|
|
1580
1903
|
.description('Publicar arquivo markdown (sobe pro GCS + registry Firestore)')
|