mixdog 0.7.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/.claude-plugin/marketplace.json +31 -0
- package/.claude-plugin/plugin.json +20 -0
- package/.gitattributes +34 -0
- package/.mcp.json +14 -0
- package/ARCHITECTURE.md +77 -0
- package/CHANGELOG.md +7 -0
- package/CONTRIBUTING.md +45 -0
- package/DATA-FLOW.md +79 -0
- package/LICENSE +21 -0
- package/README.md +389 -0
- package/SECURITY.md +138 -0
- package/UNINSTALL.md +112 -0
- package/agents/maintenance.md +5 -0
- package/agents/memory-classification.md +30 -0
- package/agents/scheduler-task.md +18 -0
- package/agents/webhook-handler.md +27 -0
- package/agents/worker.md +24 -0
- package/bin/bridge +133 -0
- package/bin/statusline-launcher.mjs +78 -0
- package/bin/statusline-lib.mjs +550 -0
- package/bin/statusline.mjs +607 -0
- package/bun.lock +802 -0
- package/commands/config.md +16 -0
- package/commands/doctor.md +13 -0
- package/commands/setup.md +17 -0
- package/defaults/cycle3-review-prompt.md +90 -0
- package/defaults/hidden-roles.json +65 -0
- package/defaults/memory-chunk-prompt.md +63 -0
- package/defaults/memory-promote-prompt.md +135 -0
- package/defaults/mixdog-config.template.json +27 -0
- package/defaults/user-workflow.json +8 -0
- package/defaults/user-workflow.md +12 -0
- package/hooks/hooks.json +73 -0
- package/hooks/lib/active-instance.cjs +77 -0
- package/hooks/lib/permission-evaluator.cjs +411 -0
- package/hooks/lib/permission-route.cjs +63 -0
- package/hooks/lib/permission-rules.cjs +170 -0
- package/hooks/lib/settings-loader.cjs +116 -0
- package/hooks/post-tool-use.cjs +84 -0
- package/hooks/pre-mcp-sandbox.cjs +158 -0
- package/hooks/pre-tool-subagent.cjs +253 -0
- package/hooks/session-start.cjs +1372 -0
- package/hooks/turn-timer.cjs +82 -0
- package/lib/claude-md-writer.cjs +386 -0
- package/lib/config-cjs.cjs +61 -0
- package/lib/hook-pipe-path.cjs +10 -0
- package/lib/keychain-cjs.cjs +263 -0
- package/lib/plugin-paths.cjs +61 -0
- package/lib/rules-builder.cjs +241 -0
- package/lib/text-utils.cjs +61 -0
- package/native/README.md +117 -0
- package/native/prebuilt/linux-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/linux-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/macos-aarch64/mixdog-shim +0 -0
- package/native/prebuilt/macos-x86_64/mixdog-shim +0 -0
- package/native/prebuilt/windows-x86_64/mixdog-shim.exe +0 -0
- package/package.json +107 -0
- package/prompts/code-review.txt +16 -0
- package/prompts/security-audit.txt +17 -0
- package/rules/bridge/00-common.md +39 -0
- package/rules/bridge/20-skip-protocol.md +18 -0
- package/rules/bridge/30-explorer.md +33 -0
- package/rules/bridge/40-cycle1-agent.md +52 -0
- package/rules/bridge/41-cycle2-agent.md +62 -0
- package/rules/bridge/42-cycle3-agent.md +44 -0
- package/rules/lead/00-tool-lead.md +61 -0
- package/rules/lead/01-general.md +23 -0
- package/rules/lead/02-channels.md +49 -0
- package/rules/lead/03-team.md +27 -0
- package/rules/lead/04-workflow.md +20 -0
- package/rules/shared/00-language.md +14 -0
- package/rules/shared/01-tool.md +138 -0
- package/scripts/bootstrap.mjs +184 -0
- package/scripts/bridge-unify-smoke.mjs +308 -0
- package/scripts/build-runtime-linux.sh +348 -0
- package/scripts/build-runtime-macos.sh +217 -0
- package/scripts/build-runtime-windows.ps1 +242 -0
- package/scripts/builtin-utils-smoke.mjs +392 -0
- package/scripts/check-json.mjs +45 -0
- package/scripts/check-syntax-changed.mjs +102 -0
- package/scripts/check-syntax.mjs +58 -0
- package/scripts/code-graph-batch.test.mjs +33 -0
- package/scripts/config-preserve-smoke.mjs +180 -0
- package/scripts/doctor.mjs +484 -0
- package/scripts/edit-normalize-fuzz.mjs +130 -0
- package/scripts/edit-normalize-smoke.mjs +401 -0
- package/scripts/edit-operation-smoke.mjs +369 -0
- package/scripts/edit2-smoke.mjs +63 -0
- package/scripts/fuzzy-e2e.mjs +28 -0
- package/scripts/fuzzy-smoke.mjs +26 -0
- package/scripts/generate-runtime-manifest.mjs +166 -0
- package/scripts/guard-smoke.mjs +66 -0
- package/scripts/hidden-role-schema-smoke.mjs +162 -0
- package/scripts/hook-routing-smoke.mjs +29 -0
- package/scripts/inject-input.ps1 +204 -0
- package/scripts/io-complex-smoke.mjs +667 -0
- package/scripts/io-explore-bench.mjs +424 -0
- package/scripts/io-guardrails-smoke.mjs +205 -0
- package/scripts/io-mini-bench-baseline.json +11 -0
- package/scripts/io-mini-bench.mjs +216 -0
- package/scripts/io-route-harness.mjs +933 -0
- package/scripts/io-telemetry-report.mjs +691 -0
- package/scripts/mutation-bench.mjs +564 -0
- package/scripts/mutation-io-smoke.mjs +1081 -0
- package/scripts/native-patch-bridge-smoke.mjs +288 -0
- package/scripts/native-patch-smoke.mjs +304 -0
- package/scripts/patch-interior-context-smoke.mjs +49 -0
- package/scripts/patch-newline-utf8-smoke.mjs +157 -0
- package/scripts/perf-hook-smoke.mjs +71 -0
- package/scripts/permission-eval-smoke.mjs +426 -0
- package/scripts/prep-patch.mjs +53 -0
- package/scripts/prep-shim.mjs +96 -0
- package/scripts/provider-cache-smoke.mjs +687 -0
- package/scripts/report-runtime-health.mjs +132 -0
- package/scripts/run-mcp.mjs +1547 -0
- package/scripts/salvage-v4a-shatter.test.mjs +58 -0
- package/scripts/scoped-cache-io-smoke.mjs +103 -0
- package/scripts/shell-policy-round3-smoke.mjs +46 -0
- package/scripts/smoke-runtime-negative.ps1 +100 -0
- package/scripts/smoke-runtime-negative.sh +95 -0
- package/scripts/stall-policy-smoke.mjs +50 -0
- package/scripts/start-memory-worker.mjs +23 -0
- package/scripts/statusline-launcher-smoke.mjs +82 -0
- package/scripts/stress-atomic-write.mjs +1028 -0
- package/scripts/test-config-rmw-restore.mjs +122 -0
- package/scripts/test-fault-inject.mjs +164 -0
- package/scripts/test-large-file.mjs +174 -0
- package/scripts/tool-edge-smoke.mjs +209 -0
- package/scripts/uninstall.mjs +201 -0
- package/scripts/webhook-selfheal-smoke.mjs +29 -0
- package/scripts/write-overwrite-guard-smoke.mjs +56 -0
- package/server-main.mjs +3055 -0
- package/server.mjs +468 -0
- package/setup/config-merge.mjs +254 -0
- package/setup/install.mjs +120 -0
- package/setup/launch-core.mjs +507 -0
- package/setup/launch.mjs +101 -0
- package/setup/setup-server.mjs +3206 -0
- package/setup/setup.html +3693 -0
- package/skills/retro-skill-proposer/SKILL.md +92 -0
- package/skills/schedule-add/SKILL.md +77 -0
- package/skills/setup/SKILL.md +346 -0
- package/skills/webhook-add/SKILL.md +81 -0
- package/src/agent/bridge-stall-watchdog.mjs +337 -0
- package/src/agent/index.mjs +2138 -0
- package/src/agent/orchestrator/activity-bus.mjs +38 -0
- package/src/agent/orchestrator/ai-wrapped-dispatch.mjs +1010 -0
- package/src/agent/orchestrator/bridge-retry.mjs +220 -0
- package/src/agent/orchestrator/bridge-trace.mjs +583 -0
- package/src/agent/orchestrator/cache-mtime.mjs +58 -0
- package/src/agent/orchestrator/config.mjs +358 -0
- package/src/agent/orchestrator/context/collect.mjs +651 -0
- package/src/agent/orchestrator/dispatch-persist.mjs +549 -0
- package/src/agent/orchestrator/drain-registry.mjs +50 -0
- package/src/agent/orchestrator/explore-validator.mjs +8 -0
- package/src/agent/orchestrator/internal-roles.mjs +118 -0
- package/src/agent/orchestrator/internal-tools.mjs +88 -0
- package/src/agent/orchestrator/jobs.mjs +116 -0
- package/src/agent/orchestrator/mcp/client.mjs +364 -0
- package/src/agent/orchestrator/providers/anthropic-betas.mjs +21 -0
- package/src/agent/orchestrator/providers/anthropic-oauth.mjs +1745 -0
- package/src/agent/orchestrator/providers/anthropic.mjs +437 -0
- package/src/agent/orchestrator/providers/gemini.mjs +1175 -0
- package/src/agent/orchestrator/providers/grok-oauth.mjs +782 -0
- package/src/agent/orchestrator/providers/model-catalog.mjs +241 -0
- package/src/agent/orchestrator/providers/openai-compat.mjs +1467 -0
- package/src/agent/orchestrator/providers/openai-oauth-ws.mjs +1890 -0
- package/src/agent/orchestrator/providers/openai-oauth.mjs +1307 -0
- package/src/agent/orchestrator/providers/openai-ws.mjs +104 -0
- package/src/agent/orchestrator/providers/registry.mjs +192 -0
- package/src/agent/orchestrator/providers/retry-classifier.mjs +325 -0
- package/src/agent/orchestrator/session/abort-lookup.mjs +13 -0
- package/src/agent/orchestrator/session/cache/post-edit-marks.mjs +42 -0
- package/src/agent/orchestrator/session/cache/prefetch-cache.mjs +142 -0
- package/src/agent/orchestrator/session/cache/read-cache.mjs +319 -0
- package/src/agent/orchestrator/session/cache/scoped-cache-outcome.mjs +11 -0
- package/src/agent/orchestrator/session/cache/scoped-cache.mjs +361 -0
- package/src/agent/orchestrator/session/cache/util.mjs +49 -0
- package/src/agent/orchestrator/session/loop.mjs +1478 -0
- package/src/agent/orchestrator/session/manager.mjs +1975 -0
- package/src/agent/orchestrator/session/read-dedup.mjs +6 -0
- package/src/agent/orchestrator/session/result-classification.mjs +65 -0
- package/src/agent/orchestrator/session/save-session-worker.mjs +18 -0
- package/src/agent/orchestrator/session/store.mjs +624 -0
- package/src/agent/orchestrator/session/stream-watchdog.mjs +130 -0
- package/src/agent/orchestrator/session/tool-result-offload.mjs +166 -0
- package/src/agent/orchestrator/session/trim.mjs +491 -0
- package/src/agent/orchestrator/smart-bridge/CACHE-SHARD.md +115 -0
- package/src/agent/orchestrator/smart-bridge/bridge-llm.mjs +327 -0
- package/src/agent/orchestrator/smart-bridge/cache-obs.mjs +150 -0
- package/src/agent/orchestrator/smart-bridge/cache-strategy.mjs +228 -0
- package/src/agent/orchestrator/smart-bridge/index.mjs +215 -0
- package/src/agent/orchestrator/smart-bridge/profiles.mjs +37 -0
- package/src/agent/orchestrator/smart-bridge/registry.mjs +348 -0
- package/src/agent/orchestrator/smart-bridge/session-builder.mjs +116 -0
- package/src/agent/orchestrator/stall-policy.mjs +195 -0
- package/src/agent/orchestrator/tool-loop-guard.mjs +75 -0
- package/src/agent/orchestrator/tools/bash-policy-scan.mjs +77 -0
- package/src/agent/orchestrator/tools/bash-session.mjs +721 -0
- package/src/agent/orchestrator/tools/builtin/advisory-lock.mjs +171 -0
- package/src/agent/orchestrator/tools/builtin/arg-guard.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/atomic-write.mjs +236 -0
- package/src/agent/orchestrator/tools/builtin/bash-tool.mjs +480 -0
- package/src/agent/orchestrator/tools/builtin/binary-file.mjs +76 -0
- package/src/agent/orchestrator/tools/builtin/builtin-tools.mjs +256 -0
- package/src/agent/orchestrator/tools/builtin/cache-layers.mjs +386 -0
- package/src/agent/orchestrator/tools/builtin/cwd-utils.mjs +37 -0
- package/src/agent/orchestrator/tools/builtin/device-paths.mjs +154 -0
- package/src/agent/orchestrator/tools/builtin/diagnostics-tool.mjs +292 -0
- package/src/agent/orchestrator/tools/builtin/diff-utils.mjs +109 -0
- package/src/agent/orchestrator/tools/builtin/edit-base-guard.mjs +58 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-plan.mjs +240 -0
- package/src/agent/orchestrator/tools/builtin/edit-byte-utils.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/edit-commit.mjs +74 -0
- package/src/agent/orchestrator/tools/builtin/edit-context-utils.mjs +242 -0
- package/src/agent/orchestrator/tools/builtin/edit-diagnostics.mjs +211 -0
- package/src/agent/orchestrator/tools/builtin/edit-engine.mjs +1364 -0
- package/src/agent/orchestrator/tools/builtin/edit-failure-context.mjs +126 -0
- package/src/agent/orchestrator/tools/builtin/edit-hint.mjs +141 -0
- package/src/agent/orchestrator/tools/builtin/edit-match-utils.mjs +194 -0
- package/src/agent/orchestrator/tools/builtin/edit-partial-write.mjs +60 -0
- package/src/agent/orchestrator/tools/builtin/edit-stale-refresh.mjs +168 -0
- package/src/agent/orchestrator/tools/builtin/edit-tool.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/edit-utf8-guard.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fs-reachability.mjs +48 -0
- package/src/agent/orchestrator/tools/builtin/fuzzy-match.mjs +99 -0
- package/src/agent/orchestrator/tools/builtin/glob-walk.mjs +170 -0
- package/src/agent/orchestrator/tools/builtin/grep-formatting.mjs +113 -0
- package/src/agent/orchestrator/tools/builtin/hash-utils.mjs +6 -0
- package/src/agent/orchestrator/tools/builtin/list-formatting.mjs +7 -0
- package/src/agent/orchestrator/tools/builtin/list-tool.mjs +593 -0
- package/src/agent/orchestrator/tools/builtin/native-edit-runner.mjs +89 -0
- package/src/agent/orchestrator/tools/builtin/notebook-edit-tool.mjs +300 -0
- package/src/agent/orchestrator/tools/builtin/open-config-tool.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/path-diagnostics.mjs +152 -0
- package/src/agent/orchestrator/tools/builtin/path-locks.mjs +35 -0
- package/src/agent/orchestrator/tools/builtin/path-utils.mjs +201 -0
- package/src/agent/orchestrator/tools/builtin/read-args.mjs +103 -0
- package/src/agent/orchestrator/tools/builtin/read-batch.mjs +172 -0
- package/src/agent/orchestrator/tools/builtin/read-constants.mjs +40 -0
- package/src/agent/orchestrator/tools/builtin/read-formatting.mjs +118 -0
- package/src/agent/orchestrator/tools/builtin/read-image-resize.mjs +189 -0
- package/src/agent/orchestrator/tools/builtin/read-image.mjs +88 -0
- package/src/agent/orchestrator/tools/builtin/read-lines.mjs +12 -0
- package/src/agent/orchestrator/tools/builtin/read-mode-tool.mjs +455 -0
- package/src/agent/orchestrator/tools/builtin/read-open.mjs +190 -0
- package/src/agent/orchestrator/tools/builtin/read-range-index.mjs +271 -0
- package/src/agent/orchestrator/tools/builtin/read-ranges.mjs +26 -0
- package/src/agent/orchestrator/tools/builtin/read-single-tool.mjs +728 -0
- package/src/agent/orchestrator/tools/builtin/read-snapshot-runtime.mjs +173 -0
- package/src/agent/orchestrator/tools/builtin/read-special-files.mjs +268 -0
- package/src/agent/orchestrator/tools/builtin/read-streaming.mjs +602 -0
- package/src/agent/orchestrator/tools/builtin/read-tool.mjs +530 -0
- package/src/agent/orchestrator/tools/builtin/read-windows.mjs +107 -0
- package/src/agent/orchestrator/tools/builtin/rename-tool.mjs +196 -0
- package/src/agent/orchestrator/tools/builtin/rg-runner.mjs +422 -0
- package/src/agent/orchestrator/tools/builtin/search-builders.mjs +158 -0
- package/src/agent/orchestrator/tools/builtin/search-tool.mjs +869 -0
- package/src/agent/orchestrator/tools/builtin/shell-analysis.mjs +653 -0
- package/src/agent/orchestrator/tools/builtin/shell-jobs.mjs +936 -0
- package/src/agent/orchestrator/tools/builtin/shell-output.mjs +36 -0
- package/src/agent/orchestrator/tools/builtin/shell-runtime.mjs +214 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-helpers.mjs +143 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-store.mjs +206 -0
- package/src/agent/orchestrator/tools/builtin/snapshot-validation.mjs +98 -0
- package/src/agent/orchestrator/tools/builtin/text-stats.mjs +69 -0
- package/src/agent/orchestrator/tools/builtin/windows-roots.mjs +23 -0
- package/src/agent/orchestrator/tools/builtin/write-tool.mjs +401 -0
- package/src/agent/orchestrator/tools/builtin.mjs +500 -0
- package/src/agent/orchestrator/tools/code-graph-prewarm-worker.mjs +39 -0
- package/src/agent/orchestrator/tools/code-graph-tool-defs.mjs +24 -0
- package/src/agent/orchestrator/tools/code-graph.mjs +4095 -0
- package/src/agent/orchestrator/tools/cwd-tool.mjs +298 -0
- package/src/agent/orchestrator/tools/destructive-warning.mjs +323 -0
- package/src/agent/orchestrator/tools/edit-normalize.mjs +603 -0
- package/src/agent/orchestrator/tools/env-scrub.mjs +100 -0
- package/src/agent/orchestrator/tools/graph-binary-fetcher.mjs +144 -0
- package/src/agent/orchestrator/tools/graph-manifest.json +26 -0
- package/src/agent/orchestrator/tools/host-input.mjs +204 -0
- package/src/agent/orchestrator/tools/mutation-content-cache.mjs +67 -0
- package/src/agent/orchestrator/tools/mutation-planner.mjs +75 -0
- package/src/agent/orchestrator/tools/next-call-utils.mjs +48 -0
- package/src/agent/orchestrator/tools/patch-binary-fetcher.mjs +133 -0
- package/src/agent/orchestrator/tools/patch-manifest.json +26 -0
- package/src/agent/orchestrator/tools/patch-tool-defs.mjs +20 -0
- package/src/agent/orchestrator/tools/patch.mjs +2754 -0
- package/src/agent/orchestrator/tools/progress-message.mjs +118 -0
- package/src/agent/orchestrator/tools/result-compression.mjs +279 -0
- package/src/agent/orchestrator/tools/shell-command.mjs +865 -0
- package/src/agent/orchestrator/tools/shell-exec-policy.mjs +89 -0
- package/src/agent/orchestrator/tools/shell-policy-danger-target.mjs +27 -0
- package/src/agent/orchestrator/tools/shell-policy-imports.mjs +7 -0
- package/src/agent/orchestrator/tools/shell-policy.mjs +345 -0
- package/src/agent/orchestrator/tools/shell-snapshot.mjs +313 -0
- package/src/agent/orchestrator/workflow-store.mjs +93 -0
- package/src/agent/tool-defs.mjs +103 -0
- package/src/channels/backends/discord.mjs +784 -0
- package/src/channels/data/voice-runtime-manifest.json +138 -0
- package/src/channels/index.mjs +3229 -0
- package/src/channels/lib/cli-worker-host.mjs +12 -0
- package/src/channels/lib/config-lock.mjs +13 -0
- package/src/channels/lib/config.mjs +292 -0
- package/src/channels/lib/drop-trace.mjs +71 -0
- package/src/channels/lib/event-pipeline.mjs +81 -0
- package/src/channels/lib/event-queue.mjs +345 -0
- package/src/channels/lib/executor.mjs +168 -0
- package/src/channels/lib/format.mjs +188 -0
- package/src/channels/lib/holidays.mjs +138 -0
- package/src/channels/lib/hook-pipe-server.mjs +802 -0
- package/src/channels/lib/interaction-workflows.mjs +184 -0
- package/src/channels/lib/memory-client.mjs +149 -0
- package/src/channels/lib/output-forwarder.mjs +765 -0
- package/src/channels/lib/runtime-paths.mjs +479 -0
- package/src/channels/lib/scheduler.mjs +723 -0
- package/src/channels/lib/session-control.mjs +36 -0
- package/src/channels/lib/session-discovery.mjs +103 -0
- package/src/channels/lib/settings.mjs +11 -0
- package/src/channels/lib/state-file.mjs +68 -0
- package/src/channels/lib/status-snapshot.mjs +219 -0
- package/src/channels/lib/tool-format.mjs +140 -0
- package/src/channels/lib/transcript-discovery.mjs +195 -0
- package/src/channels/lib/voice-runtime-fetcher.mjs +734 -0
- package/src/channels/lib/webhook.mjs +1179 -0
- package/src/channels/lib/whisper-server.mjs +477 -0
- package/src/channels/tool-defs.mjs +170 -0
- package/src/daemon/host.mjs +118 -0
- package/src/daemon/mcp-transport.mjs +47 -0
- package/src/daemon/session.mjs +100 -0
- package/src/daemon/thin-client.mjs +71 -0
- package/src/daemon/transport.mjs +163 -0
- package/src/memory/data/runtime-manifest.json +40 -0
- package/src/memory/index.mjs +3305 -0
- package/src/memory/lib/agent-ipc.mjs +93 -0
- package/src/memory/lib/bridge-trace-queries.mjs +120 -0
- package/src/memory/lib/core-memory-store.mjs +330 -0
- package/src/memory/lib/embedding-provider.mjs +269 -0
- package/src/memory/lib/embedding-worker.mjs +323 -0
- package/src/memory/lib/llm-worker-host.mjs +17 -0
- package/src/memory/lib/memory-cycle.mjs +11 -0
- package/src/memory/lib/memory-cycle1.mjs +641 -0
- package/src/memory/lib/memory-cycle2.mjs +1284 -0
- package/src/memory/lib/memory-cycle3.mjs +540 -0
- package/src/memory/lib/memory-embed.mjs +299 -0
- package/src/memory/lib/memory-extraction.mjs +5 -0
- package/src/memory/lib/memory-maintenance-store.mjs +32 -0
- package/src/memory/lib/memory-ops-policy.mjs +190 -0
- package/src/memory/lib/memory-recall-id-patch.mjs +15 -0
- package/src/memory/lib/memory-recall-read-query.mjs +7 -0
- package/src/memory/lib/memory-recall-scope-filter.mjs +63 -0
- package/src/memory/lib/memory-recall-store.mjs +621 -0
- package/src/memory/lib/memory-retrievers.mjs +112 -0
- package/src/memory/lib/memory-score.mjs +71 -0
- package/src/memory/lib/memory-text-utils.mjs +58 -0
- package/src/memory/lib/memory.mjs +412 -0
- package/src/memory/lib/model-profile.mjs +85 -0
- package/src/memory/lib/pg/adapter.mjs +308 -0
- package/src/memory/lib/pg/process.mjs +360 -0
- package/src/memory/lib/pg/supervisor.mjs +396 -0
- package/src/memory/lib/project-id-resolver.mjs +86 -0
- package/src/memory/lib/runtime-fetcher.mjs +442 -0
- package/src/memory/lib/trace-store.mjs +728 -0
- package/src/memory/tool-defs.mjs +79 -0
- package/src/search/index.mjs +1173 -0
- package/src/search/lib/backends/anthropic-oauth.mjs +98 -0
- package/src/search/lib/backends/exa.mjs +50 -0
- package/src/search/lib/backends/firecrawl.mjs +61 -0
- package/src/search/lib/backends/gemini-api.mjs +83 -0
- package/src/search/lib/backends/grok-oauth.mjs +86 -0
- package/src/search/lib/backends/index.mjs +150 -0
- package/src/search/lib/backends/openai-api.mjs +144 -0
- package/src/search/lib/backends/openai-oauth.mjs +98 -0
- package/src/search/lib/backends/openai-web-search.mjs +76 -0
- package/src/search/lib/backends/tavily.mjs +55 -0
- package/src/search/lib/backends/xai-api.mjs +113 -0
- package/src/search/lib/cache.mjs +131 -0
- package/src/search/lib/config.mjs +192 -0
- package/src/search/lib/formatter.mjs +115 -0
- package/src/search/lib/provider-usage.mjs +67 -0
- package/src/search/lib/providers.mjs +47 -0
- package/src/search/lib/search-intent.mjs +109 -0
- package/src/search/lib/setup-handler.mjs +261 -0
- package/src/search/lib/state.mjs +201 -0
- package/src/search/lib/web-tools.mjs +1207 -0
- package/src/search/tool-defs.mjs +83 -0
- package/src/setup/defender-exclusion.mjs +183 -0
- package/src/shared/abort-controller.mjs +15 -0
- package/src/shared/atomic-file.mjs +420 -0
- package/src/shared/config.mjs +350 -0
- package/src/shared/daemon-recycle.mjs +108 -0
- package/src/shared/disable-claude-builtins.mjs +88 -0
- package/src/shared/err-text.mjs +12 -0
- package/src/shared/llm/cost.mjs +66 -0
- package/src/shared/llm/http-agent.mjs +123 -0
- package/src/shared/llm/index.mjs +41 -0
- package/src/shared/llm/pid-cleanup.mjs +27 -0
- package/src/shared/llm/usage-log.mjs +47 -0
- package/src/shared/plugin-paths.mjs +58 -0
- package/src/shared/schedules-store.mjs +70 -0
- package/src/shared/seed.mjs +119 -0
- package/src/shared/user-cwd.mjs +213 -0
- package/src/shared/user-data-guard.mjs +238 -0
- package/src/status/aggregator.mjs +584 -0
- package/src/status/server.mjs +413 -0
- package/tools.json +1653 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
let pending = Promise.resolve();
|
|
2
|
+
function withConfigLock(fn) {
|
|
3
|
+
const next = pending.then(() => fn());
|
|
4
|
+
pending = next.then(() => {
|
|
5
|
+
}, (e) => {
|
|
6
|
+
process.stderr.write(`[config-lock] Error: ${e}
|
|
7
|
+
`);
|
|
8
|
+
});
|
|
9
|
+
return next;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
withConfigLock
|
|
13
|
+
};
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { readFileSync, mkdirSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { DiscordBackend } from "../backends/discord.mjs";
|
|
4
|
+
import { readSection, updateSection, CONFIG_PATH as MIXDOG_CONFIG_PATH, getDiscordToken, diagnoseDiscordTokenValue } from "../../shared/config.mjs";
|
|
5
|
+
import { listSchedules } from "../../shared/schedules-store.mjs";
|
|
6
|
+
import { isHolidaySync } from "./holidays.mjs";
|
|
7
|
+
if (!process.env.CLAUDE_PLUGIN_DATA) {
|
|
8
|
+
process.stderr.write(
|
|
9
|
+
"mixdog: CLAUDE_PLUGIN_DATA not set.\n This plugin must be run through Claude Code.\n"
|
|
10
|
+
);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const DATA_DIR = process.env.CLAUDE_PLUGIN_DATA;
|
|
14
|
+
const PLUGIN_ROOT = process.env.CLAUDE_PLUGIN_ROOT ?? new URL("..", import.meta.url).pathname;
|
|
15
|
+
const CONFIG_FILE = MIXDOG_CONFIG_PATH;
|
|
16
|
+
const DEFAULT_ACCESS = {
|
|
17
|
+
dmPolicy: "allowlist",
|
|
18
|
+
allowFrom: [],
|
|
19
|
+
channels: {}
|
|
20
|
+
};
|
|
21
|
+
const DEFAULT_CONFIG = {
|
|
22
|
+
backend: "discord",
|
|
23
|
+
discord: { token: "" },
|
|
24
|
+
access: DEFAULT_ACCESS,
|
|
25
|
+
mainChannel: "main",
|
|
26
|
+
channelsConfig: {
|
|
27
|
+
main: { channelId: "", mode: "interactive" }
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
// Shared defaults layer (DND / per-channel respectQuiet). Merge
|
|
31
|
+
// semantics: user values win; defaults only fill missing fields.
|
|
32
|
+
// Helper is exported so the setup UI and runtime both produce the same
|
|
33
|
+
// shape when the file has missing sections.
|
|
34
|
+
const CONFIG_DEFAULTS = {
|
|
35
|
+
quiet: { schedule: "23:00-09:00", holidays: false },
|
|
36
|
+
schedules: { respectQuiet: true },
|
|
37
|
+
webhook: { enabled: true, respectQuiet: false }
|
|
38
|
+
};
|
|
39
|
+
const DEFAULT_HOLIDAY_COUNTRY = "KR";
|
|
40
|
+
function normalizeHolidaySetting(value) {
|
|
41
|
+
if (value === true) return DEFAULT_HOLIDAY_COUNTRY;
|
|
42
|
+
if (typeof value === "string") {
|
|
43
|
+
const code = value.trim().toUpperCase();
|
|
44
|
+
return /^[A-Z]{2}$/.test(code) ? code : false;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
function applyDefaults(config) {
|
|
49
|
+
const out = { ...(config || {}) };
|
|
50
|
+
out.quiet = { ...CONFIG_DEFAULTS.quiet, ...(out.quiet || {}) };
|
|
51
|
+
out.quiet.holidays = normalizeHolidaySetting(out.quiet.holidays);
|
|
52
|
+
out.schedules = { ...CONFIG_DEFAULTS.schedules, ...(out.schedules || {}) };
|
|
53
|
+
out.webhook = { ...CONFIG_DEFAULTS.webhook, ...(out.webhook || {}) };
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Shared DND / quiet-window helper used by scheduler + webhook.
|
|
58
|
+
*
|
|
59
|
+
* Signature contract (as of 0.1.62):
|
|
60
|
+
* isInQuietWindow(cfg, now = new Date(), tz = null) -> boolean
|
|
61
|
+
*
|
|
62
|
+
* `cfg` accepts exactly two shapes (top-level config with `.quiet`
|
|
63
|
+
* subtree, or a flat `{ schedule, holidays }` descriptor); anything
|
|
64
|
+
* else returns `false`.
|
|
65
|
+
*
|
|
66
|
+
* `tz` is an optional IANA timezone. When set, both the schedule
|
|
67
|
+
* window (HH:MM) and the holiday/weekend day are evaluated in that
|
|
68
|
+
* zone; when absent, the host's local timezone is used (unchanged
|
|
69
|
+
* behavior for callers that omit it, e.g. webhook.mjs).
|
|
70
|
+
*
|
|
71
|
+
* Behavior:
|
|
72
|
+
* - Schedule window uses "HH:MM-HH:MM". Midnight-crossing windows
|
|
73
|
+
* (start > end, e.g. "23:00-09:00") are honored. When start === end
|
|
74
|
+
* the window is treated as empty/never (preserved doc-ambiguous
|
|
75
|
+
* behavior — callers should avoid that shape).
|
|
76
|
+
* - `holidays` enabled AND today is a recognized holiday => true,
|
|
77
|
+
* regardless of schedule window.
|
|
78
|
+
* - `holidays === false` or missing => holidays ignored.
|
|
79
|
+
*
|
|
80
|
+
* Holiday detection strategy (0.1.63):
|
|
81
|
+
* Sync, non-blocking lookup via holidays.mjs `isHolidaySync`, backed
|
|
82
|
+
* by a pre-warmed in-memory cache (Nager-sourced). The `holidays`
|
|
83
|
+
* value doubles as the ISO country code (`true` => default country).
|
|
84
|
+
* - cache WARM => real public-holiday data (weekday holidays count).
|
|
85
|
+
* - cache COLD => documented fallback: weekend-only (Sat/Sun), while
|
|
86
|
+
* an async warm is kicked off for the next evaluation. No blocking
|
|
87
|
+
* I/O and no heuristics beyond this weekend fallback.
|
|
88
|
+
*
|
|
89
|
+
* Exported so scheduler.mjs and webhook.mjs can share one implementation.
|
|
90
|
+
*/
|
|
91
|
+
// Day-of-week and HH:MM for `now`, in `tz` when given, else host-local.
|
|
92
|
+
// An invalid IANA `tz` makes `Intl.DateTimeFormat` throw a RangeError;
|
|
93
|
+
// we catch it once and fall back to host-local rather than propagating.
|
|
94
|
+
function quietDayTime(now, tz) {
|
|
95
|
+
if (tz) {
|
|
96
|
+
try {
|
|
97
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
98
|
+
hour12: false, timeZone: tz,
|
|
99
|
+
hour: "2-digit", minute: "2-digit", weekday: "short",
|
|
100
|
+
}).formatToParts(now).reduce((acc, p) => { acc[p.type] = p.value; return acc; }, {});
|
|
101
|
+
const hour = parts.hour === "24" ? "00" : parts.hour;
|
|
102
|
+
const dowMap = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
|
|
103
|
+
return {
|
|
104
|
+
dow: dowMap[parts.weekday] ?? now.getDay(),
|
|
105
|
+
hhmm: `${hour}:${parts.minute}`,
|
|
106
|
+
};
|
|
107
|
+
} catch {
|
|
108
|
+
// Invalid timezone — fall through to host-local.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
dow: now.getDay(),
|
|
113
|
+
hhmm: `${String(now.getHours()).padStart(2, "0")}:${String(now.getMinutes()).padStart(2, "0")}`,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Return the target calendar day as a plain 'YYYY-MM-DD' string, in `tz`
|
|
117
|
+
// when given (else host-local). A string (not a Date) keeps the holiday
|
|
118
|
+
// contract symmetric: isHolidaySync compares the same string, so there
|
|
119
|
+
// is no UTC<->local round-trip to shift the day on UTC+12..+14 hosts.
|
|
120
|
+
// An invalid IANA `tz` throws a RangeError; catch once, fall to local.
|
|
121
|
+
function quietHolidayDateStr(now, tz) {
|
|
122
|
+
if (tz) {
|
|
123
|
+
try {
|
|
124
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
125
|
+
timeZone: tz, year: "numeric", month: "2-digit", day: "2-digit",
|
|
126
|
+
}).formatToParts(now).reduce((acc, p) => { acc[p.type] = p.value; return acc; }, {});
|
|
127
|
+
return `${parts.year}-${parts.month}-${parts.day}`;
|
|
128
|
+
} catch {
|
|
129
|
+
// Invalid timezone — fall through to host-local.
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
|
|
133
|
+
}
|
|
134
|
+
function isInQuietWindow(cfg, now = new Date(), tz = null) {
|
|
135
|
+
if (!cfg || typeof cfg !== "object") return false;
|
|
136
|
+
// Auto-detect shape: prefer cfg.quiet when present, else treat cfg as
|
|
137
|
+
// the flat { schedule, holidays } descriptor.
|
|
138
|
+
const quiet = cfg.quiet && typeof cfg.quiet === "object" ? cfg.quiet : cfg;
|
|
139
|
+
const schedule = quiet.schedule;
|
|
140
|
+
const holidaysOn = quiet.holidays === true || (typeof quiet.holidays === "string" && !!quiet.holidays.trim());
|
|
141
|
+
const country = quiet.holidays === true
|
|
142
|
+
? DEFAULT_HOLIDAY_COUNTRY
|
|
143
|
+
: (typeof quiet.holidays === "string" ? quiet.holidays.trim().toUpperCase() : null);
|
|
144
|
+
|
|
145
|
+
// Holiday branch: toggle on AND today qualifies => quiet regardless of window.
|
|
146
|
+
// Sync, pre-warmed cache lookup; cold cache falls back to weekend-only.
|
|
147
|
+
if (holidaysOn) {
|
|
148
|
+
const holiday = isHolidaySync(quietHolidayDateStr(now, tz), country);
|
|
149
|
+
if (holiday === true) return true;
|
|
150
|
+
if (holiday === null) {
|
|
151
|
+
// Cold cache: documented Sat/Sun fallback until the async warm lands.
|
|
152
|
+
const { dow } = quietDayTime(now, tz);
|
|
153
|
+
if (dow === 0 || dow === 6) return true;
|
|
154
|
+
}
|
|
155
|
+
// Warm cache + not a holiday: fall through to the schedule window.
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Schedule window check (TZ-aware when tz is set; host-local otherwise).
|
|
159
|
+
if (!schedule || typeof schedule !== "string") return false;
|
|
160
|
+
const parts = schedule.split("-");
|
|
161
|
+
if (parts.length !== 2) return false;
|
|
162
|
+
const [start, end] = parts;
|
|
163
|
+
// start === end => empty window (never matches); documented caveat.
|
|
164
|
+
const { hhmm } = quietDayTime(now, tz);
|
|
165
|
+
if (start > end) return hhmm >= start || hhmm < end; // midnight-crossing
|
|
166
|
+
return hhmm >= start && hhmm < end;
|
|
167
|
+
}
|
|
168
|
+
function loadConfig() {
|
|
169
|
+
try {
|
|
170
|
+
let raw = readSection("channels");
|
|
171
|
+
raw = raw && typeof raw === "object" ? raw : {};
|
|
172
|
+
// Schedules live in `${CLAUDE_PLUGIN_DATA}/schedules/<name>/` (single
|
|
173
|
+
// source of truth). The legacy `raw.schedules.items` / `raw.nonInteractive`
|
|
174
|
+
// / `raw.interactive` arrays in mixdog-config.json are no longer read.
|
|
175
|
+
const scheduleEntries = listSchedules().filter((s) => s.enabled !== false);
|
|
176
|
+
// Channel-presence routing (no `type` field): an entry WITH a channel is
|
|
177
|
+
// dispatched directly to that channel; an entry WITHOUT a channel is
|
|
178
|
+
// injected into the current (Lead) session. Mirrors the webhook model.
|
|
179
|
+
raw.nonInteractive = scheduleEntries.filter((i) => !!i.channel);
|
|
180
|
+
raw.interactive = scheduleEntries.filter((i) => !i.channel);
|
|
181
|
+
const accessChannels = { ...raw.access?.channels ?? {} };
|
|
182
|
+
// voice config lives at the top level of mixdog-config.json (peer of
|
|
183
|
+
// channels), so readSection("channels") never sees it. Pull it explicitly.
|
|
184
|
+
let voice = {};
|
|
185
|
+
try {
|
|
186
|
+
const v = readSection("voice");
|
|
187
|
+
if (v && typeof v === "object") voice = v;
|
|
188
|
+
} catch { /* missing section is fine */ }
|
|
189
|
+
const discordToken = getDiscordToken();
|
|
190
|
+
const discordTokenProblem = diagnoseDiscordTokenValue(discordToken, raw);
|
|
191
|
+
if (discordTokenProblem) {
|
|
192
|
+
process.stderr.write(`mixdog: discord token ignored: ${discordTokenProblem}\n`);
|
|
193
|
+
}
|
|
194
|
+
return applyDefaults({
|
|
195
|
+
...DEFAULT_CONFIG,
|
|
196
|
+
...raw,
|
|
197
|
+
backend: "discord",
|
|
198
|
+
discord: { ...DEFAULT_CONFIG.discord, ...(({ token: _, ...rest }) => rest)(raw.discord || {}), ...(discordToken && !discordTokenProblem ? { token: discordToken } : {}) },
|
|
199
|
+
access: {
|
|
200
|
+
...DEFAULT_ACCESS,
|
|
201
|
+
// Drop the retired pairing-era keys at the config layer too (the
|
|
202
|
+
// Discord backend's normalizeAccess() is the runtime belt): legacy
|
|
203
|
+
// dmPolicy "pairing" → "allowlist", and the `pending` code store is
|
|
204
|
+
// gone entirely.
|
|
205
|
+
...(({ pending: _pending, ...rest }) => rest)(raw.access || {}),
|
|
206
|
+
...(raw.access?.dmPolicy === "pairing" ? { dmPolicy: "allowlist" } : {}),
|
|
207
|
+
channels: accessChannels,
|
|
208
|
+
},
|
|
209
|
+
voice: { ...(raw.voice || {}), ...voice }
|
|
210
|
+
});
|
|
211
|
+
} catch (err) {
|
|
212
|
+
if (err.code === "ENOENT") {
|
|
213
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
214
|
+
updateSection("channels", () => DEFAULT_CONFIG);
|
|
215
|
+
process.stderr.write(
|
|
216
|
+
`mixdog: default channels config created in ${MIXDOG_CONFIG_PATH}
|
|
217
|
+
edit discord.token and channelsConfig.main.channelId to connect.
|
|
218
|
+
`
|
|
219
|
+
);
|
|
220
|
+
return applyDefaults(DEFAULT_CONFIG);
|
|
221
|
+
}
|
|
222
|
+
throw err;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const HEADLESS_BACKEND = {
|
|
226
|
+
name: "headless",
|
|
227
|
+
async connect() {
|
|
228
|
+
},
|
|
229
|
+
async disconnect() {
|
|
230
|
+
},
|
|
231
|
+
async sendMessage() {
|
|
232
|
+
return { sentIds: [] };
|
|
233
|
+
},
|
|
234
|
+
async fetchMessages() {
|
|
235
|
+
return [];
|
|
236
|
+
},
|
|
237
|
+
async react() {
|
|
238
|
+
},
|
|
239
|
+
async removeReaction() {
|
|
240
|
+
},
|
|
241
|
+
async editMessage() {
|
|
242
|
+
return "";
|
|
243
|
+
},
|
|
244
|
+
async deleteMessage() {
|
|
245
|
+
},
|
|
246
|
+
async downloadAttachment() {
|
|
247
|
+
return Buffer.alloc(0);
|
|
248
|
+
},
|
|
249
|
+
on() {
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
function createBackend(config) {
|
|
253
|
+
const discordToken = getDiscordToken();
|
|
254
|
+
const discordTokenProblem = diagnoseDiscordTokenValue(discordToken, config);
|
|
255
|
+
if (discordTokenProblem) {
|
|
256
|
+
process.stderr.write(`mixdog: discord token ignored: ${discordTokenProblem}\n`);
|
|
257
|
+
}
|
|
258
|
+
if (config.backend !== "discord" || !discordToken || discordTokenProblem) {
|
|
259
|
+
process.stderr.write("mixdog: discord bot not configured; channel worker running in headless mode\n");
|
|
260
|
+
return HEADLESS_BACKEND;
|
|
261
|
+
}
|
|
262
|
+
const stateDir = config.discord.stateDir ?? join(DATA_DIR, "discord");
|
|
263
|
+
mkdirSync(stateDir, { recursive: true });
|
|
264
|
+
return new DiscordBackend({
|
|
265
|
+
...config.discord,
|
|
266
|
+
configPath: CONFIG_FILE,
|
|
267
|
+
access: config.access,
|
|
268
|
+
// Single-source channel setup: the main channel is auto-allowed inside
|
|
269
|
+
// DiscordBackend.loadAccess() so a configured channelsConfig.main.channelId
|
|
270
|
+
// is enough for both inbound and outbound — no separate access.channels entry.
|
|
271
|
+
mainChannelId: config.channelsConfig?.main?.channelId
|
|
272
|
+
}, stateDir);
|
|
273
|
+
}
|
|
274
|
+
const PROFILE_FILE = join(DATA_DIR, "profile.json");
|
|
275
|
+
function loadProfileConfig() {
|
|
276
|
+
try {
|
|
277
|
+
return JSON.parse(readFileSync(PROFILE_FILE, "utf8"));
|
|
278
|
+
} catch {
|
|
279
|
+
return {};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
DATA_DIR,
|
|
284
|
+
DEFAULT_HOLIDAY_COUNTRY,
|
|
285
|
+
PLUGIN_ROOT,
|
|
286
|
+
applyDefaults,
|
|
287
|
+
createBackend,
|
|
288
|
+
getDiscordToken,
|
|
289
|
+
isInQuietWindow,
|
|
290
|
+
loadConfig,
|
|
291
|
+
loadProfileConfig
|
|
292
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { statSync, renameSync, createWriteStream } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir } from "os";
|
|
4
|
+
// ── drop-trace (output-forwarder) ───────────────────────────────────────────
|
|
5
|
+
const _dtDataDir = process.env.CLAUDE_PLUGIN_DATA || join(homedir(), ".mixdog-data");
|
|
6
|
+
const _dtLog = join(_dtDataDir, "drop-trace.log");
|
|
7
|
+
const DROP_TRACE_ENABLED =
|
|
8
|
+
process.env.MIXDOG_DROP_TRACE === "1" ||
|
|
9
|
+
process.env.MIXDOG_DROP_TRACE === "true" ||
|
|
10
|
+
process.env.MIXDOG_DEBUG_CHANNELS === "1" ||
|
|
11
|
+
process.env.MIXDOG_DEBUG_CHANNELS === "true";
|
|
12
|
+
// One-shot rotation at module init (10 MB threshold, .1 suffix overwrite).
|
|
13
|
+
if (DROP_TRACE_ENABLED) {
|
|
14
|
+
try { if (statSync(_dtLog).size > 10 * 1024 * 1024) renameSync(_dtLog, _dtLog + '.1') } catch {}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ── Buffered drop-trace writer ───────────────────────────────────────────────
|
|
18
|
+
// Flushes every 1 s OR when the buffer reaches 64 KB — whichever fires first.
|
|
19
|
+
// Drains synchronously on process exit so no log lines are lost.
|
|
20
|
+
let _dtBuf = "";
|
|
21
|
+
let _dtBufBytes = 0;
|
|
22
|
+
let _dtFlushTimer = null;
|
|
23
|
+
let _dtStream = null;
|
|
24
|
+
function _dtGetStream() {
|
|
25
|
+
if (!_dtStream) _dtStream = createWriteStream(_dtLog, { flags: "a" });
|
|
26
|
+
return _dtStream;
|
|
27
|
+
}
|
|
28
|
+
function _dtFlush() {
|
|
29
|
+
if (_dtFlushTimer) { clearTimeout(_dtFlushTimer); _dtFlushTimer = null; }
|
|
30
|
+
if (!_dtBuf) return;
|
|
31
|
+
try { _dtGetStream().write(_dtBuf); } catch {}
|
|
32
|
+
_dtBuf = "";
|
|
33
|
+
_dtBufBytes = 0;
|
|
34
|
+
}
|
|
35
|
+
function _dtScheduleFlush() {
|
|
36
|
+
if (_dtFlushTimer) return;
|
|
37
|
+
_dtFlushTimer = setTimeout(_dtFlush, 1000);
|
|
38
|
+
if (_dtFlushTimer.unref) _dtFlushTimer.unref();
|
|
39
|
+
}
|
|
40
|
+
function _dtAppend(line) {
|
|
41
|
+
_dtBuf += line;
|
|
42
|
+
_dtBufBytes += Buffer.byteLength(line);
|
|
43
|
+
if (_dtBufBytes >= 65536) { _dtFlush(); return; }
|
|
44
|
+
_dtScheduleFlush();
|
|
45
|
+
}
|
|
46
|
+
process.on("exit", _dtFlush);
|
|
47
|
+
// Note: do not install a module-level SIGTERM handler that calls
|
|
48
|
+
// process.exit() here. The channels worker owns shutdown sequencing
|
|
49
|
+
// (forwarder drain, queue persist, etc.) and a library-level exit(0)
|
|
50
|
+
// preempts that drain. The `exit` listener above still synchronously
|
|
51
|
+
// flushes buffered trace bytes when the worker exits on its own terms.
|
|
52
|
+
|
|
53
|
+
function _dtPreview(text) {
|
|
54
|
+
if (!text) return "";
|
|
55
|
+
const s = String(text).slice(0, 121).replace(/\n/g, "\\n");
|
|
56
|
+
return s.length > 120 ? s.slice(0, 120) + "…" : s;
|
|
57
|
+
}
|
|
58
|
+
function dropTrace(event, fields) {
|
|
59
|
+
if (!DROP_TRACE_ENABLED) return;
|
|
60
|
+
try {
|
|
61
|
+
const ts = new Date().toISOString();
|
|
62
|
+
if (!fields) {
|
|
63
|
+
_dtAppend(`[${ts}][pid=${process.pid}] ${event}\n`);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const kv = " " + Object.entries(fields).map(([k, v]) => `${k}=${v}`).join(" ");
|
|
67
|
+
_dtAppend(`[${ts}][pid=${process.pid}] ${event}${kv}\n`);
|
|
68
|
+
} catch {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { dropTrace, _dtPreview, DROP_TRACE_ENABLED };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { EventQueue } from "./event-queue.mjs";
|
|
2
|
+
import { applyParser, evaluateFilter, applyTemplate, logEvent } from "./executor.mjs";
|
|
3
|
+
class EventPipeline {
|
|
4
|
+
rules;
|
|
5
|
+
queue;
|
|
6
|
+
constructor(config, channelsConfig) {
|
|
7
|
+
const rawRules = config?.rules;
|
|
8
|
+
this.rules = (Array.isArray(rawRules) ? rawRules : [])
|
|
9
|
+
.filter((r) => r && typeof r === "object" && r.enabled !== false);
|
|
10
|
+
this.queue = new EventQueue(config?.queue, channelsConfig);
|
|
11
|
+
}
|
|
12
|
+
getQueue() {
|
|
13
|
+
return this.queue;
|
|
14
|
+
}
|
|
15
|
+
start() {
|
|
16
|
+
this.queue.start();
|
|
17
|
+
}
|
|
18
|
+
stop() {
|
|
19
|
+
this.queue.stop();
|
|
20
|
+
}
|
|
21
|
+
reloadConfig(config, channelsConfig) {
|
|
22
|
+
const rawRules = config?.rules;
|
|
23
|
+
this.rules = (Array.isArray(rawRules) ? rawRules : [])
|
|
24
|
+
.filter((r) => r && typeof r === "object" && r.enabled !== false);
|
|
25
|
+
this.queue.reloadConfig(config?.queue, channelsConfig);
|
|
26
|
+
}
|
|
27
|
+
// ── Source: webhook ───────────────────────────────────────────────
|
|
28
|
+
/** Handle an incoming webhook event */
|
|
29
|
+
handleWebhook(endpointName, body, headers) {
|
|
30
|
+
const rule = this.rules.find((r) => r.source === "webhook" && r.name === endpointName);
|
|
31
|
+
if (!rule) return false;
|
|
32
|
+
const data = applyParser(rule.parser, body, headers);
|
|
33
|
+
if (rule.filter && !evaluateFilter(rule.filter, data)) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
const prompt = applyTemplate(rule.execute, data);
|
|
37
|
+
this.enqueue(rule, prompt);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// ── Direct enqueue (folder-based webhooks) ─────────────────────────
|
|
41
|
+
enqueueDirect(name, prompt, channel, exec = "interactive", instruction) {
|
|
42
|
+
const item = {
|
|
43
|
+
name,
|
|
44
|
+
source: "webhook",
|
|
45
|
+
priority: "normal",
|
|
46
|
+
prompt,
|
|
47
|
+
instruction,
|
|
48
|
+
exec,
|
|
49
|
+
channel,
|
|
50
|
+
timestamp: Date.now()
|
|
51
|
+
};
|
|
52
|
+
this.queue.enqueue(item);
|
|
53
|
+
}
|
|
54
|
+
// ── Common enqueue ────────────────────────────────────────────────
|
|
55
|
+
enqueue(rule, prompt) {
|
|
56
|
+
const item = {
|
|
57
|
+
name: rule.name,
|
|
58
|
+
source: rule.source,
|
|
59
|
+
priority: rule.priority,
|
|
60
|
+
prompt,
|
|
61
|
+
exec: rule.exec,
|
|
62
|
+
channel: rule.channel,
|
|
63
|
+
script: rule.script,
|
|
64
|
+
timestamp: Date.now()
|
|
65
|
+
};
|
|
66
|
+
this.queue.enqueue(item);
|
|
67
|
+
}
|
|
68
|
+
// ── Status ────────────────────────────────────────────────────────
|
|
69
|
+
getRules() {
|
|
70
|
+
return this.rules;
|
|
71
|
+
}
|
|
72
|
+
getStatus() {
|
|
73
|
+
return {
|
|
74
|
+
rules: this.rules.length,
|
|
75
|
+
queue: this.queue.getStatus()
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export {
|
|
80
|
+
EventPipeline
|
|
81
|
+
};
|