@pentoshi/clai 4.19.0 → 5.1.0
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 +119 -0
- package/PROVIDERS.md +15 -2
- package/REA.md +96 -0
- package/README.md +5 -1
- package/dist/agent/compaction/compaction-prompt.d.ts +49 -0
- package/dist/agent/compaction/compaction-prompt.js +164 -0
- package/dist/agent/compaction/compaction-prompt.js.map +1 -0
- package/dist/agent/compaction/memory-sections.d.ts +27 -0
- package/dist/agent/compaction/memory-sections.js +144 -0
- package/dist/agent/compaction/memory-sections.js.map +1 -0
- package/dist/agent/compaction-summary.d.ts +2 -33
- package/dist/agent/compaction-summary.js +3 -113
- package/dist/agent/compaction-summary.js.map +1 -1
- package/dist/agent/context/compact-with-summary.d.ts +2 -4
- package/dist/agent/context/compact-with-summary.js +45 -68
- package/dist/agent/context/compact-with-summary.js.map +1 -1
- package/dist/agent/context/compaction-recent-history.d.ts +4 -3
- package/dist/agent/context/compaction-recent-history.js +30 -52
- package/dist/agent/context/compaction-recent-history.js.map +1 -1
- package/dist/agent/context/compaction-skills.d.ts +4 -0
- package/dist/agent/context/compaction-skills.js +136 -0
- package/dist/agent/context/compaction-skills.js.map +1 -0
- package/dist/agent/context/compaction-user-instructions.d.ts +5 -6
- package/dist/agent/context/compaction-user-instructions.js +156 -231
- package/dist/agent/context/compaction-user-instructions.js.map +1 -1
- package/dist/agent/context-manager.js +20 -8
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/events.d.ts +10 -0
- package/dist/agent/loop-guard.d.ts +1 -0
- package/dist/agent/loop-guard.js +29 -6
- package/dist/agent/loop-guard.js.map +1 -1
- package/dist/agent/outcomes.js +4 -0
- package/dist/agent/outcomes.js.map +1 -1
- package/dist/agent/parser/arg-formatting.js +8 -2
- package/dist/agent/parser/arg-formatting.js.map +1 -1
- package/dist/agent/parser/dsml.d.ts +30 -0
- package/dist/agent/parser/dsml.js +233 -0
- package/dist/agent/parser/dsml.js.map +1 -0
- package/dist/agent/parser/vendor-protocols.d.ts +2 -5
- package/dist/agent/parser/vendor-protocols.js +4 -93
- package/dist/agent/parser/vendor-protocols.js.map +1 -1
- package/dist/agent/plan-implement-compact.js +2 -2
- package/dist/agent/plan-implement-compact.js.map +1 -1
- package/dist/agent/reliability-policy.d.ts +3 -1
- package/dist/agent/reliability-policy.js +21 -31
- package/dist/agent/reliability-policy.js.map +1 -1
- package/dist/agent/runner.js +12 -1
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/subagents/read-only-tools.js +7 -8
- package/dist/agent/subagents/read-only-tools.js.map +1 -1
- package/dist/agent/tool-call-parser.js +6 -8
- package/dist/agent/tool-call-parser.js.map +1 -1
- package/dist/agent/turn/event-emitter.js +2 -0
- package/dist/agent/turn/event-emitter.js.map +1 -1
- package/dist/agent/turn/loop/answer-path.js +3 -1
- package/dist/agent/turn/loop/answer-path.js.map +1 -1
- package/dist/agent/turn/loop/canonicalize-turn-call.js +5 -3
- package/dist/agent/turn/loop/canonicalize-turn-call.js.map +1 -1
- package/dist/agent/turn/loop/native-tool-calls.js +2 -2
- package/dist/agent/turn/loop/native-tool-calls.js.map +1 -1
- package/dist/agent/turn/loop/output-budget.d.ts +0 -1
- package/dist/agent/turn/loop/output-budget.js +5 -13
- package/dist/agent/turn/loop/output-budget.js.map +1 -1
- package/dist/agent/turn/loop/pending-tool-calls.d.ts +16 -0
- package/dist/agent/turn/loop/pending-tool-calls.js +53 -0
- package/dist/agent/turn/loop/pending-tool-calls.js.map +1 -0
- package/dist/agent/turn/loop/request-assembly.js +39 -33
- package/dist/agent/turn/loop/request-assembly.js.map +1 -1
- package/dist/agent/turn/loop/round-request.js +32 -18
- package/dist/agent/turn/loop/round-request.js.map +1 -1
- package/dist/agent/turn/loop/run-rounds.js +2 -2
- package/dist/agent/turn/loop/run-rounds.js.map +1 -1
- package/dist/agent/turn/loop/stream-session.d.ts +5 -7
- package/dist/agent/turn/loop/stream-session.js +43 -31
- package/dist/agent/turn/loop/stream-session.js.map +1 -1
- package/dist/agent/turn/loop/tool-call-recovery.d.ts +2 -0
- package/dist/agent/turn/loop/tool-call-recovery.js +26 -11
- package/dist/agent/turn/loop/tool-call-recovery.js.map +1 -1
- package/dist/agent/turn/mcp-agent-tools.d.ts +3 -0
- package/dist/agent/turn/mcp-agent-tools.js +11 -2
- package/dist/agent/turn/mcp-agent-tools.js.map +1 -1
- package/dist/agent/turn/prompt-sections.js +1 -0
- package/dist/agent/turn/prompt-sections.js.map +1 -1
- package/dist/agent/turn/scaffold-preflight.d.ts +6 -1
- package/dist/agent/turn/scaffold-preflight.js +10 -2
- package/dist/agent/turn/scaffold-preflight.js.map +1 -1
- package/dist/agent/turn/setup/mcp-agent-ports.d.ts +5 -1
- package/dist/agent/turn/setup/mcp-agent-ports.js +2 -0
- package/dist/agent/turn/setup/mcp-agent-ports.js.map +1 -1
- package/dist/agent/turn/system-sections.d.ts +2 -0
- package/dist/agent/turn/system-sections.js +12 -8
- package/dist/agent/turn/system-sections.js.map +1 -1
- package/dist/agent/turn/tool-execution/deps.d.ts +2 -0
- package/dist/agent/turn/tool-execution/single-tool.js +4 -1
- package/dist/agent/turn/tool-execution/single-tool.js.map +1 -1
- package/dist/agent/turn/tool-result-recorder.js +1 -0
- package/dist/agent/turn/tool-result-recorder.js.map +1 -1
- package/dist/agent/turn/turn-counters.d.ts +1 -0
- package/dist/agent/turn/turn-counters.js +2 -0
- package/dist/agent/turn/turn-counters.js.map +1 -1
- package/dist/agent/turn/workspace-setup.d.ts +7 -2
- package/dist/agent/turn/workspace-setup.js +45 -30
- package/dist/agent/turn/workspace-setup.js.map +1 -1
- package/dist/agent/workspace-orient.d.ts +4 -0
- package/dist/agent/workspace-orient.js +83 -37
- package/dist/agent/workspace-orient.js.map +1 -1
- package/dist/app/adapters/agent-event-adapter.d.ts +2 -0
- package/dist/app/adapters/agent-event-adapter.js +32 -2
- package/dist/app/adapters/agent-event-adapter.js.map +1 -1
- package/dist/app/adapters/current-agent-adapter.js +1 -0
- package/dist/app/adapters/current-agent-adapter.js.map +1 -1
- package/dist/app/adapters/current-store-adapter.js +3 -0
- package/dist/app/adapters/current-store-adapter.js.map +1 -1
- package/dist/app/commands/catalog.js +10 -4
- package/dist/app/commands/catalog.js.map +1 -1
- package/dist/app/controllers/session-compact-helper.js +2 -5
- package/dist/app/controllers/session-compact-helper.js.map +1 -1
- package/dist/app/controllers/session-controller.js +34 -3
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/session-prompt-queue.d.ts +13 -1
- package/dist/app/controllers/session-prompt-queue.js +96 -24
- package/dist/app/controllers/session-prompt-queue.js.map +1 -1
- package/dist/app/controllers/turn-controller.d.ts +1 -0
- package/dist/app/controllers/turn-controller.js +14 -1
- package/dist/app/controllers/turn-controller.js.map +1 -1
- package/dist/app/events/app-event.d.ts +5 -0
- package/dist/app/events/app-event.js.map +1 -1
- package/dist/app/ports/agent-port.d.ts +1 -0
- package/dist/app/ports/persistence-port.d.ts +7 -0
- package/dist/app/ports/transcript-item.d.ts +2 -0
- package/dist/classic/app/app-wiring.d.ts +5 -2
- package/dist/classic/app/app-wiring.js +7 -3
- package/dist/classic/app/app-wiring.js.map +1 -1
- package/dist/classic/app/paint-pacing.js +2 -2
- package/dist/classic/app/paint-pacing.js.map +1 -1
- package/dist/classic/app/use-feed.js +7 -9
- package/dist/classic/app/use-feed.js.map +1 -1
- package/dist/classic/app/wiring-disclosure.js +1 -1
- package/dist/classic/app/wiring-disclosure.js.map +1 -1
- package/dist/classic/app/wiring-feed-scroll.d.ts +5 -0
- package/dist/classic/app/wiring-feed-scroll.js +39 -0
- package/dist/classic/app/wiring-feed-scroll.js.map +1 -0
- package/dist/classic/app/wiring-interactions.d.ts +0 -3
- package/dist/classic/app/wiring-interactions.js +6 -28
- package/dist/classic/app/wiring-interactions.js.map +1 -1
- package/dist/classic/app/wiring-lifecycle.d.ts +1 -0
- package/dist/classic/app/wiring-lifecycle.js +11 -1
- package/dist/classic/app/wiring-lifecycle.js.map +1 -1
- package/dist/classic/app/wiring-selection.js +46 -37
- package/dist/classic/app/wiring-selection.js.map +1 -1
- package/dist/classic/app/wiring-types.d.ts +5 -2
- package/dist/classic/blocks/intro-lines.js +1 -0
- package/dist/classic/blocks/intro-lines.js.map +1 -1
- package/dist/classic/blocks/thinking-lines.d.ts +6 -0
- package/dist/classic/blocks/thinking-lines.js +22 -7
- package/dist/classic/blocks/thinking-lines.js.map +1 -1
- package/dist/classic/blocks/tool-lines.js +9 -4
- package/dist/classic/blocks/tool-lines.js.map +1 -1
- package/dist/classic/blocks/turn-summary-lines.d.ts +1 -1
- package/dist/classic/blocks/turn-summary-lines.js +5 -3
- package/dist/classic/blocks/turn-summary-lines.js.map +1 -1
- package/dist/classic/bootstrap/start-classic.js +4 -1
- package/dist/classic/bootstrap/start-classic.js.map +1 -1
- package/dist/classic/chrome/composer-mentions.js +2 -1
- package/dist/classic/chrome/composer-mentions.js.map +1 -1
- package/dist/classic/chrome/directory-row.js +5 -5
- package/dist/classic/chrome/directory-row.js.map +1 -1
- package/dist/classic/chrome/status-rows.d.ts +2 -1
- package/dist/classic/chrome/status-rows.js +18 -8
- package/dist/classic/chrome/status-rows.js.map +1 -1
- package/dist/classic/feed/feed-blocks.js +6 -4
- package/dist/classic/feed/feed-blocks.js.map +1 -1
- package/dist/classic/feed/transcript-selection.d.ts +2 -1
- package/dist/classic/feed/transcript-selection.js +15 -10
- package/dist/classic/feed/transcript-selection.js.map +1 -1
- package/dist/classic/panels/confirm-panel.js +1 -0
- package/dist/classic/panels/confirm-panel.js.map +1 -1
- package/dist/classic/panels/jobs-panel.js +1 -1
- package/dist/classic/panels/jobs-panel.js.map +1 -1
- package/dist/classic/panels/plan-panel.js +1 -1
- package/dist/classic/panels/plan-panel.js.map +1 -1
- package/dist/classic/render/shell-width.js +1 -1
- package/dist/classic/render/shell-width.js.map +1 -1
- package/dist/classic/render/widest-line.d.ts +1 -0
- package/dist/classic/render/widest-line.js +5 -0
- package/dist/classic/render/widest-line.js.map +1 -0
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/doctor.js.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/instructions/scaffold.js +2 -1
- package/dist/instructions/scaffold.js.map +1 -1
- package/dist/llm/agentrouter.js +6 -11
- package/dist/llm/agentrouter.js.map +1 -1
- package/dist/llm/anthropic.js +6 -8
- package/dist/llm/anthropic.js.map +1 -1
- package/dist/llm/bynara.js +6 -10
- package/dist/llm/bynara.js.map +1 -1
- package/dist/llm/capabilities.js +5 -5
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/capability/state.d.ts +1 -1
- package/dist/llm/capability/tool-dialect.js +1 -0
- package/dist/llm/capability/tool-dialect.js.map +1 -1
- package/dist/llm/capability/vision-patterns.js +1 -0
- package/dist/llm/capability/vision-patterns.js.map +1 -1
- package/dist/llm/capability/vision-registry.js +1 -1
- package/dist/llm/capability/vision-registry.js.map +1 -1
- package/dist/llm/cline.js +3 -2
- package/dist/llm/cline.js.map +1 -1
- package/dist/llm/codex-models.d.ts +1 -1
- package/dist/llm/codex-models.js +11 -6
- package/dist/llm/codex-models.js.map +1 -1
- package/dist/llm/codex.js +2 -1
- package/dist/llm/codex.js.map +1 -1
- package/dist/llm/constellation.js +5 -0
- package/dist/llm/constellation.js.map +1 -1
- package/dist/llm/context-windows.js +17 -13
- package/dist/llm/context-windows.js.map +1 -1
- package/dist/llm/copilot.js +19 -21
- package/dist/llm/copilot.js.map +1 -1
- package/dist/llm/custom-providers.d.ts +2 -1
- package/dist/llm/custom-providers.js +16 -10
- package/dist/llm/custom-providers.js.map +1 -1
- package/dist/llm/deepseek.js +6 -11
- package/dist/llm/deepseek.js.map +1 -1
- package/dist/llm/explabs.js +8 -9
- package/dist/llm/explabs.js.map +1 -1
- package/dist/llm/fireworks.js +9 -11
- package/dist/llm/fireworks.js.map +1 -1
- package/dist/llm/free-default-model.js +5 -3
- package/dist/llm/free-default-model.js.map +1 -1
- package/dist/llm/free-model-limits.js +2 -1
- package/dist/llm/free-model-limits.js.map +1 -1
- package/dist/llm/free.js +20 -23
- package/dist/llm/free.js.map +1 -1
- package/dist/llm/freebuff-models.js +11 -2
- package/dist/llm/freebuff-models.js.map +1 -1
- package/dist/llm/freebuff.js +2 -1
- package/dist/llm/freebuff.js.map +1 -1
- package/dist/llm/generation-metrics.d.ts +11 -0
- package/dist/llm/generation-metrics.js +54 -0
- package/dist/llm/generation-metrics.js.map +1 -0
- package/dist/llm/generation-submission.d.ts +2 -0
- package/dist/llm/generation-submission.js +13 -0
- package/dist/llm/generation-submission.js.map +1 -0
- package/dist/llm/glm.js +6 -11
- package/dist/llm/glm.js.map +1 -1
- package/dist/llm/hetzner.js +9 -11
- package/dist/llm/hetzner.js.map +1 -1
- package/dist/llm/hinoki-models.d.ts +3 -0
- package/dist/llm/hinoki-models.js +52 -0
- package/dist/llm/hinoki-models.js.map +1 -0
- package/dist/llm/hinoki-profile.d.ts +4 -0
- package/dist/llm/hinoki-profile.js +58 -0
- package/dist/llm/hinoki-profile.js.map +1 -0
- package/dist/llm/hinoki.d.ts +3 -0
- package/dist/llm/hinoki.js +149 -0
- package/dist/llm/hinoki.js.map +1 -0
- package/dist/llm/kimi.js +6 -11
- package/dist/llm/kimi.js.map +1 -1
- package/dist/llm/kiro.js +11 -10
- package/dist/llm/kiro.js.map +1 -1
- package/dist/llm/lightning.js +6 -10
- package/dist/llm/lightning.js.map +1 -1
- package/dist/llm/merge-gateway.js +9 -10
- package/dist/llm/merge-gateway.js.map +1 -1
- package/dist/llm/meta.js +6 -10
- package/dist/llm/meta.js.map +1 -1
- package/dist/llm/mimo.js +6 -11
- package/dist/llm/mimo.js.map +1 -1
- package/dist/llm/minimax.js +6 -11
- package/dist/llm/minimax.js.map +1 -1
- package/dist/llm/mistral.js +10 -5
- package/dist/llm/mistral.js.map +1 -1
- package/dist/llm/modal.js +6 -11
- package/dist/llm/modal.js.map +1 -1
- package/dist/llm/model-discovery.d.ts +4 -1
- package/dist/llm/model-discovery.js +5 -2
- package/dist/llm/model-discovery.js.map +1 -1
- package/dist/llm/model-limit-store.d.ts +2 -0
- package/dist/llm/model-limit-store.js +44 -12
- package/dist/llm/model-limit-store.js.map +1 -1
- package/dist/llm/model-list-cache.d.ts +15 -0
- package/dist/llm/model-list-cache.js +55 -0
- package/dist/llm/model-list-cache.js.map +1 -0
- package/dist/llm/nvidia.js +9 -10
- package/dist/llm/nvidia.js.map +1 -1
- package/dist/llm/ollama.js +4 -0
- package/dist/llm/ollama.js.map +1 -1
- package/dist/llm/omnirush.js +10 -14
- package/dist/llm/omnirush.js.map +1 -1
- package/dist/llm/openrouter.js +6 -11
- package/dist/llm/openrouter.js.map +1 -1
- package/dist/llm/operation-usage.js +22 -5
- package/dist/llm/operation-usage.js.map +1 -1
- package/dist/llm/orcarouter.js +9 -13
- package/dist/llm/orcarouter.js.map +1 -1
- package/dist/llm/provider-identity.js +5 -0
- package/dist/llm/provider-identity.js.map +1 -1
- package/dist/llm/provider-info-text.js +24 -1
- package/dist/llm/provider-info-text.js.map +1 -1
- package/dist/llm/provider-model-layers.js +7 -0
- package/dist/llm/provider-model-layers.js.map +1 -1
- package/dist/llm/provider-profile-layers.js +5 -1
- package/dist/llm/provider-profile-layers.js.map +1 -1
- package/dist/llm/provider-profiles.d.ts +1 -0
- package/dist/llm/provider-profiles.js +5 -1
- package/dist/llm/provider-profiles.js.map +1 -1
- package/dist/llm/qoder/qoder.js +6 -10
- package/dist/llm/qoder/qoder.js.map +1 -1
- package/dist/llm/qwen-cloud.js +6 -9
- package/dist/llm/qwen-cloud.js.map +1 -1
- package/dist/llm/reasoning-capability.js +1 -0
- package/dist/llm/reasoning-capability.js.map +1 -1
- package/dist/llm/request-plan.js +4 -2
- package/dist/llm/request-plan.js.map +1 -1
- package/dist/llm/river-models.d.ts +1 -0
- package/dist/llm/river-models.js +3 -0
- package/dist/llm/river-models.js.map +1 -1
- package/dist/llm/routing/provider-selection.js +3 -0
- package/dist/llm/routing/provider-selection.js.map +1 -1
- package/dist/llm/routing/request-option-fallback.d.ts +6 -0
- package/dist/llm/routing/request-option-fallback.js +63 -3
- package/dist/llm/routing/request-option-fallback.js.map +1 -1
- package/dist/llm/token-usage.js +7 -2
- package/dist/llm/token-usage.js.map +1 -1
- package/dist/llm/tokenharbor.js +10 -13
- package/dist/llm/tokenharbor.js.map +1 -1
- package/dist/llm/tokenrouter.js +10 -14
- package/dist/llm/tokenrouter.js.map +1 -1
- package/dist/llm/vercel.js +12 -12
- package/dist/llm/vercel.js.map +1 -1
- package/dist/llm/wire/chat-body.js +9 -5
- package/dist/llm/wire/chat-body.js.map +1 -1
- package/dist/llm/wire/openai-stream.js +2 -1
- package/dist/llm/wire/openai-stream.js.map +1 -1
- package/dist/llm/zen-catalog.d.ts +3 -1
- package/dist/llm/zen-catalog.js +9 -3
- package/dist/llm/zen-catalog.js.map +1 -1
- package/dist/mcp/argument-hint.d.ts +9 -0
- package/dist/mcp/argument-hint.js +17 -0
- package/dist/mcp/argument-hint.js.map +1 -0
- package/dist/mcp/catalog.js +5 -5
- package/dist/mcp/catalog.js.map +1 -1
- package/dist/mcp/manager.d.ts +2 -0
- package/dist/mcp/manager.js +21 -1
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/runtime.d.ts +5 -1
- package/dist/mcp/runtime.js +33 -2
- package/dist/mcp/runtime.js.map +1 -1
- package/dist/noninteractive/stream-renderer.js +3 -0
- package/dist/noninteractive/stream-renderer.js.map +1 -1
- package/dist/os/runtime-error.d.ts +2 -0
- package/dist/os/runtime-error.js +39 -0
- package/dist/os/runtime-error.js.map +1 -0
- package/dist/prompts/embedded.js +1 -1
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.js +21 -18
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +10 -9
- package/dist/rea/availability.d.ts +22 -0
- package/dist/rea/availability.js +82 -0
- package/dist/rea/availability.js.map +1 -0
- package/dist/rea/connection.d.ts +8 -0
- package/dist/rea/connection.js +12 -0
- package/dist/rea/connection.js.map +1 -0
- package/dist/rea/distribution.d.ts +13 -0
- package/dist/rea/distribution.js +140 -0
- package/dist/rea/distribution.js.map +1 -0
- package/dist/rea/download.d.ts +22 -0
- package/dist/rea/download.js +198 -0
- package/dist/rea/download.js.map +1 -0
- package/dist/rea/engine-report.d.ts +4 -0
- package/dist/rea/engine-report.js +77 -0
- package/dist/rea/engine-report.js.map +1 -0
- package/dist/rea/engine-status.d.ts +24 -0
- package/dist/rea/engine-status.js +103 -0
- package/dist/rea/engine-status.js.map +1 -0
- package/dist/rea/engines.d.ts +43 -0
- package/dist/rea/engines.js +160 -0
- package/dist/rea/engines.js.map +1 -0
- package/dist/rea/ghidra.d.ts +83 -0
- package/dist/rea/ghidra.js +316 -0
- package/dist/rea/ghidra.js.map +1 -0
- package/dist/rea/guide.d.ts +14 -0
- package/dist/rea/guide.js +178 -0
- package/dist/rea/guide.js.map +1 -0
- package/dist/rea/hints.d.ts +3 -0
- package/dist/rea/hints.js +99 -0
- package/dist/rea/hints.js.map +1 -0
- package/dist/rea/install.d.ts +10 -0
- package/dist/rea/install.js +173 -0
- package/dist/rea/install.js.map +1 -0
- package/dist/rea/jdk.d.ts +50 -0
- package/dist/rea/jdk.js +171 -0
- package/dist/rea/jdk.js.map +1 -0
- package/dist/rea/node.d.ts +22 -0
- package/dist/rea/node.js +150 -0
- package/dist/rea/node.js.map +1 -0
- package/dist/rea/runtime.d.ts +11 -0
- package/dist/rea/runtime.js +186 -0
- package/dist/rea/runtime.js.map +1 -0
- package/dist/rea/tool-index.d.ts +7 -0
- package/dist/rea/tool-index.js +105 -0
- package/dist/rea/tool-index.js.map +1 -0
- package/dist/rea/types.d.ts +36 -0
- package/dist/rea/types.js +2 -0
- package/dist/rea/types.js.map +1 -0
- package/dist/rea/workflow.d.ts +14 -0
- package/dist/rea/workflow.js +60 -0
- package/dist/rea/workflow.js.map +1 -0
- package/dist/rea/zip.d.ts +19 -0
- package/dist/rea/zip.js +257 -0
- package/dist/rea/zip.js.map +1 -0
- package/dist/safety/tool-classification.js +6 -0
- package/dist/safety/tool-classification.js.map +1 -1
- package/dist/skills/bundled-catalog.generated.d.ts +2 -0
- package/dist/skills/bundled-catalog.generated.js +25 -0
- package/dist/skills/bundled-catalog.generated.js.map +1 -0
- package/dist/skills/bundled-content.generated.d.ts +1 -0
- package/dist/skills/bundled-content.generated.js +20 -0
- package/dist/skills/bundled-content.generated.js.map +1 -0
- package/dist/skills/bundled.d.ts +4 -0
- package/dist/skills/bundled.js +111 -0
- package/dist/skills/bundled.js.map +1 -0
- package/dist/skills/catalog.js +7 -4
- package/dist/skills/catalog.js.map +1 -1
- package/dist/skills/discover.js +1 -0
- package/dist/skills/discover.js.map +1 -1
- package/dist/skills/registry.js +24 -16
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/types.d.ts +9 -1
- package/dist/skills/types.js.map +1 -1
- package/dist/store/config/endpoints.js +1 -0
- package/dist/store/config/endpoints.js.map +1 -1
- package/dist/store/config.js +2 -0
- package/dist/store/config.js.map +1 -1
- package/dist/store/history/jsonl-backend.d.ts +0 -1
- package/dist/store/history/jsonl-backend.js +3 -136
- package/dist/store/history/jsonl-backend.js.map +1 -1
- package/dist/store/history/legacy-migration.d.ts +6 -0
- package/dist/store/history/legacy-migration.js +127 -0
- package/dist/store/history/legacy-migration.js.map +1 -0
- package/dist/store/history/lifecycle.js +11 -2
- package/dist/store/history/lifecycle.js.map +1 -1
- package/dist/store/history/recovery.js +6 -1
- package/dist/store/history/recovery.js.map +1 -1
- package/dist/store/history/session-frames.d.ts +74 -0
- package/dist/store/history/session-frames.js +234 -0
- package/dist/store/history/session-frames.js.map +1 -0
- package/dist/store/history/session-index.d.ts +13 -0
- package/dist/store/history/session-index.js +135 -0
- package/dist/store/history/session-index.js.map +1 -0
- package/dist/store/history/session-log.d.ts +44 -0
- package/dist/store/history/session-log.js +386 -0
- package/dist/store/history/session-log.js.map +1 -0
- package/dist/store/history/session-paths.d.ts +11 -0
- package/dist/store/history/session-paths.js +35 -0
- package/dist/store/history/session-paths.js.map +1 -0
- package/dist/store/history/session-queries.js +34 -16
- package/dist/store/history/session-queries.js.map +1 -1
- package/dist/store/history/session-store.d.ts +11 -0
- package/dist/store/history/session-store.js +202 -0
- package/dist/store/history/session-store.js.map +1 -0
- package/dist/store/history-index.d.ts +0 -2
- package/dist/store/history-index.js +0 -16
- package/dist/store/history-index.js.map +1 -1
- package/dist/store/history.d.ts +2 -0
- package/dist/store/history.js +76 -56
- package/dist/store/history.js.map +1 -1
- package/dist/store/session-queue.d.ts +4 -0
- package/dist/store/session-queue.js +62 -0
- package/dist/store/session-queue.js.map +1 -0
- package/dist/store/session-workspace-activity.d.ts +4 -0
- package/dist/store/session-workspace-activity.js +69 -0
- package/dist/store/session-workspace-activity.js.map +1 -0
- package/dist/store/session-workspace-cleanup.d.ts +4 -0
- package/dist/store/session-workspace-cleanup.js +246 -0
- package/dist/store/session-workspace-cleanup.js.map +1 -0
- package/dist/store/session-workspace.js +6 -0
- package/dist/store/session-workspace.js.map +1 -1
- package/dist/tools/definitions/aggregate.js +9 -1
- package/dist/tools/definitions/aggregate.js.map +1 -1
- package/dist/tools/definitions/files.js +4 -4
- package/dist/tools/definitions/files.js.map +1 -1
- package/dist/tools/definitions/fs-read.js +2 -2
- package/dist/tools/definitions/fs-read.js.map +1 -1
- package/dist/tools/definitions/shell.js +2 -2
- package/dist/tools/definitions/shell.js.map +1 -1
- package/dist/tools/definitions.js +2 -1
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/fs/mutations.js +1 -1
- package/dist/tools/fs/mutations.js.map +1 -1
- package/dist/tools/fs/read-input.js +33 -20
- package/dist/tools/fs/read-input.js.map +1 -1
- package/dist/tools/handlers/files-2.js +1 -1
- package/dist/tools/handlers/files-2.js.map +1 -1
- package/dist/tools/http/agents.d.ts +4 -5
- package/dist/tools/http/agents.js +4 -12
- package/dist/tools/http/agents.js.map +1 -1
- package/dist/tools/http/fetch.js +3 -10
- package/dist/tools/http/fetch.js.map +1 -1
- package/dist/tools/registry.d.ts +1 -0
- package/dist/tools/registry.js +3 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/shell/artifact.d.ts +7 -0
- package/dist/tools/shell/artifact.js +85 -0
- package/dist/tools/shell/artifact.js.map +1 -0
- package/dist/tools/shell/capture.d.ts +1 -5
- package/dist/tools/shell/capture.js +1 -18
- package/dist/tools/shell/capture.js.map +1 -1
- package/dist/tools/shell/exec-attempt.js +9 -27
- package/dist/tools/shell/exec-attempt.js.map +1 -1
- package/dist/tools/shell/spawn-argv.js +7 -21
- package/dist/tools/shell/spawn-argv.js.map +1 -1
- package/dist/tools/skills.js +11 -1
- package/dist/tools/skills.js.map +1 -1
- package/dist/tui-v2/app/App.js +5 -9
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/layout-widths.js +3 -2
- package/dist/tui-v2/app/layout-widths.js.map +1 -1
- package/dist/tui-v2/bootstrap/patch-opentui-selection.d.ts +6 -0
- package/dist/tui-v2/bootstrap/patch-opentui-selection.js +27 -0
- package/dist/tui-v2/bootstrap/patch-opentui-selection.js.map +1 -0
- package/dist/tui-v2/bootstrap/patch-opentui-wheel.d.ts +9 -0
- package/dist/tui-v2/bootstrap/patch-opentui-wheel.js +23 -0
- package/dist/tui-v2/bootstrap/patch-opentui-wheel.js.map +1 -0
- package/dist/tui-v2/bootstrap/runtime-view.js +4 -0
- package/dist/tui-v2/bootstrap/runtime-view.js.map +1 -1
- package/dist/tui-v2/bootstrap/start-tui-v2.js +8 -1
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/jobs/jobs-panel.js +1 -9
- package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
- package/dist/tui-v2/components/modal/confirm-modal.js +1 -0
- package/dist/tui-v2/components/modal/confirm-modal.js.map +1 -1
- package/dist/tui-v2/components/pager/pager.js +2 -2
- package/dist/tui-v2/components/pager/pager.js.map +1 -1
- package/dist/tui-v2/components/plan/plan-view.js +24 -4
- package/dist/tui-v2/components/plan/plan-view.js.map +1 -1
- package/dist/tui-v2/components/status/context-limit-chip.js +2 -2
- package/dist/tui-v2/components/status/status-line.js +13 -12
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/transcript/compacted-row.js +3 -1
- package/dist/tui-v2/components/transcript/compacted-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/intro-card.js +5 -8
- package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/linkable-text.d.ts +2 -0
- package/dist/tui-v2/components/transcript/linkable-text.js +22 -2
- package/dist/tui-v2/components/transcript/linkable-text.js.map +1 -1
- package/dist/tui-v2/components/transcript/pending-arguments.d.ts +6 -0
- package/dist/tui-v2/components/transcript/pending-arguments.js +16 -0
- package/dist/tui-v2/components/transcript/pending-arguments.js.map +1 -0
- package/dist/tui-v2/components/transcript/selection-snap.d.ts +43 -0
- package/dist/tui-v2/components/transcript/selection-snap.js +68 -0
- package/dist/tui-v2/components/transcript/selection-snap.js.map +1 -0
- package/dist/tui-v2/components/transcript/thinking-block.d.ts +2 -0
- package/dist/tui-v2/components/transcript/thinking-block.js +37 -19
- package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
- package/dist/tui-v2/components/transcript/thinking-presentation.d.ts +0 -2
- package/dist/tui-v2/components/transcript/thinking-presentation.js +0 -52
- package/dist/tui-v2/components/transcript/thinking-presentation.js.map +1 -1
- package/dist/tui-v2/components/transcript/tool-card.js +4 -3
- package/dist/tui-v2/components/transcript/tool-card.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.js +20 -6
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-scroll-port.d.ts +2 -0
- package/dist/tui-v2/components/transcript/transcript-scroll-port.js +37 -0
- package/dist/tui-v2/components/transcript/transcript-scroll-port.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-view.js +159 -109
- package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +2 -4
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/composer/composer-highlight.js +2 -1
- package/dist/tui-v2/composer/composer-highlight.js.map +1 -1
- package/dist/tui-v2/composer/composer-wheel.d.ts +1 -1
- package/dist/tui-v2/composer/composer-wheel.js +4 -4
- package/dist/tui-v2/composer/composer-wheel.js.map +1 -1
- package/dist/tui-v2/rendering/ansi-to-styled.js +16 -20
- package/dist/tui-v2/rendering/ansi-to-styled.js.map +1 -1
- package/dist/types.d.ts +10 -7
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/ui/mentions/expand.js +4 -0
- package/dist/ui/mentions/expand.js.map +1 -1
- package/dist/ui-core/bootstrap/fatal-diagnostics.d.ts +1 -0
- package/dist/ui-core/bootstrap/fatal-diagnostics.js +9 -0
- package/dist/ui-core/bootstrap/fatal-diagnostics.js.map +1 -0
- package/dist/ui-core/bootstrap/lifecycle.d.ts +4 -0
- package/dist/ui-core/bootstrap/lifecycle.js +27 -4
- package/dist/ui-core/bootstrap/lifecycle.js.map +1 -1
- package/dist/ui-core/commands/command-handlers.js +2 -0
- package/dist/ui-core/commands/command-handlers.js.map +1 -1
- package/dist/ui-core/commands/picker-commands.d.ts +6 -2
- package/dist/ui-core/commands/picker-commands.js +31 -17
- package/dist/ui-core/commands/picker-commands.js.map +1 -1
- package/dist/ui-core/commands/rea-commands.d.ts +3 -0
- package/dist/ui-core/commands/rea-commands.js +176 -0
- package/dist/ui-core/commands/rea-commands.js.map +1 -0
- package/dist/ui-core/commands/rea-engines-commands.d.ts +37 -0
- package/dist/ui-core/commands/rea-engines-commands.js +433 -0
- package/dist/ui-core/commands/rea-engines-commands.js.map +1 -0
- package/dist/ui-core/composer/completion.js +3 -0
- package/dist/ui-core/composer/completion.js.map +1 -1
- package/dist/ui-core/controllers/overlay-controller.d.ts +1 -1
- package/dist/ui-core/controllers/selection-controller.d.ts +2 -1
- package/dist/ui-core/controllers/selection-controller.js +27 -0
- package/dist/ui-core/controllers/selection-controller.js.map +1 -1
- package/dist/ui-core/layout/compute-layout.d.ts +2 -2
- package/dist/ui-core/layout/compute-layout.js +3 -3
- package/dist/ui-core/layout/compute-layout.js.map +1 -1
- package/dist/ui-core/motion/wheel-scroll.d.ts +9 -0
- package/dist/ui-core/motion/wheel-scroll.js +36 -0
- package/dist/ui-core/motion/wheel-scroll.js.map +1 -0
- package/dist/ui-core/rendering/compaction-pager-source.d.ts +4 -0
- package/dist/ui-core/rendering/compaction-pager-source.js +65 -0
- package/dist/ui-core/rendering/compaction-pager-source.js.map +1 -0
- package/dist/ui-core/rendering/duration.d.ts +3 -1
- package/dist/ui-core/rendering/duration.js +12 -3
- package/dist/ui-core/rendering/duration.js.map +1 -1
- package/dist/ui-core/rendering/incremental-strip.js +4 -1
- package/dist/ui-core/rendering/incremental-strip.js.map +1 -1
- package/dist/ui-core/rendering/intro-header.d.ts +3 -0
- package/dist/ui-core/rendering/intro-header.js +146 -161
- package/dist/ui-core/rendering/intro-header.js.map +1 -1
- package/dist/ui-core/rendering/job-tail-source.js +30 -2
- package/dist/ui-core/rendering/job-tail-source.js.map +1 -1
- package/dist/ui-core/rendering/markdown/bold-lines.d.ts +1 -0
- package/dist/ui-core/rendering/markdown/bold-lines.js +79 -0
- package/dist/ui-core/rendering/markdown/bold-lines.js.map +1 -0
- package/dist/ui-core/rendering/markdown.d.ts +1 -0
- package/dist/ui-core/rendering/markdown.js +19 -13
- package/dist/ui-core/rendering/markdown.js.map +1 -1
- package/dist/ui-core/rendering/open-tool-output.d.ts +1 -0
- package/dist/ui-core/rendering/open-tool-output.js +8 -0
- package/dist/ui-core/rendering/open-tool-output.js.map +1 -1
- package/dist/ui-core/rendering/pending-arguments.d.ts +2 -0
- package/dist/ui-core/rendering/pending-arguments.js +6 -0
- package/dist/ui-core/rendering/pending-arguments.js.map +1 -0
- package/dist/ui-core/rendering/plan-view.js +0 -4
- package/dist/ui-core/rendering/plan-view.js.map +1 -1
- package/dist/ui-core/rendering/render-markdown-lines.d.ts +1 -0
- package/dist/ui-core/rendering/render-markdown-lines.js +1 -0
- package/dist/ui-core/rendering/render-markdown-lines.js.map +1 -1
- package/dist/ui-core/rendering/streaming-markdown.js +1 -1
- package/dist/ui-core/rendering/streaming-markdown.js.map +1 -1
- package/dist/ui-core/rendering/strip-tool-surfaces.js +7 -7
- package/dist/ui-core/rendering/strip-tool-surfaces.js.map +1 -1
- package/dist/ui-core/rendering/text-width.d.ts +1 -0
- package/dist/ui-core/rendering/text-width.js +22 -2
- package/dist/ui-core/rendering/text-width.js.map +1 -1
- package/dist/ui-core/rendering/thinking-tail.js +6 -2
- package/dist/ui-core/rendering/thinking-tail.js.map +1 -1
- package/dist/ui-core/rendering/tool-output-pager-source.d.ts +4 -0
- package/dist/ui-core/rendering/tool-output-pager-source.js +94 -0
- package/dist/ui-core/rendering/tool-output-pager-source.js.map +1 -0
- package/dist/ui-core/rendering/tool-presenter.js +47 -64
- package/dist/ui-core/rendering/tool-presenter.js.map +1 -1
- package/dist/ui-core/state/hydrate/classic-transcript.js +2 -0
- package/dist/ui-core/state/hydrate/classic-transcript.js.map +1 -1
- package/dist/ui-core/state/semantic-document.d.ts +4 -0
- package/dist/ui-core/state/semantic-document.js.map +1 -1
- package/dist/ui-core/state/transcript/apply-app-event.d.ts +2 -2
- package/dist/ui-core/state/transcript/apply-app-event.js +164 -384
- package/dist/ui-core/state/transcript/apply-app-event.js.map +1 -1
- package/dist/ui-core/state/transcript/tool-lifecycle.d.ts +19 -0
- package/dist/ui-core/state/transcript/tool-lifecycle.js +102 -0
- package/dist/ui-core/state/transcript/tool-lifecycle.js.map +1 -0
- package/dist/ui-core/state/transcript-hydrate.js +3 -0
- package/dist/ui-core/state/transcript-hydrate.js.map +1 -1
- package/dist/ui-core/state/transcript-types.d.ts +3 -0
- package/dist/ui-core/state/transcript-types.js.map +1 -1
- package/dist/ui-core/state/transcript-window.d.ts +9 -0
- package/dist/ui-core/state/transcript-window.js +9 -0
- package/dist/ui-core/state/transcript-window.js.map +1 -1
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/dist/version.generated.js.map +1 -1
- package/guides/security-skill.md +59 -0
- package/package.json +11 -3
- package/resources/skills/clai-superman-skill/SKILL.md +73 -0
- package/resources/skills/clai-superman-skill/references/ai-agents.md +51 -0
- package/resources/skills/clai-superman-skill/references/cloud-platform.md +48 -0
- package/resources/skills/clai-superman-skill/references/code-supply-chain.md +61 -0
- package/resources/skills/clai-superman-skill/references/crypto-contracts.md +46 -0
- package/resources/skills/clai-superman-skill/references/evidence-reporting.md +86 -0
- package/resources/skills/clai-superman-skill/references/identity-ad.md +51 -0
- package/resources/skills/clai-superman-skill/references/mobile-client.md +52 -0
- package/resources/skills/clai-superman-skill/references/novel-research.md +97 -0
- package/resources/skills/clai-superman-skill/references/operations.md +109 -0
- package/resources/skills/clai-superman-skill/references/security-operations.md +55 -0
- package/resources/skills/clai-superman-skill/references/sources.md +51 -0
- package/resources/skills/clai-superman-skill/references/systems-protocols.md +52 -0
- package/resources/skills/clai-superman-skill/references/web-api.md +65 -0
- package/resources/skills/clai-superman-skill/references/wireless-iot-ot.md +49 -0
- package/test/fixtures/security-skill-scenarios.json +191 -0
- package/dist/agent/context/compaction-work-history.d.ts +0 -13
- package/dist/agent/context/compaction-work-history.js +0 -150
- package/dist/agent/context/compaction-work-history.js.map +0 -1
- package/dist/tui-v2/components/transcript/transcript-scrollbar.d.ts +0 -29
- package/dist/tui-v2/components/transcript/transcript-scrollbar.js +0 -211
- package/dist/tui-v2/components/transcript/transcript-scrollbar.js.map +0 -1
|
@@ -53,7 +53,7 @@ These are defaults for a strong professional. Adapt when evidence demands it; sa
|
|
|
53
53
|
- **Plan tasks** = roadmap inside a durable plan the user accepts — not "start coding now".
|
|
54
54
|
- When an ACTIVE PLAN exists, follow its task states: `in_progress` → work → **read/analyze results** → `done` only when that outcome holds → open next. Never mark done because a command was fired. You are advised to work through every task, but the plan is not a hard gate: you may stop with tasks unfinished when genuinely blocked, when the user tells you to stop, or when the situation requires it — report the remaining tasks honestly instead of forcing completion. Use plan.clear to discard a plan that should no longer run.
|
|
55
55
|
|
|
56
|
-
**Parallelism:** Parallelize independent reads. Choose synchronous chat execution, a normal background job, or a Responder job from the task's actual latency, interactivity, dependencies, and need for concurrent work. Commands are never automatically backgrounded: shell.exec stays foreground unless you explicitly choose background:"always" or responder:true; background:"never" takes precedence, and legacy background:"auto" behaves like omission. You choose foreground timeoutMs in milliseconds (1000–1800000; default 60000). timeoutMs is ignored for background and Responder jobs, which have no execution deadline. No command-name heuristic changes execution mode, timeout units, budgets, or ownership. Responder
|
|
56
|
+
**Parallelism:** Parallelize independent reads. Choose synchronous chat execution, a normal background job, or a Responder job from the task's actual latency, interactivity, dependencies, and need for concurrent work. Commands are never automatically backgrounded: shell.exec stays foreground unless you explicitly choose background:"always" or responder:true; background:"never" takes precedence, and legacy background:"auto" behaves like omission. You choose foreground timeoutMs in milliseconds (1000–1800000; default 60000). timeoutMs is ignored for background and Responder jobs, which have no execution deadline. No command-name heuristic changes execution mode, timeout units, budgets, or ownership. Always delegate finite work expected to exceed 4–5 minutes to Responder with shell.exec responder:true, including long test suites, builds, scans, and CI watches. Use foreground for shorter finite work, with sufficient timeout. Interactive sessions use terminal tools; persistent servers/watchers use named background:"always" jobs, never Responder. **Images:** vision/OCR/scratch path before asking re-save. Adapt defaults when evidence demands.
|
|
57
57
|
|
|
58
58
|
**Minimize information load:** Decide the proof before each command; use quiet flags/pipes so output is that signal. Finite chatty work → shell.exec with selective output/artifacts; persistent work → background shell.exec + selective tail. Avoid duplicate noisy dumps; context is expensive, artifacts are cheap.
|
|
59
59
|
|
|
@@ -90,7 +90,7 @@ Default foreground `timeoutMs` is 60000ms (60s). You decide the budget in millis
|
|
|
90
90
|
|
|
91
91
|
# TOOLS (use these EXACT argument names)
|
|
92
92
|
|
|
93
|
-
- shell.exec: {"command":"<cmd>","cwd":"<optional>","timeoutMs":<optional ms>,"background":"<auto|never|always>","name":"<optional job label>","responder":<optional bool>} — foreground by default for every command; no automatic backgrounding. You choose the foreground millisecond deadline (default 60000); timeoutMs is ignored for background and Responder execution. Choose enough time before launching finite work to receive its output in one call. Persistent servers/watchers/listeners: explicitly choose background:"always" plus a name; launch confirms only that the OS started it, so shell.tail and probe readiness, and check shell.jobs before starting another copy. For normal pollable finite jobs, use background:"always" and shell.wait; for
|
|
93
|
+
- shell.exec: {"command":"<cmd>","cwd":"<optional>","timeoutMs":<optional ms>,"background":"<auto|never|always>","name":"<optional job label>","responder":<optional bool>} — foreground by default for every command; no automatic backgrounding. You choose the foreground millisecond deadline (default 60000); timeoutMs is ignored for background and Responder execution. Choose enough time before launching finite work to receive its output in one call. Persistent servers/watchers/listeners: explicitly choose background:"always" plus a name; launch confirms only that the OS started it, so shell.tail and probe readiness, and check shell.jobs before starting another copy. For normal pollable finite jobs, use background:"always" and shell.wait; for finite work expected to exceed 4–5 minutes, always use responder:true and analyze terminal delivery with job.read instead of polling. background:"never" forces foreground even with responder:true; auto is a compatibility alias for omission. Prefer cwd over `cd`; Unix uses POSIX `/bin/sh`, so use portable syntax (explicit `bash -lc` only when required). Cost or command names never override your execution choice.
|
|
94
94
|
- shell.jobs: {} / shell.tail: {"id":"<job-id>","bytes":<optional>,"offset":<optional byte offset>,"stream":"<stdout|stderr|combined>"} / shell.stop: {"id":"<job-id>"} — tail defaults to stdout; for incremental polling reuse the prior nextOffset as offset on the SAME stream (stdout or stderr). combined is snapshot-only and rejects offset.
|
|
95
95
|
- terminal.start: {"command":"<interactive command>","cwd":"<optional>","terminalMode":"<required|preferred|pipe>","columns":<optional>,"rows":<optional>,"idleTimeoutMs":<optional>,"lifetimeTimeoutMs":<optional>,"deadlineMs":<optional>} — persistent writable REPL/console for SSH, Python, debuggers, database shells, Metasploit, Meterpreter, and similar prompt-driven programs. preferred uses a PTY or explicitly reports pipe degradation; required refuses fallback (choose this for SSH passwords/readline consoles); pipe is only for stdin-driven programs that do not need a TTY. Dimensions are 2–1000 (defaults 80×24). Startup deadlineMs is 100–120000 (default 10000), NOT session lifetime. idleTimeoutMs is an optional 1000–86400000 inactivity cap; lifetimeTimeoutMs is an optional 1000–604800000 absolute cap; both are unset by default. Do not impose a short idle cap while the user enters a password. Start returns an initial page after waiting up to 1000ms for output; if no prompt is visible, read from nextCursor.
|
|
96
96
|
- terminal.send: {"id":"<session id>","kind":"<text|secret|control|eof>","text":"<text only when kind=text>","secretPrompt":"<optional non-secret local prompt label>","secretSource":"<auto|user|prompt>","submit":"<enter|none>","control":"<interrupt|eof|suspend|escape|tab|backspace|up|down|left|right>","cursor":<optional>,"quietMs":<optional>,"deadlineMs":<optional>,"view":"<plain|encoded>"} — send exactly one ordered action. secretSource defaults to auto: reuse one clearly labeled user-provided password from the current request, earlier user messages or carried credentials; otherwise open masked input. user requires an unambiguous supplied password without prompting; prompt forces masked entry. NEVER put a password in text, command, secretPrompt, an environment variable or a fallback script. submit defaults to enter (adds Enter itself); none types without submitting. quietMs is 25–5000 (default 250); deadlineMs is 100–120000 (default 30000). Quiet means output paused, NOT command finished. After delivery=delivered/unknown or a delivered action's deadline, never resend; continue from page.nextCursor with terminal.read.
|
|
@@ -100,7 +100,7 @@ Default foreground `timeoutMs` is 60000ms (60s). You decide the budget in millis
|
|
|
100
100
|
- Optional multi-file read: fs.read {"files":[{"path":"src/app.ts","offset":1,"limit":80},{"path":"src/config.ts","pattern":"export","context":2}]} for 1–10 necessary known files. Put each file’s filters directly inside its entry; omit top-level path/options. Single-file reads remain appropriate. Do not add irrelevant files to fill the limit. Results are ordered and labeled; inspect each file’s status and continuation independently. Use shell searches first when paths are unknown.
|
|
101
101
|
- fs.write: {"path":"<file>","content":"<data>"} — new/full rewrite. Existing file → prefer fs.edit/replaceLines; for a full rewrite preserve all required lines and inspect the diff. Parent dirs auto-created; trust bytes/hash, don't re-read solely to verify.
|
|
102
102
|
- fs.writeMany: {"files":[{"path":"<file>","content":"<data>"}, ...]} — up to 50 complete files; prefer for scaffolds.
|
|
103
|
-
- fs.edit: {"path":"<file>","oldText":"<exact>","newText":"<replacement>","expectedReplacements":<optional>} — surgical edits on existing files.
|
|
103
|
+
- fs.edit: {"path":"<file>","oldText":"<exact non-empty match>","newText":"<replacement>","expectedReplacements":<optional>} — surgical edits on existing files. Copy oldText from current file evidence; never pass "". newText is required; "" deletes the match. Create files with fs.write; insert at start/end with fs.append, or retain an existing anchor in oldText/newText for insertion within a file.
|
|
104
104
|
- fs.replaceLines: {"path":"<file>","startLine":<1-indexed>,"endLine":<inclusive>,"content":"<replacement>"} — line-range replace; empty/delete:true deletes. Re-read first; prefer fs.edit when exact text anchors better.
|
|
105
105
|
- fs.append: {"path":"<file>","content":"<data>","position":"<optional>","expectedPriorBytes":<optional>} — builds a long file in ordered chunks. Send the complete literal chunk, wait for its receipt, then use after_bytes as the next expectedPriorBytes or omit it.
|
|
106
106
|
- FILE WRITE POLICY: New → complete fs.write; existing → fs.edit/replaceLines unless full rewrite is clearer. Too large for one call → fs.write the first substantial part, then fs.append substantial remaining chunks in order. Never copy omitted legacy payload metadata into a new call. Check diffs for duplicates/missing imports. Never invent written content.
|
|
@@ -136,10 +136,11 @@ User messages are sent exactly as written. If a message includes an explicit loc
|
|
|
136
136
|
# OPERATING RULES
|
|
137
137
|
|
|
138
138
|
- DO THE TASK. Pick the best tool and run it. Do not wait for the user to name a tool.
|
|
139
|
-
- MATCH THE DELIVERABLE. Research/explain/compare → answer in chat (tables for comparisons). Do NOT scaffold a project or plan.create for pure Q&A. Do NOT write into the user project to "save" an answer unless asked.
|
|
139
|
+
- MATCH THE DELIVERABLE. Research/explain/compare → answer in chat (tables for comparisons). Do NOT scaffold a project or plan.create for pure Q&A. Do NOT write into the user project to "save" an answer unless asked.
|
|
140
|
+
- FILE PLACEMENT. Deliverables (projects, source, scripts, reports, docs) go to the user's location, else cwd if it is the task folder (empty, or the project the task concerns), else a new named folder under it; state the path. New work never adopts an existing same/similarly-named folder or file: pick a free name (e.g. watch-website-2) unless the user points at it or cwd is inside it. Scratch only under {{scratch}} (tool outputs in {{scratch}}/temp), only for disposable probes, captures and notes — never deliverables, never the temp root or a project.
|
|
140
141
|
- NEW APPS / BUILDS: prefer latest stable packages and current framework setups (e.g. current React/Vite/Next/Tailwind majors). If you are unsure about today's scaffold/config, web.search or web.fetch official docs before inventing outdated steps.
|
|
141
142
|
- STAY ON TARGET. Narrow tools for narrow questions. One focused recon command beats a bundled sweep; broaden only when the engagement needs it.
|
|
142
|
-
- EXISTING PROJECTS: preserve installed dependency versions and conventions
|
|
143
|
+
- EXISTING PROJECTS: preserve installed dependency versions and conventions; consult docs for the installed version when unsure; do not upgrade unrelated dependencies.
|
|
143
144
|
- HIGH-SIGNAL COMMANDS: apply minimize-information-load above on **every** domain (builds, tests, git, docker, scans, installs — not only fuzzers). Prefer quiet flags, status filters, structured output + jq, failure-only test output. Scanners (ffuf/gobuster/feroxbuster/…): filter at the command (`-mc`/`-fc`/`-fs`) and ALWAYS emit machine output (`-o out.json -of json`) so hits carry status + size. Never use blanket `ffuf -mc all`; retain its useful default matcher or specify purposeful statuses, then calibrate `-fc`/`-fs` from a nonexistent-path baseline. Do NOT pass `ffuf -s` (silent mode hides the Status/Size columns, leaving bare paths you cannot triage — you will not know what actually exists). To inspect a finished job, read the JSON artifact (or tail stdout, whose hit lines keep `[Status: N, Size: N]`) — keep every real status (2xx/3xx/4xx/5xx) with its size, drop only `:: Progress:`/spinner/`[2K` noise — never fs.read the whole scanner log. Use evidence → check missing executables if needed → purposeful run. When a card/artifact already has content, use it — never claim empty tools or re-fire solely because context is head+tail capped. Filter noise, not truth: large files → shell searches / fs.read pattern or offset windows; if a footer says hasMore/auto-head, page next — do not invent unread lines.
|
|
144
145
|
- VERIFY BEFORE CLAIMING. Coding: (1) stack checks that apply — typecheck, build, unit/integration tests — fix failures first; (2) then live/runtime proof when a server or UI applies (background shell.exec + tail + localhost probe). Report only what those checks showed. Remote pentest: evidence from tools against the remote target — NEVER start a local dev server to "finish" a website assessment; NEVER treat the clai workspace as the target.
|
|
145
146
|
- Don't run two equivalent scanners just to pad steps; do escalate when coverage is incomplete.
|
|
@@ -189,16 +190,16 @@ Give every child a lean, task-specific brief: target goal and deliverable, relev
|
|
|
189
190
|
- Start slow work early when its expected value and independence justify parallel execution; otherwise use the smallest direct action that can answer the current question.
|
|
190
191
|
- **TWO KINDS OF JOB.** (1) *Normal/pollable* — explicitly choose `background:"always"` without `responder:true`; YOU own them. For finite jobs, call shell.wait with a sufficient wait budget instead of polling in a loop. For persistent servers/watchers, use shell.tail plus a readiness probe, then shell.stop when cleanup is required. (2) *Responder/fire-and-continue* — finite work explicitly launched with `responder:true`. Never delegate a server/watcher because it does not self-complete. Select either mode only when it fits the task; all work otherwise stays synchronous. Trust the returned receipt's responder ownership and its single follow-up policy.
|
|
191
192
|
- **RESPONDER = FIRE-AND-CONTINUE.** After launching one, move on instead of sleeping, polling, tailing, or reading its log to watch progress. A launch is not a completion guarantee: the user can cancel it, so say the result will be delivered only if the job reaches a terminal receipt and never promise automatic completion. Each terminal receipt is injected at the next safe model boundary. Analyze it once, gather only bounded evidence still needed, then call job.read by job or notification id before giving a final response. job.read requires no plan and atomically records delivered + read; never create or update a plan merely to consume a receipt. If an active plan exists, add only evidence-driven follow-ups and let its Responder child settle automatically from the same receipt. If only report creation remains while Responder work is running or unread, leave it open and stop; completion resumes the session. Never sleep/poll/tail-loop.
|
|
192
|
-
- Never launch a duplicate while a matching job is active. On a Responder completion, inspect only filtered result lines or a bounded shell.tail window, then job.read when satisfied. Add follow-up tasks only when an active plan exists and the result requires more work.
|
|
193
|
+
- Never launch a duplicate while a matching job is active. On a Responder completion, inspect only filtered result lines or a bounded shell.tail window, then job.read when satisfied. Add follow-up tasks only when an active plan exists and the result requires more work. Always delegate finite work expected to exceed 4–5 minutes with shell.exec responder:true, even without independent work remaining; shorter installs/scaffolds/builds/tests may stay foreground with sufficient timeoutMs; if a finite job receipt says `responder:false`/omits responder, use shell.wait to terminal status instead of re-running or repeatedly polling.
|
|
193
194
|
- Localhost: curl via shell.exec or http.fetch to localhost/127.0.0.1 (GET/HEAD auto-owned) — never web.fetch for loopback/private.
|
|
194
195
|
- Long installs/scaffolds may be quiet for minutes: keep the foreground call and wait; do not abandon, duplicate, or re-scaffold.
|
|
195
196
|
- Double Esc cancels the live turn, queued prompts, and all session-owned Responder jobs; single Esc only dismisses/arms cancellation.
|
|
196
197
|
|
|
197
198
|
# BUILDING SOFTWARE
|
|
198
199
|
|
|
199
|
-
-
|
|
200
|
-
- Establish
|
|
201
|
-
- Prefer official non-interactive scaffolders into a NEW EMPTY subfolder. The scaffold **destination** is that subfolder (e.g. Desktop/blogging-app), not the parent Desktop. Scaffolders refuse non-empty dirs ("Operation cancelled") — that is FAILURE, not success. Existing project → CONTINUE (implement feature); never re-scaffold. Do not scaffold into a hidden temp tree and merge/delete it with shell loops; preserve existing config and use fs tools or hand-write the known tree. If scaffolding fails, hand-write a minimal correct tree and install deps.
|
|
200
|
+
- Place work per FILE PLACEMENT. Resolve absolute destinations with a leading `/` — never turn `/Users/…/Desktop` into relative `Users/…` under cwd. Never write user app source into the agent package tree.
|
|
201
|
+
- Establish project root and stack from existing context; if uncertain, inspect only what resolves it — no repeated discovery once location and manifests are known. Match the lockfile's package manager (package-lock → npm, pnpm-lock → pnpm, yarn.lock → yarn, bun.lockb → bun). Empty path → pick a sensible modern default and say which.
|
|
202
|
+
- Prefer official non-interactive scaffolders into a NEW EMPTY subfolder. The scaffold **destination** is that subfolder (e.g. Desktop/blogging-app), not the parent Desktop. Scaffolders refuse non-empty dirs ("Operation cancelled") — that is FAILURE, not success. Existing target project → CONTINUE (implement feature); never re-scaffold. Do not scaffold into a hidden temp tree and merge/delete it with shell loops; preserve existing config and use fs tools or hand-write the known tree. If scaffolding fails, hand-write a minimal correct tree and install deps.
|
|
202
203
|
- **THE DELIVERABLE IS THE WORKING FEATURE, not the scaffold.** Replace starter boilerplate (default Vite/Next/CRA pages, "Welcome to…") with what the user asked for. Leaving the default starter is a failure even if it builds.
|
|
203
204
|
- Synthesize explicit and implicit acceptance criteria and invariants from the ask (e.g. todo → add/list/toggle/delete ± persist; plus empty/duplicate/error states and data surviving reload). Implement until those hold, not until a checkbox feels done.
|
|
204
205
|
- Before editing existing code, inspect the contracts it touches — types, function signatures, callers, schemas, config, API/response shapes — and trace the data flow through them, so a change satisfies every caller and preserves invariants instead of breaking a hidden one.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface ReaEngine {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly name: string;
|
|
4
|
+
readonly ready: boolean;
|
|
5
|
+
readonly code: string | undefined;
|
|
6
|
+
readonly reason: string | undefined;
|
|
7
|
+
readonly failed: readonly string[];
|
|
8
|
+
readonly java: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface ReaBlockedGroup {
|
|
11
|
+
readonly tools: readonly string[];
|
|
12
|
+
readonly remediation: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ReaAvailability {
|
|
15
|
+
readonly engines: readonly ReaEngine[];
|
|
16
|
+
readonly open: ReadonlySet<string>;
|
|
17
|
+
readonly deep: ReadonlySet<string>;
|
|
18
|
+
readonly blocked: ReadonlySet<string>;
|
|
19
|
+
readonly blockedGroups: readonly ReaBlockedGroup[];
|
|
20
|
+
}
|
|
21
|
+
export declare function parseReaAvailability(text: string): ReaAvailability | undefined;
|
|
22
|
+
export declare function readyEngines(availability: ReaAvailability | undefined): readonly ReaEngine[];
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const DEEP_SURFACES = new Set(["official-proxy", "enhanced"]);
|
|
2
|
+
const BLOCKED_REASONS = new Set(["provider_missing", "provider_unavailable"]);
|
|
3
|
+
const MAX_REASON_CHARS = 160;
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function strings(value) {
|
|
8
|
+
return Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
|
|
9
|
+
}
|
|
10
|
+
function compact(value) {
|
|
11
|
+
if (typeof value !== "string")
|
|
12
|
+
return undefined;
|
|
13
|
+
const text = value.replace(/\s+/g, " ").trim();
|
|
14
|
+
if (!text)
|
|
15
|
+
return undefined;
|
|
16
|
+
return text.length > MAX_REASON_CHARS ? `${text.slice(0, MAX_REASON_CHARS - 1)}…` : text;
|
|
17
|
+
}
|
|
18
|
+
function engine(candidate) {
|
|
19
|
+
if (!isRecord(candidate) || !isRecord(candidate.provider))
|
|
20
|
+
return undefined;
|
|
21
|
+
const { id, name } = candidate.provider;
|
|
22
|
+
if (typeof id !== "string" || !/^[a-z][a-z0-9-]{0,31}$/.test(id))
|
|
23
|
+
return undefined;
|
|
24
|
+
const availability = isRecord(candidate.availability) ? candidate.availability : {};
|
|
25
|
+
const diagnostics = isRecord(availability.diagnostics) ? availability.diagnostics : {};
|
|
26
|
+
const checks = Array.isArray(diagnostics.checks) ? diagnostics.checks.filter(isRecord) : [];
|
|
27
|
+
const java = diagnostics.java_version;
|
|
28
|
+
return {
|
|
29
|
+
id,
|
|
30
|
+
name: typeof name === "string" && name.length <= 64 ? name : id,
|
|
31
|
+
ready: availability.status === "available",
|
|
32
|
+
code: typeof availability.code === "string" ? availability.code : undefined,
|
|
33
|
+
reason: compact(availability.reason),
|
|
34
|
+
failed: checks.filter((check) => check.ok === false && typeof check.name === "string").map((check) => String(check.name)).slice(0, 12),
|
|
35
|
+
java: typeof java === "string" && /^[0-9A-Za-z._+-]{1,24}$/.test(java) ? java : undefined,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export function parseReaAvailability(text) {
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(text);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
const session = isRecord(parsed) && isRecord(parsed.result) ? parsed.result : parsed;
|
|
47
|
+
if (!isRecord(session) || !Array.isArray(session.analysis_provider_candidates))
|
|
48
|
+
return undefined;
|
|
49
|
+
const engines = session.analysis_provider_candidates.flatMap((candidate) => engine(candidate) ?? []);
|
|
50
|
+
const groups = isRecord(session.tool_availability) && Array.isArray(session.tool_availability.groups)
|
|
51
|
+
? session.tool_availability.groups.filter(isRecord)
|
|
52
|
+
: [];
|
|
53
|
+
const open = new Set();
|
|
54
|
+
const deep = new Set();
|
|
55
|
+
const blocked = new Set();
|
|
56
|
+
const blockedGroups = [];
|
|
57
|
+
for (const group of groups) {
|
|
58
|
+
const names = strings(group.names);
|
|
59
|
+
if (typeof group.surface === "string" && DEEP_SURFACES.has(group.surface)) {
|
|
60
|
+
for (const name of names)
|
|
61
|
+
deep.add(name);
|
|
62
|
+
}
|
|
63
|
+
if (group.available === true)
|
|
64
|
+
continue;
|
|
65
|
+
if (group.reason === "target_required") {
|
|
66
|
+
for (const name of names)
|
|
67
|
+
open.add(name);
|
|
68
|
+
}
|
|
69
|
+
else if (typeof group.reason === "string" && BLOCKED_REASONS.has(group.reason)) {
|
|
70
|
+
for (const name of names)
|
|
71
|
+
blocked.add(name);
|
|
72
|
+
blockedGroups.push({ tools: names, remediation: compact(group.remediation) ?? "a prerequisite is missing" });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (engines.length === 0 && open.size === 0 && deep.size === 0 && blocked.size === 0)
|
|
76
|
+
return undefined;
|
|
77
|
+
return { engines, open, deep, blocked, blockedGroups };
|
|
78
|
+
}
|
|
79
|
+
export function readyEngines(availability) {
|
|
80
|
+
return availability?.engines.filter((entry) => entry.ready) ?? [];
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=availability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"availability.js","sourceRoot":"","sources":["../../src/rea/availability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpRuntime } from "../mcp/runtime.js";
|
|
2
|
+
import type { McpServerStatus, McpToolMetadata } from "../mcp/types.js";
|
|
3
|
+
export interface ReaConnection {
|
|
4
|
+
readonly server: McpServerStatus | undefined;
|
|
5
|
+
readonly selected: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function reaTools(runtime: Pick<McpRuntime, "getState">): McpToolMetadata[];
|
|
8
|
+
export declare function reaConnection(runtime: Pick<McpRuntime, "getState">): ReaConnection;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { REA_SERVER } from "./workflow.js";
|
|
2
|
+
export function reaTools(runtime) {
|
|
3
|
+
return runtime.getState().snapshot.tools.filter((tool) => tool.serverName === REA_SERVER);
|
|
4
|
+
}
|
|
5
|
+
export function reaConnection(runtime) {
|
|
6
|
+
const { snapshot, selection } = runtime.getState();
|
|
7
|
+
const server = snapshot.statuses.find((entry) => entry.name === REA_SERVER);
|
|
8
|
+
const selected = server?.status === "ready" &&
|
|
9
|
+
(selection.mode === "all" || (selection.mode === "servers" && selection.serverNames.includes(REA_SERVER)));
|
|
10
|
+
return { server, selected };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/rea/connection.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,MAAM,UAAU,QAAQ,CAAC,OAAqC;IAC5D,OAAO,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAqC;IACjE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IACnD,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAC5E,MAAM,QAAQ,GAAG,MAAM,EAAE,MAAM,KAAK,OAAO;QACzC,CAAC,SAAS,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7G,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface NpmRelease {
|
|
2
|
+
readonly name: string;
|
|
3
|
+
readonly version: string;
|
|
4
|
+
readonly tarball: string;
|
|
5
|
+
readonly integrity: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function officialUrl(value: string): URL;
|
|
8
|
+
export declare function fetchBytes(url: string, limit: number, signal?: AbortSignal, onProgress?: (received: number, total?: number) => void): Promise<Buffer>;
|
|
9
|
+
export declare function fetchJson(url: string, signal?: AbortSignal): Promise<unknown>;
|
|
10
|
+
export declare function jsonObject(value: unknown): Record<string, unknown>;
|
|
11
|
+
export declare function npmRelease(name: "rea-agents" | "npm", tag?: string, signal?: AbortSignal): Promise<NpmRelease>;
|
|
12
|
+
export declare function verifyIntegrity(bytes: Buffer, integrity: string): void;
|
|
13
|
+
export declare function extractPackage(bytes: Buffer, destination: string, archiveRoot: string): Promise<void>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createHash, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { Readable } from "node:stream";
|
|
4
|
+
import { pipeline } from "node:stream/promises";
|
|
5
|
+
const ORIGINS = new Set(["https://nodejs.org", "https://registry.npmjs.org"]);
|
|
6
|
+
const VERSION = /^\d+\.\d+\.\d+$/;
|
|
7
|
+
const STALL_TIMEOUT_MS = 60_000;
|
|
8
|
+
const PROGRESS_STEP_BYTES = 256 * 1024;
|
|
9
|
+
export function officialUrl(value) {
|
|
10
|
+
const url = new URL(value);
|
|
11
|
+
if (!ORIGINS.has(url.origin) || url.username || url.password) {
|
|
12
|
+
throw new Error(`Refusing unofficial download origin: ${url.origin}`);
|
|
13
|
+
}
|
|
14
|
+
return url;
|
|
15
|
+
}
|
|
16
|
+
export async function fetchBytes(url, limit, signal, onProgress) {
|
|
17
|
+
const stall = new AbortController();
|
|
18
|
+
let timer;
|
|
19
|
+
const watch = () => {
|
|
20
|
+
clearTimeout(timer);
|
|
21
|
+
timer = setTimeout(() => stall.abort(new Error(`Download stalled: no data for ${STALL_TIMEOUT_MS / 1000}s (${url})`)), STALL_TIMEOUT_MS);
|
|
22
|
+
};
|
|
23
|
+
watch();
|
|
24
|
+
try {
|
|
25
|
+
const response = await fetch(officialUrl(url), {
|
|
26
|
+
redirect: "error",
|
|
27
|
+
signal: signal ? AbortSignal.any([signal, stall.signal]) : stall.signal,
|
|
28
|
+
headers: { "User-Agent": "clai-rea-installer" },
|
|
29
|
+
});
|
|
30
|
+
if (!response.ok)
|
|
31
|
+
throw new Error(`Download failed: HTTP ${response.status} (${url})`);
|
|
32
|
+
const encoding = response.headers.get("content-encoding")?.toLowerCase();
|
|
33
|
+
const declared = Number(response.headers.get("content-length"));
|
|
34
|
+
const length = encoding && encoding !== "identity" ? 0 : declared;
|
|
35
|
+
if (declared > limit) {
|
|
36
|
+
await response.body?.cancel();
|
|
37
|
+
throw new Error(`Download exceeds ${limit} bytes`);
|
|
38
|
+
}
|
|
39
|
+
const reader = response.body?.getReader();
|
|
40
|
+
if (!reader)
|
|
41
|
+
throw new Error(`Empty download: ${url}`);
|
|
42
|
+
const exact = length > 0 ? Buffer.allocUnsafe(length) : undefined;
|
|
43
|
+
const chunks = [];
|
|
44
|
+
let received = 0;
|
|
45
|
+
let reported = 0;
|
|
46
|
+
try {
|
|
47
|
+
for (;;) {
|
|
48
|
+
const { value, done } = await reader.read();
|
|
49
|
+
if (done)
|
|
50
|
+
break;
|
|
51
|
+
watch();
|
|
52
|
+
if (received + value.byteLength > limit)
|
|
53
|
+
throw new Error(`Download exceeds ${limit} bytes`);
|
|
54
|
+
if (exact) {
|
|
55
|
+
if (received + value.byteLength > exact.byteLength)
|
|
56
|
+
throw new Error("Download exceeds its declared length");
|
|
57
|
+
exact.set(value, received);
|
|
58
|
+
}
|
|
59
|
+
else
|
|
60
|
+
chunks.push(value);
|
|
61
|
+
received += value.byteLength;
|
|
62
|
+
if (received - reported >= PROGRESS_STEP_BYTES) {
|
|
63
|
+
reported = received;
|
|
64
|
+
onProgress?.(received, length > 0 ? length : undefined);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (received === 0 || (exact && received !== exact.byteLength))
|
|
68
|
+
throw new Error("Incomplete download");
|
|
69
|
+
onProgress?.(received, length > 0 ? length : undefined);
|
|
70
|
+
return exact ?? Buffer.concat(chunks, received);
|
|
71
|
+
}
|
|
72
|
+
finally {
|
|
73
|
+
await reader.cancel().catch(() => undefined);
|
|
74
|
+
reader.releaseLock();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
clearTimeout(timer);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export async function fetchJson(url, signal) {
|
|
82
|
+
return JSON.parse((await fetchBytes(url, 4 * 1024 * 1024, signal)).toString("utf8"));
|
|
83
|
+
}
|
|
84
|
+
export function jsonObject(value) {
|
|
85
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
86
|
+
throw new Error("Invalid release metadata");
|
|
87
|
+
return value;
|
|
88
|
+
}
|
|
89
|
+
export async function npmRelease(name, tag = "latest", signal) {
|
|
90
|
+
if (tag !== "latest" && !VERSION.test(tag))
|
|
91
|
+
throw new Error("Invalid package version");
|
|
92
|
+
const metadata = jsonObject(await fetchJson(`https://registry.npmjs.org/${name}/${tag}`, signal));
|
|
93
|
+
const dist = jsonObject(metadata.dist);
|
|
94
|
+
if (metadata.name !== name || typeof metadata.version !== "string" || !VERSION.test(metadata.version) ||
|
|
95
|
+
typeof dist.tarball !== "string" || typeof dist.integrity !== "string") {
|
|
96
|
+
throw new Error(`Invalid official ${name} release metadata`);
|
|
97
|
+
}
|
|
98
|
+
const url = officialUrl(dist.tarball);
|
|
99
|
+
if (url.origin !== "https://registry.npmjs.org" || !url.pathname.startsWith(`/${name}/-/`)) {
|
|
100
|
+
throw new Error(`Invalid official ${name} package URL`);
|
|
101
|
+
}
|
|
102
|
+
return { name, version: metadata.version, tarball: url.href, integrity: dist.integrity };
|
|
103
|
+
}
|
|
104
|
+
export function verifyIntegrity(bytes, integrity) {
|
|
105
|
+
const match = /^sha(256|512)-([A-Za-z0-9+/]+={0,2})$/.exec(integrity);
|
|
106
|
+
if (!match)
|
|
107
|
+
throw new Error("A SHA-256 or SHA-512 package checksum is required");
|
|
108
|
+
const actual = createHash(`sha${match[1]}`).update(bytes).digest();
|
|
109
|
+
const expected = Buffer.from(match[2], "base64");
|
|
110
|
+
if (actual.length !== expected.length || !timingSafeEqual(actual, expected))
|
|
111
|
+
throw new Error("Downloaded package checksum mismatch");
|
|
112
|
+
}
|
|
113
|
+
export async function extractPackage(bytes, destination, archiveRoot) {
|
|
114
|
+
await mkdir(destination, { recursive: true, mode: 0o700 });
|
|
115
|
+
const { Unpack } = await import("tar");
|
|
116
|
+
let total = 0;
|
|
117
|
+
let entries = 0;
|
|
118
|
+
const unpack = new Unpack({
|
|
119
|
+
cwd: destination, strip: 1, strict: true,
|
|
120
|
+
preserveOwner: false, noMtime: true, maxDecompressionRatio: 200,
|
|
121
|
+
filter: (path, entry) => {
|
|
122
|
+
const parts = path.replace(/\\/g, "/").replace(/\/$/, "").split("/");
|
|
123
|
+
if (parts[0] !== archiveRoot || parts.some((part) => !part || part === ".." || part === "." || /[:\0]/.test(part))) {
|
|
124
|
+
unpack.abort(new Error("Unsafe path in downloaded archive"));
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
if (!("type" in entry) || (entry.type !== "File" && entry.type !== "Directory"))
|
|
128
|
+
return false;
|
|
129
|
+
total += entry.size;
|
|
130
|
+
entries += 1;
|
|
131
|
+
if (total > 512 * 1024 * 1024 || entries > 30_000) {
|
|
132
|
+
unpack.abort(new Error("Downloaded archive exceeds extraction limits"));
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
await pipeline(Readable.from([bytes]), unpack);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=distribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distribution.js","sourceRoot":"","sources":["../../src/rea/distribution.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type FetchFunction = (input: string, init?: RequestInit) => Promise<Response>;
|
|
2
|
+
export interface RequestOptions {
|
|
3
|
+
readonly hosts: readonly string[];
|
|
4
|
+
readonly maxBytes: number;
|
|
5
|
+
readonly signal?: AbortSignal | undefined;
|
|
6
|
+
readonly headers?: Readonly<Record<string, string>> | undefined;
|
|
7
|
+
readonly fetch?: FetchFunction | undefined;
|
|
8
|
+
readonly stallMs?: number | undefined;
|
|
9
|
+
}
|
|
10
|
+
export interface DownloadOptions extends RequestOptions {
|
|
11
|
+
readonly sha256?: string | undefined;
|
|
12
|
+
readonly bytes?: number | undefined;
|
|
13
|
+
readonly onProgress?: ((received: number, total?: number) => void) | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface DownloadResult {
|
|
16
|
+
readonly bytes: number;
|
|
17
|
+
readonly sha256: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function allowedHost(url: URL, hosts: readonly string[]): boolean;
|
|
20
|
+
export declare function fetchText(url: string, options: RequestOptions): Promise<string>;
|
|
21
|
+
export declare function fetchJsonValue(url: string, options: RequestOptions): Promise<unknown>;
|
|
22
|
+
export declare function downloadFile(url: string, destination: string, options: DownloadOptions): Promise<DownloadResult>;
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { rm } from "node:fs/promises";
|
|
4
|
+
import { Readable } from "node:stream";
|
|
5
|
+
import { pipeline } from "node:stream/promises";
|
|
6
|
+
import { publish } from "./install.js";
|
|
7
|
+
const MAX_REDIRECTS = 5;
|
|
8
|
+
const STALL_TIMEOUT_MS = 60_000;
|
|
9
|
+
const PROGRESS_STEP_BYTES = 1024 * 1024;
|
|
10
|
+
const REDIRECTS = new Set([301, 302, 303, 307, 308]);
|
|
11
|
+
export function allowedHost(url, hosts) {
|
|
12
|
+
if (url.protocol !== "https:" || url.username || url.password || url.port)
|
|
13
|
+
return false;
|
|
14
|
+
return hosts.some((host) => host.startsWith("*.") ? url.hostname.endsWith(host.slice(1)) : url.hostname === host);
|
|
15
|
+
}
|
|
16
|
+
function checkedUrl(value, hosts) {
|
|
17
|
+
let url;
|
|
18
|
+
try {
|
|
19
|
+
url = new URL(value);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
throw new Error(`Refusing malformed download URL: ${value.slice(0, 80)}`);
|
|
23
|
+
}
|
|
24
|
+
if (!allowedHost(url, hosts))
|
|
25
|
+
throw new Error(`Refusing unofficial download origin: ${url.origin}`);
|
|
26
|
+
return url;
|
|
27
|
+
}
|
|
28
|
+
async function open(url, options, signal) {
|
|
29
|
+
const request = options.fetch ?? fetch;
|
|
30
|
+
let current = checkedUrl(url, options.hosts);
|
|
31
|
+
for (let hop = 0; hop <= MAX_REDIRECTS; hop += 1) {
|
|
32
|
+
const response = await request(current.href, {
|
|
33
|
+
redirect: "manual",
|
|
34
|
+
signal,
|
|
35
|
+
headers: { "User-Agent": "clai-rea-installer", ...options.headers },
|
|
36
|
+
});
|
|
37
|
+
if (!REDIRECTS.has(response.status))
|
|
38
|
+
return response;
|
|
39
|
+
const location = response.headers.get("location");
|
|
40
|
+
await response.body?.cancel().catch(() => undefined);
|
|
41
|
+
if (!location)
|
|
42
|
+
throw new Error(`Download redirect without a location (${current.origin})`);
|
|
43
|
+
current = checkedUrl(new URL(location, current).href, options.hosts);
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Download redirected more than ${MAX_REDIRECTS} times`);
|
|
46
|
+
}
|
|
47
|
+
function stallGuard(options) {
|
|
48
|
+
const stall = new AbortController();
|
|
49
|
+
const limit = options.stallMs ?? STALL_TIMEOUT_MS;
|
|
50
|
+
let timer;
|
|
51
|
+
const touch = () => {
|
|
52
|
+
clearTimeout(timer);
|
|
53
|
+
timer = setTimeout(() => stall.abort(new Error(`Download stalled: no data for ${Math.round(limit / 1000)}s`)), limit);
|
|
54
|
+
};
|
|
55
|
+
touch();
|
|
56
|
+
return {
|
|
57
|
+
signal: options.signal ? AbortSignal.any([options.signal, stall.signal]) : stall.signal,
|
|
58
|
+
touch,
|
|
59
|
+
stop: () => clearTimeout(timer),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function cancelled(signal) {
|
|
63
|
+
return signal.reason instanceof Error ? signal.reason : new Error("Download cancelled");
|
|
64
|
+
}
|
|
65
|
+
async function* chunksOf(body, signal) {
|
|
66
|
+
const reader = body.getReader();
|
|
67
|
+
const onAbort = () => {
|
|
68
|
+
reader.cancel(cancelled(signal)).catch(() => undefined);
|
|
69
|
+
};
|
|
70
|
+
if (signal.aborted)
|
|
71
|
+
onAbort();
|
|
72
|
+
else
|
|
73
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
74
|
+
try {
|
|
75
|
+
for (;;) {
|
|
76
|
+
const { value, done } = await reader.read();
|
|
77
|
+
if (signal.aborted)
|
|
78
|
+
throw cancelled(signal);
|
|
79
|
+
if (done)
|
|
80
|
+
return;
|
|
81
|
+
yield value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
signal.removeEventListener("abort", onAbort);
|
|
86
|
+
reader.cancel().catch(() => undefined);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function requestFailure(response, host) {
|
|
90
|
+
const base = `Request failed: HTTP ${response.status} (${host})`;
|
|
91
|
+
const remaining = response.headers.get("x-ratelimit-remaining");
|
|
92
|
+
const reset = Number(response.headers.get("x-ratelimit-reset"));
|
|
93
|
+
const retryAfter = Number(response.headers.get("retry-after"));
|
|
94
|
+
const limited = response.status === 429 || ((response.status === 403 || response.status === 503) && (remaining === "0" || retryAfter > 0));
|
|
95
|
+
if (!limited)
|
|
96
|
+
return base;
|
|
97
|
+
const seconds = Number.isFinite(retryAfter) && retryAfter > 0 ? retryAfter : Number.isFinite(reset) && reset > 0 ? Math.max(0, reset - Math.floor(Date.now() / 1000)) : undefined;
|
|
98
|
+
const minutes = seconds === undefined ? undefined : Math.max(1, Math.ceil(seconds / 60));
|
|
99
|
+
return `${base}: ${host} is rate limiting this network${minutes === undefined ? "" : `; try again in about ${minutes} minute${minutes === 1 ? "" : "s"}`}`;
|
|
100
|
+
}
|
|
101
|
+
export async function fetchText(url, options) {
|
|
102
|
+
const guard = stallGuard(options);
|
|
103
|
+
try {
|
|
104
|
+
const response = await open(url, options, guard.signal);
|
|
105
|
+
if (!response.ok) {
|
|
106
|
+
await response.body?.cancel().catch(() => undefined);
|
|
107
|
+
throw new Error(requestFailure(response, new URL(url).hostname));
|
|
108
|
+
}
|
|
109
|
+
if (!response.body)
|
|
110
|
+
throw new Error("Empty response");
|
|
111
|
+
const chunks = [];
|
|
112
|
+
let received = 0;
|
|
113
|
+
for await (const chunk of chunksOf(response.body, guard.signal)) {
|
|
114
|
+
guard.touch();
|
|
115
|
+
received += chunk.byteLength;
|
|
116
|
+
if (received > options.maxBytes)
|
|
117
|
+
throw new Error(`Response exceeds ${options.maxBytes} bytes`);
|
|
118
|
+
chunks.push(chunk);
|
|
119
|
+
}
|
|
120
|
+
return Buffer.concat(chunks, received).toString("utf8");
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
guard.stop();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export async function fetchJsonValue(url, options) {
|
|
127
|
+
const text = await fetchText(url, options);
|
|
128
|
+
try {
|
|
129
|
+
return JSON.parse(text);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
throw new Error("Release metadata is not valid JSON");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
export async function downloadFile(url, destination, options) {
|
|
136
|
+
const expected = options.sha256?.toLowerCase();
|
|
137
|
+
if (expected !== undefined && !/^[0-9a-f]{64}$/.test(expected))
|
|
138
|
+
throw new Error("A SHA-256 checksum is required for downloads");
|
|
139
|
+
const guard = stallGuard(options);
|
|
140
|
+
const partial = `${destination}.part`;
|
|
141
|
+
try {
|
|
142
|
+
await rm(partial, { force: true });
|
|
143
|
+
const response = await open(url, options, guard.signal);
|
|
144
|
+
if (!response.ok) {
|
|
145
|
+
await response.body?.cancel().catch(() => undefined);
|
|
146
|
+
throw new Error(`Download failed: HTTP ${response.status} (${new URL(url).hostname})`);
|
|
147
|
+
}
|
|
148
|
+
const encoding = response.headers.get("content-encoding")?.toLowerCase();
|
|
149
|
+
const declared = encoding && encoding !== "identity" ? 0 : Number(response.headers.get("content-length"));
|
|
150
|
+
const total = options.bytes ?? (Number.isFinite(declared) && declared > 0 ? declared : undefined);
|
|
151
|
+
const refuse = async (message) => {
|
|
152
|
+
await response.body?.cancel().catch(() => undefined);
|
|
153
|
+
throw new Error(message);
|
|
154
|
+
};
|
|
155
|
+
if ((total ?? 0) > options.maxBytes)
|
|
156
|
+
await refuse(`Download exceeds ${options.maxBytes} bytes`);
|
|
157
|
+
if (options.bytes !== undefined && declared > 0 && declared !== options.bytes) {
|
|
158
|
+
await refuse(`Download size ${declared} does not match the published size ${options.bytes}`);
|
|
159
|
+
}
|
|
160
|
+
if (!response.body)
|
|
161
|
+
throw new Error("Empty download");
|
|
162
|
+
const hash = createHash("sha256");
|
|
163
|
+
let received = 0;
|
|
164
|
+
let reported = 0;
|
|
165
|
+
async function* counted(body) {
|
|
166
|
+
for await (const chunk of chunksOf(body, guard.signal)) {
|
|
167
|
+
guard.touch();
|
|
168
|
+
received += chunk.byteLength;
|
|
169
|
+
if (received > options.maxBytes || (total !== undefined && received > total)) {
|
|
170
|
+
throw new Error(`Download exceeds ${total ?? options.maxBytes} bytes`);
|
|
171
|
+
}
|
|
172
|
+
hash.update(chunk);
|
|
173
|
+
if (received - reported >= PROGRESS_STEP_BYTES) {
|
|
174
|
+
reported = received;
|
|
175
|
+
options.onProgress?.(received, total);
|
|
176
|
+
}
|
|
177
|
+
yield chunk;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
await pipeline(Readable.from(counted(response.body)), createWriteStream(partial, { flags: "wx", mode: 0o600 }), { signal: guard.signal });
|
|
181
|
+
if (received === 0 || (total !== undefined && received !== total))
|
|
182
|
+
throw new Error("Incomplete download");
|
|
183
|
+
const digest = hash.digest("hex");
|
|
184
|
+
if (expected !== undefined && digest !== expected)
|
|
185
|
+
throw new Error("Downloaded file checksum mismatch");
|
|
186
|
+
options.onProgress?.(received, total);
|
|
187
|
+
await publish(partial, destination);
|
|
188
|
+
return { bytes: received, sha256: digest };
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
await rm(partial, { force: true }).catch(() => undefined);
|
|
192
|
+
throw guard.signal.aborted && guard.signal.reason instanceof Error ? guard.signal.reason : error;
|
|
193
|
+
}
|
|
194
|
+
finally {
|
|
195
|
+
guard.stop();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=download.js.map
|