@orkastery/cli 0.2.0 → 0.4.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/LICENSE +1 -1
- package/README.md +86 -65
- package/adapters/README.md +30 -15
- package/adapters/claude-code/.claude-plugin/plugin.json +11 -5
- package/adapters/claude-code/README.md +110 -8
- package/adapters/claude-code/commands/check.md +4 -3
- package/adapters/claude-code/commands/goal.md +3 -2
- package/adapters/claude-code/commands/master.md +3 -2
- package/adapters/claude-code/commands/onboarding.md +21 -0
- package/adapters/claude-code/commands/ork.md +99 -27
- package/adapters/claude-code/hooks/hooks.json +6 -1
- package/adapters/claude-code/hooks/ork-guard.js +1 -1
- package/adapters/claude-code/hooks/ork-sensor.js +66 -0
- package/adapters/codex/skills/ork/SKILL.md +57 -0
- package/adapters/hermes/README.md +161 -0
- package/adapters/hermes/bin/ork-abrir-thread.sh +2 -0
- package/adapters/hermes/bin/ork-brain.sh +4 -0
- package/adapters/hermes/bin/ork-hitl-answer.py +82 -0
- package/adapters/hermes/bin/ork-maestro.sh +6 -0
- package/adapters/hermes/bin/ork-master-enviar.py +84 -0
- package/adapters/hermes/bin/ork-pulse-enviar.py +47 -0
- package/adapters/hermes/hermes.plugin.json +24 -4
- package/adapters/hermes/hitl-ingress/__init__.py +356 -0
- package/adapters/hermes/hitl-ingress/plugin.yaml +4 -0
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +75 -22
- package/adapters/openclaw/README.md +136 -27
- package/adapters/openclaw/bin/ork-brain.sh +4 -0
- package/adapters/openclaw/construir.sh +19 -0
- package/adapters/openclaw/dist/hitl-ingress.js +199 -0
- package/adapters/openclaw/dist/index.js +437 -0
- package/adapters/openclaw/openclaw.plugin.json +39 -134
- package/adapters/openclaw/package.json +26 -0
- package/adapters/openclaw/src/hitl-ingress.ts +180 -0
- package/adapters/openclaw/src/index.ts +460 -0
- package/adapters/openclaw/src/tipos-openclaw.d.ts +58 -0
- package/adapters/openclaw/tsconfig.json +15 -0
- package/assets/docs/markdownlint-cli2.jsonc +22 -0
- package/assets/docs/padroes/documentacao-de-produto.md +133 -0
- package/assets/docs/padroes/roadmap-de-produto.md +98 -0
- package/assets/docs/produto/README.md +14 -0
- package/assets/docs/produto/_modelo-feature.md +59 -0
- package/assets/docs/roadmap/README.md +14 -0
- package/assets/docs/roadmap/_modelo-item.md +73 -0
- package/assets/orkmind-native-schema.json +32 -0
- package/assets/orkmind_bridge.py +357 -0
- package/assets/orkmind_fixture.py +67 -0
- package/assets/orkmind_prospective.py +138 -0
- package/assets/reference-tariffs-i07.json +23 -0
- package/dist/adapters/claude-bg.js +488 -39
- package/dist/adapters/codex-controller-sensor.js +449 -0
- package/dist/adapters/codex-controller-worker.js +361 -0
- package/dist/adapters/codex-controller.js +252 -0
- package/dist/adapters/codex-events.js +205 -0
- package/dist/adapters/codex-question.js +26 -0
- package/dist/adapters/codex-runner.js +133 -0
- package/dist/adapters/codex.js +394 -0
- package/dist/agents-md.js +84 -0
- package/dist/auditoria.js +12 -9
- package/dist/auditrun.js +5 -4
- package/dist/board.js +174 -23
- package/dist/branch-de-estado.js +136 -0
- package/dist/canarios-hitl.js +177 -0
- package/dist/canarios-i43.js +543 -0
- package/dist/canarios-pulse.js +147 -0
- package/dist/canarios-sensores.js +129 -0
- package/dist/canarios.js +111 -2
- package/dist/catalogo.js +9 -0
- package/dist/ci.js +223 -0
- package/dist/ciclos.js +2 -1
- package/dist/claim-lint.js +64 -0
- package/dist/claims.js +60 -0
- package/dist/company-brain-capture.js +195 -0
- package/dist/company-brain-cli.js +123 -0
- package/dist/company-brain-client.js +61 -0
- package/dist/company-brain-contract.js +166 -0
- package/dist/company-brain-journal.js +192 -0
- package/dist/company-brain-mcp.js +33 -0
- package/dist/company-brain-migration.js +60 -0
- package/dist/company-brain-source.js +177 -0
- package/dist/company-brain-worker.js +18 -0
- package/dist/conducao-texto.js +61 -0
- package/dist/conducao.js +876 -0
- package/dist/contrato-publico.js +39 -0
- package/dist/creation-operation-store.js +251 -0
- package/dist/creation-operation.js +148 -0
- package/dist/decisao-autonoma.js +183 -0
- package/dist/delegation.js +79 -0
- package/dist/demo.js +120 -0
- package/dist/docs.js +828 -0
- package/dist/doctor.js +184 -25
- package/dist/entrega-pr.js +117 -0
- package/dist/escopo-escrita.js +71 -0
- package/dist/estado-thread.js +222 -0
- package/dist/evalrunner.js +12 -0
- package/dist/fabrica-estado.js +329 -0
- package/dist/fabrica-publicar.js +76 -0
- package/dist/fix.js +22 -1
- package/dist/gates.js +59 -11
- package/dist/handoff.js +39 -23
- package/dist/hitl-canais.js +333 -0
- package/dist/hitl-classificacao.js +131 -0
- package/dist/hitl-contract.js +465 -0
- package/dist/hitl-estado.js +136 -0
- package/dist/hitl-gates.js +554 -0
- package/dist/hitl-ingress-receipt.js +382 -0
- package/dist/hitl-local-atestado.js +57 -0
- package/dist/hitl-local-receipt.js +328 -0
- package/dist/hitl-local.js +143 -0
- package/dist/hitl-lock.js +139 -0
- package/dist/hitl-lote.js +223 -0
- package/dist/hitl-native-offer.js +97 -0
- package/dist/hitl-native.js +65 -0
- package/dist/hitl-presentation.js +209 -0
- package/dist/hitl-public-receipt.js +176 -0
- package/dist/hitl-resumo.js +209 -0
- package/dist/hitl-sessions.js +475 -0
- package/dist/hitl.js +711 -0
- package/dist/horario.js +269 -0
- package/dist/hosts.js +198 -22
- package/dist/index.js +1741 -94
- package/dist/indice.js +99 -0
- package/dist/init.js +28 -3
- package/dist/integracoes-locais.js +17 -0
- package/dist/leases.js +65 -21
- package/dist/ledger-stats.js +272 -0
- package/dist/ledger.js +109 -2
- package/dist/licoes.js +221 -0
- package/dist/liveness.js +218 -0
- package/dist/maestro-actions.js +51 -0
- package/dist/maestro-authority.js +152 -0
- package/dist/maestro-cli.js +97 -0
- package/dist/maestro-contract.js +55 -0
- package/dist/maestro-discovery.js +132 -0
- package/dist/maestro-runtime.js +268 -0
- package/dist/maestro-snapshot.js +86 -0
- package/dist/maestro-sources.js +224 -0
- package/dist/manifest.js +165 -6
- package/dist/maquina.js +102 -0
- package/dist/master-audit.js +101 -0
- package/dist/master-batch.js +43 -0
- package/dist/master-digest.js +149 -0
- package/dist/master-migracao.js +155 -0
- package/dist/master.js +361 -77
- package/dist/mcp-artifacts.js +234 -0
- package/dist/mcp-git.js +433 -0
- package/dist/mcp-install.js +310 -0
- package/dist/mcp-maestro.js +25 -0
- package/dist/mcp-server.js +469 -0
- package/dist/mcp-ship.js +436 -0
- package/dist/mcp-verify.js +173 -0
- package/dist/memoria-humana.js +207 -0
- package/dist/memoria.js +314 -78
- package/dist/memory-migration.js +279 -0
- package/dist/memory-prospective.js +148 -0
- package/dist/modos-migracao.js +191 -0
- package/dist/modos.js +151 -15
- package/dist/monitor-lock.js +110 -0
- package/dist/objective.js +449 -0
- package/dist/ocupacao.js +267 -0
- package/dist/onboarding.js +303 -0
- package/dist/orkmind.js +389 -90
- package/dist/orquestracao.js +96 -69
- package/dist/phase.js +612 -151
- package/dist/playbook-capabilities.js +150 -0
- package/dist/playbook-contracts.js +188 -0
- package/dist/policies.js +72 -0
- package/dist/portfolio-context.js +61 -0
- package/dist/portfolio.js +180 -0
- package/dist/preflight.js +207 -0
- package/dist/process-audit.js +112 -0
- package/dist/project-state.js +93 -0
- package/dist/prompts.js +25 -5
- package/dist/prova-minima.js +112 -0
- package/dist/pulse-cadencia.js +163 -0
- package/dist/pulse-consentimento.js +260 -0
- package/dist/pulse-delivery.js +323 -0
- package/dist/pulse-resposta.js +542 -0
- package/dist/pulse.js +262 -0
- package/dist/ratelimit.js +35 -2
- package/dist/recall.js +80 -3
- package/dist/redacao-saida.js +45 -0
- package/dist/redacao-url.js +66 -0
- package/dist/retry.js +640 -118
- package/dist/roadmap-reservas.js +243 -0
- package/dist/runtime-ambiente.js +38 -0
- package/dist/runtime-context.js +215 -0
- package/dist/runtime-profiles.js +869 -0
- package/dist/runtimes.js +103 -0
- package/dist/sandbox.js +9 -0
- package/dist/session-events.js +203 -0
- package/dist/session-watcher-claude.js +637 -0
- package/dist/session-watcher.js +700 -0
- package/dist/sessoes-adopt.js +154 -0
- package/dist/sessoes-inventario.js +159 -0
- package/dist/sessoes.js +16 -35
- package/dist/setup.js +691 -0
- package/dist/ship.js +168 -19
- package/dist/slug.js +1 -1
- package/dist/thread-close.js +115 -0
- package/dist/thread.js +142 -28
- package/dist/tokens.js +1 -1
- package/dist/util.js +4 -2
- package/dist/verify-sandbox.js +265 -0
- package/dist/verify.js +270 -25
- package/dist/versao.js +60 -0
- package/dist/worktree.js +31 -2
- package/dist/write-activation.js +291 -0
- package/dist/yaml.js +5 -1
- package/eval/casos/master-metrics.json +1 -1
- package/eval/casos/onboarding.json +102 -0
- package/eval/casos/orkastery-bootstrap.json +37 -3
- package/eval/casos/scope-check-capability-map.json +45 -7
- package/eval/casos/ship-release.json +3 -3
- package/eval/fixtures/b0-slug-e-modos/caso.json +35 -22
- package/eval/fixtures/b2-master-log/caso.json +1 -1
- package/eval/fixtures/fx-adapter-editado-detectado/caso.json +19 -0
- package/eval/fixtures/fx-auto-quiet/caso.json +11 -0
- package/eval/fixtures/fx-blanket-approve/caso.json +10 -0
- package/eval/fixtures/fx-check-runtime-cruzado/caso.json +20 -0
- package/eval/fixtures/fx-codex-dry/caso.json +18 -0
- package/eval/fixtures/fx-donewhen-executavel/caso.json +15 -0
- package/eval/fixtures/fx-estado-dividido/caso.json +15 -0
- package/eval/fixtures/fx-fase-orfa/caso.json +116 -0
- package/eval/fixtures/fx-happy/caso.json +6 -4
- package/eval/fixtures/fx-hitl-latency/caso.json +20 -0
- package/eval/fixtures/fx-indice-reversao/caso.json +25 -0
- package/eval/fixtures/fx-listagem-abertas/caso.json +16 -0
- package/eval/fixtures/fx-maestro-bootstrap/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-escritor/caso.json +21 -0
- package/eval/fixtures/fx-modo-aposentado-leitor/caso.json +16 -0
- package/eval/fixtures/fx-objective-oscillation/caso.json +14 -0
- package/eval/fixtures/fx-omnicanal/caso.json +17 -0
- package/eval/fixtures/fx-sensores-runtime/caso.json +17 -0
- package/monitor/company-brain.cjs +17 -0
- package/monitor/pulse-scope.cjs +45 -0
- package/monitor/pulse.cron +18 -0
- package/monitor/varredura-pulse.sh +27 -0
- package/package.json +28 -7
- package/references/definition-of-done.md +2 -2
- package/schemas/claims.schema.json +25 -0
- package/schemas/company-brain.schema.json +1158 -0
- package/schemas/creation-operation.schema.json +365 -0
- package/schemas/maestro-snapshot.schema.json +2716 -0
- package/skills/README.md +3 -3
- package/skills/core/onboarding/SKILL.md +50 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +95 -65
- package/skills/core/thread-state/SKILL.md +3 -1
- package/skills/governance/decision-triage/SKILL.md +4 -4
- package/skills/governance/narrative-guardian/SKILL.md +1 -1
- package/skills/governance/roadmap-keeper/SKILL.md +1 -1
- package/skills/governance/scope-check-capability-map/SKILL.md +17 -7
- package/skills/observability/thread-tracing/SKILL.md +1 -1
- package/skills/phases/check-quality/SKILL.md +2 -2
- package/skills/phases/goal-definition/SKILL.md +1 -1
- package/skills/phases/master-metrics/SKILL.md +9 -7
- package/skills/phases/plan-specification/SKILL.md +1 -1
- package/skills/phases/ship-release/SKILL.md +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ParserCodex = exports.LIMITE_LINHA_CODEX = void 0;
|
|
4
|
+
exports.falhaDeContaDoErroCodex = falhaDeContaDoErroCodex;
|
|
5
|
+
exports.classificarMensagem = classificarMensagem;
|
|
6
|
+
/** D4/D5: stream e rollout são observações de turno, nunca aprovação de CHECK. */
|
|
7
|
+
const gates_1 = require("../gates");
|
|
8
|
+
const claude_bg_1 = require("./claude-bg");
|
|
9
|
+
const indisponivel = () => ({ disponivel: false, input: null, cachedInput: null,
|
|
10
|
+
output: null, total: null, unidade: 'tokens', escopo: 'turno', fonte: 'unavailable' });
|
|
11
|
+
const falha = () => ({ classificacao: 'gate_blocked', motivo: 'runtime.unavailable' });
|
|
12
|
+
const sucesso = () => ({ classificacao: 'fase_concluida', motivo: null });
|
|
13
|
+
const humano = () => ({ classificacao: 'human.pending', motivo: 'human.pending' });
|
|
14
|
+
/** I-33 (D12): motivos da conta so saem de erro estruturado do runtime (`falhaDeContaDoErroCodex`). */
|
|
15
|
+
const MOTIVOS_DA_CONTA = ['runtime.quota-exhausted', 'runtime.auth-missing'];
|
|
16
|
+
function motivo(v) {
|
|
17
|
+
if (v === undefined || v === null)
|
|
18
|
+
return null;
|
|
19
|
+
if (typeof v !== 'string' || !Object.hasOwn(gates_1.DESCRICAO_DO_MOTIVO, v))
|
|
20
|
+
return falha();
|
|
21
|
+
// Texto do agente declarando cota ou login nao e evidencia da conta: vira falha comum.
|
|
22
|
+
if (MOTIVOS_DA_CONTA.includes(v))
|
|
23
|
+
return falha();
|
|
24
|
+
return v === 'human.pending' ? humano() : { classificacao: 'gate_blocked', motivo: v };
|
|
25
|
+
}
|
|
26
|
+
const LIMITE_ERRO_CODEX = 300;
|
|
27
|
+
/**
|
|
28
|
+
* I-33 (D12): falha da conta no erro ESTRUTURADO do turno codex. O rollout grava
|
|
29
|
+
* `task_complete.error` com `codex_error_info` em snake_case (`usage_limit_exceeded`, a linha real
|
|
30
|
+
* do incidente de 18/09); o app-server manda `turn.error.codexErrorInfo` em camelCase
|
|
31
|
+
* (`usageLimitExceeded`, `unauthorized`). As duas formas viram o mesmo codigo; `unauthorized` e
|
|
32
|
+
* login perdido, o resto passa pelos padroes da D1 junto com a mensagem do runtime.
|
|
33
|
+
*/
|
|
34
|
+
function falhaDeContaDoErroCodex(erro, agoraMs = Date.now()) {
|
|
35
|
+
if (!erro || typeof erro !== 'object' || Array.isArray(erro))
|
|
36
|
+
return null;
|
|
37
|
+
const e = erro;
|
|
38
|
+
const info = e.codex_error_info ?? e.codexErrorInfo ?? e.codigo;
|
|
39
|
+
const bruto = typeof info === 'string' ? info
|
|
40
|
+
: info && typeof info === 'object' && !Array.isArray(info) ? Object.keys(info)[0] ?? '' : '';
|
|
41
|
+
const codigo = bruto.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase().replace(/[^a-z0-9_]/g, '').slice(0, 64);
|
|
42
|
+
const mensagem = typeof (e.message ?? e.mensagem) === 'string'
|
|
43
|
+
? String(e.message ?? e.mensagem).replace(/\p{Cc}/gu, ' ').trim().slice(0, LIMITE_ERRO_CODEX) : '';
|
|
44
|
+
const trecho = [codigo, mensagem].filter(Boolean).join(': ').slice(0, 200);
|
|
45
|
+
if (codigo === 'unauthorized')
|
|
46
|
+
return { motivo: 'runtime.auth-missing', resetEm: null, fonte: 'sem-horario', trecho };
|
|
47
|
+
const sinal = (0, claude_bg_1.parseFalhaDeConta)(trecho, agoraMs);
|
|
48
|
+
return sinal ? { ...sinal, trecho } : null;
|
|
49
|
+
}
|
|
50
|
+
function classificarMensagem(texto) {
|
|
51
|
+
if (typeof texto !== 'string')
|
|
52
|
+
return sucesso();
|
|
53
|
+
// Trechos citados e exemplos de comandos não descrevem o estado deste turno.
|
|
54
|
+
const linhas = texto.replace(/```[\s\S]*?```/g, '').split('\n')
|
|
55
|
+
.filter(l => !/^\s*(?:>|["“])/.test(l));
|
|
56
|
+
const final = linhas.join('\n').trim().split(/\n\s*\n/).at(-1) ?? '';
|
|
57
|
+
const estado = /(?:^|\n)\s*(?:motivo|gate_blocked|bloquead[oa](?:\s+por)?|blocked(?:\s+by)?)\s*[:=]?\s*`?([a-z]+[._][a-z_.-]+)`?/i.exec(final);
|
|
58
|
+
if (estado)
|
|
59
|
+
return motivo(estado[1]) ?? falha();
|
|
60
|
+
const pergunta = final.replace(/`[^`]*`/g, '').trim();
|
|
61
|
+
if (/(?:preciso|aguardo|aguardando|waiting for|need)\s+(?:da?\s+)?(?:sua|your|confirmação|resposta|autorização|approval|confirmation)/i.test(pergunta))
|
|
62
|
+
return humano();
|
|
63
|
+
if (/\?\s*$/.test(pergunta) &&
|
|
64
|
+
/(?:\b(?:você|voce|you|confirma|confirme|deseja|prefere|autoriza|posso|can you|could you|should I)\b|(?:qual|which|what)\s+(?:é\s+o\s+|is\s+the\s+)?(?:diretório|diretorio|caminho|arquivo|opção|opcao|directory|path|file|option))/i.test(pergunta))
|
|
65
|
+
return humano();
|
|
66
|
+
return sucesso();
|
|
67
|
+
}
|
|
68
|
+
function tokens(v, fonte, escopo) {
|
|
69
|
+
if (!v || typeof v !== 'object')
|
|
70
|
+
return indisponivel();
|
|
71
|
+
const p = v;
|
|
72
|
+
const input = p.input_tokens ?? p.total_input_tokens;
|
|
73
|
+
const cached = p.cached_input_tokens ?? p.cache_read_input_tokens;
|
|
74
|
+
const output = p.output_tokens ?? p.total_output_tokens;
|
|
75
|
+
if (![input, output].every(n => Number.isSafeInteger(n) && Number(n) >= 0) ||
|
|
76
|
+
(cached !== undefined && (!Number.isSafeInteger(cached) || Number(cached) < 0 || Number(cached) > Number(input))))
|
|
77
|
+
return indisponivel();
|
|
78
|
+
const total = p.total_tokens ?? Number(input) + Number(output);
|
|
79
|
+
if (!Number.isSafeInteger(total) || Number(total) < Number(input) + Number(output))
|
|
80
|
+
return indisponivel();
|
|
81
|
+
return { disponivel: true, input: Number(input), cachedInput: cached === undefined ? null : Number(cached),
|
|
82
|
+
output: Number(output), total: Number(total), unidade: 'tokens', escopo, fonte };
|
|
83
|
+
}
|
|
84
|
+
exports.LIMITE_LINHA_CODEX = 1024 * 1024;
|
|
85
|
+
class ParserCodex {
|
|
86
|
+
pendente = Buffer.alloc(0);
|
|
87
|
+
descartando = false;
|
|
88
|
+
estado;
|
|
89
|
+
eventosValidos = 0;
|
|
90
|
+
constructor(estado) {
|
|
91
|
+
this.estado = estado ? structuredClone(estado) : { turnId: null, turnIdOrigem: null, mensagem: null,
|
|
92
|
+
tokens: indisponivel(), invalido: false, turnos: 0 };
|
|
93
|
+
// Cursor antigo sem o campo nao vira proveniencia explicita por omissao.
|
|
94
|
+
this.estado.turnIdOrigem = this.estado.turnIdOrigem ?? null;
|
|
95
|
+
}
|
|
96
|
+
get bytesPendentes() { return this.pendente.length; }
|
|
97
|
+
push(chunk, agoraMs = Date.now()) {
|
|
98
|
+
const dados = typeof chunk === 'string' ? Buffer.from(chunk) : chunk;
|
|
99
|
+
const saida = [];
|
|
100
|
+
let inicio = 0;
|
|
101
|
+
for (let i = 0; i < dados.length; i++) {
|
|
102
|
+
if (dados[i] !== 10)
|
|
103
|
+
continue;
|
|
104
|
+
const linha = Buffer.concat([this.pendente, dados.subarray(inicio, i)]);
|
|
105
|
+
if (!this.descartando && linha.length <= exports.LIMITE_LINHA_CODEX) {
|
|
106
|
+
try {
|
|
107
|
+
if (linha.length) {
|
|
108
|
+
const e = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(linha));
|
|
109
|
+
const terminal = this.evento(e, agoraMs);
|
|
110
|
+
if (terminal)
|
|
111
|
+
saida.push(terminal);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
this.estado.invalido = true;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else
|
|
119
|
+
this.estado.invalido = true;
|
|
120
|
+
this.pendente = Buffer.alloc(0);
|
|
121
|
+
this.descartando = false;
|
|
122
|
+
inicio = i + 1;
|
|
123
|
+
}
|
|
124
|
+
const resto = dados.subarray(inicio);
|
|
125
|
+
if (this.pendente.length + resto.length > exports.LIMITE_LINHA_CODEX) {
|
|
126
|
+
this.descartando = true;
|
|
127
|
+
this.estado.invalido = true;
|
|
128
|
+
this.pendente = Buffer.alloc(0);
|
|
129
|
+
}
|
|
130
|
+
else if (!this.descartando)
|
|
131
|
+
this.pendente = Buffer.concat([this.pendente, resto]);
|
|
132
|
+
return saida;
|
|
133
|
+
}
|
|
134
|
+
evento(bruto, agoraMs) {
|
|
135
|
+
if (!bruto || typeof bruto !== 'object')
|
|
136
|
+
return null;
|
|
137
|
+
const e = bruto; // fronteira JSON validada campo a campo abaixo
|
|
138
|
+
const p = e.type === 'event_msg' ? e.payload : e;
|
|
139
|
+
if (!p || typeof p !== 'object' || typeof p.type !== 'string')
|
|
140
|
+
return null;
|
|
141
|
+
if (e.timestamp !== undefined && (typeof e.timestamp !== 'string' ||
|
|
142
|
+
!Number.isFinite(Date.parse(e.timestamp)) || Date.parse(e.timestamp) > agoraMs)) {
|
|
143
|
+
this.estado.invalido = true;
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
if (p.type === 'turn.started' || p.type === 'task_started') {
|
|
147
|
+
this.estado.turnos++;
|
|
148
|
+
this.estado.turnoAberto = true;
|
|
149
|
+
this.estado.turnoIniciadoEm = e.timestamp ?? null;
|
|
150
|
+
// A origem vem da presenca do campo na fonte, jamais do formato do valor.
|
|
151
|
+
const daFonte = typeof p.turn_id === 'string' && p.turn_id ? p.turn_id : null;
|
|
152
|
+
this.estado.turnId = daFonte ?? `stream-${this.estado.turnos}`;
|
|
153
|
+
this.estado.turnIdOrigem = daFonte === null ? 'gerado' : 'explicito';
|
|
154
|
+
this.estado.mensagem = null;
|
|
155
|
+
this.estado.tokens = indisponivel();
|
|
156
|
+
this.eventosValidos++;
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const turnId = e.type === 'token_usage_record' ? e.payload?.turn_id : p.turn_id;
|
|
160
|
+
if (typeof turnId === 'string' && this.estado.turnId && turnId !== this.estado.turnId)
|
|
161
|
+
return null;
|
|
162
|
+
if (p.type === 'token_count') {
|
|
163
|
+
this.estado.tokens = tokens(p.info?.total_token_usage, 'rollout.token_count', 'sessao');
|
|
164
|
+
this.eventosValidos++;
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (e.type === 'token_usage_record') {
|
|
168
|
+
this.estado.tokens = tokens(e.payload?.turn_token_usage ?? e.payload?.usage, 'rollout.token_usage_record', 'turno');
|
|
169
|
+
this.eventosValidos++;
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const resposta = e.type === 'response_item' && e.payload?.type === 'message' && e.payload?.role === 'assistant'
|
|
173
|
+
&& Array.isArray(e.payload.content) ? e.payload.content.filter((c) => c.type === 'output_text' && typeof c.text === 'string').map((c) => c.text).join('\n') : undefined;
|
|
174
|
+
const mensagem = resposta ?? (p.type === 'item.completed' && p.item?.type === 'agent_message' ? p.item.text :
|
|
175
|
+
p.type === 'agent_message' ? p.message : undefined);
|
|
176
|
+
if (mensagem !== undefined) {
|
|
177
|
+
this.estado.mensagem = classificarMensagem(mensagem);
|
|
178
|
+
this.eventosValidos++;
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
if (!['turn.completed', 'turn.failed', 'task_complete', 'task_failed'].includes(p.type))
|
|
182
|
+
return null;
|
|
183
|
+
this.eventosValidos++;
|
|
184
|
+
this.estado.turnoAberto = false;
|
|
185
|
+
// I-33 (D12): turno com `error` estruturado nunca e conclusao, mesmo sem mensagem final.
|
|
186
|
+
const comErro = p.error !== undefined && p.error !== null;
|
|
187
|
+
const falhou = p.type === 'turn.failed' || p.type === 'task_failed' || comErro;
|
|
188
|
+
const conta = comErro ? falhaDeContaDoErroCodex(p.error, agoraMs) : null;
|
|
189
|
+
const explicito = motivo(p.motivo ?? p.reason);
|
|
190
|
+
const mensagemFinal = typeof p.last_agent_message === 'string' && p.last_agent_message.trim()
|
|
191
|
+
? classificarMensagem(p.last_agent_message) : this.estado.mensagem ?? sucesso();
|
|
192
|
+
const classificacao = this.estado.invalido ? falha()
|
|
193
|
+
: conta ? { classificacao: 'gate_blocked', motivo: conta.motivo } : explicito ??
|
|
194
|
+
(mensagemFinal.classificacao !== 'fase_concluida' ? mensagemFinal : falhou ? falha() : sucesso());
|
|
195
|
+
if (p.usage !== undefined)
|
|
196
|
+
this.estado.tokens = tokens(p.usage, 'stream.turn.completed', 'turno');
|
|
197
|
+
return { ...classificacao, ...(conta && !this.estado.invalido ? { falhaDeConta: conta } : {}), turnId: this.estado.turnId,
|
|
198
|
+
turnIdOrigem: this.estado.turnId === null ? null : this.estado.turnIdOrigem ?? null, timestamp: e.timestamp ?? new Date(agoraMs).toISOString(),
|
|
199
|
+
numeroTurno: this.estado.turnos, timestampFonte: e.timestamp ? 'evento' : 'observacao',
|
|
200
|
+
fonte: e.type === 'event_msg' ? `rollout.${p.type}` : `stream.${p.type}`,
|
|
201
|
+
tokens: structuredClone(this.estado.tokens),
|
|
202
|
+
duracaoMs: Number.isFinite(p.duration_ms) && p.duration_ms >= 0 ? p.duration_ms : null };
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
exports.ParserCodex = ParserCodex;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.projetarPergunta = projetarPergunta;
|
|
4
|
+
/** Projeção explícita de conteúdo nativo. Segredos nunca saem para o canal HITL. */
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
function projetarPergunta(params) {
|
|
7
|
+
if (params?.isBlocking !== true)
|
|
8
|
+
throw new Error('runtime.unavailable: question.nonblocking');
|
|
9
|
+
if (!Array.isArray(params.questions) || params.questions.length !== 1)
|
|
10
|
+
throw new Error('runtime.unavailable: question.multiple');
|
|
11
|
+
const q = params.questions[0];
|
|
12
|
+
if (q?.isSecret === true)
|
|
13
|
+
throw new Error('runtime.unavailable: question.secret');
|
|
14
|
+
const texto = (s, max) => typeof s === 'string' && !!s.trim() && s.length <= max && !/[\x00-\x08\x0b-\x1f\x7f]/.test(s);
|
|
15
|
+
if (!texto(q?.id, 100) || !texto(q?.question, 2000) || q.header !== undefined && (typeof q.header !== 'string' || q.header.length > 200) ||
|
|
16
|
+
q.isSecret !== undefined && q.isSecret !== false || q.isOther !== undefined && typeof q.isOther !== 'boolean' ||
|
|
17
|
+
q.options != null && (!Array.isArray(q.options) || q.options.length > 12 || q.options.some((o) => !texto(o?.label, 200) || !texto(o?.description, 1000) || `${o.label} — ${o.description}`.length > 200)))
|
|
18
|
+
throw new Error('runtime.unavailable: question.invalid');
|
|
19
|
+
const options = (q.options ?? []).map((o) => ({ label: o.label, description: o.description }));
|
|
20
|
+
if (new Set(options.map((o) => o.label)).size !== options.length)
|
|
21
|
+
throw new Error('runtime.unavailable: question.invalid');
|
|
22
|
+
// Nenhum spread do runtime: somente os campos que definem a pergunta suportada.
|
|
23
|
+
const content = { id: q.id, question: q.question, header: (q.header ?? ''),
|
|
24
|
+
isSecret: false, isOther: q.isOther === true, options };
|
|
25
|
+
return { ...content, sha256: (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(content)).digest('hex') };
|
|
26
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.identidadeProcesso = identidadeProcesso;
|
|
37
|
+
exports.estadoProcesso = estadoProcesso;
|
|
38
|
+
exports.gravarAtomico = gravarAtomico;
|
|
39
|
+
exports.iniciarSupervisor = iniciarSupervisor;
|
|
40
|
+
/** D4: supervisor independente do dispatcher, recibo derivado de close/error reais. */
|
|
41
|
+
const fs = __importStar(require("node:fs"));
|
|
42
|
+
const path = __importStar(require("node:path"));
|
|
43
|
+
const node_crypto_1 = require("node:crypto");
|
|
44
|
+
const node_child_process_1 = require("node:child_process");
|
|
45
|
+
function identidadeProcesso(pid) {
|
|
46
|
+
if (!Number.isSafeInteger(pid) || pid <= 0)
|
|
47
|
+
return null;
|
|
48
|
+
try {
|
|
49
|
+
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
50
|
+
const campos = stat.slice(stat.lastIndexOf(')') + 2).split(' ');
|
|
51
|
+
const inicio = campos[19];
|
|
52
|
+
if (!/^\d+$/.test(inicio))
|
|
53
|
+
return null;
|
|
54
|
+
return { pid, inicio, boot: fs.readFileSync('/proc/sys/kernel/random/boot_id', 'utf8').trim() };
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function estadoProcesso(id) {
|
|
61
|
+
if (!id || !Number.isSafeInteger(id.pid) || id.pid <= 0 || !id.inicio || !id.boot)
|
|
62
|
+
return 'desconhecido';
|
|
63
|
+
const atual = identidadeProcesso(id.pid);
|
|
64
|
+
if (!atual) {
|
|
65
|
+
try {
|
|
66
|
+
process.kill(id.pid, 0);
|
|
67
|
+
return 'desconhecido';
|
|
68
|
+
}
|
|
69
|
+
catch (e) {
|
|
70
|
+
return e.code === 'ESRCH' ? 'ausente' : 'desconhecido';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (atual.inicio !== id.inicio || atual.boot !== id.boot)
|
|
74
|
+
return 'ausente';
|
|
75
|
+
try {
|
|
76
|
+
const stat = fs.readFileSync(`/proc/${id.pid}/stat`, 'utf8');
|
|
77
|
+
if (stat.slice(stat.lastIndexOf(')') + 2).startsWith('Z '))
|
|
78
|
+
return 'ausente';
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return 'desconhecido';
|
|
82
|
+
}
|
|
83
|
+
return 'vivo';
|
|
84
|
+
}
|
|
85
|
+
function gravarAtomico(file, valor) {
|
|
86
|
+
const tmp = `${file}.${(0, node_crypto_1.randomUUID)()}.tmp`;
|
|
87
|
+
fs.writeFileSync(tmp, JSON.stringify(valor) + '\n', { mode: 0o600, flag: 'wx' });
|
|
88
|
+
fs.renameSync(tmp, file);
|
|
89
|
+
}
|
|
90
|
+
function iniciarSupervisor(comando, cwd, logPath, env) {
|
|
91
|
+
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
92
|
+
// FD anônimo: o pedido não fica em argv, nem em um arquivo de configuração persistente.
|
|
93
|
+
const tmp = `${logPath}.${(0, node_crypto_1.randomUUID)()}.launch`;
|
|
94
|
+
fs.writeFileSync(tmp, JSON.stringify({ comando, cwd, logPath }), { flag: 'wx', mode: 0o600 });
|
|
95
|
+
const input = fs.openSync(tmp, 'r');
|
|
96
|
+
fs.unlinkSync(tmp);
|
|
97
|
+
try {
|
|
98
|
+
const child = (0, node_child_process_1.spawn)(process.execPath, [__filename, '--run'], {
|
|
99
|
+
cwd, env, detached: true, stdio: [input, 'ignore', 'ignore'],
|
|
100
|
+
});
|
|
101
|
+
child.on('error', () => { });
|
|
102
|
+
child.unref();
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
fs.closeSync(input);
|
|
106
|
+
}
|
|
107
|
+
return { processoPath: logPath + '.process.json', reciboPath: logPath + '.exit.json' };
|
|
108
|
+
}
|
|
109
|
+
function supervisionar() {
|
|
110
|
+
const pedido = JSON.parse(fs.readFileSync(0, 'utf8'));
|
|
111
|
+
const start = Date.now();
|
|
112
|
+
const dados = { schema: 'ork.codex-process/v1', iniciadoEm: new Date(start).toISOString(),
|
|
113
|
+
supervisor: identidadeProcesso(process.pid), filho: null };
|
|
114
|
+
const out = fs.openSync(pedido.logPath, 'ax', 0o600);
|
|
115
|
+
const err = fs.openSync(pedido.logPath + '.stderr', 'ax', 0o600);
|
|
116
|
+
let erro = null;
|
|
117
|
+
const filho = (0, node_child_process_1.spawn)(pedido.comando[0], pedido.comando.slice(1), { cwd: pedido.cwd, stdio: ['ignore', out, err], env: process.env });
|
|
118
|
+
fs.closeSync(out);
|
|
119
|
+
fs.closeSync(err);
|
|
120
|
+
dados.filho = filho.pid ? identidadeProcesso(filho.pid) : null;
|
|
121
|
+
gravarAtomico(pedido.logPath + '.process.json', dados);
|
|
122
|
+
filho.once('error', e => { erro = e.code ?? 'spawn.error'; });
|
|
123
|
+
filho.once('close', (code, signal) => {
|
|
124
|
+
const recibo = { ...dados, terminadoEm: new Date().toISOString(), exitCode: code,
|
|
125
|
+
signal, duracaoMs: Date.now() - start, erro };
|
|
126
|
+
gravarAtomico(pedido.logPath + '.exit.json', recibo);
|
|
127
|
+
});
|
|
128
|
+
// Parada controlada é encaminhada; SIGKILL do supervisor nunca fabrica recibo.
|
|
129
|
+
for (const sinal of ['SIGTERM', 'SIGINT'])
|
|
130
|
+
process.on(sinal, () => { filho.kill(sinal); });
|
|
131
|
+
}
|
|
132
|
+
if (require.main === module && process.argv[2] === '--run')
|
|
133
|
+
supervisionar();
|