@orkastery/cli 0.5.6 → 0.6.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/adapters/README.md +18 -0
- package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
- package/adapters/claude-code/README.md +37 -5
- package/adapters/claude-code/agents/ork-check.md +1 -0
- package/adapters/claude-code/agents/ork-go.md +1 -0
- package/adapters/claude-code/agents/ork-goal.md +1 -0
- package/adapters/claude-code/agents/ork-master.md +1 -0
- package/adapters/claude-code/agents/ork-plan.md +1 -0
- package/adapters/claude-code/agents/ork-ship.md +1 -0
- package/adapters/claude-code/hooks/hooks.json +2 -1
- package/adapters/claude-code/hooks/ork-guard.js +15 -1
- package/adapters/claude-code/hooks/ork-resposta.js +91 -0
- package/adapters/claude-code/hooks/ork-sensor.js +18 -2
- package/adapters/claude-code/hooks/quota-signal.js +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
- package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
- package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
- package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
- package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
- package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
- package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
- package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
- package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
- package/adapters/codex/skills/ork/SKILL.md +2 -0
- package/adapters/hermes/README.md +64 -1
- package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
- package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
- package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
- package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
- package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
- package/adapters/hermes/hermes.plugin.json +4 -0
- package/adapters/hermes/hitl-ingress/__init__.py +101 -8
- package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
- package/adapters/openclaw/README.md +81 -9
- package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
- package/adapters/openclaw/dist/hitl-ingress.js +106 -9
- package/adapters/openclaw/dist/index.js +86 -0
- package/adapters/openclaw/openclaw.plugin.json +34 -4
- package/adapters/openclaw/package.json +2 -2
- package/adapters/openclaw/src/hitl-ingress.ts +103 -9
- package/adapters/openclaw/src/index.ts +94 -0
- package/assets/adapters-en/claude-code/README.md +403 -0
- package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
- package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
- package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
- package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
- package/assets/adapters-en/claude-code/commands/check.md +46 -0
- package/assets/adapters-en/claude-code/commands/go.md +46 -0
- package/assets/adapters-en/claude-code/commands/goal.md +55 -0
- package/assets/adapters-en/claude-code/commands/master.md +54 -0
- package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
- package/assets/adapters-en/claude-code/commands/ork.md +126 -0
- package/assets/adapters-en/claude-code/commands/plan.md +47 -0
- package/assets/adapters-en/claude-code/commands/ship.md +45 -0
- package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
- package/assets/adapters-en/hermes/README.md +273 -0
- package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
- package/assets/references-en/README.md +25 -0
- package/assets/references-en/code-review-axes.md +82 -0
- package/assets/references-en/definition-of-done.md +74 -0
- package/assets/references-en/performance-checklist.md +53 -0
- package/assets/references-en/security-checklist.md +101 -0
- package/assets/references-en/testing-patterns.md +51 -0
- package/assets/security-scan/defaults/.golangci.yml +2 -0
- package/assets/security-scan/defaults/eslint.config.mjs +11 -0
- package/assets/security-scan/defaults/gitleaks.toml +3 -0
- package/assets/security-scan/defaults/ruff.toml +1 -0
- package/assets/security-scan/tools-agil.json +87 -0
- package/assets/security-scan/tools.json +625 -0
- package/assets/skills-en/core/onboarding/SKILL.md +58 -0
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
- package/assets/skills-en/core/thread-state/SKILL.md +88 -0
- package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
- package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
- package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
- package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
- package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
- package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
- package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
- package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
- package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
- package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
- package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
- package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
- package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
- package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
- package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
- package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
- package/dist/adapters/claude-bg.js +123 -9
- package/dist/adapters/codex-controller-worker.js +12 -5
- package/dist/adapters/codex-events.js +16 -4
- package/dist/adapters/codex.js +3 -1
- package/dist/adapters/grok-events.js +227 -0
- package/dist/adapters/grok-mcp-servidor.js +612 -0
- package/dist/adapters/grok-mcp.js +178 -0
- package/dist/adapters/grok.js +686 -0
- package/dist/agendador-cpu.js +92 -0
- package/dist/atualizar-branch.js +245 -0
- package/dist/auditoria.js +13 -11
- package/dist/auditrun.js +51 -46
- package/dist/autorizacao-duravel.js +327 -0
- package/dist/board.js +94 -40
- package/dist/branch-de-estado.js +23 -10
- package/dist/busca-semantica.js +7 -5
- package/dist/catalogo.js +2 -1
- package/dist/changelog-reconciliacao.js +290 -0
- package/dist/check-agil.js +528 -0
- package/dist/check-modo.js +41 -0
- package/dist/check-paralelo.js +238 -0
- package/dist/ci.js +248 -45
- package/dist/ciclos.js +8 -6
- package/dist/claim-lint.js +12 -8
- package/dist/claims-conferir.js +47 -39
- package/dist/claims.js +10 -9
- package/dist/company-brain-client.js +10 -3
- package/dist/company-brain-migration.js +11 -5
- package/dist/conducao-batida.js +759 -0
- package/dist/conducao-sentinela.js +25 -8
- package/dist/conducao.js +89 -29
- package/dist/conhecimento-consulta.js +270 -0
- package/dist/conhecimento.js +111 -87
- package/dist/conta-esgotada.js +127 -0
- package/dist/dado-privado.js +816 -0
- package/dist/decisao-autonoma.js +5 -4
- package/dist/demo.js +14 -12
- package/dist/dependencias-da-worktree.js +25 -0
- package/dist/divida.js +38 -36
- package/dist/docs.js +89 -89
- package/dist/doctor-forja.js +343 -0
- package/dist/doctor-pulse-cron.js +113 -1
- package/dist/doctor.js +164 -6
- package/dist/dsn-da-memoria.js +417 -0
- package/dist/entrega-por-mod.js +503 -0
- package/dist/entrega-pr.js +154 -54
- package/dist/esgotamentos.js +13 -11
- package/dist/estado-thread.js +21 -18
- package/dist/evalrunner.js +35 -32
- package/dist/fabrica-batida.js +34 -21
- package/dist/fabrica-estado.js +33 -21
- package/dist/fix.js +21 -19
- package/dist/forja/adaptador.js +6 -0
- package/dist/forja/ambiente-de-ci.js +27 -0
- package/dist/forja/api.js +256 -0
- package/dist/forja/cache.js +89 -0
- package/dist/forja/cli.js +60 -0
- package/dist/forja/contrato.js +9 -0
- package/dist/forja/endereco.js +43 -0
- package/dist/forja/estado.js +22 -0
- package/dist/forja/executor.js +73 -0
- package/dist/forja/github/ci.js +95 -0
- package/dist/forja/github/dono-da-rede.js +18 -0
- package/dist/forja/github/metadados.js +15 -0
- package/dist/forja/github/pedidos.js +200 -0
- package/dist/forja/gitlab/ci.js +141 -0
- package/dist/forja/gitlab/consultas.js +59 -0
- package/dist/forja/gitlab/dono-da-rede.js +43 -0
- package/dist/forja/gitlab/metadados.js +15 -0
- package/dist/forja/gitlab/pedidos-abertos.js +158 -0
- package/dist/forja/gitlab/pedidos.js +141 -0
- package/dist/forja/produtor.js +32 -0
- package/dist/forja/registro.js +31 -0
- package/dist/forja/resolver.js +121 -0
- package/dist/forja/texto.js +13 -0
- package/dist/forja/versao.js +71 -0
- package/dist/forja.js +123 -80
- package/dist/handoff.js +23 -13
- package/dist/hitl-contract.js +46 -43
- package/dist/hitl-curto.js +37 -25
- package/dist/hitl-gates.js +13 -11
- package/dist/hitl-local-receipt.js +51 -0
- package/dist/hitl-local.js +11 -2
- package/dist/hitl-lock.js +5 -11
- package/dist/hitl-public-receipt.js +11 -0
- package/dist/hitl-resumo.js +44 -1
- package/dist/hitl-sessions.js +62 -9
- package/dist/hitl-texto-livre.js +7 -4
- package/dist/hitl.js +34 -31
- package/dist/horario.js +20 -1
- package/dist/hosts.js +104 -134
- package/dist/index.js +864 -554
- package/dist/indice-vetorial.js +14 -12
- package/dist/init.js +11 -2
- package/dist/integracoes-locais.js +4 -0
- package/dist/intelligence-graph-cli.js +123 -69
- package/dist/intelligence-graph-query.js +37 -22
- package/dist/leases.js +19 -18
- package/dist/ledger-stats.js +17 -16
- package/dist/ledger.js +31 -1
- package/dist/licoes.js +12 -11
- package/dist/locale-accounts.js +228 -0
- package/dist/locale-adapter.js +291 -0
- package/dist/locale-ajuda.js +86 -10
- package/dist/locale-audit.js +199 -0
- package/dist/locale-claims.js +213 -0
- package/dist/locale-conducao.js +138 -0
- package/dist/locale-conhecimento.js +181 -0
- package/dist/locale-decisao.js +205 -0
- package/dist/locale-docs.js +230 -0
- package/dist/locale-estado.js +101 -0
- package/dist/locale-forja.js +288 -0
- package/dist/locale-gerados.js +5 -0
- package/dist/locale-grafo.js +129 -0
- package/dist/locale-master.js +83 -0
- package/dist/locale-network.js +524 -0
- package/dist/locale-operacao-restante.js +931 -0
- package/dist/locale-projetos.js +100 -0
- package/dist/locale-prompts.js +194 -0
- package/dist/locale-pulse.js +140 -2
- package/dist/locale-reservas.js +87 -0
- package/dist/locale-retry.js +183 -6
- package/dist/locale-security-scan.js +69 -0
- package/dist/locale-setup.js +192 -0
- package/dist/locale-ship.js +177 -66
- package/dist/locale-thread.js +149 -5
- package/dist/locale-verify.js +80 -4
- package/dist/locale-worktree.js +246 -0
- package/dist/locale.js +553 -9
- package/dist/maestro-runtime.js +22 -3
- package/dist/manifest.js +293 -12
- package/dist/maquina-ociosa.js +211 -0
- package/dist/maquina.js +10 -5
- package/dist/master-nota-local.js +200 -0
- package/dist/master-nota.js +10 -2
- package/dist/master.js +118 -41
- package/dist/mcp-conhecimento.js +52 -0
- package/dist/mcp-experiencia.js +26 -5
- package/dist/mcp-install.js +90 -15
- package/dist/mcp-noctum.js +101 -0
- package/dist/mcp-server.js +116 -22
- package/dist/mcp-ship-transporte.js +977 -0
- package/dist/mcp-ship.js +68 -24
- package/dist/mcp-transportes.js +17 -0
- package/dist/memoria.js +63 -58
- package/dist/merge-da-entrega.js +85 -0
- package/dist/modos-migracao.js +8 -6
- package/dist/modos.js +17 -18
- package/dist/network-roadmap.js +94 -54
- package/dist/noctum-aceite.js +929 -0
- package/dist/noctum-arco.js +540 -33
- package/dist/noctum-capacidade.js +3 -3
- package/dist/noctum-changelog.js +399 -0
- package/dist/noctum-cli.js +539 -0
- package/dist/noctum-coordenacao.js +1225 -0
- package/dist/noctum-entrega.js +1217 -0
- package/dist/noctum-envelope.js +253 -17
- package/dist/noctum-execucao.js +100 -24
- package/dist/noctum-fechamento.js +416 -0
- package/dist/noctum-fila.js +49 -10
- package/dist/noctum-guarda.js +333 -0
- package/dist/noctum-integracao.js +507 -0
- package/dist/noctum-maquinas.js +387 -0
- package/dist/noctum-medicao.js +450 -0
- package/dist/noctum-modo.js +390 -0
- package/dist/noctum-pergunta-canal.js +96 -0
- package/dist/noctum-pergunta.js +115 -0
- package/dist/noctum-provas.js +838 -0
- package/dist/noctum-reconciliacao.js +594 -0
- package/dist/noctum-rede.js +102 -0
- package/dist/noctum-registro.js +215 -0
- package/dist/noctum-relatorio.js +861 -0
- package/dist/noctum-resposta.js +207 -0
- package/dist/noctum-retomada-rede.js +71 -0
- package/dist/noctum-sessoes-em-voo.js +93 -0
- package/dist/noctum-supervisao.js +649 -0
- package/dist/noctum-terminal.js +459 -0
- package/dist/noctum-transporte.js +655 -0
- package/dist/noctum-vigia.js +679 -0
- package/dist/ocupacao.js +3 -1
- package/dist/onboarding.js +16 -5
- package/dist/orkmind.js +39 -23
- package/dist/orquestracao.js +31 -35
- package/dist/parado-no-condutor.js +160 -139
- package/dist/phase.js +96 -42
- package/dist/policies.js +33 -0
- package/dist/postura-local.js +11 -6
- package/dist/preflight.js +2 -1
- package/dist/procedencia.js +9 -14
- package/dist/projeto-alvo.js +59 -20
- package/dist/prompts.js +136 -42
- package/dist/prova-minima.js +5 -6
- package/dist/pulse-cadencia.js +5 -4
- package/dist/pulse-consentimento.js +53 -1
- package/dist/pulse-delivery.js +143 -27
- package/dist/pulse-resposta.js +368 -4
- package/dist/pulse.js +136 -3
- package/dist/ratelimit.js +13 -4
- package/dist/recall.js +14 -13
- package/dist/rede-adesao.js +13 -8
- package/dist/rede-forja.js +108 -24
- package/dist/rede-status.js +63 -45
- package/dist/rede.js +86 -46
- package/dist/retomada-checkpoint.js +101 -0
- package/dist/retry.js +326 -78
- package/dist/roadmap-reservas.js +32 -32
- package/dist/runtime-ambiente.js +5 -0
- package/dist/runtime-context.js +279 -85
- package/dist/runtime-escada.js +429 -0
- package/dist/runtime-profiles.js +130 -63
- package/dist/runtimes.js +42 -5
- package/dist/saida-segura.js +3 -2
- package/dist/security-scan/agil.js +366 -0
- package/dist/security-scan/cli.js +76 -0
- package/dist/security-scan/compare.js +149 -0
- package/dist/security-scan/config.js +93 -0
- package/dist/security-scan/detect.js +97 -0
- package/dist/security-scan/executor.js +196 -0
- package/dist/security-scan/guard.js +180 -0
- package/dist/security-scan/imagem-de-lint.js +96 -0
- package/dist/security-scan/normalize/actionlint.js +12 -0
- package/dist/security-scan/normalize/eslint.js +12 -0
- package/dist/security-scan/normalize/gitleaks.js +13 -0
- package/dist/security-scan/normalize/golangci-lint.js +13 -0
- package/dist/security-scan/normalize/govulncheck.js +36 -0
- package/dist/security-scan/normalize/index.js +25 -0
- package/dist/security-scan/normalize/npm-audit.js +30 -0
- package/dist/security-scan/normalize/osv-scanner.js +32 -0
- package/dist/security-scan/normalize/oxlint.js +51 -0
- package/dist/security-scan/normalize/pip-audit.js +16 -0
- package/dist/security-scan/normalize/ruff.js +12 -0
- package/dist/security-scan/normalize/semgrep.js +20 -0
- package/dist/security-scan/normalize/trivy.js +33 -0
- package/dist/security-scan/normalize/util.js +204 -0
- package/dist/security-scan/normalize/zizmor.js +19 -0
- package/dist/security-scan/report.js +156 -0
- package/dist/security-scan/run.js +448 -0
- package/dist/security-scan/tools.js +62 -0
- package/dist/security-scan/trabalhador.js +74 -0
- package/dist/security-scan/types.js +15 -0
- package/dist/session-events.js +19 -2
- package/dist/session-watcher-claude.js +74 -19
- package/dist/session-watcher-grok.js +425 -0
- package/dist/session-watcher.js +174 -13
- package/dist/sessoes-contas.js +42 -5
- package/dist/sessoes-inventario.js +1 -1
- package/dist/sessoes.js +25 -23
- package/dist/setup.js +67 -66
- package/dist/ship-publicar.js +263 -92
- package/dist/ship.js +160 -17
- package/dist/superficie.js +14 -11
- package/dist/thread-close.js +9 -9
- package/dist/thread.js +121 -18
- package/dist/tokens.js +15 -11
- package/dist/trabalho-thread.js +297 -0
- package/dist/transporte-do-canal.js +189 -0
- package/dist/types.js +12 -1
- package/dist/util.js +5 -2
- package/dist/varredura-acoes.js +500 -0
- package/dist/verify.js +491 -32
- package/dist/worktree-local.js +12 -10
- package/dist/worktree.js +81 -85
- package/eval/casos/check-quality.json +77 -0
- package/eval/casos/security-auditor.json +148 -0
- package/eval/casos/security-remediation.json +161 -0
- package/eval/fixtures/security-scan/README.md +8 -0
- package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/go/Dockerfile +4 -0
- package/eval/fixtures/security-scan/go/README.md +4 -0
- package/eval/fixtures/security-scan/go/config.go +4 -0
- package/eval/fixtures/security-scan/go/go.mod +5 -0
- package/eval/fixtures/security-scan/go/go.sum +2 -0
- package/eval/fixtures/security-scan/go/main.go +31 -0
- package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/js/Dockerfile +3 -0
- package/eval/fixtures/security-scan/js/README.md +4 -0
- package/eval/fixtures/security-scan/js/package-lock.json +844 -0
- package/eval/fixtures/security-scan/js/package.json +10 -0
- package/eval/fixtures/security-scan/js/src/config.js +4 -0
- package/eval/fixtures/security-scan/js/src/server.js +17 -0
- package/eval/fixtures/security-scan/js/src/util.ts +4 -0
- package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
- package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
- package/eval/fixtures/security-scan/python/Dockerfile +3 -0
- package/eval/fixtures/security-scan/python/README.md +4 -0
- package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
- package/eval/fixtures/security-scan/python/app/config.py +2 -0
- package/eval/fixtures/security-scan/python/app/main.py +19 -0
- package/eval/fixtures/security-scan/python/requirements.txt +1 -0
- package/package.json +10 -5
- package/references/security-checklist.md +3 -3
- package/skills/README.md +1 -0
- package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
- package/skills/phases/check-quality/SKILL.md +16 -0
- package/skills/phases/go-implementation/SKILL.md +6 -0
- package/skills/phases/security-remediation/SKILL.md +70 -0
- package/skills/reviewers/security-auditor/SKILL.md +25 -0
|
@@ -0,0 +1,503 @@
|
|
|
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.PRAZO_MAXIMO_DA_CONFERENCIA_MS = exports.SEM_MENSAGEIRO = exports.SEM_CAIXA = exports.LIMITE_DA_MENSAGEM = exports.LIMITE_DA_CAUDA = exports.JANELA_DO_MENSAGEIRO_MS = exports.MOD_DA_ENTREGA = exports.CONTRATO_DA_ENTREGA = void 0;
|
|
37
|
+
exports.cabecalhoDaEntrega = cabecalhoDaEntrega;
|
|
38
|
+
exports.mensagemDaEntrega = mensagemDaEntrega;
|
|
39
|
+
exports.normalizarCorpo = normalizarCorpo;
|
|
40
|
+
exports.hashDoCorpo = hashDoCorpo;
|
|
41
|
+
exports.lerMensagemDaEntrega = lerMensagemDaEntrega;
|
|
42
|
+
exports.rotuloDaEntrega = rotuloDaEntrega;
|
|
43
|
+
exports.turnoQueParou = turnoQueParou;
|
|
44
|
+
exports.lerCaudaDaTranscricao = lerCaudaDaTranscricao;
|
|
45
|
+
exports.perguntaDoTurno = perguntaDoTurno;
|
|
46
|
+
exports.novaCaixaDeSaida = novaCaixaDeSaida;
|
|
47
|
+
exports.pastaDasEntregas = pastaDasEntregas;
|
|
48
|
+
exports.controleClaudeBgPorMod = controleClaudeBgPorMod;
|
|
49
|
+
exports.conferirNoReceptor = conferirNoReceptor;
|
|
50
|
+
exports.confirmarNoReceptor = confirmarNoReceptor;
|
|
51
|
+
/**
|
|
52
|
+
* RM-059 (fatia F9, T9.1; DD3 do plano dos mods, pela recomendada): a resposta do dono a uma sessao de fase
|
|
53
|
+
* `claude-bg` parada sai pelo Mensageiro de Sessoes (o mod `ork-mensageiro`), com a conferencia pelo nucleo no
|
|
54
|
+
* lado receptor. Contrato `ork.session-delivery/v1`.
|
|
55
|
+
*
|
|
56
|
+
* O caminho, de ponta a ponta:
|
|
57
|
+
*
|
|
58
|
+
* 1. `ork sessions request` abre o pedido de sessao vinculado ao turno que parou: o `uuid` da ultima mensagem do
|
|
59
|
+
* assistente na transcricao, com a sessao `blocked` no `claude agents` (G2 da thread ork-rm059mensag).
|
|
60
|
+
* 2. A resposta entra pelo ingresso local do Claude Code (o dialogo nativo do `ork_request_decision`). O
|
|
61
|
+
* `entregarNaSessao` reserva como sempre, e o `enviar` deste controle grava `session_delivery_queued` com o
|
|
62
|
+
* sha256 do corpo e poe a mensagem na caixa de saida, que so existe na memoria do servidor MCP do dono (G3):
|
|
63
|
+
* o texto da resposta nunca vai a disco, como no resto do HITL.
|
|
64
|
+
* 3. O Mensageiro da sessao do dono pega a mensagem pela `ork_session_outbox` e a leva por `$.session.send`.
|
|
65
|
+
* 4. O Mensageiro da sessao de fase so deixa a mensagem chegar ao modelo depois que o nucleo confere, pela
|
|
66
|
+
* `ork_session_inbox` do servidor preso ao despacho, que ela e aquela entrega, para aquela sessao, com aquele
|
|
67
|
+
* texto, e a reserva uma vez so. Depois de a mensagem entrar na fila, a confirmacao grava o recibo do receptor
|
|
68
|
+
* e a reconciliacao de sempre grava o `session_answered`.
|
|
69
|
+
*
|
|
70
|
+
* O que isto NAO prova: a mensagem chega ao modelo como mensagem de outra sessao, e o classificador do modo auto do
|
|
71
|
+
* Claude Code nao a le como intencao do dono. A resposta informa a sessao; ela nao destrava acao que so o dono
|
|
72
|
+
* autoriza (para isso, `claude attach`). A reserva e o recibo ficam em disco com o uid dos agentes: um processo do
|
|
73
|
+
* mesmo usuario que escreva em `.orkastery/` forja os dois, como forja o resto do estado.
|
|
74
|
+
*/
|
|
75
|
+
const fs = __importStar(require("node:fs"));
|
|
76
|
+
const path = __importStar(require("node:path"));
|
|
77
|
+
const node_crypto_1 = require("node:crypto");
|
|
78
|
+
const claude_bg_1 = require("./adapters/claude-bg");
|
|
79
|
+
const codex_question_1 = require("./adapters/codex-question");
|
|
80
|
+
const runtime_ambiente_1 = require("./runtime-ambiente");
|
|
81
|
+
const runtime_profiles_1 = require("./runtime-profiles");
|
|
82
|
+
const session_watcher_claude_1 = require("./session-watcher-claude");
|
|
83
|
+
const hitl_gates_1 = require("./hitl-gates");
|
|
84
|
+
const hitl_1 = require("./hitl");
|
|
85
|
+
const thread_1 = require("./thread");
|
|
86
|
+
const ledger_1 = require("./ledger");
|
|
87
|
+
const util_1 = require("./util");
|
|
88
|
+
exports.CONTRATO_DA_ENTREGA = 'ork.session-delivery/v1';
|
|
89
|
+
/** O mod que leva a mensagem nas duas pontas (o mesmo nome do `plugin.json` dele). */
|
|
90
|
+
exports.MOD_DA_ENTREGA = 'ork-mensageiro';
|
|
91
|
+
/** D9 da thread ork-rm059mensag: o Mensageiro conta como vivo se consultou a caixa nesta janela. */
|
|
92
|
+
exports.JANELA_DO_MENSAGEIRO_MS = 120000;
|
|
93
|
+
/** A cauda da transcricao lida para achar o turno que parou, sem seguir link. */
|
|
94
|
+
exports.LIMITE_DA_CAUDA = 256 * 1024;
|
|
95
|
+
/** A maior mensagem que o receptor confere: a resposta (ate 4096), o cabecalho e o envelope do Claude Code. */
|
|
96
|
+
exports.LIMITE_DA_MENSAGEM = 8192;
|
|
97
|
+
/** O motivo de envio recusado que vai ao ledger, ja redigido. */
|
|
98
|
+
const LIMITE_DO_MOTIVO = 200;
|
|
99
|
+
const UUID = /^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/;
|
|
100
|
+
const sha = (texto) => (0, node_crypto_1.createHash)('sha256').update(texto).digest('hex');
|
|
101
|
+
// ---------------------------------------------------------------------------------------------------------------
|
|
102
|
+
// A mensagem (D5): o nucleo compoe e o nucleo confere; o mod so a carrega.
|
|
103
|
+
// ---------------------------------------------------------------------------------------------------------------
|
|
104
|
+
function cabecalhoDaEntrega(pedidoId, envioId) {
|
|
105
|
+
return `[${exports.CONTRATO_DA_ENTREGA} pedido=${pedidoId} entrega=${envioId}] Resposta do dono à pergunta deste turno, conferida pelo núcleo do Orkastery:`;
|
|
106
|
+
}
|
|
107
|
+
function mensagemDaEntrega(pedidoId, envioId, resposta) {
|
|
108
|
+
return `${cabecalhoDaEntrega(pedidoId, envioId)}\n${resposta}`;
|
|
109
|
+
}
|
|
110
|
+
/** O corpo que o hash cobre: quebra de linha unica (LF) e sem o espaco do fim, nos dois lados. */
|
|
111
|
+
function normalizarCorpo(texto) {
|
|
112
|
+
return texto.replace(/\r\n?/g, '\n').replace(/\s+$/, '');
|
|
113
|
+
}
|
|
114
|
+
function hashDoCorpo(texto) {
|
|
115
|
+
return sha(normalizarCorpo(texto));
|
|
116
|
+
}
|
|
117
|
+
/** Um valor de atributo do envelope: uma linha so, sem aspas nem sinal de tag. */
|
|
118
|
+
const VALOR_DE_LINHA = '[^"<>\\n\\r\\v\\f\\u0085\\u2028\\u2029]{1,200}';
|
|
119
|
+
/**
|
|
120
|
+
* O envelope que o Claude Code 2.1.296 escreve em volta da mensagem de outra sessao, e so ele: os atributos que o motor
|
|
121
|
+
* conhece, na ordem em que ele os escreve (`from`, `from-session`, `hop-chain`, `from-name`, `from-mode`,
|
|
122
|
+
* `from-plugin`), cada valor numa linha so, depois a quebra de linha, o corpo e o fecho exato no fim. Qualquer outra
|
|
123
|
+
* forma recusa (D5, D20 da thread ork-rm059mensag): texto posto dentro ou antes da tag chegaria ao modelo da fase sem
|
|
124
|
+
* ter passado pelo nucleo, porque o receptor deixa a mensagem entrar como chegou.
|
|
125
|
+
*/
|
|
126
|
+
const ENVELOPE_DO_MOTOR = new RegExp('^<cross-session-message' +
|
|
127
|
+
'(?: from="[^"<>\\s]{1,300}")?' +
|
|
128
|
+
'(?: from-session="[A-Za-z0-9_-]{1,80}")?' +
|
|
129
|
+
'(?: hop-chain="[0-9a-f]{24}(?:,[0-9a-f]{24}){0,31}")?' +
|
|
130
|
+
`(?: from-name="${VALOR_DE_LINHA}")?` +
|
|
131
|
+
'(?: from-mode="[A-Za-z-]{1,40}")?' +
|
|
132
|
+
`(?: from-plugin="${VALOR_DE_LINHA}")?` +
|
|
133
|
+
'>\\n([\\s\\S]*)\\n</cross-session-message>$');
|
|
134
|
+
const CABECALHO = /^\[ork\.session-delivery\/v1 pedido=([0-9a-f-]{36}) entrega=([0-9a-f-]{36})\] /;
|
|
135
|
+
/**
|
|
136
|
+
* Le a mensagem que chegou ao receptor. Com o envelope `<cross-session-message ...>` do Claude Code, ele so passa na
|
|
137
|
+
* forma exata que o motor escreve, e sai; depois disso, o cabecalho tem de ser a primeira linha e exatamente o que o
|
|
138
|
+
* nucleo compoe. Qualquer texto a mais antes dele, dentro da tag ou na linha dele recusa: quem sabe a resposta nao poe
|
|
139
|
+
* nada antes.
|
|
140
|
+
*/
|
|
141
|
+
function lerMensagemDaEntrega(bruto) {
|
|
142
|
+
if (typeof bruto !== 'string' || bruto.length > exports.LIMITE_DA_MENSAGEM)
|
|
143
|
+
return null;
|
|
144
|
+
let texto = bruto.replace(/\r\n?/g, '\n');
|
|
145
|
+
if (texto.startsWith('<')) {
|
|
146
|
+
const envelope = ENVELOPE_DO_MOTOR.exec(texto);
|
|
147
|
+
if (!envelope)
|
|
148
|
+
return null;
|
|
149
|
+
texto = envelope[1];
|
|
150
|
+
}
|
|
151
|
+
const quebra = texto.indexOf('\n');
|
|
152
|
+
if (quebra < 0)
|
|
153
|
+
return null;
|
|
154
|
+
const linha = texto.slice(0, quebra);
|
|
155
|
+
const m = CABECALHO.exec(linha);
|
|
156
|
+
if (!m || !UUID.test(m[1]) || !UUID.test(m[2]) || linha !== cabecalhoDaEntrega(m[1], m[2]))
|
|
157
|
+
return null;
|
|
158
|
+
return { pedidoId: m[1], envioId: m[2], corpo: texto.slice(quebra + 1) };
|
|
159
|
+
}
|
|
160
|
+
function rotuloDaEntrega(pedidoId) {
|
|
161
|
+
return `Resposta do dono ao pedido ${pedidoId.slice(0, 8)}, conferida pelo núcleo`;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* As ultimas linhas `assistant` da conversa principal (as do mesmo `message.id`, porque o Claude Code grava uma
|
|
165
|
+
* linha por bloco), sem linha `user` depois, com texto e sem `tool_use`: e o turno em que a sessao parou para
|
|
166
|
+
* esperar o dono. Linha que nao e JSON (a primeira da cauda, cortada) e linha de metadado (`system`,
|
|
167
|
+
* `last-prompt`, `cost-state`, ...) nao contam.
|
|
168
|
+
*/
|
|
169
|
+
function turnoQueParou(cauda) {
|
|
170
|
+
const conversa = [];
|
|
171
|
+
for (const linha of cauda.split('\n')) {
|
|
172
|
+
let e;
|
|
173
|
+
try {
|
|
174
|
+
e = JSON.parse(linha);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (!e || typeof e !== 'object' || Array.isArray(e) || (e.type !== 'user' && e.type !== 'assistant') || e.isSidechain === true)
|
|
180
|
+
continue;
|
|
181
|
+
const mensagem = e.message && typeof e.message === 'object' ? e.message : {};
|
|
182
|
+
conversa.push({ tipo: e.type, uuid: typeof e.uuid === 'string' ? e.uuid.toLowerCase() : '',
|
|
183
|
+
idDaMensagem: typeof mensagem.id === 'string' ? mensagem.id : null, conteudo: mensagem.content });
|
|
184
|
+
}
|
|
185
|
+
const fim = conversa.at(-1);
|
|
186
|
+
if (!fim || fim.tipo !== 'assistant' || !UUID.test(fim.uuid))
|
|
187
|
+
return null;
|
|
188
|
+
const trecho = [];
|
|
189
|
+
for (let i = conversa.length - 1; i >= 0; i--) {
|
|
190
|
+
const c = conversa[i];
|
|
191
|
+
if (c.tipo !== 'assistant' || (i !== conversa.length - 1 && (fim.idDaMensagem === null || c.idDaMensagem !== fim.idDaMensagem)))
|
|
192
|
+
break;
|
|
193
|
+
trecho.unshift(c);
|
|
194
|
+
}
|
|
195
|
+
const blocos = trecho.flatMap((c) => Array.isArray(c.conteudo) ? c.conteudo
|
|
196
|
+
: typeof c.conteudo === 'string' ? [{ type: 'text', text: c.conteudo }] : []);
|
|
197
|
+
const tipo = (b) => b && typeof b === 'object' ? b.type : undefined;
|
|
198
|
+
if (blocos.some(b => tipo(b) === 'tool_use' || tipo(b) === 'server_tool_use'))
|
|
199
|
+
return null;
|
|
200
|
+
const textos = blocos.flatMap(b => {
|
|
201
|
+
const t = b && typeof b === 'object' ? b.text : undefined;
|
|
202
|
+
return tipo(b) === 'text' && typeof t === 'string' && t.trim() ? [t] : [];
|
|
203
|
+
});
|
|
204
|
+
return textos.length ? { uuid: fim.uuid, texto: textos.join('\n\n') } : null;
|
|
205
|
+
}
|
|
206
|
+
/** A cauda de um arquivo comum, sem seguir link e sem travar em FIFO; `null` quando nao ha o que ler. */
|
|
207
|
+
function lerCaudaDaTranscricao(arquivo, limite = exports.LIMITE_DA_CAUDA) {
|
|
208
|
+
let fd;
|
|
209
|
+
try {
|
|
210
|
+
fd = fs.openSync(arquivo, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return null;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
const st = fs.fstatSync(fd);
|
|
217
|
+
if (!st.isFile())
|
|
218
|
+
return null;
|
|
219
|
+
const n = Math.min(st.size, limite), buf = Buffer.alloc(n);
|
|
220
|
+
fs.readSync(fd, buf, 0, n, st.size - n);
|
|
221
|
+
return buf.toString('utf8');
|
|
222
|
+
}
|
|
223
|
+
finally {
|
|
224
|
+
fs.closeSync(fd);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/** A pergunta nativa de texto livre do turno que parou, ou o codigo do que impede projeta-la. */
|
|
228
|
+
function perguntaDoTurno(turno) {
|
|
229
|
+
const texto = turno.texto.replace(/\r\n?/g, '\n');
|
|
230
|
+
try {
|
|
231
|
+
return { pergunta: (0, codex_question_1.projetarPergunta)({ isBlocking: true, questions: [{ id: turno.uuid, question: texto, isOther: true }] }) };
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return { codigo: texto.length > 2000 ? 'pergunta.longa' : 'pergunta.invalida' };
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
exports.SEM_CAIXA = 'runtime.unavailable: a resposta para a sessão claude-bg sai pelo Mensageiro de Sessões, pelo ' +
|
|
238
|
+
'ingresso local do Claude Code (a Mesa ou o diálogo nativo); este processo não tem caixa de saída. Responda pela sessão ' +
|
|
239
|
+
'do dono com o ork-mensageiro ligado, ou pelo claude attach';
|
|
240
|
+
exports.SEM_MENSAGEIRO = 'runtime.unavailable: nenhum Mensageiro de Sessões consultou a caixa de saída desta sessão do ' +
|
|
241
|
+
'dono nos últimos 120 s; ligue o mod ork-mensageiro nesta sessão, ou responda pelo claude attach';
|
|
242
|
+
function novaCaixaDeSaida(agora = Date.now) {
|
|
243
|
+
const entradas = new Map();
|
|
244
|
+
let consultadaEm = Number.NEGATIVE_INFINITY;
|
|
245
|
+
return {
|
|
246
|
+
impedimento: () => agora() - consultadaEm <= exports.JANELA_DO_MENSAGEIRO_MS ? null : exports.SEM_MENSAGEIRO,
|
|
247
|
+
guardar: (e) => {
|
|
248
|
+
if (entradas.has(e.envioId))
|
|
249
|
+
return;
|
|
250
|
+
entradas.set(e.envioId, { ...e, criadaEm: new Date(agora()).toISOString(), tentativas: 0, ultimoEnvio: null });
|
|
251
|
+
},
|
|
252
|
+
listar: (raiz) => {
|
|
253
|
+
consultadaEm = agora();
|
|
254
|
+
const ledgers = new Map();
|
|
255
|
+
const ledger = (thread) => {
|
|
256
|
+
if (!ledgers.has(thread)) {
|
|
257
|
+
try {
|
|
258
|
+
ledgers.set(thread, (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread)));
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
ledgers.set(thread, null);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return ledgers.get(thread);
|
|
265
|
+
};
|
|
266
|
+
const saida = [];
|
|
267
|
+
for (const [id, e] of entradas) {
|
|
268
|
+
const eventos = ledger(e.thread);
|
|
269
|
+
// Respondido (ou a thread sumiu): a entrega acabou e sai da caixa. Thread fechada fica: o envio falha sozinho.
|
|
270
|
+
if (eventos === null || eventos.some(x => x.tipo === 'session_answered' && x.pedidoId === e.pedidoId)) {
|
|
271
|
+
entradas.delete(id);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
saida.push({ ...e, ultimoEnvio: e.ultimoEnvio && { ...e.ultimoEnvio },
|
|
275
|
+
reservada: eventos.some(x => x.tipo === ledger_1.TIPOS_DE_EVENTO.entregaReservada && x.envioId === e.envioId) });
|
|
276
|
+
}
|
|
277
|
+
return saida;
|
|
278
|
+
},
|
|
279
|
+
anotarEnvio: (raiz, thread, envioId, entregue, motivo) => {
|
|
280
|
+
const e = entradas.get(envioId);
|
|
281
|
+
if (!e || e.thread !== thread)
|
|
282
|
+
throw new Error('entrega.desconhecida: esta caixa de saída não tem essa entrega');
|
|
283
|
+
const limpo = motivo === undefined ? null : (0, hitl_1.redigirSegredos)(motivo.replace(/\s+/g, ' ').trim()).slice(0, LIMITE_DO_MOTIVO);
|
|
284
|
+
e.tentativas += 1;
|
|
285
|
+
e.ultimoEnvio = { em: new Date(agora()).toISOString(), entregue, motivo: limpo };
|
|
286
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread), thread, ledger_1.TIPOS_DE_EVENTO.entregaEnviada, { pedidoId: e.pedidoId, fase: e.fase,
|
|
287
|
+
sessionId: e.sessionId, envioId, entregue, motivo: limpo, via: exports.MOD_DA_ENTREGA, tentativa: e.tentativas });
|
|
288
|
+
return { ...e, ultimoEnvio: { ...e.ultimoEnvio } };
|
|
289
|
+
},
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
// ---------------------------------------------------------------------------------------------------------------
|
|
293
|
+
// O disco do receptor (D6): a reserva e o recibo, sem o texto.
|
|
294
|
+
// ---------------------------------------------------------------------------------------------------------------
|
|
295
|
+
function pastaDasEntregas(raiz, thread) {
|
|
296
|
+
return path.join((0, thread_1.dirThread)(raiz, thread), 'entregas-de-sessao');
|
|
297
|
+
}
|
|
298
|
+
function garantirPasta(raiz, thread) {
|
|
299
|
+
const pasta = pastaDasEntregas(raiz, thread);
|
|
300
|
+
fs.mkdirSync(pasta, { recursive: true, mode: 0o700 });
|
|
301
|
+
const st = fs.lstatSync(pasta);
|
|
302
|
+
if (!st.isDirectory() || st.isSymbolicLink() || (process.getuid && st.uid !== process.getuid()) || (st.mode & 0o077))
|
|
303
|
+
throw new Error('runtime.unavailable: a pasta entregas-de-sessao precisa ser 0700 do usuário do núcleo');
|
|
304
|
+
return pasta;
|
|
305
|
+
}
|
|
306
|
+
/** Grava o arquivo uma vez so (criacao exclusiva). `false` quando ele ja existia. */
|
|
307
|
+
function escreverUmaVez(arquivo, dados) {
|
|
308
|
+
let fd;
|
|
309
|
+
try {
|
|
310
|
+
fd = fs.openSync(arquivo, 'wx', 0o600);
|
|
311
|
+
}
|
|
312
|
+
catch (e) {
|
|
313
|
+
if (e.code === 'EEXIST')
|
|
314
|
+
return false;
|
|
315
|
+
throw e;
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
fs.writeFileSync(fd, JSON.stringify(dados));
|
|
319
|
+
fs.fsyncSync(fd);
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
fs.closeSync(fd);
|
|
323
|
+
}
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
/** Le um JSON privado da pasta: arquivo comum, sem link, do usuario do nucleo e sem permissao para outros. */
|
|
327
|
+
function lerPrivado(arquivo) {
|
|
328
|
+
try {
|
|
329
|
+
const st = fs.lstatSync(arquivo);
|
|
330
|
+
if (!st.isFile() || st.isSymbolicLink() || (process.getuid && st.uid !== process.getuid()) || (st.mode & 0o077))
|
|
331
|
+
return null;
|
|
332
|
+
const bruto = JSON.parse(fs.readFileSync(arquivo, 'utf8'));
|
|
333
|
+
return bruto && typeof bruto === 'object' && !Array.isArray(bruto) ? bruto : null;
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const mesmaInstancia = (a, b) => !!a && !!b &&
|
|
340
|
+
a.sessionId === b.sessionId && a.runtime === b.runtime && a.cwd === b.cwd && a.instancia === b.instancia && a.bloqueio === b.bloqueio;
|
|
341
|
+
/** O prazo mais longo que o receptor aceita no `ate` da conferencia: o mod pede bem menos (15 s). */
|
|
342
|
+
exports.PRAZO_MAXIMO_DA_CONFERENCIA_MS = 60000;
|
|
343
|
+
const lerTranscricaoPadrao = (perfil, cwd, sessionId) => {
|
|
344
|
+
const arquivo = (0, session_watcher_claude_1.arquivoDaTranscricao)(perfil, cwd, sessionId);
|
|
345
|
+
return arquivo ? lerCaudaDaTranscricao(arquivo) : null;
|
|
346
|
+
};
|
|
347
|
+
function perfilDaSessao(raiz, thread, sessionId, eventos) {
|
|
348
|
+
const registrada = (0, thread_1.lerThread)(raiz, thread).sessoes.find(s => s.sessionId === sessionId && s.runtime === 'claude-bg');
|
|
349
|
+
return (0, runtime_profiles_1.perfilDoRegistro)(eventos, { sessionId, despachadaEm: registrada?.despachadaEm });
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* O controle de resposta de sessao `claude-bg` (D2): consulta e para como o adaptador, com o ambiente do perfil da
|
|
353
|
+
* sessao; o vinculo do turno sai da transcricao; o envio poe a mensagem na caixa de saida e o recibo e o do
|
|
354
|
+
* receptor. Sem caixa no processo (o CLI, o Telegram), o controle declara o impedimento e o nucleo recusa antes de
|
|
355
|
+
* reservar (D4).
|
|
356
|
+
*/
|
|
357
|
+
function controleClaudeBgPorMod(raiz, thread, sessionId, caixa, deps = {}) {
|
|
358
|
+
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread));
|
|
359
|
+
const perfil = perfilDaSessao(raiz, thread, sessionId, eventos);
|
|
360
|
+
const ambiente = perfil ? (0, claude_bg_1.ambienteDoPerfil)(perfil) : (0, runtime_ambiente_1.ambienteDeAssinatura)();
|
|
361
|
+
const consultarAgentes = deps.consultarAgentes ?? ((env, prazoMs) => (0, claude_bg_1.consultarSessoes)(undefined, true, env, prazoMs));
|
|
362
|
+
const lerTranscricao = deps.lerTranscricao ?? lerTranscricaoPadrao;
|
|
363
|
+
return {
|
|
364
|
+
consultar: (orcamentoMs = 60000) => {
|
|
365
|
+
const r = consultarAgentes(ambiente, Math.max(1, Math.min(60000, orcamentoMs)));
|
|
366
|
+
if (!r.ok)
|
|
367
|
+
return { ok: false, sessoes: [] };
|
|
368
|
+
return { ok: true, sessoes: r.sessoes.map((s) => {
|
|
369
|
+
const base = { sessionId: s.sessionId, runtime: 'claude-bg', cwd: s.cwd ?? '', estado: s.state ?? s.status ?? '',
|
|
370
|
+
instancia: s.id && Number.isFinite(s.startedAt) ? JSON.stringify([s.id, s.startedAt]) : '' };
|
|
371
|
+
if (s.sessionId !== sessionId || base.estado !== 'blocked' || !base.cwd)
|
|
372
|
+
return base;
|
|
373
|
+
const cauda = lerTranscricao(perfil, base.cwd, sessionId);
|
|
374
|
+
const turno = cauda === null ? null : turnoQueParou(cauda);
|
|
375
|
+
if (!turno)
|
|
376
|
+
return { ...base, limitacao: { motivo: 'runtime.unavailable', codigo: 'turno.ausente', metodo: 'transcricao' } };
|
|
377
|
+
const projetada = perguntaDoTurno(turno);
|
|
378
|
+
return 'pergunta' in projetada ? { ...base, bloqueio: turno.uuid, perguntaNativa: projetada.pergunta }
|
|
379
|
+
: { ...base, bloqueio: turno.uuid, limitacao: { motivo: 'runtime.unavailable', codigo: projetada.codigo, metodo: 'transcricao' } };
|
|
380
|
+
}) };
|
|
381
|
+
},
|
|
382
|
+
parar: s => (0, util_1.exec)('claude', ['stop', s.sessionId], undefined, 10000, ambiente).ok,
|
|
383
|
+
enviar: (e) => {
|
|
384
|
+
if (!caixa)
|
|
385
|
+
throw new Error(exports.SEM_CAIXA);
|
|
386
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread), thread, ledger_1.TIPOS_DE_EVENTO.entregaNaFila, { contrato: exports.CONTRATO_DA_ENTREGA, pedidoId: e.pedidoId,
|
|
387
|
+
fase: e.fase, sessionId: e.sessao.sessionId, runtime: 'claude-bg', envioId: e.envioId, instancia: e.sessao.instancia,
|
|
388
|
+
bloqueio: e.sessao.bloqueio, textoSha256: hashDoCorpo(e.resposta), transporte: 'mod', via: exports.MOD_DA_ENTREGA });
|
|
389
|
+
caixa.guardar({ thread, pedidoId: e.pedidoId, envioId: e.envioId, fase: e.fase, sessionId: e.sessao.sessionId,
|
|
390
|
+
mensagem: mensagemDaEntrega(e.pedidoId, e.envioId, e.resposta) });
|
|
391
|
+
},
|
|
392
|
+
confirmar: (e) => {
|
|
393
|
+
if (!UUID.test(e.envioId))
|
|
394
|
+
return null;
|
|
395
|
+
const r = lerPrivado(path.join(pastaDasEntregas(raiz, thread), `${e.envioId}.recibo.json`));
|
|
396
|
+
if (!r || r.contrato !== 'ork.session-answer/v1' || r.estado !== 'recebida' || r.envioId !== e.envioId ||
|
|
397
|
+
r.pedidoId !== e.pedidoId || r.thread !== thread || r.fase !== e.fase || r.recibo !== e.recibo ||
|
|
398
|
+
!mesmaInstancia(r.sessao, e.sessao))
|
|
399
|
+
return null;
|
|
400
|
+
return r;
|
|
401
|
+
},
|
|
402
|
+
assincrono: true,
|
|
403
|
+
impedimentoDoEnvio: () => (caixa ? caixa.impedimento() : exports.SEM_CAIXA),
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/** O que o ledger diz da entrega lida, para a sessao do despacho deste servidor; o motivo quando nao bate. */
|
|
407
|
+
function contextoDoReceptor(raiz, thread, dispatchId, lida) {
|
|
408
|
+
const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, thread));
|
|
409
|
+
const despachos = eventos.filter(e => e.tipo === 'phase_dispatch' &&
|
|
410
|
+
e.identidade?.dispatchId === dispatchId);
|
|
411
|
+
const despacho = despachos[0];
|
|
412
|
+
if (despachos.length !== 1 || despacho.runtime !== 'claude-bg' || typeof despacho.sessionId !== 'string' ||
|
|
413
|
+
!UUID.test(despacho.sessionId))
|
|
414
|
+
return { motivo: 'entrega.despacho' };
|
|
415
|
+
const sessionId = despacho.sessionId;
|
|
416
|
+
const filas = eventos.filter(e => e.tipo === ledger_1.TIPOS_DE_EVENTO.entregaNaFila && e.envioId === lida.envioId);
|
|
417
|
+
if (filas.length !== 1 || filas[0].pedidoId !== lida.pedidoId)
|
|
418
|
+
return { motivo: 'entrega.desconhecida' };
|
|
419
|
+
if (filas[0].sessionId !== sessionId)
|
|
420
|
+
return { motivo: 'entrega.outra-sessao' };
|
|
421
|
+
const textoSha256 = hashDoCorpo(lida.corpo);
|
|
422
|
+
if (filas[0].textoSha256 !== textoSha256)
|
|
423
|
+
return { motivo: 'entrega.texto-diferente' };
|
|
424
|
+
const envios = eventos.filter(e => e.tipo === 'session_answer_sending' && e.pedidoId === lida.pedidoId);
|
|
425
|
+
if (envios.length !== 1 || envios[0].envioId !== lida.envioId)
|
|
426
|
+
return { motivo: 'entrega.desconhecida' };
|
|
427
|
+
const solicitado = eventos.find(e => e.tipo === 'hitl_requested' && e.pedido?.id === lida.pedidoId);
|
|
428
|
+
const pedido = solicitado?.pedido;
|
|
429
|
+
const sessao = solicitado?.sessao;
|
|
430
|
+
if (!pedido || pedido.thread !== thread || pedido.alvo?.tipo !== 'session' || pedido.alvo.sessionId !== sessionId ||
|
|
431
|
+
pedido.alvo.runtime !== 'claude-bg' || !sessao || sessao.sessionId !== sessionId || !sessao.bloqueio)
|
|
432
|
+
return { motivo: 'entrega.outra-sessao' };
|
|
433
|
+
return { sessionId, pedido, sessao, envio: envios[0], textoSha256, perfil: perfilDaSessao(raiz, thread, sessionId, eventos),
|
|
434
|
+
respondida: eventos.some(e => e.tipo === 'session_answered' && e.pedidoId === lida.pedidoId) };
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Confere e reserva, uma vez so, a entrega que chegou a sessao do despacho deste servidor. A sessao sai do
|
|
438
|
+
* despacho (`phase_dispatch` com o `dispatchId` do servidor), nunca de argumento; antes de reservar, a transcricao
|
|
439
|
+
* tem de seguir no turno do pedido (D7), para uma resposta velha nao entrar num turno que andou. O `ate` (o prazo que
|
|
440
|
+
* o mod da a conferencia, D21) e obrigatorio, e o receptor so reserva antes dele: a conferencia que chega depois de o
|
|
441
|
+
* mod ter desistido e consumido a mensagem nao deixa uma reserva sem ninguem para confirma-la. Sem `ate` (uma copia
|
|
442
|
+
* velha do mod), a conferencia recusa: falha fechada.
|
|
443
|
+
*/
|
|
444
|
+
function conferirNoReceptor(raiz, thread, dispatchId, texto, ate, deps = {}) {
|
|
445
|
+
const agora = deps.agora ?? Date.now;
|
|
446
|
+
const prazo = typeof ate === 'string' ? Date.parse(ate) : NaN;
|
|
447
|
+
if (!(Number.isFinite(prazo) && prazo - agora() <= exports.PRAZO_MAXIMO_DA_CONFERENCIA_MS)) {
|
|
448
|
+
return { confirmada: false, motivo: 'entrega.formato' };
|
|
449
|
+
}
|
|
450
|
+
const lida = lerMensagemDaEntrega(texto);
|
|
451
|
+
if (!lida)
|
|
452
|
+
return { confirmada: false, motivo: 'entrega.formato' };
|
|
453
|
+
return (0, hitl_gates_1.comLockHitl)(raiz, thread, () => {
|
|
454
|
+
const ctx = contextoDoReceptor(raiz, thread, dispatchId, lida);
|
|
455
|
+
if ('motivo' in ctx)
|
|
456
|
+
return { confirmada: false, motivo: ctx.motivo };
|
|
457
|
+
if (ctx.respondida)
|
|
458
|
+
return { confirmada: false, motivo: 'entrega.respondida' };
|
|
459
|
+
const cauda = (deps.lerTranscricao ?? lerTranscricaoPadrao)(ctx.perfil, ctx.sessao.cwd, ctx.sessionId);
|
|
460
|
+
const turno = cauda === null ? null : turnoQueParou(cauda);
|
|
461
|
+
if (!turno || turno.uuid !== ctx.sessao.bloqueio)
|
|
462
|
+
return { confirmada: false, motivo: 'entrega.turno-mudou' };
|
|
463
|
+
// O prazo e conferido aqui, dentro da trava e logo antes de reservar: a espera pela trava tambem conta.
|
|
464
|
+
if (agora() > prazo)
|
|
465
|
+
return { confirmada: false, motivo: 'entrega.prazo' };
|
|
466
|
+
const reservadaEm = new Date(agora()).toISOString();
|
|
467
|
+
if (!escreverUmaVez(path.join(garantirPasta(raiz, thread), `${lida.envioId}.reserva.json`), { contrato: exports.CONTRATO_DA_ENTREGA,
|
|
468
|
+
envioId: lida.envioId, pedidoId: lida.pedidoId, sessionId: ctx.sessionId, dispatchId, textoSha256: ctx.textoSha256, reservadaEm }))
|
|
469
|
+
return { confirmada: false, motivo: 'entrega.reservada' };
|
|
470
|
+
(0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread), thread, ledger_1.TIPOS_DE_EVENTO.entregaReservada, { pedidoId: lida.pedidoId, fase: ctx.pedido.fase,
|
|
471
|
+
sessionId: ctx.sessionId, envioId: lida.envioId, dispatchId, textoSha256: ctx.textoSha256 });
|
|
472
|
+
return { confirmada: true, pedidoId: lida.pedidoId, envioId: lida.envioId, rotulo: rotuloDaEntrega(lida.pedidoId) };
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* Confirma, depois de a mensagem entrar na fila do modelo, a entrega que este despacho reservou: grava o recibo do
|
|
477
|
+
* receptor (o `ConfirmacaoSessao` que o controle por mod le) e, fora da trava, a reconciliacao de sempre grava o
|
|
478
|
+
* `session_answered`. O turno nao e conferido de novo aqui: a mensagem ja entrou, e a reserva prova a conferencia.
|
|
479
|
+
*/
|
|
480
|
+
function confirmarNoReceptor(raiz, thread, dispatchId, envioId, texto, deps = {}) {
|
|
481
|
+
const lida = lerMensagemDaEntrega(texto);
|
|
482
|
+
if (!lida || lida.envioId !== envioId)
|
|
483
|
+
return { ok: false, estado: 'recusada', motivo: 'entrega.formato' };
|
|
484
|
+
const preparo = (0, hitl_gates_1.comLockHitl)(raiz, thread, () => {
|
|
485
|
+
const ctx = contextoDoReceptor(raiz, thread, dispatchId, lida);
|
|
486
|
+
if ('motivo' in ctx)
|
|
487
|
+
return ctx;
|
|
488
|
+
const reserva = lerPrivado(path.join(pastaDasEntregas(raiz, thread), `${lida.envioId}.reserva.json`));
|
|
489
|
+
if (!reserva || reserva.contrato !== exports.CONTRATO_DA_ENTREGA || reserva.envioId !== lida.envioId || reserva.pedidoId !== lida.pedidoId ||
|
|
490
|
+
reserva.sessionId !== ctx.sessionId || reserva.dispatchId !== dispatchId || reserva.textoSha256 !== ctx.textoSha256)
|
|
491
|
+
return { motivo: 'entrega.sem-reserva' };
|
|
492
|
+
const recibo = { contrato: 'ork.session-answer/v1', envioId: lida.envioId, pedidoId: lida.pedidoId, thread,
|
|
493
|
+
fase: ctx.pedido.fase, sessao: ctx.sessao, recibo: String(ctx.envio.recibo), estado: 'recebida' };
|
|
494
|
+
escreverUmaVez(path.join(garantirPasta(raiz, thread), `${lida.envioId}.recibo.json`), recibo);
|
|
495
|
+
return { sessionId: ctx.sessionId };
|
|
496
|
+
});
|
|
497
|
+
if ('motivo' in preparo)
|
|
498
|
+
return { ok: false, estado: 'recusada', motivo: preparo.motivo };
|
|
499
|
+
// Carregado na chamada: `hitl-sessions` importa este modulo para o controle de resposta.
|
|
500
|
+
const { reconciliarEnvioDeSessao } = require('./hitl-sessions');
|
|
501
|
+
const r = reconciliarEnvioDeSessao(raiz, thread, lida.pedidoId, controleClaudeBgPorMod(raiz, thread, preparo.sessionId, null, deps));
|
|
502
|
+
return { ok: r.ok, estado: r.estado, pedidoId: lida.pedidoId, envioId: lida.envioId, repetida: r.repetida, prova: r.prova };
|
|
503
|
+
}
|