blun-king-cli 9.1.587 → 9.1.588
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 +11 -185
- package/LIESMICH.txt +51 -13
- package/README.md +44 -47
- package/agent-spine-plugin/.codex-plugin/plugin.json +16 -4
- package/agent-spine-plugin/CHANGELOG.md +37 -5
- package/agent-spine-plugin/README.md +3 -3
- package/agent-spine-plugin/blun.plugin.json +45 -10
- package/agent-spine-plugin/docs/artifact-evaluation.md +93 -0
- package/agent-spine-plugin/docs/host-integration.md +42 -27
- package/agent-spine-plugin/docs/preflight-recall.md +4 -2
- package/agent-spine-plugin/docs/session-timeline.md +97 -236
- package/agent-spine-plugin/docs/world-model.md +25 -0
- package/agent-spine-plugin/hooks/codex.json +1 -1
- package/agent-spine-plugin/hooks/hooks.json +1 -1
- package/agent-spine-plugin/package.json +1 -3
- package/agent-spine-plugin/scripts/check-hosts.js +3 -3
- package/agent-spine-plugin/scripts/release-check.js +10 -5
- package/agent-spine-plugin/scripts/run-checks.js +4 -1
- package/agent-spine-plugin/scripts/run-tests-hermetic.js +32 -6
- package/agent-spine-plugin/src/cli-learning.js +15 -0
- package/agent-spine-plugin/src/cli.js +2 -0
- package/agent-spine-plugin/src/hook.js +32 -32
- package/agent-spine-plugin/src/lib/action-lesson-recall.js +73 -8
- package/agent-spine-plugin/src/lib/briefing.js +146 -36
- package/agent-spine-plugin/src/lib/channel-continuity.js +19 -0
- package/agent-spine-plugin/src/lib/delivery-agent-usage.js +14 -7
- package/agent-spine-plugin/src/lib/gateway-group-response.js +128 -0
- package/agent-spine-plugin/src/lib/gateway-runs.js +24 -15
- package/agent-spine-plugin/src/lib/hook-briefing-use.js +13 -3
- package/agent-spine-plugin/src/lib/hook-context.js +16 -3
- package/agent-spine-plugin/src/lib/hook-output.js +129 -5
- package/agent-spine-plugin/src/lib/hook-timeline.js +5 -3
- package/agent-spine-plugin/src/lib/indexed-memory.js +2 -2
- package/agent-spine-plugin/src/lib/learning-artifact-evaluator.js +114 -0
- package/agent-spine-plugin/src/lib/learning-context.js +11 -4
- package/agent-spine-plugin/src/lib/learning-measurements.js +2 -2
- package/agent-spine-plugin/src/lib/mcp-runtime.js +89 -3
- package/agent-spine-plugin/src/lib/mcp-source-context.js +12 -2
- package/agent-spine-plugin/src/lib/mcp-timeline-tools.js +91 -8
- package/agent-spine-plugin/src/lib/mcp-world-tools.js +2 -2
- package/agent-spine-plugin/src/lib/owned-file-lock.js +20 -1
- package/agent-spine-plugin/src/lib/persona-runtime.js +2 -2
- package/agent-spine-plugin/src/lib/preflight-delivery-id.js +27 -0
- package/agent-spine-plugin/src/lib/preflight.js +4 -4
- package/agent-spine-plugin/src/lib/session-timeline-codex.js +15 -0
- package/agent-spine-plugin/src/lib/session-timeline-contract.js +12 -4
- package/agent-spine-plugin/src/lib/session-timeline-event-extract.js +36 -7
- package/agent-spine-plugin/src/lib/session-timeline-host-origin.js +13 -10
- package/agent-spine-plugin/src/lib/session-timeline-invocation.js +1 -1
- package/agent-spine-plugin/src/lib/session-timeline-king.js +14 -0
- package/agent-spine-plugin/src/lib/session-timeline-prior.js +18 -12
- package/agent-spine-plugin/src/lib/session-timeline-provider.js +5 -0
- package/agent-spine-plugin/src/lib/session-timeline-query.js +2 -0
- package/agent-spine-plugin/src/lib/session-timeline-results.js +35 -10
- package/agent-spine-plugin/src/lib/session-timeline-source-open.js +30 -0
- package/agent-spine-plugin/src/lib/session-timeline.js +122 -75
- package/agent-spine-plugin/src/lib/source-roots.js +3 -2
- package/agent-spine-plugin/src/lib/task-knowledge-context.js +22 -1
- package/agent-spine-plugin/src/lib/timeline-continuation-update.js +100 -0
- package/agent-spine-plugin/src/lib/timeline-tool-guard.js +30 -7
- package/agent-spine-plugin/src/lib/timeline-user-feedback.js +217 -0
- package/agent-spine-plugin/src/lib/timeline-world-capture.js +233 -0
- package/agent-spine-plugin/src/lib/world-knowledge.js +59 -2
- package/agent-spine-plugin/src/lib/world-model.js +64 -9
- package/agent-spine-plugin/src/worker.js +13 -1
- package/bin/blun.js +43 -28
- package/bin/core-bootstrap.js +5 -4
- package/bin/king.js +43 -28
- package/bin/launcher-mode.js +1 -10
- package/bin/launcher-runtime.js +128 -295
- package/bin/managed-node.js +0 -0
- package/bin/managed-plugin-selection.cjs +0 -1
- package/bin/native-module-repair.js +0 -0
- package/bin/node-runtime.js +0 -0
- package/bin/node-version.js +0 -0
- package/bin/plugin-bootstrap.js +56 -120
- package/bin/private-paths.js +11 -34
- package/bin/standard-tools-bootstrap.js +34 -114
- package/bin/turn-thinking-policy.cjs +3 -11
- package/bin/update-copy.js +200 -0
- package/bin/update-lease.js +0 -0
- package/bin/update-notice.js +136 -289
- package/bin/verify-agent-behavior.cjs +122 -0
- package/bin/verify-agent-components.cjs +104 -0
- package/bin/verify-bundled-agent-sources.cjs +57 -0
- package/blun.mjs +143076 -135288
- package/bundled-agent-sources.json +701 -0
- package/package.json +12 -15
- package/standard-skills/translate-native/README.md +1293 -0
- package/standard-skills/translate-native/SKILL.md +172 -22
- package/standard-skills/translate-native/VERSION +1 -1
- package/standard-skills/translate-native/agents/openai.yaml +18 -0
- package/standard-skills/translate-native/assets/icon.svg +8 -0
- package/standard-skills/translate-native/docs/BLUN_CODE_INTEGRATION.md +76 -0
- package/standard-skills/translate-native/docs/PREMORTEM.md +489 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION.md +2035 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_API.md +1302 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_EVIDENCE_HTTP.md +136 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HEALTH_HTTP.md +130 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_HTTP_PROVIDER.md +175 -0
- package/standard-skills/translate-native/docs/WEBSITE_LOCALIZATION_RECEIPT_VERIFIER_HTTP.md +86 -0
- package/standard-skills/translate-native/integrations/AGENT_RULES.md +32 -0
- package/standard-skills/translate-native/integrations/adapters/blun-code-language-guard.js +514 -0
- package/standard-skills/translate-native/integrations/adapters/node-language-guard.js +230 -0
- package/standard-skills/translate-native/integrations/audit_log.py +327 -0
- package/standard-skills/translate-native/integrations/claude_language_hook.js +1536 -0
- package/standard-skills/translate-native/integrations/commercial_localization_profile.py +42 -0
- package/standard-skills/translate-native/integrations/delivery-policy.example.json +28 -0
- package/standard-skills/translate-native/integrations/enforced_delivery.py +543 -0
- package/standard-skills/translate-native/integrations/guard_service.py +435 -0
- package/standard-skills/translate-native/integrations/language_gateway.py +67 -0
- package/standard-skills/translate-native/integrations/mcp_auth_headers.py +198 -0
- package/standard-skills/translate-native/integrations/mcp_http_gateway.py +429 -0
- package/standard-skills/translate-native/integrations/non_language_html_entities.js +1485 -0
- package/standard-skills/translate-native/integrations/pre_output_guard.py +65 -0
- package/standard-skills/translate-native/integrations/task_router.py +101 -0
- package/standard-skills/translate-native/integrations/website_localization.py +401 -0
- package/standard-skills/translate-native/integrations/website_localization_api.py +581 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark.py +1885 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_campaign.py +1772 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_candidate.py +506 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_http.py +400 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_review_store.py +781 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_reviewer_http.py +500 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_runtime.py +1107 -0
- package/standard-skills/translate-native/integrations/website_localization_benchmark_suite.py +463 -0
- package/standard-skills/translate-native/integrations/website_localization_cms.py +2835 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_client.py +875 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_dispatch.py +805 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_http.py +588 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_lifecycle_monitor.py +991 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver.py +1441 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_runtime.py +414 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_receiver_store.py +1073 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_removal_dispatch.py +865 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_client.py +583 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery.py +964 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_delivery_runtime.py +665 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_http.py +1153 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_runtime.py +675 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_source_service.py +1125 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification.py +674 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_http.py +444 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver.py +1469 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_notification_receiver_runtime.py +1142 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_processing_monitor.py +634 -0
- package/standard-skills/translate-native/integrations/website_localization_cms_terminal_receiver_client.py +804 -0
- package/standard-skills/translate-native/integrations/website_localization_deepl_baseline.py +922 -0
- package/standard-skills/translate-native/integrations/website_localization_evidence_http.py +482 -0
- package/standard-skills/translate-native/integrations/website_localization_health.py +1541 -0
- package/standard-skills/translate-native/integrations/website_localization_health_http.py +372 -0
- package/standard-skills/translate-native/integrations/website_localization_http_provider.py +297 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_http.py +479 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_intake.py +363 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_queue.py +1449 -0
- package/standard-skills/translate-native/integrations/website_localization_native_reference_store.py +420 -0
- package/standard-skills/translate-native/integrations/website_localization_quality_profiles.py +235 -0
- package/standard-skills/translate-native/integrations/website_localization_queue.py +671 -0
- package/standard-skills/translate-native/integrations/website_localization_receipt_verifier_http.py +516 -0
- package/standard-skills/translate-native/integrations/website_localization_release.py +928 -0
- package/standard-skills/translate-native/integrations/website_localization_release_coordinator.py +1008 -0
- package/standard-skills/translate-native/integrations/website_localization_runner.py +276 -0
- package/standard-skills/translate-native/integrations/website_localization_runtime.py +862 -0
- package/standard-skills/translate-native/integrations/website_localization_service.py +350 -0
- package/standard-skills/translate-native/integrations/website_localization_supervisor.py +511 -0
- package/standard-skills/translate-native/integrations/website_localization_worker.py +663 -0
- package/standard-skills/translate-native/provenance.json +3 -4
- package/standard-skills/translate-native/references/commercial-localization.md +177 -0
- package/standard-skills/translate-native/scripts/blun_language_guard.py +7 -1
- package/standard-skills/translate-native/scripts/check_commercial_review.py +80 -0
- package/standard-skills/translate-native/scripts/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/LICENSE +21 -0
- package/standard-tools/language-guard/VERSION +1 -0
- package/standard-tools/language-guard/blun_language_guard.py +7 -1
- package/standard-tools/language-guard/check_commercial_review.py +80 -0
- package/standard-tools/language-guard/commercial_localization_profile.py +333 -0
- package/standard-tools/language-guard/language_gateway.py +62 -0
- package/standard-tools/language-guard/pre_output_guard.py +64 -0
- package/standard-tools/language-guard/provenance.json +4 -11
- package/standard-tools/manifest.json +34 -11
- package/telegram-plugin/commands/access.md +2 -10
- package/telegram-plugin/dist/bridge.mjs +64041 -687
- package/telegram-plugin/dist/mcp-server.mjs +72810 -9027
- package/telegram-plugin/dist/noise.mjs +28 -63511
- package/agent-spine-plugin/CONTRIBUTING.md +0 -52
- package/agent-spine-plugin/SECURITY.md +0 -47
- package/agent-spine-plugin/docs/assignment-continuation.md +0 -48
- package/agent-spine-plugin/docs/releasing.md +0 -85
- package/agent-spine-plugin/docs/structured-completion.md +0 -67
- package/bin/abort-listener-policy.cjs +0 -43
- package/bin/active-steer-priority-policy.cjs +0 -24
- package/bin/agent-api-http-adapter.mjs +0 -446
- package/bin/agent-api-private-http-server.mjs +0 -288
- package/bin/agent-api-runtime.mjs +0 -252
- package/bin/agent-api-service-environment.mjs +0 -236
- package/bin/agent-api-service-host.mjs +0 -209
- package/bin/agent-api-service-process.mjs +0 -171
- package/bin/agent-api-session-registry.mjs +0 -428
- package/bin/agent-api-tool-broker.cjs +0 -248
- package/bin/agent-api-turn-controller.mjs +0 -461
- package/bin/agent-api-usage-journal.cjs +0 -259
- package/bin/agent-resume-snapshot.cjs +0 -241
- package/bin/agentspine-king-goal-inbox.mjs +0 -111
- package/bin/agentspine-king-goal-intake.mjs +0 -106
- package/bin/approval-rejection-stop.cjs +0 -15
- package/bin/assistant-message-offload-policy.cjs +0 -284
- package/bin/baseline-skill-performance-policy.cjs +0 -39
- package/bin/bash-search-scope-policy.cjs +0 -49
- package/bin/codebase-search-runtime.cjs +0 -23
- package/bin/cognitive-action-checkpoint.cjs +0 -1104
- package/bin/cognitive-attention-delivery.cjs +0 -76
- package/bin/cognitive-attention-policy.cjs +0 -143
- package/bin/cognitive-attention-runtime.cjs +0 -91
- package/bin/cognitive-context-projection.cjs +0 -73
- package/bin/cognitive-cross-portal-acceptance.cjs +0 -443
- package/bin/cognitive-effective-view.cjs +0 -77
- package/bin/cognitive-focus-projection.cjs +0 -206
- package/bin/cognitive-focus-scope.cjs +0 -37
- package/bin/cognitive-goal-autostart-policy.cjs +0 -72
- package/bin/cognitive-goal-time-trigger-controller.cjs +0 -146
- package/bin/cognitive-memory-adapter.cjs +0 -282
- package/bin/cognitive-memory-command.cjs +0 -293
- package/bin/cognitive-memory-provider.cjs +0 -92
- package/bin/cognitive-salience-policy.cjs +0 -159
- package/bin/cognitive-state-store.cjs +0 -508
- package/bin/cognitive-turn-lifecycle.cjs +0 -624
- package/bin/cognitive-work-focus.cjs +0 -180
- package/bin/compaction-history-archive.cjs +0 -166
- package/bin/compaction-history-startup.cjs +0 -50
- package/bin/compaction-model-policy.cjs +0 -31
- package/bin/compaction-stage-policy.cjs +0 -21
- package/bin/compaction-transaction-policy.cjs +0 -122
- package/bin/config-write-dedup-policy.cjs +0 -27
- package/bin/context-budget-ledger.cjs +0 -31
- package/bin/context-doctor-policy.cjs +0 -70
- package/bin/context-insight-policy.cjs +0 -36
- package/bin/context-performance-policy.cjs +0 -19
- package/bin/context-pressure-policy.cjs +0 -20
- package/bin/cron-run-output.cjs +0 -45
- package/bin/cron-run-store.cjs +0 -145
- package/bin/curiosity-scout-policy.cjs +0 -49
- package/bin/default-model-output-budget-policy.cjs +0 -28
- package/bin/durable-task-resume-policy.cjs +0 -130
- package/bin/durable-task-resume-runtime.cjs +0 -117
- package/bin/durable-task-resume-store.cjs +0 -88
- package/bin/editable-tool-approval-policy.cjs +0 -540
- package/bin/editable-tool-approval-runtime.cjs +0 -99
- package/bin/effective-system-prompt-cache-policy.cjs +0 -33
- package/bin/error-memory-performance-policy.cjs +0 -113
- package/bin/file-observation-policy.cjs +0 -133
- package/bin/foreground-output-capture-policy.cjs +0 -41
- package/bin/generated-source-health.cjs +0 -142
- package/bin/glob-pattern-policy.cjs +0 -13
- package/bin/goal-completion-evidence-policy.cjs +0 -120
- package/bin/grep-output-limit-policy.cjs +0 -39
- package/bin/historical-media-projection-policy.cjs +0 -48
- package/bin/history-offload-pressure-policy.cjs +0 -33
- package/bin/html-to-research-markdown.cjs +0 -147
- package/bin/identity-context-policy.cjs +0 -764
- package/bin/identity-journal-policy.cjs +0 -107
- package/bin/input-draft-persistence.cjs +0 -77
- package/bin/king-tui-function-contract.json +0 -33
- package/bin/launcher-restart-policy.cjs +0 -150
- package/bin/live-response-repetition-guard.cjs +0 -196
- package/bin/llm-config-log-dedup-policy.cjs +0 -76
- package/bin/loop-event-record-policy.cjs +0 -174
- package/bin/managed-context-startup-policy.cjs +0 -27
- package/bin/media-activity-layout-policy.cjs +0 -34
- package/bin/media-auto-retrieval-policy.cjs +0 -90
- package/bin/media-result-policy.cjs +0 -59
- package/bin/micro-compaction-policy.cjs +0 -145
- package/bin/mistake-relevance-policy.cjs +0 -319
- package/bin/model-retry-progress-policy.cjs +0 -46
- package/bin/native-large-file-io.cjs +0 -42
- package/bin/native-runtime-cache.cjs +0 -76
- package/bin/natural-presence-policy.cjs +0 -28
- package/bin/noninteractive-shell-env-policy.cjs +0 -19
- package/bin/observer-hooks.cjs +0 -14
- package/bin/outbound-claim-provenance.cjs +0 -150
- package/bin/oversized-context-offload-policy.cjs +0 -86
- package/bin/pending-media-policy.cjs +0 -182
- package/bin/pending-token-estimate-policy.cjs +0 -41
- package/bin/personal-memory-consent-policy.cjs +0 -72
- package/bin/personal-memory-performance-policy.cjs +0 -12
- package/bin/personality-choice-policy.cjs +0 -101
- package/bin/personality-memory-adapter.cjs +0 -379
- package/bin/personality-mode.cjs +0 -46
- package/bin/personality-setup-policy.cjs +0 -197
- package/bin/proactive-compaction-policy.cjs +0 -25
- package/bin/profile-identity-resolution.cjs +0 -136
- package/bin/profile-runtime.cjs +0 -318
- package/bin/profile-tool-exclusion-policy.cjs +0 -37
- package/bin/programmatic-context-isolation.cjs +0 -25
- package/bin/programmatic-tool-runtime.mjs +0 -627
- package/bin/provider-idle-timeout-policy.cjs +0 -14
- package/bin/provider-model-refresh-deadline.cjs +0 -53
- package/bin/provider-model-refresh-policy.cjs +0 -107
- package/bin/rate-limit-recovery-policy.cjs +0 -47
- package/bin/read-batch-policy.cjs +0 -32
- package/bin/read-continuation-policy.cjs +0 -59
- package/bin/recurring-cron-history-policy.cjs +0 -124
- package/bin/relationship-continuity-policy.cjs +0 -143
- package/bin/relationship-curiosity-policy.cjs +0 -107
- package/bin/relationship-learning-policy.cjs +0 -168
- package/bin/release-artifact-freeze-policy.cjs +0 -30
- package/bin/reload-plugin-bootstrap.cjs +0 -18
- package/bin/reload-queue-policy.cjs +0 -38
- package/bin/repeated-assistant-response-policy.cjs +0 -232
- package/bin/repeated-injection-projection.cjs +0 -107
- package/bin/repeated-user-message-projection.cjs +0 -8
- package/bin/research-page-result.cjs +0 -74
- package/bin/retry-checkpoint-policy.cjs +0 -13
- package/bin/runtime-exit-ledger.cjs +0 -144
- package/bin/scoped-cron-run-policy.cjs +0 -358
- package/bin/session-checkpoint-policy.cjs +0 -25
- package/bin/session-compaction-policy.cjs +0 -84
- package/bin/session-replay-policy.cjs +0 -20
- package/bin/session-replay-window-policy.cjs +0 -40
- package/bin/session-resume-checkpoint.cjs +0 -254
- package/bin/session-scrollback-archive.cjs +0 -229
- package/bin/skill-activation-performance-policy.cjs +0 -69
- package/bin/skill-listing-performance-policy.cjs +0 -92
- package/bin/soul-organization-policy.cjs +0 -78
- package/bin/soul-preservation-policy.cjs +0 -20
- package/bin/startup-preferences.cjs +0 -131
- package/bin/streaming-flush-performance-policy.cjs +0 -28
- package/bin/structured-agent-swarm-output.cjs +0 -325
- package/bin/structured-subagent-output.cjs +0 -252
- package/bin/subagent-context-fork-policy.cjs +0 -155
- package/bin/subagent-max-tokens-handoff-policy.cjs +0 -69
- package/bin/subagent-parent-responsiveness.cjs +0 -19
- package/bin/subagent-skill-policy.cjs +0 -206
- package/bin/subagent-timeout-policy.cjs +0 -182
- package/bin/subagent-tool-policy.cjs +0 -60
- package/bin/subagent-usage-rollup-policy.cjs +0 -29
- package/bin/system-prompt-context-policy.cjs +0 -124
- package/bin/system-prompt-token-cache-policy.cjs +0 -60
- package/bin/telegram-addressed-focus.cjs +0 -55
- package/bin/telegram-addressed-priority.cjs +0 -12
- package/bin/telegram-approval-relay.cjs +0 -290
- package/bin/telegram-bot-priority.cjs +0 -17
- package/bin/telegram-console-status-policy.cjs +0 -174
- package/bin/telegram-context-projection-policy.cjs +0 -141
- package/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/bin/telegram-direct-focus-policy.cjs +0 -273
- package/bin/telegram-mcp-compatibility.cjs +0 -49
- package/bin/telegram-media-delivery-policy.cjs +0 -42
- package/bin/telegram-private-conversation-policy.cjs +0 -185
- package/bin/telegram-queue-handoff-policy.cjs +0 -73
- package/bin/telegram-remote-status-policy.cjs +0 -120
- package/bin/telegram-session-queue-runtime.mjs +0 -306
- package/bin/telegram-text-chunk-policy.cjs +0 -63
- package/bin/telegram-truncated-reply-policy.cjs +0 -37
- package/bin/telegram-urgent-policy.cjs +0 -45
- package/bin/telemetry-spool-policy.cjs +0 -57
- package/bin/thinking-activity-status-policy.cjs +0 -132
- package/bin/thinking-only-guard.cjs +0 -80
- package/bin/todo-list-turn-policy.cjs +0 -131
- package/bin/tool-call-loop-policy.cjs +0 -51
- package/bin/tool-file-persistence.cjs +0 -141
- package/bin/tool-result-offload-policy.cjs +0 -359
- package/bin/tool-result-offload-telemetry.cjs +0 -12
- package/bin/tool-schema-token-cache-policy.cjs +0 -41
- package/bin/tool-stream-preview-policy.cjs +0 -9
- package/bin/tui-functional-contract.cjs +0 -55
- package/bin/turn-tool-performance-policy.cjs +0 -486
- package/bin/usage-cache-efficiency-policy.cjs +0 -26
- package/bin/user-home-path-policy.cjs +0 -13
- package/bin/user-message-offload-policy.cjs +0 -103
- package/bin/user-prompt-hook-origin-policy.cjs +0 -34
- package/bin/user-tool-record-policy.cjs +0 -7
- package/bin/validated-learning-insight-policy.cjs +0 -58
- package/bin/validated-learning-outcome-trace.cjs +0 -107
- package/bin/validated-learning-performance-policy.cjs +0 -53
- package/bin/validated-learning-signal.cjs +0 -463
- package/bin/windows-bash-dialect-policy.cjs +0 -25
- package/bin/windows-node-crash-dump.cjs +0 -110
- package/bin/write-continuation-policy.cjs +0 -69
- package/codebase-index/README.md +0 -82
- package/codebase-index/codebase_index.py +0 -470
- package/standard-skills/agent-browser/SKILL.md +0 -19
- package/standard-skills/agent-browser/references/runtime.md +0 -8
- package/standard-skills/blun-session-inspector/SKILL.md +0 -41
- package/standard-skills/blun-session-inspector/scripts/inspect-session.cjs +0 -437
- package/standard-skills/design-taste-frontend/SKILL.md +0 -1206
- package/standard-skills/full-output-enforcement/SKILL.md +0 -49
- package/standard-skills/high-end-visual-design/SKILL.md +0 -98
- package/standard-skills/image-to-code/SKILL.md +0 -1228
- package/standard-skills/industrial-brutalist-ui/SKILL.md +0 -92
- package/standard-skills/minimalist-ui/SKILL.md +0 -85
- package/standard-skills/motion-design-taste/SKILL.md +0 -74
- package/standard-skills/playwright-testing/SKILL.md +0 -19
- package/standard-skills/playwright-testing/references/runtime.md +0 -7
- package/standard-skills/premortem/SKILL.md +0 -148
- package/standard-skills/redesign-existing-projects/SKILL.md +0 -178
- package/standard-skills/research-evidence/SKILL.md +0 -39
- package/standard-skills/research-evidence/references/evidence-format.md +0 -104
- package/standard-skills/research-evidence/scripts/evidence-collection.cjs +0 -260
- package/standard-skills/research-evidence/scripts/score-report.cjs +0 -130
- package/standard-skills/screenshot-lesen/SKILL.md +0 -52
- package/standard-skills/stitch-design-taste/DESIGN.md +0 -121
- package/standard-skills/stitch-design-taste/SKILL.md +0 -184
- package/standard-skills/telegram-channel/SKILL.md +0 -18
- package/standard-skills/telegram-channel/references/runtime.md +0 -7
- package/standard-skills/venture-flywheel/SKILL.md +0 -32
- package/standard-skills/venture-flywheel/identity/project-identity.cjs +0 -146
- package/standard-skills/venture-flywheel/policy/capability-engine.cjs +0 -114
- package/standard-skills/venture-flywheel/policy/repository-trust.cjs +0 -229
- package/standard-skills/venture-flywheel/references/BEISPIELE-phase0.md +0 -146
- package/standard-skills/venture-flywheel/references/CAPABILITY-MAP.md +0 -34
- package/standard-skills/venture-flywheel/references/SPEC-phase0-identity-trust.md +0 -77
- package/standard-skills/venture-flywheel/references/SPEC-phase0-state-events.md +0 -93
- package/standard-skills/venture-flywheel/schemas/capability-decision.schema.json +0 -13
- package/standard-skills/venture-flywheel/schemas/execution-event.schema.json +0 -44
- package/standard-skills/venture-flywheel/schemas/project-identity.schema.json +0 -32
- package/standard-skills/venture-flywheel/schemas/repository-trust.schema.json +0 -57
- package/standard-skills/venture-flywheel/schemas/run-transition.schema.json +0 -59
- package/standard-skills/venture-flywheel/state/execution-event.cjs +0 -191
- package/standard-skills/venture-flywheel/state/task-state-machine.cjs +0 -190
- package/standard-skills/web-lesen/SKILL.md +0 -73
- package/standard-skills/web-lesen/scripts/crawl_public.py +0 -379
- package/standard-skills/windows-mcp/SKILL.md +0 -19
- package/standard-skills/windows-mcp/references/runtime.md +0 -9
- package/telegram-plugin/DELIVERY.md +0 -36
- package/telegram-plugin/bin/telegram-approval-relay.cjs +0 -290
- package/telegram-plugin/bin/telegram-console-status-policy.cjs +0 -175
- package/telegram-plugin/bin/telegram-delivery-lifecycle.cjs +0 -125
- package/telegram-plugin/bin/telegram-direct-reply-policy.cjs +0 -48
- package/telegram-plugin/bin/telegram-launcher-status-queue.cjs +0 -122
- package/telegram-plugin/bin/telegram-private-conversation-policy.cjs +0 -186
- package/telegram-plugin/bin/telegram-remote-status-policy.cjs +0 -121
- package/telegram-plugin/bin/telegram-reply-parts.cjs +0 -149
- package/telegram-plugin/bin/telegram-text-chunk-policy.cjs +0 -63
- package/telegram-plugin/bin/telegram-typing-keepalive.cjs +0 -89
- package/telegram-plugin/compat/mcp-server-fa511cd1.mjs +0 -73825
- /package/{bin → scripts}/fix-node-pty-perms.js +0 -0
|
@@ -1,379 +0,0 @@
|
|
|
1
|
-
"""Bounded, credential-free public HTTPS crawling with Crawl4AI extraction/BFS."""
|
|
2
|
-
import argparse
|
|
3
|
-
import asyncio
|
|
4
|
-
import contextlib
|
|
5
|
-
import hashlib
|
|
6
|
-
import ipaddress
|
|
7
|
-
import json
|
|
8
|
-
import os
|
|
9
|
-
import re
|
|
10
|
-
import socket
|
|
11
|
-
import stat
|
|
12
|
-
import sys
|
|
13
|
-
import time
|
|
14
|
-
from datetime import datetime, timezone
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
from urllib.parse import parse_qsl, unquote, urljoin, urlsplit, urlunsplit
|
|
17
|
-
from urllib.robotparser import RobotFileParser
|
|
18
|
-
|
|
19
|
-
import aiohttp
|
|
20
|
-
|
|
21
|
-
AGENT = 'BLUN-PublicResearch/1.0'
|
|
22
|
-
BODY_LIMIT = 2 * 1024 * 1024
|
|
23
|
-
SENSITIVE_QUERY = re.compile(
|
|
24
|
-
r'^(?:(?:access|refresh|id|oauth)[_-]?token|token|api[_-]?key|key|client[_-]?secret|'
|
|
25
|
-
r'password|passwd|secret|signature|sig|auth|authorization|bearer|jwt|session(?:[_-]?id)?|'
|
|
26
|
-
r'code|credentials?|x-(?:amz|goog)-.*)$', re.I)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class CrawlError(Exception):
|
|
30
|
-
def __init__(self, code, status=None):
|
|
31
|
-
super().__init__(code)
|
|
32
|
-
self.code = code
|
|
33
|
-
self.status = status
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def require_plain_directory(directory):
|
|
37
|
-
directory = Path(directory)
|
|
38
|
-
if not directory.is_absolute() or '..' in directory.parts:
|
|
39
|
-
raise CrawlError('absolute-output-path-required')
|
|
40
|
-
for entry in reversed((directory, *directory.parents)):
|
|
41
|
-
info = entry.lstat()
|
|
42
|
-
if (stat.S_ISLNK(info.st_mode)
|
|
43
|
-
or getattr(info, 'st_file_attributes', 0) & getattr(stat, 'FILE_ATTRIBUTE_REPARSE_POINT', 0)):
|
|
44
|
-
raise CrawlError('linked-output-path')
|
|
45
|
-
if not stat.S_ISDIR(info.st_mode):
|
|
46
|
-
raise CrawlError('output-directory-required')
|
|
47
|
-
return directory
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def new_output_directory(home):
|
|
51
|
-
home = Path(home)
|
|
52
|
-
if not home.is_absolute() or not home.exists():
|
|
53
|
-
raise CrawlError('app-home-required')
|
|
54
|
-
base = require_plain_directory(home)
|
|
55
|
-
for name in ('artifacts', 'web-crawl'):
|
|
56
|
-
base = base / name
|
|
57
|
-
try:
|
|
58
|
-
base.mkdir()
|
|
59
|
-
except FileExistsError:
|
|
60
|
-
pass
|
|
61
|
-
require_plain_directory(base)
|
|
62
|
-
import tempfile
|
|
63
|
-
return require_plain_directory(Path(tempfile.mkdtemp(prefix='crawl-', dir=base)))
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def public_ip(value):
|
|
67
|
-
try:
|
|
68
|
-
address = ipaddress.ip_address(value)
|
|
69
|
-
if not address.is_global or address.is_multicast or address.is_reserved:
|
|
70
|
-
return False
|
|
71
|
-
if address.version == 6:
|
|
72
|
-
return address in ipaddress.ip_network('2000::/3') and not address.sixtofour and not address.teredo
|
|
73
|
-
return address not in ipaddress.ip_network('192.0.0.0/24')
|
|
74
|
-
except ValueError:
|
|
75
|
-
return False
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def normalize_url(value):
|
|
79
|
-
if not isinstance(value, str) or len(value) > 4096 or re.search(r'[\x00-\x20\\]', value):
|
|
80
|
-
raise CrawlError('invalid-url')
|
|
81
|
-
parsed = urlsplit(value)
|
|
82
|
-
if parsed.scheme != 'https' or parsed.username is not None or parsed.password is not None:
|
|
83
|
-
raise CrawlError('public-https-required')
|
|
84
|
-
if parsed.port not in (None, 443) or not parsed.hostname:
|
|
85
|
-
raise CrawlError('public-https-required')
|
|
86
|
-
host = parsed.hostname.encode('idna').decode('ascii').lower().rstrip('.')
|
|
87
|
-
try:
|
|
88
|
-
ipaddress.ip_address(host)
|
|
89
|
-
if not public_ip(host): raise CrawlError('private-address')
|
|
90
|
-
except ValueError:
|
|
91
|
-
if ('.' not in host or not re.fullmatch(r'[a-z0-9.-]+', host)
|
|
92
|
-
or host.endswith(('.local', '.localhost', '.internal', '.test', '.invalid'))):
|
|
93
|
-
raise CrawlError('public-host-required')
|
|
94
|
-
path = parsed.path or '/'
|
|
95
|
-
decoded = path
|
|
96
|
-
for _ in range(3):
|
|
97
|
-
decoded = unquote(decoded)
|
|
98
|
-
if '\\' in decoded or any(part in ('.', '..') for part in decoded.split('/')):
|
|
99
|
-
raise CrawlError('ambiguous-path')
|
|
100
|
-
if re.search(r'/(?:login|logout|signin|signout|oauth|auth|account)(?:/|$)', decoded, re.I):
|
|
101
|
-
raise CrawlError('login-path-not-crawled')
|
|
102
|
-
for key, _ in parse_qsl(parsed.query, keep_blank_values=True):
|
|
103
|
-
if any(SENSITIVE_QUERY.fullmatch(part) for part in re.split(r'[\[\].]+', key)):
|
|
104
|
-
raise CrawlError('credential-query-not-crawled')
|
|
105
|
-
authority = '[' + host + ']' if ':' in host else host
|
|
106
|
-
return urlunsplit(('https', authority, path, parsed.query, ''))
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
class Scope:
|
|
110
|
-
def __init__(self, start):
|
|
111
|
-
self.start = normalize_url(start)
|
|
112
|
-
parsed = urlsplit(self.start)
|
|
113
|
-
self.origin = urlunsplit((parsed.scheme, parsed.netloc, '', '', ''))
|
|
114
|
-
self.prefix = parsed.path if parsed.path.endswith('/') else parsed.path.rsplit('/', 1)[0] + '/'
|
|
115
|
-
|
|
116
|
-
def check(self, value, base=None, robots=False):
|
|
117
|
-
checked = normalize_url(urljoin(base or self.start, value))
|
|
118
|
-
parsed = urlsplit(checked)
|
|
119
|
-
if urlunsplit((parsed.scheme, parsed.netloc, '', '', '')) != self.origin:
|
|
120
|
-
raise CrawlError('outside-origin')
|
|
121
|
-
if not robots and not unquote(parsed.path).startswith(unquote(self.prefix)):
|
|
122
|
-
raise CrawlError('outside-path-scope')
|
|
123
|
-
return checked
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
class PublicResolver(aiohttp.abc.AbstractResolver):
|
|
127
|
-
async def resolve(self, host, port=0, family=socket.AF_UNSPEC):
|
|
128
|
-
addresses = await asyncio.get_running_loop().getaddrinfo(
|
|
129
|
-
host, port, type=socket.SOCK_STREAM, family=family)
|
|
130
|
-
if not addresses or any(not public_ip(row[4][0]) for row in addresses):
|
|
131
|
-
raise CrawlError('private-address')
|
|
132
|
-
# The connector receives these checked IPs directly, with the original
|
|
133
|
-
# hostname retained for certificate validation. There is no second DNS lookup.
|
|
134
|
-
return [dict(hostname=host, host=row[4][0], port=port, family=row[0],
|
|
135
|
-
proto=row[2], flags=socket.AI_NUMERICHOST) for row in addresses]
|
|
136
|
-
|
|
137
|
-
async def close(self):
|
|
138
|
-
pass
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
async def read_body(response, maximum):
|
|
142
|
-
if int(response.headers.get('Content-Length', '0')) > maximum:
|
|
143
|
-
raise CrawlError('body-limit')
|
|
144
|
-
chunks, size = [], 0
|
|
145
|
-
async for chunk in response.content.iter_chunked(16384):
|
|
146
|
-
size += len(chunk)
|
|
147
|
-
if size > maximum:
|
|
148
|
-
raise CrawlError('body-limit')
|
|
149
|
-
chunks.append(chunk)
|
|
150
|
-
return b''.join(chunks)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
class PublicStrategy:
|
|
154
|
-
def __init__(self, scope, max_pages):
|
|
155
|
-
self.scope, self.max_pages = scope, max_pages
|
|
156
|
-
self.attempts = 0
|
|
157
|
-
self.session = None
|
|
158
|
-
self.robots = None
|
|
159
|
-
self.lock = asyncio.Lock()
|
|
160
|
-
self.last_fetch = 0
|
|
161
|
-
self.inflight = set()
|
|
162
|
-
self.closed = False
|
|
163
|
-
self.errors = {}
|
|
164
|
-
|
|
165
|
-
async def __aenter__(self):
|
|
166
|
-
self.closed = False
|
|
167
|
-
self.session = aiohttp.ClientSession(
|
|
168
|
-
connector=aiohttp.TCPConnector(resolver=PublicResolver(), use_dns_cache=False,
|
|
169
|
-
force_close=True, limit=1),
|
|
170
|
-
cookie_jar=aiohttp.DummyCookieJar(), trust_env=False,
|
|
171
|
-
timeout=aiohttp.ClientTimeout(total=15, connect=5),
|
|
172
|
-
headers={'User-Agent': AGENT, 'Accept': 'text/html,application/xhtml+xml',
|
|
173
|
-
'Accept-Encoding': 'identity'}, auto_decompress=False)
|
|
174
|
-
return self
|
|
175
|
-
|
|
176
|
-
async def __aexit__(self, *args):
|
|
177
|
-
self.closed = True
|
|
178
|
-
owned = [task for task in self.inflight if task is not asyncio.current_task()]
|
|
179
|
-
for task in owned:
|
|
180
|
-
task.cancel()
|
|
181
|
-
if owned:
|
|
182
|
-
await asyncio.gather(*owned, return_exceptions=True)
|
|
183
|
-
if self.session:
|
|
184
|
-
await self.session.close()
|
|
185
|
-
|
|
186
|
-
async def fetch(self, url, robots=False):
|
|
187
|
-
current = self.scope.check(url, robots=robots)
|
|
188
|
-
for _ in range(4):
|
|
189
|
-
delay = (self.robots.crawl_delay(AGENT) or 0) if not robots and self.robots else 0
|
|
190
|
-
if delay > 10:
|
|
191
|
-
raise CrawlError('robots-delay-exceeds-budget')
|
|
192
|
-
await asyncio.sleep(max(0, max(0.4, delay) - (time.monotonic() - self.last_fetch)))
|
|
193
|
-
self.last_fetch = time.monotonic()
|
|
194
|
-
async with self.session.get(current, allow_redirects=False) as response:
|
|
195
|
-
if any(value.strip().lower() == 'challenge'
|
|
196
|
-
for value in response.headers.getall('cf-mitigated', ())):
|
|
197
|
-
raise CrawlError('challenge-page-not-crawled', status=response.status)
|
|
198
|
-
if response.status in (301, 302, 303, 307, 308):
|
|
199
|
-
location = response.headers.get('Location')
|
|
200
|
-
if not location: raise CrawlError('redirect-without-location')
|
|
201
|
-
current = self.scope.check(location, base=current, robots=robots)
|
|
202
|
-
if not robots and self.robots and not self.robots.can_fetch(AGENT, current):
|
|
203
|
-
raise CrawlError('robots-disallowed')
|
|
204
|
-
continue
|
|
205
|
-
if robots and response.status in (404, 410):
|
|
206
|
-
return current, b'', 'text/plain'
|
|
207
|
-
if response.status != 200:
|
|
208
|
-
raise CrawlError('http-status-' + str(response.status), status=response.status)
|
|
209
|
-
if response.headers.get('Content-Encoding', 'identity').lower() != 'identity':
|
|
210
|
-
raise CrawlError('unsupported-content-encoding')
|
|
211
|
-
mime = response.headers.get('Content-Type', '').split(';')[0].lower().strip()
|
|
212
|
-
if mime not in (('text/plain',) if robots else ('text/html', 'application/xhtml+xml')):
|
|
213
|
-
raise CrawlError('unsupported-content-type')
|
|
214
|
-
return current, await read_body(response, 256 * 1024 if robots else BODY_LIMIT), mime
|
|
215
|
-
raise CrawlError('redirect-limit')
|
|
216
|
-
|
|
217
|
-
async def crawl(self, url, **kwargs):
|
|
218
|
-
if self.closed:
|
|
219
|
-
raise CrawlError('crawler-closed')
|
|
220
|
-
task = asyncio.current_task()
|
|
221
|
-
self.inflight.add(task)
|
|
222
|
-
try:
|
|
223
|
-
return await self._crawl(url)
|
|
224
|
-
except Exception as error:
|
|
225
|
-
code, status = 'crawl-error', None
|
|
226
|
-
if isinstance(error, CrawlError):
|
|
227
|
-
if isinstance(error.code, str) and re.fullmatch(r'[a-z0-9-]{1,64}', error.code):
|
|
228
|
-
code = error.code
|
|
229
|
-
status = error.status
|
|
230
|
-
elif isinstance(error, TimeoutError):
|
|
231
|
-
code = 'request-timeout'
|
|
232
|
-
elif isinstance(error, UnicodeError):
|
|
233
|
-
code = 'invalid-text-encoding'
|
|
234
|
-
elif isinstance(error, aiohttp.ClientError):
|
|
235
|
-
code = 'network-error'
|
|
236
|
-
self.errors[url] = dict(reason=code, status=status)
|
|
237
|
-
raise
|
|
238
|
-
finally:
|
|
239
|
-
self.inflight.discard(task)
|
|
240
|
-
|
|
241
|
-
async def _crawl(self, url):
|
|
242
|
-
from crawl4ai.models import AsyncCrawlResponse
|
|
243
|
-
checked = self.scope.check(url)
|
|
244
|
-
async with self.lock:
|
|
245
|
-
if self.attempts >= self.max_pages: raise CrawlError('page-limit')
|
|
246
|
-
self.attempts += 1
|
|
247
|
-
if self.robots is None:
|
|
248
|
-
_, raw, _ = await self.fetch(self.scope.origin + '/robots.txt', robots=True)
|
|
249
|
-
self.robots = RobotFileParser()
|
|
250
|
-
self.robots.parse(raw.decode('utf-8', errors='strict').splitlines())
|
|
251
|
-
if not self.robots.can_fetch(AGENT, checked): raise CrawlError('robots-disallowed')
|
|
252
|
-
final, raw, mime = await self.fetch(checked)
|
|
253
|
-
html = raw.decode('utf-8', errors='strict')
|
|
254
|
-
from lxml import html as lhtml
|
|
255
|
-
document = lhtml.fromstring(html)
|
|
256
|
-
if document.xpath('//form[@id="challenge-form" or @id="anomaly-form" or @id="challenge-stage"]'):
|
|
257
|
-
raise CrawlError('challenge-page-not-crawled', status=200)
|
|
258
|
-
if document.xpath('//input[translate(@type, "PASSWORD", "password")="password"]'):
|
|
259
|
-
raise CrawlError('login-page-not-crawled', status=200)
|
|
260
|
-
return AsyncCrawlResponse(html=html,
|
|
261
|
-
response_headers={'content-type': mime}, status_code=200,
|
|
262
|
-
redirected_url=final)
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
async def run_crawl(scope, directory, max_pages=6, depth=1, seconds=60, strategy=None):
|
|
266
|
-
if not 1 <= max_pages <= 12 or not 0 <= depth <= 2 or not 1 <= seconds <= 120:
|
|
267
|
-
raise CrawlError('invalid-budget')
|
|
268
|
-
directory = require_plain_directory(directory)
|
|
269
|
-
os.environ['CRAWL4_AI_BASE_DIRECTORY'] = str(directory)
|
|
270
|
-
from crawl4ai import AsyncWebCrawler, BrowserConfig, CacheMode, CrawlerRunConfig
|
|
271
|
-
from crawl4ai.deep_crawling import BFSDeepCrawlStrategy
|
|
272
|
-
from crawl4ai.deep_crawling.filters import FilterChain, URLFilter
|
|
273
|
-
from crawl4ai.async_logger import AsyncLogger
|
|
274
|
-
from crawl4ai.content_scraping_strategy import LXMLWebScrapingStrategy
|
|
275
|
-
from lxml import html as lhtml
|
|
276
|
-
|
|
277
|
-
class ArticleScraper(LXMLWebScrapingStrategy):
|
|
278
|
-
def scrap(self, url, html, **kwargs):
|
|
279
|
-
document = lhtml.fromstring(html)
|
|
280
|
-
for selector in ('main', 'article', '[role="main"]'):
|
|
281
|
-
if document.cssselect(selector):
|
|
282
|
-
kwargs['css_selector'] = selector
|
|
283
|
-
break
|
|
284
|
-
return super().scrap(url, html, **kwargs)
|
|
285
|
-
|
|
286
|
-
admitted = {scope.start}
|
|
287
|
-
class InScope(URLFilter):
|
|
288
|
-
def apply(self, url):
|
|
289
|
-
try:
|
|
290
|
-
checked = scope.check(url)
|
|
291
|
-
if checked not in admitted:
|
|
292
|
-
if len(admitted) >= max_pages:
|
|
293
|
-
return False
|
|
294
|
-
admitted.add(checked)
|
|
295
|
-
return True
|
|
296
|
-
except (CrawlError, ValueError):
|
|
297
|
-
return False
|
|
298
|
-
|
|
299
|
-
strategy = strategy or PublicStrategy(scope, max_pages)
|
|
300
|
-
# This Crawl4AI version stops before yielding its last allowed streaming page.
|
|
301
|
-
# One planner sentinel plus transport/consumer caps preserves that page safely.
|
|
302
|
-
plan = BFSDeepCrawlStrategy(max_depth=depth, include_external=False, max_pages=max_pages + 1,
|
|
303
|
-
filter_chain=FilterChain([InScope()]))
|
|
304
|
-
config = CrawlerRunConfig(deep_crawl_strategy=plan, cache_mode=CacheMode.DISABLED,
|
|
305
|
-
stream=True, max_retries=0, check_robots_txt=False, fallback_fetch_function=None,
|
|
306
|
-
page_timeout=15000, word_count_threshold=1, remove_forms=True, exclude_all_images=True,
|
|
307
|
-
excluded_tags=['nav', 'footer', 'script', 'style'], verbose=False,
|
|
308
|
-
scraping_strategy=ArticleScraper())
|
|
309
|
-
report = dict(schema='blun.public-crawl/v1', start=scope.start, scope=scope.origin + scope.prefix,
|
|
310
|
-
limits=dict(pages=max_pages, depth=depth, seconds=seconds, bytesPerPage=BODY_LIMIT),
|
|
311
|
-
siteComplete=False, pages=[], failures=[], outcome='bounded',
|
|
312
|
-
javascript=False, authenticated=False, contentAuthority='untrusted-source')
|
|
313
|
-
results = []
|
|
314
|
-
try:
|
|
315
|
-
async with asyncio.timeout(seconds):
|
|
316
|
-
async with AsyncWebCrawler(crawler_strategy=strategy,
|
|
317
|
-
config=BrowserConfig(verbose=False), base_directory=str(directory),
|
|
318
|
-
logger=AsyncLogger(verbose=False, log_file=None)) as crawler:
|
|
319
|
-
stream = await crawler.arun(scope.start, config=config)
|
|
320
|
-
async with contextlib.aclosing(stream):
|
|
321
|
-
async for result in stream:
|
|
322
|
-
results.append(result)
|
|
323
|
-
if len(results) >= max_pages:
|
|
324
|
-
break
|
|
325
|
-
except TimeoutError:
|
|
326
|
-
report['outcome'] = 'time-limit'
|
|
327
|
-
for result in results:
|
|
328
|
-
if not result.success or not result.markdown:
|
|
329
|
-
error = getattr(strategy, 'errors', {}).get(result.url, {})
|
|
330
|
-
report['failures'].append(dict(url=result.url,
|
|
331
|
-
status=error.get('status') or result.status_code,
|
|
332
|
-
reason=error.get('reason', 'page-unavailable')))
|
|
333
|
-
continue
|
|
334
|
-
content = result.markdown.raw_markdown if hasattr(result.markdown, 'raw_markdown') else str(result.markdown)
|
|
335
|
-
if not content.strip():
|
|
336
|
-
report['failures'].append(dict(url=result.url, reason='empty-markdown'))
|
|
337
|
-
continue
|
|
338
|
-
data = content.encode('utf-8')
|
|
339
|
-
if len(data) > BODY_LIMIT:
|
|
340
|
-
report['failures'].append(dict(url=result.url, reason='markdown-limit'))
|
|
341
|
-
continue
|
|
342
|
-
digest = hashlib.sha256(data).hexdigest()
|
|
343
|
-
filename = 'page-' + str(len(report['pages']) + 1) + '-' + digest[:12] + '.md'
|
|
344
|
-
require_plain_directory(directory)
|
|
345
|
-
with (directory / filename).open('x', encoding='utf-8', newline='\n') as output:
|
|
346
|
-
output.write(content)
|
|
347
|
-
report['pages'].append(dict(url=result.redirected_url or result.url, file=filename,
|
|
348
|
-
sha256=digest, bytes=len(data), retrievedAt=datetime.now(timezone.utc).isoformat(),
|
|
349
|
-
depth=(result.metadata or {}).get('depth', 0)))
|
|
350
|
-
if report['failures'] and report['outcome'] == 'bounded': report['outcome'] = 'partial'
|
|
351
|
-
if not report['pages'] and report['outcome'] == 'bounded': report['outcome'] = 'unavailable'
|
|
352
|
-
require_plain_directory(directory)
|
|
353
|
-
with (directory / 'manifest.json').open('x', encoding='utf-8', newline='\n') as output:
|
|
354
|
-
json.dump(report, output, ensure_ascii=True, indent=2)
|
|
355
|
-
return report
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
def main():
|
|
359
|
-
parser = argparse.ArgumentParser()
|
|
360
|
-
parser.add_argument('url')
|
|
361
|
-
parser.add_argument('--pages', type=int, default=6)
|
|
362
|
-
parser.add_argument('--depth', type=int, default=1)
|
|
363
|
-
parser.add_argument('--seconds', type=int, default=60)
|
|
364
|
-
args = parser.parse_args()
|
|
365
|
-
scope = Scope(args.url)
|
|
366
|
-
home = Path(os.environ.get('BLUN_HOME', str(Path.home() / '.blun')))
|
|
367
|
-
directory = new_output_directory(home)
|
|
368
|
-
with contextlib.redirect_stdout(sys.stderr):
|
|
369
|
-
report = asyncio.run(run_crawl(scope, directory, args.pages, args.depth, args.seconds))
|
|
370
|
-
print(json.dumps(dict(directory=str(directory), **report), ensure_ascii=True))
|
|
371
|
-
return 0 if report['pages'] and not report['failures'] and report['outcome'] == 'bounded' else 1
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if __name__ == '__main__':
|
|
375
|
-
try:
|
|
376
|
-
raise SystemExit(main())
|
|
377
|
-
except (CrawlError, ValueError) as error:
|
|
378
|
-
print(json.dumps({'error': str(error)}))
|
|
379
|
-
raise SystemExit(1)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: windows-mcp
|
|
3
|
-
description: Use Windows desktop automation through a tightly allowlisted MCP contract with telemetry disabled, explicit activation, and user-visible control boundaries.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Windows MCP
|
|
7
|
-
|
|
8
|
-
Use this skill only when the user explicitly requests Windows desktop control or when a named workflow cannot be verified through browser or shell tools.
|
|
9
|
-
|
|
10
|
-
## Safety workflow
|
|
11
|
-
|
|
12
|
-
1. Read [references/runtime.md](references/runtime.md) before enabling the descriptor.
|
|
13
|
-
2. Confirm the exact application, window, and action boundary with the user.
|
|
14
|
-
3. Keep telemetry off and enable only the allowlisted visual interaction tools.
|
|
15
|
-
4. Capture state before acting, perform the smallest required interaction, then capture state again.
|
|
16
|
-
5. Never enable shell, registry, filesystem, process, or application-launch capabilities through this standard descriptor.
|
|
17
|
-
6. Reuse equivalent user configuration and never start a duplicate MCP process.
|
|
18
|
-
|
|
19
|
-
The descriptor being present does not authorize desktop control.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# Windows MCP Runtime Contract
|
|
2
|
-
|
|
3
|
-
- Tested contract: Windows MCP 0.8.5.
|
|
4
|
-
- The standard descriptor is disabled by default and must be enabled by an explicit user decision.
|
|
5
|
-
- Anonymous telemetry is disabled with `ANONYMIZED_TELEMETRY=false`.
|
|
6
|
-
- Safe allowlist: `Screenshot`, `Snapshot`, `Click`, `Type`, `Scroll`, `Move`, `Shortcut`, `Wait`, and `WaitFor`.
|
|
7
|
-
- Shell, registry, filesystem, process, and application-management tools are excluded.
|
|
8
|
-
- The runtime is external and is not bundled with BLUN Code. Enabling it may require an external package download.
|
|
9
|
-
- Existing equivalent user configuration wins; never launch a duplicate server.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# File Reply Receipts
|
|
2
|
-
|
|
3
|
-
File-bearing `reply` calls retain acknowledged message IDs in the channel's
|
|
4
|
-
`reply-deliveries` directory. Text-only calls keep their existing behavior.
|
|
5
|
-
|
|
6
|
-
- Supply a unique `delivery_id` for one intended delivery and keep it unchanged
|
|
7
|
-
on retries. Completed retries return the original IDs without sending again.
|
|
8
|
-
- IDs bind the bot, recipient, reply target, rendered chunks, formatting, file
|
|
9
|
-
order, names, paths and actual bytes. Reusing an ID with another payload fails
|
|
10
|
-
before sending. A new ID is for a deliberate new delivery, not error recovery.
|
|
11
|
-
- Legacy calls without an ID resume an identical incomplete batch. After a
|
|
12
|
-
successful unkeyed batch, another unkeyed call is a new delivery. This is not
|
|
13
|
-
global file deduplication and cannot cover loss of the final MCP response.
|
|
14
|
-
Error and success results include the generated ID for subsequent retries.
|
|
15
|
-
- Each request is marked in-flight before contacting Telegram. An acknowledged
|
|
16
|
-
message ID is committed immediately. An explicit grammY Bot API 4xx rejection
|
|
17
|
-
makes only that part retryable. Network errors, process death during a send,
|
|
18
|
-
malformed success responses and failed acknowledgement commits remain
|
|
19
|
-
uncertain. Automatic retry stops; check Telegram before deciding to send anew.
|
|
20
|
-
- A best-effort aggregate outbox log is not the part receipt. Its failure must
|
|
21
|
-
not turn an already confirmed delivery into a retryable send error.
|
|
22
|
-
|
|
23
|
-
The store uses Node's built-in SQLite API, already required by the application,
|
|
24
|
-
with FULL synchronous commits. A separate SQLite writer transaction serializes
|
|
25
|
-
file deliveries for this channel and is released by the OS on process death.
|
|
26
|
-
A concurrent attempt fails busy without sending. No bot credentials, message
|
|
27
|
-
text or file contents are saved in the receipt database, only IDs, payload
|
|
28
|
-
digests and progress. Existing channel-state attachment restrictions still apply.
|
|
29
|
-
|
|
30
|
-
Limits are 50MB per regular file, 1024 total parts per call and 10000 retained
|
|
31
|
-
delivery receipts. The store never silently evicts proofs; capacity, corruption
|
|
32
|
-
or unsupported schema failures stop new sends. Preserve the database before
|
|
33
|
-
maintenance. Deleting receipts is not a safe way to retry uncertain deliveries.
|
|
34
|
-
|
|
35
|
-
This protects this MCP file-reply path. It does not make Telegram's network API
|
|
36
|
-
exactly-once, coordinate independent fallback senders, or prove live delivery.
|