@weavecode/weave 0.1.0 → 0.1.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/node_modules/@weavecode/cli/dist/cli.js +4 -4
- package/node_modules/@weavecode/cli/dist/commands/chpass.js +1 -1
- package/node_modules/@weavecode/cli/dist/commands/daemon-auth.js +1 -1
- package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
- package/node_modules/@weavecode/cli/dist/commands/dashboard.d.ts +0 -2
- package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -1
- package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
- package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
- package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
- package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
- package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
- package/node_modules/@weavecode/cli/dist/commands/uninstall.js +1 -1
- package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +5 -3
- package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +44 -1
- package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +6 -4
- package/node_modules/@weavecode/cli/dist/i18n/index.js +1 -1
- package/node_modules/@weavecode/cli/dist/i18n/t.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +4 -4
- package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
- package/node_modules/@weavecode/cli/dist/init/git-commit.js +2 -2
- package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
- package/node_modules/@weavecode/cli/dist/init/harnesses/codex.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/helpers-gen.d.ts +4 -0
- package/node_modules/@weavecode/cli/dist/init/helpers-gen.js +1 -20
- package/node_modules/@weavecode/cli/dist/init/instruction-link.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/mcp-gen.d.ts +3 -20
- package/node_modules/@weavecode/cli/dist/init/mcp-gen.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/plugin-templates.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
- package/node_modules/@weavecode/cli/dist/init/settings-gen.d.ts +3 -30
- package/node_modules/@weavecode/cli/dist/init/settings-gen.js +1 -1
- package/node_modules/@weavecode/cli/dist/init/uninstall.js +6 -6
- package/node_modules/@weavecode/cli/dist/init/wiring.js +1 -1
- package/node_modules/@weavecode/cli/dist/parser.js +1 -1
- package/node_modules/@weavecode/cli/dist/statusline/ansi.js +1 -1
- package/node_modules/@weavecode/cli/dist/statusline/mock-input.js +1 -1
- package/node_modules/@weavecode/cli/dist/statusline/preview.js +2 -2
- package/node_modules/@weavecode/cli/package.json +5 -5
- package/node_modules/@weavecode/core/dist/harness-checks.js +1 -1
- package/node_modules/@weavecode/core/dist/harness.d.ts +45 -2
- package/node_modules/@weavecode/core/dist/harness.js +1 -1
- package/node_modules/@weavecode/core/dist/index.d.ts +1 -1
- package/node_modules/@weavecode/core/dist/index.js +1 -1
- package/node_modules/@weavecode/core/dist/platform.js +1 -1
- package/node_modules/@weavecode/core/dist/terminal.d.ts +28 -4
- package/node_modules/@weavecode/core/dist/terminal.js +1 -1
- package/node_modules/@weavecode/core/dist/types.d.ts +188 -11
- package/node_modules/@weavecode/core/dist/types.js +1 -1
- package/node_modules/@weavecode/core/dist/utils/fs.js +1 -1
- package/node_modules/@weavecode/core/dist/utils/logger.js +1 -1
- package/node_modules/@weavecode/core/package.json +1 -1
- package/node_modules/@weavecode/harness/dist/claude/assets.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/capture.d.ts +11 -1
- package/node_modules/@weavecode/harness/dist/claude/capture.js +5 -5
- package/node_modules/@weavecode/harness/dist/claude/detect.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/event-source.d.ts +1 -1
- package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/helpers-gen.d.ts +5 -0
- package/node_modules/@weavecode/harness/dist/claude/helpers-gen.js +20 -0
- package/node_modules/@weavecode/harness/dist/claude/index.d.ts +5 -1
- package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/mcp-gen.d.ts +22 -0
- package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -0
- package/node_modules/@weavecode/harness/dist/claude/messaging.d.ts +11 -2
- package/node_modules/@weavecode/harness/dist/claude/messaging.js +4 -1
- package/node_modules/@weavecode/harness/dist/claude/model-aliases.d.ts +25 -0
- package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -0
- package/node_modules/@weavecode/harness/dist/claude/peers.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/plugins.js +4 -4
- package/node_modules/@weavecode/harness/dist/claude/prompt-inbox.js +1 -1
- package/node_modules/@weavecode/harness/dist/claude/prompt.js +3 -3
- package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -1
- package/node_modules/@weavecode/harness/dist/claude/settings-gen.d.ts +32 -0
- package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -0
- package/node_modules/@weavecode/harness/dist/claude/transcript.d.ts +16 -0
- package/node_modules/@weavecode/harness/dist/claude/transcript.js +4 -2
- package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
- package/node_modules/@weavecode/harness/dist/codex/detect.js +1 -1
- package/node_modules/@weavecode/harness/dist/codex/messaging.js +1 -1
- package/node_modules/@weavecode/harness/dist/codex/plugin-state.js +1 -1
- package/node_modules/@weavecode/harness/dist/codex/toml.js +9 -9
- package/node_modules/@weavecode/harness/dist/driver.d.ts +58 -1
- package/node_modules/@weavecode/harness/dist/driver.js +1 -1
- package/node_modules/@weavecode/harness/dist/index.d.ts +1 -0
- package/node_modules/@weavecode/harness/dist/index.js +1 -1
- package/node_modules/@weavecode/harness/dist/init/generated.d.ts +37 -0
- package/node_modules/@weavecode/harness/dist/init/generated.js +2 -0
- package/node_modules/@weavecode/harness/dist/init/pipeline.js +1 -1
- package/node_modules/@weavecode/harness/dist/registry-wiring.d.ts +3 -1
- package/node_modules/@weavecode/harness/dist/registry-wiring.js +1 -1
- package/node_modules/@weavecode/harness/dist/shared/install-link.js +1 -1
- package/node_modules/@weavecode/harness/package.json +2 -2
- package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
- package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
- package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
- package/node_modules/@weavecode/server/dist/daemon/api-log.d.ts +48 -0
- package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -0
- package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
- package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/claude-liveness.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
- package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.d.ts +6 -1
- package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/opener.d.ts +102 -19
- package/node_modules/@weavecode/server/dist/daemon/opener.js +97 -7
- package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
- package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.d.ts +4 -3
- package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/server.d.ts +8 -0
- package/node_modules/@weavecode/server/dist/daemon/server.js +6 -6
- package/node_modules/@weavecode/server/dist/daemon/session-probe.d.ts +59 -2
- package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +10 -0
- package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
- package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
- package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.d.ts +4 -1
- package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
- package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
- package/node_modules/@weavecode/server/dist/db/db.js +20 -2
- package/node_modules/@weavecode/server/dist/db/paths.d.ts +4 -0
- package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
- package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
- package/node_modules/@weavecode/server/dist/hooks/inbox-socket.d.ts +17 -4
- package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -1
- package/node_modules/@weavecode/server/dist/hooks/inbox-worker.d.ts +20 -6
- package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
- package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/message-deliverer.d.ts +171 -13
- package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +3 -2
- package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
- package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
- package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/promptbox.d.ts +13 -0
- package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
- package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
- package/node_modules/@weavecode/server/dist/hooks/question-tracker.d.ts +6 -4
- package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/sequence-engine.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/session-purge.d.ts +4 -0
- package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/session-sweeper.d.ts +5 -8
- package/node_modules/@weavecode/server/dist/hooks/session-sweeper.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
- package/node_modules/@weavecode/server/dist/hooks/toolkit.d.ts +8 -0
- package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
- package/node_modules/@weavecode/server/dist/hooks/watch-engine.d.ts +7 -0
- package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
- package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
- package/node_modules/@weavecode/server/dist/install/apply-update.d.ts +1 -1
- package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
- package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
- package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
- package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
- package/node_modules/@weavecode/server/dist/install/fingerprint.d.ts +5 -1
- package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
- package/node_modules/@weavecode/server/dist/install/git-classify.d.ts +30 -0
- package/node_modules/@weavecode/server/dist/install/git-classify.js +1 -0
- package/node_modules/@weavecode/server/dist/install/global-config.js +2 -2
- package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
- package/node_modules/@weavecode/server/dist/install/init-files.d.ts +46 -0
- package/node_modules/@weavecode/server/dist/install/init-files.js +2 -0
- package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
- package/node_modules/@weavecode/server/dist/install/installer.js +3 -3
- package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
- package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
- package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
- package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
- package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
- package/node_modules/@weavecode/server/dist/install/project-config.d.ts +0 -2
- package/node_modules/@weavecode/server/dist/install/project-config.js +2 -2
- package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
- package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
- package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
- package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
- package/node_modules/@weavecode/server/dist/install/updates.d.ts +17 -5
- package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
- package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
- package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
- package/node_modules/@weavecode/server/dist/market/import.js +2 -2
- package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
- package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
- package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
- package/node_modules/@weavecode/server/dist/registry.js +2 -2
- package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
- package/node_modules/@weavecode/server/dist/repositories/hook-events.js +2 -2
- package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
- package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
- package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
- package/node_modules/@weavecode/server/dist/repositories/projects.d.ts +7 -0
- package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
- package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
- package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
- package/node_modules/@weavecode/server/dist/repositories/sessions.d.ts +17 -4
- package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
- package/node_modules/@weavecode/server/dist/repositories/uploads.d.ts +66 -0
- package/node_modules/@weavecode/server/dist/repositories/uploads.js +7 -0
- package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
- package/node_modules/@weavecode/server/dist/statusline/generator.js +81 -40
- package/node_modules/@weavecode/server/dist/statusline/manager.d.ts +2 -0
- package/node_modules/@weavecode/server/dist/statusline/manager.js +4 -4
- package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
- package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
- package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
- package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
- package/node_modules/@weavecode/server/dist/watch/sync-scheduler.d.ts +8 -4
- package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
- package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
- package/node_modules/@weavecode/server/package.json +4 -4
- package/node_modules/@weavecode/server/web/dist/assets/index-D5WFh77i.css +11 -0
- package/node_modules/@weavecode/server/web/dist/assets/index-DJibaGnJ.js +585 -0
- package/node_modules/@weavecode/server/web/dist/index.html +14 -2
- package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-plugin-creator/skills/weave-plugin-creator/SKILL.md +2 -2
- package/node_modules/@weavecode/templates/package.json +2 -2
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/package.json +20 -17
- package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/README.md +50 -32
- package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.d.ts +86 -40
- package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.es.js +860 -353
- package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.js +860 -353
- package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/package.json +20 -17
- package/package.json +6 -6
- package/node_modules/@weavecode/server/web/dist/assets/index-BOzaRlQE.js +0 -560
- package/node_modules/@weavecode/server/web/dist/assets/index-ChX8G8cT.css +0 -11
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import ur from"node:http";import{WEAVE_VERSION as dr}from"../version.js";import{checkHarness as mr,isHarness as T}from"@weavecode/core";import j from"node:fs";import S from"node:path";import{hooksRoot as pr}from"../hooks/mirror.js";import{syncPlugins as fr}from"../hooks/plugin-project-state.js";import{getLibraryScan as Y,invalidateScan as k}from"../install/scan-cache.js";import{installSkill as hr,uninstallSkill as gr,installMcp as yr,uninstallMcp as br,installFileAsset as wr,uninstallFileAsset as kr,InstallConflictError as Z,AssetNotFoundError as O}from"../install/installer.js";import{isFileAssetCategory as rr}from"../install/file-assets.js";import{installCapabilities as jr}from"../install/capabilities.js";import{readMcpRows as Sr}from"../install/mcp-rows.js";import{writeGlobalMcpServer as vr,removeGlobalMcpServer as Pr,installGlobalSkill as Nr,uninstallGlobalSkill as Er,readGlobalSkillGroups as Ir,resolveGlobalSkillDir as er,listGlobalSkillFiles as Tr,readGlobalSkillFile as Or,ClaudeJsonCorruptError as Br}from"../install/global-config.js";import{writeCodexMcpServer as Cr,removeCodexMcpServer as Gr,codexMcpExists as Dr,CodexTomlCorruptError as Jr}from"../install/codex-toml.js";import{setMcpEnableOverride as Mr}from"../install/settings-mcp.js";import{readProjectConfig as tr,writeProjectConfig as $r}from"../install/project-config.js";import{applyUpdate as Ar,syncAll as xr}from"../install/apply-update.js";import{buildLibraryIndex as Fr}from"../install/library-index.js";import{importFromDir as Lr,importFromGit as Rr,importLibraryIntoMarket as Ur}from"../market/import.js";import{marketDir as B,readManifest as Hr}from"../market/manifest.js";import{marketIdOf as Kr}from"../market/identity.js";import{isInsideDir as C,toRelPosix as Wr}from"../market/resolve.js";import{checkMarketUpdates as zr}from"../market/updates.js";import{refreshMarketItems as qr}from"../market/refresh.js";import{ensureBuiltinMarket as _r,isBuiltinMarketDir as v}from"../market/builtin.js";import{removeInstalled as Vr}from"../market/install-link.js";import{readProjectFile as Qr,readGlobalFile as Xr,PathEscapeError as Yr,FileTooLargeError as Zr}from"../install/reader.js";import{listGlobalFileAssets as re}from"../install/global-file-assets.js";import{readStatuslineConfig as ar,readStatuslineScript as ee,applyStatuslineConfig as ir,readGlobalStatuslineConfig as sr,writeGlobalStatuslineConfig as te}from"../statusline/manager.js";import{DEFAULT_STATUSLINE_CONFIG as ae}from"../statusline/config.js";import{FingerprintCache as G}from"../install/fingerprint.js";import{detectUpdates as ie}from"../install/updates.js";import{detectPluginTemplateUpdates as se}from"../install/plugin-templates.js";import{readBody as f,sendJson as i}from"./http.js";import{handleHooksRoutes as ne}from"./hooks-routes.js";import{handleToolkitRoutes as oe}from"./toolkit-routes.js";import{handleCaptureRoutes as ce}from"./capture-routes.js";import{purgeProjectPipeline as le}from"./hook-pipeline.js";import{projectFileNamespaces as ue}from"../hooks/toolkit.js";import{listBrowseRoots as de,listDirectoryChildren as me}from"./fs-browser.js";import{DEFAULT_AI_SETTINGS as pe,readDaemonSettings as P,writeDaemonSettings as fe,terminalPresetsFor as he}from"./settings.js";import{defaultProjectOpener as N,readTerminalCounts as ge,terminalBackendFor as ye}from"./opener.js";import{applyLaunchOnLogin as be}from"./auto-start.js";import{DAEMON_HOST as we}from"./port.js";import{pluginStateSurfaces as ke,pluginSurfaces as nr,pluginSurfaceFor as or}from"../surfaces.js";import{readPluginRows as je}from"../install/plugin-rows.js";import{installPluginPack as Se}from"../install/plugin-install.js";import{handleAuthRoutes as ve}from"./auth-routes.js";import{handleAiRoutes as Pe}from"./ai-routes.js";import{hasAiKey as Ne,writeAiKey as Ee}from"./ai-config.js";import{accessUrls as Ie}from"./tls.js";import{projectHarnesses as Te,withProjectHarnesses as cr}from"./project-harnesses.js";export const DAEMON_VERSION=dr;export function weaveRequestHandler(s){const r=s.fingerprintCache??new G,t={...s,fingerprintCache:r};return(u,o)=>{Oe(u,o,t)}}export function createWeaveServer(s){return ur.createServer(weaveRequestHandler(s))}async function Oe(s,r,t){const u=new URL(s.url??"/",`http://${we}`);let o=u.pathname;if(o.startsWith("/api/")?o=o.slice(4):o==="/api"&&(o="/"),o==="/health"&&s.method==="GET"){i(r,200,{service:"weave-daemon",version:DAEMON_VERSION,pid:process.pid,port:t.port,uptimeMs:Math.round(process.uptime()*1e3)});return}if(await ve(s,r,t,o)||await Pe(s,r,t,o))return;if(t.auth&&!Ce(s,o,t)&&!t.auth.isAuthenticated(s.headers)){i(r,401,{error:"Unauthorized"});return}if(await ne(s,r,t,o,u)||await oe(s,r,t,o,u)||await ce(s,r,t,o))return;const y=o.match(/^\/projects\/(\d+)\/hooks$/);if(y&&s.method==="GET"){if(!t.hookEvents){i(r,503,{error:"Hook ingestion unavailable"});return}const a=Number(y[1]),e=Me(u.searchParams.get("limit")),n=u.searchParams.get("sessionId"),c=u.searchParams.get("beforeId"),l=c?Number(c):void 0,d=(u.searchParams.get("types")??"").split(",").map(h=>h.trim()).filter(Boolean);if(n){i(r,200,{events:t.hookEvents.listBySession(n,e??300,l,d)});return}i(r,200,{events:t.hookEvents.listByProject(a,e)});return}if(o==="/settings"){if(s.method==="GET"){i(r,200,{settings:lr(await P(),t.aiKeyPath),presets:he(process.platform),platform:process.platform,urls:Ie(t.port,t.tlsPort??0)});return}if(s.method==="PUT"){let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}const e=a.ai?.apiKey;e!==void 0&&Ee(typeof e=="string"?e:null,t.aiKeyPath);const n=await fe({...a,ai:De(a.ai)});t.hookEvents?.resetPrune(),(t.autoStart??be)(n.startup?.launchOnLogin??!1),t.dataBus?.emit({key:"settings"}),i(r,200,lr(n,t.aiKeyPath));return}}const b=o.match(/^\/projects\/(\d+)\/open$/);if(b&&s.method==="POST"){const a=t.projects.getById(Number(b[1]));if(!a){i(r,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(e.target!=="explorer"&&e.target!=="terminal"){i(r,400,{error:'Invalid "target" (explorer|terminal)'});return}const n=t.opener??N;try{if(!(await j.promises.stat(a.path)).isDirectory())throw new Error(`Not a directory: ${a.path}`);if(e.target==="explorer")await n.openExplorer(a.path);else{const c=await P();await n.openTerminal(a.path,c.terminal),setTimeout(()=>{t.terminalRefresher?.refreshNow()},600)}i(r,200,{ok:!0,target:e.target,path:a.path})}catch(c){i(r,400,{error:c instanceof Error?c.message:"Open failed"})}return}const g=o.match(/^\/projects\/(\d+)\/new-session$/);if(g&&s.method==="POST"){const a=t.projects.getById(Number(g[1]));if(!a){i(r,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await f(s)||"{}")}catch{i(r,400,{error:"Invalid JSON body"});return}const n=await Te(a.path,t.harnesses);if(e.harness!==void 0&&!T(e.harness)){i(r,400,{error:'Invalid "harness"'});return}const c=e.harness;if(c&&!n.some(m=>m.id===c)){i(r,409,{error:`Harness "${c}" is not integrated in this project`});return}const l=c?[c]:n.map(m=>m.id),d=l.map(m=>({id:m,spec:t.harnesses?.get(m)?.resume})).find(m=>m.spec?.bin);if(!d){i(r,501,{error:`Harness "${l[0]}" cannot start an interactive session`});return}const h=d.spec,p=t.opener??N;try{if(!(await j.promises.stat(a.path)).isDirectory())throw new Error(`Not a directory: ${a.path}`);const m=await P();await p.runInTerminal(a.path,[h.bin],m.terminal),setTimeout(()=>{t.terminalRefresher?.refreshNow()},600),i(r,200,{ok:!0,command:h.bin,cwd:a.path})}catch(m){i(r,400,{error:m instanceof Error?m.message:"Open failed"})}return}if(o==="/fs/roots"&&s.method==="GET"){const a=t.libraries?t.libraries.list().map(n=>n.path):[],e=await de(a);i(r,200,{roots:e});return}if(o==="/fs/children"&&s.method==="GET"){const a=u.searchParams.get("path");if(!a){i(r,400,{error:'Missing "path" query parameter'});return}try{const e=await me(a);i(r,200,{children:e})}catch(e){i(r,400,{error:`Cannot list directory: ${String(e)}`})}return}if(o==="/capabilities"&&s.method==="GET"){i(r,200,jr());return}if(o==="/libraries"&&s.method==="GET"){i(r,200,{libraries:t.libraries?t.libraries.list():[]});return}if(o==="/libraries"&&s.method==="POST"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!a.path||!a.kind){i(r,400,{error:'Missing "path" or "kind"'});return}if(!["skill","mcp","both"].includes(a.kind)){i(r,400,{error:'Invalid "kind" (skill|mcp|both)'});return}const e=t.libraries.add({path:a.path,kind:a.kind});t.dataBus?.emit({key:"libraries"}),i(r,201,e);return}const w=o.match(/^\/libraries\/(\d+)\/assets$/);if(w&&s.method==="GET"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}const a=t.libraries.getById(Number(w[1]));if(!a){i(r,404,{error:"Library not found"});return}const{plugins:e,skills:n,mcp:c,files:l}=await Y(a.path),d=a.kind==="skill"||a.kind==="both"?e:[],h=a.kind==="mcp"||a.kind==="both"?c:[],p=a.kind==="skill"||a.kind==="both"?Object.values(l).flat():null;i(r,200,{library:a,skills:n,mcp:h,files:p,plugins:d});return}const J=o.match(/^\/libraries\/(\d+)$/);if(J&&s.method==="DELETE"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}const a=Number(J[1]),e=t.libraries.getById(a);e&&await k(e.path),t.libraries.remove(a),t.dataBus?.emit({key:"libraries"}),t.dataBus?.emit({key:"market"}),i(r,200,{ok:!0});return}if(o==="/market"&&s.method==="GET"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}const a=await Promise.all(t.libraries.list().map(e=>I(e,t.libraries.dataDir)));i(r,200,{items:a});return}if(o==="/market"&&s.method==="POST"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}const e={libraries:t.libraries,dataDir:t.libraries.dataDir};try{if(a.kind==="dir"&&a.path){const n=await Lr(a.path,e);n.refreshed&&t.fingerprintCache?.invalidate(n.dir),await k(n.dir),t.dataBus?.emit({key:"market"}),i(r,201,{item:await I(t.libraries.getById(n.libraryId),t.libraries.dataDir)})}else if(a.kind==="git"&&a.url){const n=await Rr(a.url,e);n.refreshed&&t.fingerprintCache?.invalidate(n.dir),await k(n.dir),t.dataBus?.emit({key:"market"}),i(r,201,{item:await I(t.libraries.getById(n.libraryId),t.libraries.dataDir)})}else i(r,400,{error:'Invalid body (kind: "dir" + path | "git" + url)'})}catch(n){i(r,400,{error:n instanceof Error?n.message:"Import failed"})}return}if(o==="/market/check-updates"&&s.method==="POST"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}let a={};const e=(await f(s)).trim();if(e)try{a=JSON.parse(e)}catch{i(r,400,{error:"Invalid JSON body"});return}const n=t.libraries.list().filter(l=>!v(l.path,t.libraries.dataDir)).filter(l=>!a.ids?.length||a.ids.includes(l.id));for(const l of n)await k(l.path);const c=await zr(n.map(l=>({id:l.id,dir:l.path})));t.dataBus?.emit({key:"market"}),i(r,200,{results:c});return}if(o==="/market/refresh"&&s.method==="POST"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}let a={};const e=(await f(s)).trim();if(e)try{a=JSON.parse(e)}catch{i(r,400,{error:"Invalid JSON body"});return}const n=t.libraries.list().filter(p=>!a.ids?.length||a.ids.includes(p.id)),c=[];for(const p of n.filter(m=>v(m.path,t.libraries.dataDir))){const m=await _r({libraries:t.libraries});c.push({id:p.id,status:m.error?"failed":"refreshed"})}const l=n.filter(p=>!v(p.path,t.libraries.dataDir)).map(p=>({id:p.id,dir:p.path})),d=[...await qr(l,{libraries:t.libraries,dataDir:t.libraries.dataDir}),...c],h=new Map(l.map(p=>[p.id,p.dir]));for(const p of d)if(p.status==="refreshed"){const m=h.get(p.id);m&&(t.fingerprintCache?.invalidate(m),await k(m))}t.dataBus?.emit({key:"market"}),i(r,200,{results:d});return}const M=o.match(/^\/market\/(\d+)$/);if(M&&s.method==="DELETE"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}const a=t.libraries.getById(Number(M[1]));if(!a){i(r,404,{error:"Library not found"});return}if(v(a.path,t.libraries.dataDir)){i(r,409,{error:"Built-in market is owned by weave and cannot be deleted",note:"It is re-materialized from @weavecode/templates on every daemon start."});return}if(!C(a.path,B(t.libraries.dataDir))){i(r,400,{error:"Not a market resource (legacy row \u2014 use DELETE /libraries/:id)"});return}let e;try{await(t.pluginSurface??or("claude")).removeMarketplace(a.path)}catch(n){e=`Host marketplace deregistration failed: ${n instanceof Error?n.message:String(n)}`}await Vr(a.path),t.libraries.remove(a.id),await k(a.path),t.dataBus?.emit({key:"market"}),t.dataBus?.emit({key:"libraries"}),i(r,200,{ok:!0,removed:a.path,installedCopiesKept:!0,...e?{warning:e}:{},note:"The host cascade-uninstalls plugins installed from this market; other installed copies are kept."});return}const $=o.match(/^\/libraries\/(\d+)\/market-import$/);if($&&s.method==="POST"){if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}const a=t.libraries.getById(Number($[1]));if(!a){i(r,404,{error:"Library not found"});return}try{const e=a.path,n=await Ur(a,{libraries:t.libraries,dataDir:t.libraries.dataDir});await k(e),await k(n.dir),i(r,200,{item:await I(t.libraries.getById(n.libraryId),t.libraries.dataDir)})}catch(e){i(r,400,{error:e instanceof Error?e.message:"Import failed"})}return}const A=o.match(/^\/projects\/(\d+)\/install$/);if(A&&s.method==="POST"){const a=t.projects.getById(Number(A[1]));if(!a){i(r,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}try{if(e.category==="skill"){if(!e.name||!e.sourceDir){i(r,400,{error:'Missing "name" or "sourceDir"'});return}const n=e.agent??"claude",c=e.scope==="user"?await Nr(e.sourceDir,e.name,n):await hr(a.path,e.sourceDir,e.name,n);i(r,201,{category:"skill",name:e.name,scope:e.scope??"project",agent:n,path:c})}else if(e.category&&rr(e.category)){if(!e.name||!e.sourceFile){i(r,400,{error:'Missing "name" or "sourceFile"'});return}const n=e.agent??"claude",c=e.scope??"project",l=await wr(a.path,e.category,e.name,e.sourceFile,n,c);i(r,201,{category:e.category,name:e.name,scope:c,agent:n,path:l})}else if(e.category==="mcp"){if(!e.name||!e.mcpConfig){i(r,400,{error:'Missing "name" or "mcpConfig"'});return}if(e.agent==="codex"){if(e.scope==="project"){i(r,400,{error:'Codex MCP servers are user-level (~/.codex/config.toml) \u2014 use scope "user"'});return}if(await Dr(e.name)){E(r,new Z(`MCP server "${e.name}" is already configured in ~/.codex/config.toml`));return}await Cr(e.name,e.mcpConfig)}else e.scope==="user"?await vr(e.name,e.mcpConfig):await yr(a.path,e.name,e.mcpConfig);i(r,201,{category:"mcp",name:e.name,scope:e.agent==="codex"?"user":e.scope??"project",agent:e.agent??"claude"})}else if(e.category==="plugin"){if(!e.name||!e.sourceDir){i(r,400,{error:'Missing "name" or "sourceDir"'});return}if(e.scope&&e.scope!=="user"){i(r,400,{error:'Plugin install currently only supports scope "user"'});return}const n=e.agent??"claude",c=nr().find(h=>h.harness===n);if(!c){i(r,400,{error:`No plugin install surface for runtime: ${n}`});return}const l=n==="claude"&&t.pluginSurface?t.pluginSurface:c.surface,d=await Se(l,{dir:e.sourceDir,name:e.name,version:e.version,description:e.description});t.dataBus?.emit({key:"toolkit"}),i(r,201,{category:"plugin",key:d.key,scope:"user",agent:n,alreadyInstalled:d.alreadyInstalled})}else i(r,400,{error:'Invalid "category" (skill|mcp|plugin|command|agent|workflow|rule|output-style)'})}catch(n){E(r,n)}return}const x=o.match(/^\/projects\/(\d+)\/uninstall$/);if(x&&s.method==="POST"){const a=t.projects.getById(Number(x[1]));if(!a){i(r,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}try{if(e.category==="skill"){if(!e.name){i(r,400,{error:'Missing "name"'});return}const n=e.agent??"claude";e.scope==="user"?await Er(e.name,n):await gr(a.path,e.name,n)}else if(e.category&&rr(e.category)){if(!e.name){i(r,400,{error:'Missing "name"'});return}await kr(a.path,e.category,e.name,e.agent??"claude",e.scope??"project")}else if(e.category==="mcp"){if(!e.name){i(r,400,{error:'Missing "name"'});return}if(e.agent==="codex"){if(!await Gr(e.name)){E(r,new O(`MCP server "${e.name}" is not configured in ~/.codex/config.toml`));return}}else e.scope==="user"?await Pr(e.name):await br(a.path,e.name)}else{i(r,400,{error:'Invalid "category" (skill|mcp|command|agent|workflow|rule|output-style)'});return}i(r,200,{ok:!0})}catch(n){E(r,n)}return}const F=o.match(/^\/projects\/(\d+)\/file$/);if(F&&s.method==="GET"){const a=t.projects.getById(Number(F[1]));if(!a){i(r,404,{error:"Project not found"});return}const e=u.searchParams.get("path");if(!e){i(r,400,{error:'Missing "path" query parameter'});return}try{const n=await Qr(a.path,e);i(r,200,{path:e,content:n.content,size:n.size})}catch(n){D(r,n)}return}if(o==="/global-file"&&s.method==="GET"){const a=u.searchParams.get("path");if(!a){i(r,400,{error:'Missing "path" query parameter'});return}try{const e=await Xr(a);i(r,200,{path:a,content:e.content,size:e.size})}catch(e){D(r,e)}return}const L=o.match(/^\/projects\/(\d+)\/mcp$/);if(L&&s.method==="GET"){const a=t.projects.getById(Number(L[1]));if(!a){i(r,404,{error:"Project not found"});return}i(r,200,{rows:await Sr(a.path)});return}const R=o.match(/^\/projects\/(\d+)\/harness-checks$/);if(R&&s.method==="GET"){const a=t.projects.getById(Number(R[1]));if(!a){i(r,404,{error:"Project not found"});return}i(r,200,{checks:await mr(a.path)});return}if(o.match(/^\/projects\/(\d+)\/skills\/global$/)&&s.method==="GET"){i(r,200,{groups:await Ir()});return}if(o.match(/^\/projects\/(\d+)\/skills\/global\/files$/)&&s.method==="GET"){const a=u.searchParams.get("source"),e=u.searchParams.get("name"),n=u.searchParams.get("pluginKey")??void 0;if(!a||!e){i(r,400,{error:'Missing "source" or "name" query parameter'});return}const c=await er(a,e,n);if(!c){i(r,404,{error:"Skill not found"});return}i(r,200,{files:await Tr(c)});return}if(o.match(/^\/projects\/(\d+)\/skills\/global\/file$/)&&s.method==="GET"){const a=u.searchParams.get("source"),e=u.searchParams.get("name"),n=u.searchParams.get("pluginKey")??void 0,c=u.searchParams.get("path");if(!a||!e||!c){i(r,400,{error:'Missing "source", "name" or "path" query parameter'});return}const l=await er(a,e,n);if(!l){i(r,404,{error:"Skill not found"});return}try{const d=await Or(l,c);i(r,200,{path:c,content:d.content,size:d.size})}catch(d){D(r,d)}return}const U=o.match(/^\/projects\/(\d+)\/plugins\/state$/);if(U){const a=t.projects.getById(Number(U[1]));if(!a){i(r,404,{error:"Project not found"});return}if(s.method==="GET"){i(r,200,{rows:await je(a.path)});return}if(s.method==="PUT"){let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!T(e.runtime)||!e.key||!e.scope||!["user","project","local"].includes(e.scope)||!e.state||!["on","off","inherit"].includes(e.state)){i(r,400,{error:'Missing or invalid "runtime"/"key"/"scope" (user|project|local)/"state" (on|off|inherit)'});return}const n=e.scope,c=e.state;try{const l=nr().find(d=>d.harness===e.runtime);if(l)await(e.runtime==="claude"&&t.pluginSurface?t.pluginSurface:l.surface).setEnabledOverride(a.path,n,e.key,c);else{const d=ke().find(h=>h.harness===e.runtime);if(!d||n!=="user"||c==="inherit"){i(r,400,{error:"This runtime only supports user-scope on/off overrides"});return}await d.state.writeGlobalEnabled(e.key,c==="on")}t.dataBus?.emit({key:"toolkit"}),i(r,200,{ok:!0})}catch(l){i(r,400,{error:l instanceof Error?l.message:"Plugin state write failed"})}return}}if(o.match(/^\/projects\/(\d+)\/plugins\/uninstall$/)&&s.method==="POST"){let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!T(a.runtime)||!a.key){i(r,400,{error:'Missing or invalid "runtime"/"key"'});return}try{const e=a.runtime==="claude"&&t.pluginSurface?t.pluginSurface:or(a.runtime),{name:n,market:c}=e.parsePluginKey(a.key);await e.uninstall(n,c),i(r,200,{ok:!0})}catch(e){i(r,400,{error:e instanceof Error?e.message:"Plugin uninstall failed"})}return}const H=o.match(/^\/projects\/(\d+)\/mcp\/enable$/);if(H){const a=t.projects.getById(Number(H[1]));if(!a){i(r,404,{error:"Project not found"});return}if(s.method==="PUT"){let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!e.name||!e.state){i(r,400,{error:'Missing "name" or "state"'});return}if(!["on","off","inherit"].includes(e.state)){i(r,400,{error:'Invalid "state" (on|off|inherit)'});return}await Mr(a.path,e.name,e.state),i(r,200,{ok:!0});return}}const K=o.match(/^\/projects\/(\d+)\/updates$/);if(K&&s.method==="GET"){const a=t.projects.getById(Number(K[1]));if(!a){i(r,404,{error:"Project not found"});return}const e=t.fingerprintCache??new G;if(!t.libraries){const c=await se(a.path,e);i(r,200,{skills:[],mcp:[],files:[],pluginTemplates:c,available:c.filter(l=>l.outdated).length});return}const n=await ie(a.path,t.libraries.list(),e);i(r,200,n);return}const W=o.match(/^\/projects\/(\d+)\/update$/);if(W&&s.method==="POST"){const a=t.projects.getById(Number(W[1]));if(!a){i(r,404,{error:"Project not found"});return}if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!e.category||!e.name||!e.scope){i(r,400,{error:'Missing "category", "name", or "scope"'});return}if(!["skill","mcp","command","agent","workflow","rule","output-style"].includes(e.category)){i(r,400,{error:'Invalid "category"'});return}try{const n=await Fr(t.libraries.list());await Ar(a.path,{category:e.category,name:e.name,scope:e.scope,agent:e.agent},n),i(r,200,{ok:!0,category:e.category,name:e.name,scope:e.scope})}catch(n){i(r,400,{error:n instanceof Error?n.message:"Update failed"})}return}const z=o.match(/^\/projects\/(\d+)\/sync-all$/);if(z&&s.method==="POST"){const a=t.projects.getById(Number(z[1]));if(!a){i(r,404,{error:"Project not found"});return}if(!t.libraries){i(r,503,{error:"Libraries unavailable"});return}try{const e=t.fingerprintCache??new G,n=await xr(a.path,t.libraries.list(),e);let c=n;try{const l=t.hookPlugins?.list().map(h=>h.id)??[],d=fr(a,l,{projects:t.projects});c={...n,pluginSync:{syncedAt:d}}}catch{}i(r,200,c),t.updatesRefresher?.refreshNow(!0)}catch(e){i(r,400,{error:e instanceof Error?e.message:"Sync failed"})}return}const q=o.match(/^\/projects\/(\d+)\/config$/);if(q){const a=t.projects.getById(Number(q[1]));if(!a){i(r,404,{error:"Project not found"});return}if(s.method==="GET"){i(r,200,await tr(a.path));return}if(s.method==="PUT"){let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}const n=await tr(a.path),c={autoSync:e.autoSync??n.autoSync,lastSyncAt:e.lastSyncAt??n.lastSyncAt};await $r(a.path,c),i(r,200,c);return}}if(o==="/statusline/global"){if(s.method==="GET"){i(r,200,{config:await sr()});return}if(s.method==="PUT"){let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}try{await te(a);for(const e of t.projects.list()){const n=await ar(e.path);n.source==="global"&&await ir(e.path,n)}t.dataBus?.emit({key:"statusline"}),i(r,200,{ok:!0})}catch(e){i(r,400,{error:e instanceof Error?e.message:"Global statusline update failed"})}return}}if(o==="/statusline/default"&&s.method==="GET"){i(r,200,{config:ae});return}const _=o.match(/^\/projects\/(\d+)\/statusline$/);if(_){const a=t.projects.getById(Number(_[1]));if(!a){i(r,404,{error:"Project not found"});return}if(s.method==="GET"){const[e,n,c]=await Promise.all([ar(a.path),ee(a.path),sr()]);i(r,200,{config:e,script:n,globalConfig:c});return}if(s.method==="PUT"){let e;try{e=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}try{await ir(a.path,e),t.dataBus?.emit({key:"statusline",projectPath:a.path}),i(r,200,{ok:!0})}catch(n){i(r,400,{error:n instanceof Error?n.message:"Statusline update failed"})}return}}if(o==="/events"&&s.method==="GET"){Be(s,r,t);return}if(o==="/assets"&&s.method==="GET"){const a=u.searchParams.get("path");if(!a){i(r,400,{error:'Missing "path" query parameter'});return}if(!t.watch){i(r,503,{error:"Watch service unavailable"});return}const e=await ue(a),n=t.watch.getAssets(a).map(c=>{const l=e.get(c.relPath);return l?{...c,namespace:l}:c});i(r,200,{projectPath:a,assets:n});return}if(o==="/global-file-assets"&&s.method==="GET"){i(r,200,{assets:await re()});return}if(o==="/projects"&&s.method==="GET"){i(r,200,{projects:await cr(t.projects.list(),t.harnesses)});return}if(o==="/projects/archived"&&s.method==="GET"){i(r,200,{projects:await cr(t.projects.listArchived(),t.harnesses)});return}const V=o.match(/^\/projects\/(\d+)\/archive$/);if(V&&s.method==="POST"){const a=t.projects.getById(Number(V[1]));if(!a){i(r,404,{error:"Project not found"});return}if(a.archivedAt){i(r,200,{project:a,purged:{events:0,dispatches:0,sessions:0,messages:0}});return}const e=t.hookDispatches?.deleteByProject(a.id)??0,n=t.hookEvents?.deleteByProject(a.id)??0,c=t.messageDeliverer?.forgetProject(a.id)??0;t.sessionWatches?.deleteByProject(a.id),t.sessionSequences?.deleteByProject(a.id);const l=t.hookSessions?.removeByProject(a.id)??0;t.projects.setArchived(a.id,!0),le(t.hooksDir??pr(),a.token),t.watch?.reconcile(),t.dataBus?.emit({key:"projects"}),i(r,200,{project:t.projects.getById(a.id),purged:{events:n,dispatches:e,sessions:l,messages:c}});return}const Q=o.match(/^\/projects\/(\d+)\/restore$/);if(Q&&s.method==="POST"){const a=t.projects.getById(Number(Q[1]));if(!a){i(r,404,{error:"Project not found"});return}if(!a.archivedAt){i(r,200,{project:a});return}t.projects.setArchived(a.id,!1),t.hookMirror?.syncProject(a.id),t.watch?.reconcile(),t.dataBus?.emit({key:"projects"}),i(r,200,{project:t.projects.getById(a.id)});return}if(o==="/projects/order"&&s.method==="PUT"){let a;try{a=JSON.parse(await f(s))}catch{i(r,400,{error:"Invalid JSON body"});return}if(!Array.isArray(a.ids)||!a.ids.every(e=>Number.isInteger(e))){i(r,400,{error:'Invalid "ids" (integer array expected)'});return}t.projects.setOrder(a.ids),t.dataBus?.emit({key:"projects"}),i(r,200,{projects:t.projects.list()});return}const X=o.match(/^\/projects\/(\d+)\/terminals$/);if(X&&s.method==="GET"){const a=t.projects.getById(Number(X[1]));if(!a){i(r,404,{error:"Project not found"});return}const e=await P(),n=t.opener?.listTerminals??N.listTerminals,c=ye(e.terminal).enumerable?await n(a.path,e.terminal):[];i(r,200,{projectId:a.id,terminals:c});return}if(o==="/terminals/counts"&&s.method==="GET"){if(t.terminalRefresher)i(r,200,{counts:t.terminalRefresher.lastSnapshot?.counts??{}}),t.terminalRefresher.tick(!0);else{const a=t.opener??N;i(r,200,{counts:await ge(t.projects.list(),a)})}return}if(s.method==="GET"&&t.staticDir){Ge(r,o,t.staticDir);return}i(r,404,{error:"Not found"})}function Be(s,r,t){if(!t.watch&&!t.hookBus&&!t.dataBus){r.statusCode=503,r.setHeader("content-type","application/json"),r.end(JSON.stringify({error:"Event stream unavailable"}));return}r.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"}),r.write(`: connected
|
|
1
|
+
import dt from"node:http";import{WEAVE_VERSION as pt}from"../version.js";import{checkHarness as gt,isHarness as M}from"@weavecode/core";import j from"node:fs";import S from"node:path";import{hooksRoot as yt}from"../hooks/mirror.js";import{syncPlugins as bt}from"../hooks/plugin-project-state.js";import{getLibraryScan as rt,invalidateScan as k}from"../install/scan-cache.js";import{installSkill as wt,uninstallSkill as kt,installMcp as jt,uninstallMcp as St,installFileAsset as vt,uninstallFileAsset as Pt,InstallConflictError as at,AssetNotFoundError as B}from"../install/installer.js";import{isFileAssetCategory as it}from"../install/file-assets.js";import{installCapabilities as It}from"../install/capabilities.js";import{readMcpRows as Nt}from"../install/mcp-rows.js";import{writeGlobalMcpServer as Et,removeGlobalMcpServer as Tt,installGlobalSkill as Ot,uninstallGlobalSkill as Mt,readGlobalSkillGroups as Bt,resolveGlobalSkillDir as ot,listGlobalSkillFiles as Ct,readGlobalSkillFile as Gt,ClaudeJsonCorruptError as Jt}from"../install/global-config.js";import{writeCodexMcpServer as At,removeCodexMcpServer as Dt,codexMcpExists as $t,CodexTomlCorruptError as Ft}from"../install/codex-toml.js";import{setMcpEnableOverride as xt}from"../install/settings-mcp.js";import{readProjectConfig as nt,writeProjectConfig as Lt}from"../install/project-config.js";import{applyUpdate as Rt,syncAll as Ut}from"../install/apply-update.js";import{buildLibraryIndex as Ht}from"../install/library-index.js";import{importFromDir as Kt,importFromGit as Wt,importLibraryIntoMarket as zt}from"../market/import.js";import{marketDir as C,readManifest as _t}from"../market/manifest.js";import{marketIdOf as Vt}from"../market/identity.js";import{isInsideDir as G,toRelPosix as Qt}from"../market/resolve.js";import{checkMarketUpdates as Xt}from"../market/updates.js";import{refreshMarketItems as Yt}from"../market/refresh.js";import{ensureBuiltinMarket as Zt,isBuiltinMarketDir as I}from"../market/builtin.js";import{removeInstalled as qt}from"../market/install-link.js";import{readProjectFile as te,readGlobalFile as ee,PathEscapeError as re,FileTooLargeError as ae}from"../install/reader.js";import{listGlobalFileAssets as ie}from"../install/global-file-assets.js";import{readStatuslineConfig as st,readStatuslineScript as oe,applyStatuslineConfig as ct,readGlobalStatuslineConfig as lt,writeGlobalStatuslineConfig as ne}from"../statusline/manager.js";import{DEFAULT_STATUSLINE_CONFIG as se}from"../statusline/config.js";import{FingerprintCache as J}from"../install/fingerprint.js";import{detectUpdates as ce}from"../install/updates.js";import{detectPluginTemplateUpdates as le}from"../install/plugin-templates.js";import{detectInitFileUpdates as ue,needsInit as me}from"../install/init-files.js";import{readBody as d,sendJson as i}from"./http.js";import{ApiLogger as fe}from"./api-log.js";import{handleHooksRoutes as he}from"./hooks-routes.js";import{handleToolkitRoutes as de}from"./toolkit-routes.js";import{handleCaptureRoutes as pe}from"./capture-routes.js";import{purgeProjectPipeline as ge}from"./hook-pipeline.js";import{projectFileNamespaces as ye}from"../hooks/toolkit.js";import{listBrowseRoots as be,listDirectoryChildren as we}from"./fs-browser.js";import{DEFAULT_AI_SETTINGS as ke,readDaemonSettings as v,writeDaemonSettings as je,terminalPresetsFor as Se}from"./settings.js";import{closeTerminalsIn as ve,defaultProjectOpener as P,readTerminalCounts as Pe,terminalBackendFor as Ie}from"./opener.js";import{applyLaunchOnLogin as Ne}from"./auto-start.js";import{DAEMON_HOST as Ee}from"./port.js";import{pluginStateSurfaces as Te,pluginSurfaces as ut,pluginSurfaceFor as mt}from"../surfaces.js";import{readPluginRows as Oe}from"../install/plugin-rows.js";import{installPluginPack as Me}from"../install/plugin-install.js";import{handleAuthRoutes as Be}from"./auth-routes.js";import{handleAiRoutes as Ce}from"./ai-routes.js";import{hasAiKey as Ge,writeAiKey as Je}from"./ai-config.js";import{accessUrls as Ae}from"./tls.js";import{projectHarnesses as De,withProjectHarnesses as ft}from"./project-harnesses.js";export const DAEMON_VERSION=pt;export function weaveRequestHandler(o){const t=o.fingerprintCache??new J,r=o.apiLog??new fe,u={...o,fingerprintCache:t,apiLog:r};return(s,g)=>{r.begin(s,g),$e(s,g,u)}}export function createWeaveServer(o){return dt.createServer(weaveRequestHandler(o))}async function $e(o,t,r){const u=new URL(o.url??"/",`http://${Ee}`);let s=u.pathname;if(s.startsWith("/api/")?s=s.slice(4):s==="/api"&&(s="/"),s==="/health"&&o.method==="GET"){i(t,200,{service:"weave-daemon",version:DAEMON_VERSION,pid:process.pid,port:r.port,uptimeMs:Math.round(process.uptime()*1e3)});return}if(await Be(o,t,r,s)||await Ce(o,t,r,s))return;if(r.auth&&!xe(o,s,r)&&!r.auth.isAuthenticated(o.headers)){i(t,401,{error:"Unauthorized"});return}if(s==="/api-logs"&&o.method==="GET"){if(!r.apiLog){i(t,503,{error:"API log unavailable"});return}const a=u.searchParams.get("status"),e=u.searchParams.get("limit"),n=await r.apiLog.query({from:u.searchParams.get("from")??void 0,to:u.searchParams.get("to")??void 0,path:u.searchParams.get("path")??void 0,method:u.searchParams.get("method")??void 0,status:a==null?void 0:Number(a),limit:e==null?void 0:Number(e)});i(t,200,n);return}if(await he(o,t,r,s,u)||await de(o,t,r,s,u)||await pe(o,t,r,s))return;const g=s.match(/^\/projects\/(\d+)\/hooks$/);if(g&&o.method==="GET"){if(!r.hookEvents){i(t,503,{error:"Hook ingestion unavailable"});return}const a=Number(g[1]),e=Ke(u.searchParams.get("limit")),n=u.searchParams.get("sessionId"),c=u.searchParams.get("beforeId"),l=c?Number(c):void 0,m=(u.searchParams.get("types")??"").split(",").map(p=>p.trim()).filter(Boolean);if(n){const p=r.hookEvents.listBySession(n,e??300,l,m),h=r.uploads?.imagesBySession(n);i(t,200,{events:p.map(f=>{const N=h?.get(f.id);return N?.length?{...f,images:N.map(O=>({id:O.id,name:O.name,mediaType:O.mediaType}))}:f})});return}i(t,200,{events:r.hookEvents.listByProject(a,e)});return}if(s==="/settings"){if(o.method==="GET"){i(t,200,{settings:ht(await v(),r.aiKeyPath),presets:Se(process.platform),platform:process.platform,urls:Ae(r.port,r.tlsPort??0)});return}if(o.method==="PUT"){let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}const e=a.ai?.apiKey;e!==void 0&&Je(typeof e=="string"?e:null,r.aiKeyPath);const n=await je({...a,ai:Ue(a.ai)});r.hookEvents?.resetPrune(),(r.autoStart??Ne)(n.startup?.launchOnLogin??!1),r.dataBus?.emit({key:"settings"}),i(t,200,ht(n,r.aiKeyPath));return}}const b=s.match(/^\/projects\/(\d+)\/open$/);if(b&&o.method==="POST"){const a=r.projects.getById(Number(b[1]));if(!a){i(t,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(e.target!=="explorer"&&e.target!=="terminal"){i(t,400,{error:'Invalid "target" (explorer|terminal)'});return}const n=r.opener??P;try{if(!(await j.promises.stat(a.path)).isDirectory())throw new Error(`Not a directory: ${a.path}`);if(e.target==="explorer")await n.openExplorer(a.path);else{const l=await v();await n.openTerminal(a.path,l.terminal),setTimeout(()=>{r.terminalRefresher?.refreshNow()},600)}i(t,200,{ok:!0,target:e.target,path:a.path})}catch(c){i(t,400,{error:c instanceof Error?c.message:"Open failed"})}return}const y=s.match(/^\/projects\/(\d+)\/close-terminal$/);if(y&&o.method==="POST"){const a=r.projects.getById(Number(y[1]));if(!a){i(t,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await d(o)||"{}")}catch{i(t,400,{error:"Invalid JSON body"});return}if(!Array.isArray(e.paneIds)||e.paneIds.length===0||e.paneIds.some(l=>typeof l!="string")){i(t,400,{error:"paneIds must be a non-empty array of strings"});return}const n=r.opener??P,c=await v();try{const m=await(n.closeTerminals??ve)(a.path,c.terminal,e.paneIds);setTimeout(()=>{r.terminalRefresher?.refreshNow()},600),i(t,200,{ok:!0,closed:m})}catch(l){i(t,400,{error:l instanceof Error?l.message:"Close failed"})}return}const w=s.match(/^\/projects\/(\d+)\/new-session$/);if(w&&o.method==="POST"){const a=r.projects.getById(Number(w[1]));if(!a){i(t,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await d(o)||"{}")}catch{i(t,400,{error:"Invalid JSON body"});return}const n=await De(a.path,r.harnesses);if(e.harness!==void 0&&!M(e.harness)){i(t,400,{error:'Invalid "harness"'});return}const c=e.harness;if(c&&!n.some(f=>f.id===c)){i(t,409,{error:`Harness "${c}" is not integrated in this project`});return}const l=c?[c]:n.map(f=>f.id),m=l.map(f=>({id:f,spec:r.harnesses?.get(f)?.resume})).find(f=>f.spec?.bin);if(!m){i(t,501,{error:`Harness "${l[0]}" cannot start an interactive session`});return}const p=m.spec,h=r.opener??P;try{if(!(await j.promises.stat(a.path)).isDirectory())throw new Error(`Not a directory: ${a.path}`);const N=await v();await h.runInTerminal(a.path,[p.bin],N.terminal),setTimeout(()=>{r.terminalRefresher?.refreshNow()},600),i(t,200,{ok:!0,command:p.bin,cwd:a.path})}catch(f){i(t,400,{error:f instanceof Error?f.message:"Open failed"})}return}if(s==="/fs/roots"&&o.method==="GET"){const a=r.libraries?r.libraries.list().map(n=>n.path):[],e=await be(a);i(t,200,{roots:e});return}if(s==="/fs/children"&&o.method==="GET"){const a=u.searchParams.get("path");if(!a){i(t,400,{error:'Missing "path" query parameter'});return}try{const e=await we(a);i(t,200,{children:e})}catch(e){i(t,400,{error:`Cannot list directory: ${String(e)}`})}return}if(s==="/capabilities"&&o.method==="GET"){i(t,200,It());return}if(s==="/libraries"&&o.method==="GET"){i(t,200,{libraries:r.libraries?r.libraries.list():[]});return}if(s==="/libraries"&&o.method==="POST"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!a.path||!a.kind){i(t,400,{error:'Missing "path" or "kind"'});return}if(!["skill","mcp","both"].includes(a.kind)){i(t,400,{error:'Invalid "kind" (skill|mcp|both)'});return}const e=r.libraries.add({path:a.path,kind:a.kind});r.dataBus?.emit({key:"libraries"}),i(t,201,e);return}const D=s.match(/^\/libraries\/(\d+)\/assets$/);if(D&&o.method==="GET"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}const a=r.libraries.getById(Number(D[1]));if(!a){i(t,404,{error:"Library not found"});return}const{plugins:e,skills:n,mcp:c,files:l}=await rt(a.path),m=a.kind==="skill"||a.kind==="both"?e:[],p=a.kind==="mcp"||a.kind==="both"?c:[],h=a.kind==="skill"||a.kind==="both"?Object.values(l).flat():null;i(t,200,{library:a,skills:n,mcp:p,files:h,plugins:m});return}const $=s.match(/^\/libraries\/(\d+)$/);if($&&o.method==="DELETE"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}const a=Number($[1]),e=r.libraries.getById(a);e&&await k(e.path),r.libraries.remove(a),r.dataBus?.emit({key:"libraries"}),r.dataBus?.emit({key:"market"}),i(t,200,{ok:!0});return}if(s==="/market"&&o.method==="GET"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}const a=await Promise.all(r.libraries.list().map(e=>T(e,r.libraries.dataDir)));i(t,200,{items:a});return}if(s==="/market"&&o.method==="POST"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}const e={libraries:r.libraries,dataDir:r.libraries.dataDir};try{if(a.kind==="dir"&&a.path){const n=await Kt(a.path,e);n.refreshed&&r.fingerprintCache?.invalidate(n.dir),await k(n.dir),r.dataBus?.emit({key:"market"}),i(t,201,{item:await T(r.libraries.getById(n.libraryId),r.libraries.dataDir)})}else if(a.kind==="git"&&a.url){const n=await Wt(a.url,e);n.refreshed&&r.fingerprintCache?.invalidate(n.dir),await k(n.dir),r.dataBus?.emit({key:"market"}),i(t,201,{item:await T(r.libraries.getById(n.libraryId),r.libraries.dataDir)})}else i(t,400,{error:'Invalid body (kind: "dir" + path | "git" + url)'})}catch(n){i(t,400,{error:n instanceof Error?n.message:"Import failed"})}return}if(s==="/market/check-updates"&&o.method==="POST"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}let a={};const e=(await d(o)).trim();if(e)try{a=JSON.parse(e)}catch{i(t,400,{error:"Invalid JSON body"});return}const n=r.libraries.list().filter(l=>!I(l.path,r.libraries.dataDir)).filter(l=>!a.ids?.length||a.ids.includes(l.id));for(const l of n)await k(l.path);const c=await Xt(n.map(l=>({id:l.id,dir:l.path})));r.dataBus?.emit({key:"market"}),i(t,200,{results:c});return}if(s==="/market/refresh"&&o.method==="POST"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}let a={};const e=(await d(o)).trim();if(e)try{a=JSON.parse(e)}catch{i(t,400,{error:"Invalid JSON body"});return}const n=r.libraries.list().filter(h=>!a.ids?.length||a.ids.includes(h.id)),c=[];for(const h of n.filter(f=>I(f.path,r.libraries.dataDir))){const f=await Zt({libraries:r.libraries});c.push({id:h.id,status:f.error?"failed":"refreshed"})}const l=n.filter(h=>!I(h.path,r.libraries.dataDir)).map(h=>({id:h.id,dir:h.path})),m=[...await Yt(l,{libraries:r.libraries,dataDir:r.libraries.dataDir}),...c],p=new Map(l.map(h=>[h.id,h.dir]));for(const h of m)if(h.status==="refreshed"){const f=p.get(h.id);f&&(r.fingerprintCache?.invalidate(f),await k(f))}r.dataBus?.emit({key:"market"}),i(t,200,{results:m});return}const F=s.match(/^\/market\/(\d+)$/);if(F&&o.method==="DELETE"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}const a=r.libraries.getById(Number(F[1]));if(!a){i(t,404,{error:"Library not found"});return}if(I(a.path,r.libraries.dataDir)){i(t,409,{error:"Built-in market is owned by weave and cannot be deleted",note:"It is re-materialized from @weavecode/templates on every daemon start."});return}if(!G(a.path,C(r.libraries.dataDir))){i(t,400,{error:"Not a market resource (legacy row \u2014 use DELETE /libraries/:id)"});return}let e;try{await(r.pluginSurface??mt("claude")).removeMarketplace(a.path)}catch(n){e=`Host marketplace deregistration failed: ${n instanceof Error?n.message:String(n)}`}await qt(a.path),r.libraries.remove(a.id),await k(a.path),r.dataBus?.emit({key:"market"}),r.dataBus?.emit({key:"libraries"}),i(t,200,{ok:!0,removed:a.path,installedCopiesKept:!0,...e?{warning:e}:{},note:"The host cascade-uninstalls plugins installed from this market; other installed copies are kept."});return}const x=s.match(/^\/libraries\/(\d+)\/market-import$/);if(x&&o.method==="POST"){if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}const a=r.libraries.getById(Number(x[1]));if(!a){i(t,404,{error:"Library not found"});return}try{const e=a.path,n=await zt(a,{libraries:r.libraries,dataDir:r.libraries.dataDir});await k(e),await k(n.dir),i(t,200,{item:await T(r.libraries.getById(n.libraryId),r.libraries.dataDir)})}catch(e){i(t,400,{error:e instanceof Error?e.message:"Import failed"})}return}const L=s.match(/^\/projects\/(\d+)\/install$/);if(L&&o.method==="POST"){const a=r.projects.getById(Number(L[1]));if(!a){i(t,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}try{if(e.category==="skill"){if(!e.name||!e.sourceDir){i(t,400,{error:'Missing "name" or "sourceDir"'});return}const n=e.agent??"claude",c=e.scope==="user"?await Ot(e.sourceDir,e.name,n):await wt(a.path,e.sourceDir,e.name,n);i(t,201,{category:"skill",name:e.name,scope:e.scope??"project",agent:n,path:c})}else if(e.category&&it(e.category)){if(!e.name||!e.sourceFile){i(t,400,{error:'Missing "name" or "sourceFile"'});return}const n=e.agent??"claude",c=e.scope??"project",l=await vt(a.path,e.category,e.name,e.sourceFile,n,c);i(t,201,{category:e.category,name:e.name,scope:c,agent:n,path:l})}else if(e.category==="mcp"){if(!e.name||!e.mcpConfig){i(t,400,{error:'Missing "name" or "mcpConfig"'});return}if(e.agent==="codex"){if(e.scope==="project"){i(t,400,{error:'Codex MCP servers are user-level (~/.codex/config.toml) \u2014 use scope "user"'});return}if(await $t(e.name)){E(t,new at(`MCP server "${e.name}" is already configured in ~/.codex/config.toml`));return}await At(e.name,e.mcpConfig)}else e.scope==="user"?await Et(e.name,e.mcpConfig):await jt(a.path,e.name,e.mcpConfig);i(t,201,{category:"mcp",name:e.name,scope:e.agent==="codex"?"user":e.scope??"project",agent:e.agent??"claude"})}else if(e.category==="plugin"){if(!e.name||!e.sourceDir){i(t,400,{error:'Missing "name" or "sourceDir"'});return}if(e.scope&&e.scope!=="user"){i(t,400,{error:'Plugin install currently only supports scope "user"'});return}const n=e.agent??"claude",c=ut().find(p=>p.harness===n);if(!c){i(t,400,{error:`No plugin install surface for runtime: ${n}`});return}const l=n==="claude"&&r.pluginSurface?r.pluginSurface:c.surface,m=await Me(l,{dir:e.sourceDir,name:e.name,version:e.version,description:e.description});r.dataBus?.emit({key:"toolkit"}),i(t,201,{category:"plugin",key:m.key,scope:"user",agent:n,alreadyInstalled:m.alreadyInstalled})}else i(t,400,{error:'Invalid "category" (skill|mcp|plugin|command|agent|workflow|rule|output-style)'})}catch(n){E(t,n)}return}const R=s.match(/^\/projects\/(\d+)\/uninstall$/);if(R&&o.method==="POST"){const a=r.projects.getById(Number(R[1]));if(!a){i(t,404,{error:"Project not found"});return}let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}try{if(e.category==="skill"){if(!e.name){i(t,400,{error:'Missing "name"'});return}const n=e.agent??"claude";e.scope==="user"?await Mt(e.name,n):await kt(a.path,e.name,n)}else if(e.category&&it(e.category)){if(!e.name){i(t,400,{error:'Missing "name"'});return}await Pt(a.path,e.category,e.name,e.agent??"claude",e.scope??"project")}else if(e.category==="mcp"){if(!e.name){i(t,400,{error:'Missing "name"'});return}if(e.agent==="codex"){if(!await Dt(e.name)){E(t,new B(`MCP server "${e.name}" is not configured in ~/.codex/config.toml`));return}}else e.scope==="user"?await Tt(e.name):await St(a.path,e.name)}else{i(t,400,{error:'Invalid "category" (skill|mcp|command|agent|workflow|rule|output-style)'});return}i(t,200,{ok:!0})}catch(n){E(t,n)}return}const U=s.match(/^\/projects\/(\d+)\/file$/);if(U&&o.method==="GET"){const a=r.projects.getById(Number(U[1]));if(!a){i(t,404,{error:"Project not found"});return}const e=u.searchParams.get("path");if(!e){i(t,400,{error:'Missing "path" query parameter'});return}try{const n=await te(a.path,e);i(t,200,{path:e,content:n.content,size:n.size})}catch(n){A(t,n)}return}if(s==="/global-file"&&o.method==="GET"){const a=u.searchParams.get("path");if(!a){i(t,400,{error:'Missing "path" query parameter'});return}try{const e=await ee(a);i(t,200,{path:a,content:e.content,size:e.size})}catch(e){A(t,e)}return}const H=s.match(/^\/projects\/(\d+)\/mcp$/);if(H&&o.method==="GET"){const a=r.projects.getById(Number(H[1]));if(!a){i(t,404,{error:"Project not found"});return}i(t,200,{rows:await Nt(a.path)});return}const K=s.match(/^\/projects\/(\d+)\/harness-checks$/);if(K&&o.method==="GET"){const a=r.projects.getById(Number(K[1]));if(!a){i(t,404,{error:"Project not found"});return}i(t,200,{checks:await gt(a.path)});return}if(s.match(/^\/projects\/(\d+)\/skills\/global$/)&&o.method==="GET"){i(t,200,{groups:await Bt()});return}if(s.match(/^\/projects\/(\d+)\/skills\/global\/files$/)&&o.method==="GET"){const a=u.searchParams.get("source"),e=u.searchParams.get("name"),n=u.searchParams.get("pluginKey")??void 0;if(!a||!e){i(t,400,{error:'Missing "source" or "name" query parameter'});return}const c=await ot(a,e,n);if(!c){i(t,404,{error:"Skill not found"});return}i(t,200,{files:await Ct(c)});return}if(s.match(/^\/projects\/(\d+)\/skills\/global\/file$/)&&o.method==="GET"){const a=u.searchParams.get("source"),e=u.searchParams.get("name"),n=u.searchParams.get("pluginKey")??void 0,c=u.searchParams.get("path");if(!a||!e||!c){i(t,400,{error:'Missing "source", "name" or "path" query parameter'});return}const l=await ot(a,e,n);if(!l){i(t,404,{error:"Skill not found"});return}try{const m=await Gt(l,c);i(t,200,{path:c,content:m.content,size:m.size})}catch(m){A(t,m)}return}const W=s.match(/^\/projects\/(\d+)\/plugins\/state$/);if(W){const a=r.projects.getById(Number(W[1]));if(!a){i(t,404,{error:"Project not found"});return}if(o.method==="GET"){i(t,200,{rows:await Oe(a.path)});return}if(o.method==="PUT"){let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!M(e.runtime)||!e.key||!e.scope||!["user","project","local"].includes(e.scope)||!e.state||!["on","off","inherit"].includes(e.state)){i(t,400,{error:'Missing or invalid "runtime"/"key"/"scope" (user|project|local)/"state" (on|off|inherit)'});return}const n=e.scope,c=e.state;try{const l=ut().find(m=>m.harness===e.runtime);if(l)await(e.runtime==="claude"&&r.pluginSurface?r.pluginSurface:l.surface).setEnabledOverride(a.path,n,e.key,c);else{const m=Te().find(p=>p.harness===e.runtime);if(!m||n!=="user"||c==="inherit"){i(t,400,{error:"This runtime only supports user-scope on/off overrides"});return}await m.state.writeGlobalEnabled(e.key,c==="on")}r.dataBus?.emit({key:"toolkit"}),i(t,200,{ok:!0})}catch(l){i(t,400,{error:l instanceof Error?l.message:"Plugin state write failed"})}return}}if(s.match(/^\/projects\/(\d+)\/plugins\/uninstall$/)&&o.method==="POST"){let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!M(a.runtime)||!a.key){i(t,400,{error:'Missing or invalid "runtime"/"key"'});return}try{const e=a.runtime==="claude"&&r.pluginSurface?r.pluginSurface:mt(a.runtime),{name:n,market:c}=e.parsePluginKey(a.key);await e.uninstall(n,c),i(t,200,{ok:!0})}catch(e){i(t,400,{error:e instanceof Error?e.message:"Plugin uninstall failed"})}return}const z=s.match(/^\/projects\/(\d+)\/mcp\/enable$/);if(z){const a=r.projects.getById(Number(z[1]));if(!a){i(t,404,{error:"Project not found"});return}if(o.method==="PUT"){let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!e.name||!e.state){i(t,400,{error:'Missing "name" or "state"'});return}if(!["on","off","inherit"].includes(e.state)){i(t,400,{error:'Invalid "state" (on|off|inherit)'});return}await xt(a.path,e.name,e.state),i(t,200,{ok:!0});return}}const _=s.match(/^\/projects\/(\d+)\/updates$/);if(_&&o.method==="GET"){const a=r.projects.getById(Number(_[1]));if(!a){i(t,404,{error:"Project not found"});return}const e=r.fingerprintCache??new J;if(!r.libraries){const c=await le(a.path,e),l=await ue(a.path);i(t,200,{skills:[],mcp:[],files:[],pluginTemplates:c,initFiles:l,available:c.filter(m=>m.outdated).length+l.filter(m=>m.outdated&&m.syncClass==="auto").length,needsInit:me(l)});return}const n=await ce(a.path,r.libraries.list(),e);i(t,200,n);return}const V=s.match(/^\/projects\/(\d+)\/update$/);if(V&&o.method==="POST"){const a=r.projects.getById(Number(V[1]));if(!a){i(t,404,{error:"Project not found"});return}if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!e.category||!e.name||!e.scope){i(t,400,{error:'Missing "category", "name", or "scope"'});return}if(!["skill","mcp","command","agent","workflow","rule","output-style"].includes(e.category)){i(t,400,{error:'Invalid "category"'});return}try{const c=await Ht(r.libraries.list());await Rt(a.path,{category:e.category,name:e.name,scope:e.scope,agent:e.agent},c),i(t,200,{ok:!0,category:e.category,name:e.name,scope:e.scope})}catch(c){i(t,400,{error:c instanceof Error?c.message:"Update failed"})}return}const Q=s.match(/^\/projects\/(\d+)\/sync-all$/);if(Q&&o.method==="POST"){const a=r.projects.getById(Number(Q[1]));if(!a){i(t,404,{error:"Project not found"});return}if(!r.libraries){i(t,503,{error:"Libraries unavailable"});return}try{const e=r.fingerprintCache??new J,n=await Ut(a.path,r.libraries.list(),e);let c=n;try{const l=r.hookPlugins?.list().map(p=>p.id)??[],m=bt(a,l,{projects:r.projects});c={...n,pluginSync:{syncedAt:m}}}catch{}i(t,200,c),r.updatesRefresher?.refreshNow(!0)}catch(e){i(t,400,{error:e instanceof Error?e.message:"Sync failed"})}return}const X=s.match(/^\/projects\/(\d+)\/config$/);if(X){const a=r.projects.getById(Number(X[1]));if(!a){i(t,404,{error:"Project not found"});return}if(o.method==="GET"){i(t,200,await nt(a.path));return}if(o.method==="PUT"){let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}const n=await nt(a.path),c={lastSyncAt:e.lastSyncAt??n.lastSyncAt};await Lt(a.path,c),i(t,200,c);return}}if(s==="/statusline/global"){if(o.method==="GET"){i(t,200,{config:await lt()});return}if(o.method==="PUT"){let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}try{await ne(a);for(const e of r.projects.list()){const n=await st(e.path);n.source==="global"&&await ct(e.path,n)}r.dataBus?.emit({key:"statusline"}),i(t,200,{ok:!0})}catch(e){i(t,400,{error:e instanceof Error?e.message:"Global statusline update failed"})}return}}if(s==="/statusline/default"&&o.method==="GET"){i(t,200,{config:se});return}const Y=s.match(/^\/projects\/(\d+)\/statusline$/);if(Y){const a=r.projects.getById(Number(Y[1]));if(!a){i(t,404,{error:"Project not found"});return}if(o.method==="GET"){const[e,n,c]=await Promise.all([st(a.path),oe(a.path),lt()]);i(t,200,{config:e,script:n,globalConfig:c});return}if(o.method==="PUT"){let e;try{e=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}try{await ct(a.path,e),r.dataBus?.emit({key:"statusline",projectPath:a.path}),i(t,200,{ok:!0})}catch(n){i(t,400,{error:n instanceof Error?n.message:"Statusline update failed"})}return}}if(s==="/events"&&o.method==="GET"){Fe(o,t,r);return}if(s==="/assets"&&o.method==="GET"){const a=u.searchParams.get("path");if(!a){i(t,400,{error:'Missing "path" query parameter'});return}if(!r.watch){i(t,503,{error:"Watch service unavailable"});return}const e=await ye(a),n=r.watch.getAssets(a).map(c=>{const l=e.get(c.relPath);return l?{...c,namespace:l}:c});i(t,200,{projectPath:a,assets:n});return}if(s==="/global-file-assets"&&o.method==="GET"){i(t,200,{assets:await ie()});return}if(s==="/projects"&&o.method==="GET"){i(t,200,{projects:await ft(r.projects.list(),r.harnesses)});return}if(s==="/projects/archived"&&o.method==="GET"){i(t,200,{projects:await ft(r.projects.listArchived(),r.harnesses)});return}const Z=s.match(/^\/projects\/(\d+)\/archive$/);if(Z&&o.method==="POST"){const a=r.projects.getById(Number(Z[1]));if(!a){i(t,404,{error:"Project not found"});return}if(a.archivedAt){i(t,200,{project:a,purged:{events:0,dispatches:0,sessions:0,messages:0}});return}const e=r.hookDispatches?.deleteByProject(a.id)??0,n=r.hookEvents?.deleteByProject(a.id)??0;r.uploads?.pruneUnreferenced();const c=r.messageDeliverer?.forgetProject(a.id)??0;r.sessionWatches?.deleteByProject(a.id),r.sessionSequences?.deleteByProject(a.id);const l=r.hookSessions?.removeByProject(a.id)??0;r.projects.setArchived(a.id,!0),ge(r.hooksDir??yt(),a.token),r.watch?.reconcile(),r.dataBus?.emit({key:"projects"}),i(t,200,{project:r.projects.getById(a.id),purged:{events:n,dispatches:e,sessions:l,messages:c}});return}const q=s.match(/^\/projects\/(\d+)\/restore$/);if(q&&o.method==="POST"){const a=r.projects.getById(Number(q[1]));if(!a){i(t,404,{error:"Project not found"});return}if(!a.archivedAt){i(t,200,{project:a});return}r.projects.setArchived(a.id,!1),r.hookMirror?.syncProject(a.id),r.watch?.reconcile(),r.dataBus?.emit({key:"projects"}),i(t,200,{project:r.projects.getById(a.id)});return}if(s==="/projects/order"&&o.method==="PUT"){let a;try{a=JSON.parse(await d(o))}catch{i(t,400,{error:"Invalid JSON body"});return}if(!Array.isArray(a.ids)||!a.ids.every(e=>Number.isInteger(e))){i(t,400,{error:'Invalid "ids" (integer array expected)'});return}r.projects.setOrder(a.ids),r.dataBus?.emit({key:"projects"}),i(t,200,{projects:r.projects.list()});return}const tt=s.match(/^\/projects\/(\d+)\/panes$/);if(tt&&o.method==="GET"){const a=r.projects.getById(Number(tt[1]));if(!a){i(t,404,{error:"Project not found"});return}const e=await v(),n=r.opener?.listPanes??P.listPanes;try{i(t,200,{projectId:a.id,panes:await n(a.path,e.terminal)})}catch(c){i(t,409,{error:c instanceof Error?c.message:"Cannot list panes"})}return}const et=s.match(/^\/projects\/(\d+)\/terminals$/);if(et&&o.method==="GET"){const a=r.projects.getById(Number(et[1]));if(!a){i(t,404,{error:"Project not found"});return}const e=await v(),n=r.opener?.listTerminals??P.listTerminals,c=Ie(e.terminal).enumerable?await n(a.path,e.terminal):[];i(t,200,{projectId:a.id,terminals:c});return}if(s==="/terminals/counts"&&o.method==="GET"){if(r.terminalRefresher)i(t,200,{counts:r.terminalRefresher.lastSnapshot?.counts??{}}),r.terminalRefresher.tick(!0);else{const a=r.opener??P;i(t,200,{counts:await Pe(r.projects.list(),a)})}return}if(o.method==="GET"&&r.staticDir){Re(t,s,r.staticDir);return}i(t,404,{error:"Not found"})}function Fe(o,t,r){if(!r.watch&&!r.hookBus&&!r.dataBus){t.statusCode=503,t.setHeader("content-type","application/json"),t.end(JSON.stringify({error:"Event stream unavailable"}));return}t.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive","x-accel-buffering":"no"}),t.write(`: connected
|
|
2
2
|
|
|
3
|
-
`);const u=[];
|
|
3
|
+
`);const u=[];r.watch&&(u.push(r.watch.subscribe(s=>{t.write(`data: ${JSON.stringify({type:"asset",...s})}
|
|
4
4
|
|
|
5
|
-
`)})),u.push(
|
|
5
|
+
`)})),u.push(r.watch.subscribeProjects(s=>{t.write(`data: ${JSON.stringify({type:"project",...s})}
|
|
6
6
|
|
|
7
|
-
`)}))),
|
|
7
|
+
`)}))),r.hookBus&&u.push(r.hookBus.subscribe(s=>{t.write(`data: ${JSON.stringify({type:"hook",...s})}
|
|
8
8
|
|
|
9
|
-
`)})),
|
|
9
|
+
`)})),r.dataBus&&u.push(r.dataBus.subscribe(s=>{const g=s.payload===void 0?"invalidate":"push";t.write(`data: ${JSON.stringify({type:g,...s})}
|
|
10
10
|
|
|
11
|
-
`)})),
|
|
11
|
+
`)})),r.inflightRefresher?.refreshNow(),r.terminalRefresher?.onSubscriberJoin(),r.updatesRefresher?.onSubscriberJoin(),o.on("close",()=>{for(const s of u)s()})}function xe(o,t,r){if(t==="/health")return!0;if(o.method!=="GET")return!1;if((o.headers.accept??"").includes("text/html"))return!0;if(!r.staticDir)return!1;const u=S.normalize(t).replace(/^([/\\]\.\.[/\\])+/,""),s=S.join(r.staticDir,u);return s.startsWith(r.staticDir)&&j.existsSync(s)&&j.statSync(s).isFile()}function Le(o,t){o.setHeader("cache-control",t.startsWith("/assets/")?"public, max-age=31536000, immutable":"no-cache")}function Re(o,t,r){const u=S.normalize(t).replace(/^([/\\]\.\.[/\\])+/,""),s=S.join(r,u);if(!s.startsWith(r)){o.statusCode=403,o.setHeader("content-type","application/json"),o.end(JSON.stringify({error:"Forbidden"}));return}j.stat(s,(g,b)=>{if(!g&&b.isFile()){o.setHeader("content-type",He(s)),Le(o,t),o.setHeader("content-length",String(b.size)),j.createReadStream(s).pipe(o);return}j.readFile(S.join(r,"index.html"),(y,w)=>{if(y){o.statusCode=404,o.setHeader("content-type","application/json"),o.end(JSON.stringify({error:"Not found"}));return}o.setHeader("content-type","text/html"),o.setHeader("cache-control","no-cache"),o.end(w)})})}function ht(o,t){const r=o.ai??ke;return{...o,ai:{baseUrl:r.baseUrl,model:r.model,apiKeySet:Ge(t)}}}function Ue(o){if(!o)return;const{apiKey:t,...r}=o;return r}function He(o){return o.endsWith(".js")?"text/javascript":o.endsWith(".css")?"text/css":o.endsWith(".html")?"text/html":o.endsWith(".svg")?"image/svg+xml":o.endsWith(".json")?"application/json":"application/octet-stream"}function Ke(o){const t=Number(o??"100");return!Number.isFinite(t)||t<=0?100:Math.min(Math.floor(t),500)}function E(o,t){t instanceof at?o.statusCode=409:t instanceof B?o.statusCode=404:t instanceof Jt||t instanceof Ft?o.statusCode=500:o.statusCode=400,o.setHeader("content-type","application/json"),o.end(JSON.stringify({error:t instanceof Error?t.message:"Install failed"}))}async function T(o,t){const r=G(o.path,C(t)),u=r?await _t(o.path):null,s=I(o.path,t);return{id:o.id,kind:o.kind,addedAt:o.addedAt,path:o.path,relPath:G(o.path,t)?Qt(o.path,t):null,resourceId:r?S.basename(o.path):null,managed:r,builtin:s,namespace:r?Vt(o.path,C(t)):void 0,legacy:!u&&!s,source:s?"builtin":u?.source??"legacy",origin:u?.origin??null,importedAt:u?.importedAt??null,commit:u?.commit??null,tags:await _e(o.path)}}const We={command:"command",agent:"agent",workflow:"workflow",rule:"rules","output-style":"output-style"};async function ze(o){const{plugins:t,skills:r,mcp:u,files:s}=await rt(o),g={},b=(y,w)=>{w>0&&(g[y]=(g[y]??0)+w)};b("skill",r.length),b("mcp",u.length);for(const[y,w]of Object.entries(s))b(We[y]??y,w.length);return b("plugin",t.length),b("mods",t.filter(y=>y.kind==="mod"||y.components.includes("mod")).length),g}async function _e(o){try{return await ze(o)}catch{return{}}}function A(o,t){t instanceof re?o.statusCode=403:t instanceof ae?o.statusCode=413:t instanceof B?o.statusCode=404:o.statusCode=400,o.setHeader("content-type","application/json"),o.end(JSON.stringify({error:t instanceof Error?t.message:"Read failed"}))}
|
|
@@ -1,17 +1,74 @@
|
|
|
1
1
|
/** 读文件尾部(读不到 → null,不猜)。 */
|
|
2
2
|
export declare function readTail(path: string, bytes?: number): string | null;
|
|
3
|
+
/**
|
|
4
|
+
* 装配用兜底:路径从库里该会话最近一条事件的旁路字段补回(与入站侧读同一个
|
|
5
|
+
* `transcriptPath`)。每个会话在 daemon 生命周期里最多查一次——查到即写回内存。
|
|
6
|
+
*/
|
|
7
|
+
export declare function dbTranscriptPathResolver(events: {
|
|
8
|
+
listBySession(sessionId: string, limit?: number): Array<{
|
|
9
|
+
payload: string;
|
|
10
|
+
}>;
|
|
11
|
+
}): (sessionId: string) => string | null;
|
|
3
12
|
export declare class SessionProbe {
|
|
13
|
+
/**
|
|
14
|
+
* 路径的内存副本没了以后的兜底(daemon 重启后第一拍):不补的话,重启后**没有
|
|
15
|
+
* 新事件**的会话(已收尾 / 闲置中的那些)模型与模式会一直显示「未知」。
|
|
16
|
+
*/
|
|
17
|
+
private readonly fallbackPath?;
|
|
18
|
+
constructor(
|
|
19
|
+
/**
|
|
20
|
+
* 路径的内存副本没了以后的兜底(daemon 重启后第一拍):不补的话,重启后**没有
|
|
21
|
+
* 新事件**的会话(已收尾 / 闲置中的那些)模型与模式会一直显示「未知」。
|
|
22
|
+
*/
|
|
23
|
+
fallbackPath?: ((sessionId: string) => string | null) | undefined);
|
|
4
24
|
/** sessionId → 转录路径(内存态;hook 事件每次上报都覆盖刷新)。 */
|
|
5
25
|
private readonly paths;
|
|
6
|
-
/** 路径 →
|
|
26
|
+
/** 路径 → 上次读到的事实(按文件大小缓存:没长过就不重读)。 */
|
|
7
27
|
private readonly marks;
|
|
28
|
+
/** sessionId → 最后已知的模型/模式(读到就记;见 `latched`)。 */
|
|
29
|
+
private readonly known;
|
|
30
|
+
/**
|
|
31
|
+
* sessionId → 宿主落定的换模型(`PostModelSwitch`)+ 记下的那一刻转录里还是哪个
|
|
32
|
+
* 模型。转录只在 assistant 消息上照会模型,切完不跑一轮就永远读不到新值——故
|
|
33
|
+
* 换模型这件事得由事件先说,等转录自己跟上(照会的值不再是 `stale`)才交还给它。
|
|
34
|
+
*/
|
|
35
|
+
private readonly switched;
|
|
8
36
|
noteTranscript(sessionId: string, path: string | null): void;
|
|
37
|
+
private pathOf;
|
|
9
38
|
forget(sessionId: string): void;
|
|
39
|
+
/** 宿主落定的换模型(`PostModelSwitch` 的 `to_model`):立刻生效,见 `switched`。 */
|
|
40
|
+
noteModel(sessionId: string, model: string): void;
|
|
41
|
+
/**
|
|
42
|
+
* 转录还在不在:true/false;路径都不知道 → null(不猜)。
|
|
43
|
+
*
|
|
44
|
+
* 会话行是采集出来的、与转录那份文件同生不同死——转录被清理/删掉后列表照旧
|
|
45
|
+
* 有行,`claude --resume <id>` 却在 pane 里当场报 "No conversation found"。
|
|
46
|
+
* 故「打开」前与列表渲染前都得先问这一句。空文件也算没有(没有可接的对话)。
|
|
47
|
+
*/
|
|
48
|
+
transcriptPresent(sessionId: string): boolean | null;
|
|
10
49
|
/**
|
|
11
50
|
* 单会话的中断时刻(ms):转录最后一条中断标记**晚于**最后一条 hook 事件才算
|
|
12
51
|
* ——之后任何事件(用户又发了一条、工具收尾)都会把它盖过去,故是自愈的;
|
|
13
52
|
* 未知路径/读不到/没标记一律 null(不猜)。
|
|
14
53
|
*/
|
|
15
54
|
interruptedAt(sessionId: string, lastSeenAt: string): number | null;
|
|
16
|
-
|
|
55
|
+
/** 最近一轮真跑过的模型(转录 `message.model`);未知/读不到一律 null(不猜)。 */
|
|
56
|
+
currentModel(sessionId: string): string | null;
|
|
57
|
+
/** 最后一次活动时的执行模式(转录 `permissionMode`);Shift+Tab 不留痕,故是「最后已知」。 */
|
|
58
|
+
currentMode(sessionId: string): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* 模型/模式在 UI 上承诺的是**最后已知**,不是「此刻尾窗里有没有」:尾窗只有 64KB,
|
|
61
|
+
* 一轮的尾巴若被一条大记录占满、或刚压缩完还没有 assistant 条目,这一拍就什么
|
|
62
|
+
* 都读不到。更要命的是读空的那一拍会按文件大小被缓存住——会话一完成文件不再
|
|
63
|
+
* 增长,那口 null 就钉死了,界面上直接掉回「未知」。故读到就记住,读空沿用:
|
|
64
|
+
* 值只会被**更新的值**替换,不会被读空擦掉。中断标记不参与闩(它按「晚于最后
|
|
65
|
+
* 一条事件」判,陈旧标记必须能被新事件盖过)。
|
|
66
|
+
*/
|
|
67
|
+
private latched;
|
|
68
|
+
/**
|
|
69
|
+
* 换模型事件压过转录:只要转录照会的还是切换前那个模型(切完还没真跑一轮),
|
|
70
|
+
* 就答事件说的新值;转录自己跟上(照会别的值)即交还给它。
|
|
71
|
+
*/
|
|
72
|
+
private switchedModel;
|
|
73
|
+
private factsOf;
|
|
17
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{closeSync as
|
|
1
|
+
import{closeSync as o,openSync as c,readSync as i,statSync as a}from"node:fs";import{currentModelAt as h,currentModeAt as u,interruptMarkerAt as f}from"@weavecode/harness";const d=64*1024,m={model:null,mode:null};export function readTail(s,t=d){try{const e=a(s).size,n=Math.max(0,e-t),r=c(s,"r");try{const l=Buffer.alloc(e-n);return i(r,l,0,l.length,n),l.toString("utf8")}finally{o(r)}}catch{return null}}export function dbTranscriptPathResolver(s){return t=>{try{const e=JSON.parse(s.listBySession(t,1)[0]?.payload??"");return typeof e.transcriptPath=="string"&&e.transcriptPath?e.transcriptPath:null}catch{return null}}}export class SessionProbe{fallbackPath;constructor(t){this.fallbackPath=t}paths=new Map;marks=new Map;known=new Map;switched=new Map;noteTranscript(t,e){e&&this.paths.set(t,e)}pathOf(t){const e=this.paths.get(t);if(e)return e;const n=this.fallbackPath?.(t)??null;return n&&this.paths.set(t,n),n}forget(t){this.paths.delete(t),this.known.delete(t),this.switched.delete(t)}noteModel(t,e){const n=this.pathOf(t);this.switched.set(t,{stale:n?this.factsOf(n).model:null,model:e})}transcriptPresent(t){const e=this.pathOf(t);return e?this.factsOf(e).size>0:null}interruptedAt(t,e){const n=this.pathOf(t);if(!n)return null;const r=this.factsOf(n).markerAt;if(r===null)return null;const l=Date.parse(e);return Number.isFinite(l)&&r>l?r:null}currentModel(t){return this.latched(t).model}currentMode(t){return this.latched(t).mode}latched(t){const e=this.pathOf(t),n=e?this.factsOf(e):m,r=this.known.get(t),l={model:this.switchedModel(t,n.model)??r?.model??null,mode:n.mode??r?.mode??null};return(!r||r.model!==l.model||r.mode!==l.mode)&&this.known.set(t,l),l}switchedModel(t,e){const n=this.switched.get(t);return n&&e===n.stale?n.model:e}factsOf(t){let e;try{e=a(t).size}catch{return{size:-1,markerAt:null,model:null,mode:null}}const n=this.marks.get(t);if(n&&n.size===e)return n;const r=readTail(t),l={size:e,markerAt:r===null?null:f(r),model:r===null?null:h(r),mode:r===null?null:u(r)};return this.marks.set(t,l),l}}
|
|
@@ -34,6 +34,8 @@ export interface DaemonSettings {
|
|
|
34
34
|
hooks: HooksSettings;
|
|
35
35
|
/** 事件日志(hook_events)保留策略——缺省走默认值(读时归一化)。 */
|
|
36
36
|
events?: EventsSettings;
|
|
37
|
+
/** 会话闲置移除策略(无操作 n 天后自动移除)——缺省走默认值(读时归一化)。 */
|
|
38
|
+
sessions?: SessionsSettings;
|
|
37
39
|
/** 开机自启动 daemon(系统级自启动项;缺省关闭——读时归一化)。 */
|
|
38
40
|
startup?: StartupSettings;
|
|
39
41
|
/** 监听面(绑定地址;缺省放开 0.0.0.0——读时归一化)。 */
|
|
@@ -48,6 +50,10 @@ export interface HooksSettings {
|
|
|
48
50
|
export interface EventsSettings {
|
|
49
51
|
retentionDays: number;
|
|
50
52
|
}
|
|
53
|
+
/** 会话闲置移除保留天数(= lastSeenAt 起算的无操作窗,到期自动移除会话行)。 */
|
|
54
|
+
export interface SessionsSettings {
|
|
55
|
+
idleDays: number;
|
|
56
|
+
}
|
|
51
57
|
/** daemon 是否随系统登录自启(默认关)。 */
|
|
52
58
|
export interface StartupSettings {
|
|
53
59
|
launchOnLogin: boolean;
|
|
@@ -71,6 +77,10 @@ export declare const DEFAULT_HOOKS_SETTINGS: HooksSettings;
|
|
|
71
77
|
/** 保留 90 天:与总览「大于30天」档兼容,留足回溯窗口。 */
|
|
72
78
|
export declare const DEFAULT_EVENT_RETENTION_DAYS = 90;
|
|
73
79
|
export declare const DEFAULT_EVENTS_SETTINGS: EventsSettings;
|
|
80
|
+
/** 闲置 90 天移除:与事件日志同界(会话行连同其事件一起走),总览「大于30天」
|
|
81
|
+
* 档仍留有 30-90 天窗口可看;新会话随首个事件即建档,不会被快清误伤。 */
|
|
82
|
+
export declare const DEFAULT_SESSION_IDLE_DAYS = 90;
|
|
83
|
+
export declare const DEFAULT_SESSIONS_SETTINGS: SessionsSettings;
|
|
74
84
|
export declare const DEFAULT_STARTUP_SETTINGS: StartupSettings;
|
|
75
85
|
/** 默认放开绑定(局域网可达):dashboard 密码认证是这层的兜底。HTTPS 与 HTTP 并存(见 daemon/tls.ts)。 */
|
|
76
86
|
export declare const DEFAULT_SERVER_SETTINGS: ServerSettings;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{openDatabase as
|
|
2
|
-
ON CONFLICT(key) DO UPDATE SET value = excluded.value`);e.exec("BEGIN");try{for(const[r
|
|
1
|
+
import{openDatabase as y}from"../db/db.js";import{getDbPath as b}from"../db/paths.js";import{DEFAULT_BIND_HOST as E}from"./port.js";export const SUPPORTED_LOCALES=["zh-CN","en"],DEFAULT_LOCALE="zh-CN",DEFAULT_TERMINAL_SETTINGS={preset:"auto",customCommand:""},DEFAULT_HOOKS_SETTINGS={enabled:!0},DEFAULT_EVENT_RETENTION_DAYS=90,DEFAULT_EVENTS_SETTINGS={retentionDays:DEFAULT_EVENT_RETENTION_DAYS},DEFAULT_SESSION_IDLE_DAYS=90,DEFAULT_SESSIONS_SETTINGS={idleDays:DEFAULT_SESSION_IDLE_DAYS},DEFAULT_STARTUP_SETTINGS={launchOnLogin:!1},DEFAULT_SERVER_SETTINGS={bindHost:E,tlsPort:6443},DEFAULT_AI_SETTINGS={baseUrl:"",model:""},DEFAULT_DAEMON_SETTINGS={terminal:DEFAULT_TERMINAL_SETTINGS,locale:DEFAULT_LOCALE,hooks:DEFAULT_HOOKS_SETTINGS,events:DEFAULT_EVENTS_SETTINGS,sessions:DEFAULT_SESSIONS_SETTINGS,startup:DEFAULT_STARTUP_SETTINGS,server:DEFAULT_SERVER_SETTINGS,ai:DEFAULT_AI_SETTINGS};export function resolveLocale(e){return SUPPORTED_LOCALES.includes(e)?e:DEFAULT_LOCALE}export const ALL_TERMINAL_PRESETS=["auto","wt","powershell","cmd","terminal","iterm","gnome","konsole","wezterm","ghostty","custom"];const L={auto:"\u81EA\u52A8\uFF08\u63A2\u6D4B\u53EF\u7528\u7EC8\u7AEF\uFF09",wt:"Windows Terminal",powershell:"PowerShell",cmd:"\u547D\u4EE4\u63D0\u793A\u7B26 (cmd)",terminal:"Terminal.app",iterm:"iTerm2",gnome:"gnome-terminal",konsole:"Konsole",wezterm:"WezTerm",ghostty:"Ghostty",custom:"\u81EA\u5B9A\u4E49\u547D\u4EE4"};export function terminalPresetsFor(e){return(e==="win32"?["auto","wt","wezterm","powershell","cmd","custom"]:e==="darwin"?["auto","terminal","iterm","wezterm","ghostty","custom"]:["auto","gnome","konsole","wezterm","ghostty","custom"]).map(o=>({id:o,label:L[o]}))}function p(e){return Number.isInteger(e)&&e>=0&&e<=65535?e:DEFAULT_SERVER_SETTINGS.tlsPort}function T(e){const n=e??{},o=n.terminal??{},s=n.hooks??{},r=n.events??{},u=n.sessions??{},d=n.startup??{},l=n.server??{},i=n.ai??{},h=Number.isInteger(r.retentionDays)&&r.retentionDays>=1?r.retentionDays:DEFAULT_EVENTS_SETTINGS.retentionDays,S=Number.isInteger(u.idleDays)&&u.idleDays>=1?u.idleDays:DEFAULT_SESSIONS_SETTINGS.idleDays;return{terminal:{preset:ALL_TERMINAL_PRESETS.includes(o.preset)?o.preset:DEFAULT_TERMINAL_SETTINGS.preset,customCommand:typeof o.customCommand=="string"?o.customCommand:""},locale:resolveLocale(n.locale),hooks:{enabled:typeof s.enabled=="boolean"?s.enabled:DEFAULT_HOOKS_SETTINGS.enabled},events:{retentionDays:h},sessions:{idleDays:S},startup:{launchOnLogin:typeof d.launchOnLogin=="boolean"?d.launchOnLogin:DEFAULT_STARTUP_SETTINGS.launchOnLogin},server:{bindHost:typeof l.bindHost=="string"&&l.bindHost.trim()!==""?l.bindHost.trim():DEFAULT_SERVER_SETTINGS.bindHost,tlsPort:p(l.tlsPort)},ai:{baseUrl:typeof i.baseUrl=="string"?i.baseUrl.trim():"",model:typeof i.model=="string"?i.model.trim():""}}}const t={terminalPreset:"terminal.preset",terminalCustomCommand:"terminal.customCommand",locale:"locale",hooksEnabled:"hooks.enabled",eventRetentionDays:"events.retentionDays",sessionIdleDays:"sessions.idleDays",startupLaunchOnLogin:"startup.launchOnLogin",serverBindHost:"server.bindHost",serverTlsPort:"server.tlsPort",aiBaseUrl:"ai.baseUrl",aiModel:"ai.model"};let a=null,c=null;export function setDaemonSettingsDb(e){a=e,c=null}function D(e){if(a)return e(a);const n=y(b());try{return e(n)}finally{n.close()}}function g(e){const n=e.prepare("SELECT key, value FROM settings").all();return new Map(n.map(o=>[o.key,o.value]))}function v(e){return T({terminal:{preset:e.get(t.terminalPreset),customCommand:e.get(t.terminalCustomCommand)},locale:e.get(t.locale),...e.has(t.hooksEnabled)?{hooks:{enabled:e.get(t.hooksEnabled)==="true"}}:{},...e.has(t.eventRetentionDays)?{events:{retentionDays:Number(e.get(t.eventRetentionDays))}}:{},...e.has(t.sessionIdleDays)?{sessions:{idleDays:Number(e.get(t.sessionIdleDays))}}:{},...e.has(t.startupLaunchOnLogin)?{startup:{launchOnLogin:e.get(t.startupLaunchOnLogin)==="true"}}:{},...e.has(t.serverBindHost)||e.has(t.serverTlsPort)?{server:{...e.has(t.serverBindHost)?{bindHost:e.get(t.serverBindHost)}:{},...e.has(t.serverTlsPort)?{tlsPort:Number(e.get(t.serverTlsPort))}:{}}}:{},...e.has(t.aiBaseUrl)||e.has(t.aiModel)?{ai:{baseUrl:e.get(t.aiBaseUrl)??"",model:e.get(t.aiModel)??""}}:{}})}function f(e){return[[t.terminalPreset,e.terminal.preset],[t.terminalCustomCommand,e.terminal.customCommand],[t.locale,e.locale],[t.hooksEnabled,String(e.hooks.enabled)],[t.eventRetentionDays,String(e.events?.retentionDays??DEFAULT_EVENT_RETENTION_DAYS)],[t.sessionIdleDays,String(e.sessions?.idleDays??DEFAULT_SESSION_IDLE_DAYS)],[t.startupLaunchOnLogin,String(e.startup?.launchOnLogin??!1)],[t.serverBindHost,e.server?.bindHost??E],[t.serverTlsPort,String(e.server?.tlsPort??DEFAULT_SERVER_SETTINGS.tlsPort)],[t.aiBaseUrl,e.ai?.baseUrl??""],[t.aiModel,e.ai?.model??""]]}function N(e,n){const o=e.prepare(`INSERT INTO settings (key, value) VALUES (?, ?)
|
|
2
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`);e.exec("BEGIN");try{for(const[s,r]of n)o.run(s,r);e.exec("COMMIT")}catch(s){throw e.exec("ROLLBACK"),s}}function m(){try{return D(e=>v(g(e)))}catch{return DEFAULT_DAEMON_SETTINGS}}export async function readDaemonSettings(){return m()}export function readDaemonSettingsSync(){return m()}export function readHooksEnabled(){const e=c;if(e&&e.db===a)return e.value;const n=m().hooks.enabled;return c={db:a,value:n},n}export async function writeDaemonSettings(e){const n=T(e);return D(o=>N(o,f(n))),c=null,n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ee from"node:http";import{openDatabase as se}from"../db/db.js";import{ProjectRepository as oe}from"../repositories/projects.js";import{HookEventRepository as te}from"../repositories/hook-events.js";import{LibraryRepository as re}from"../repositories/libraries.js";import{HookRuleRepository as V}from"../repositories/hook-rules.js";import{HookDispatchRepository as ne}from"../repositories/hook-dispatches.js";import{PluginStateRepository as S}from"../repositories/plugin-states.js";import{SessionRepository as ie}from"../repositories/sessions.js";import{createRuntimeRegistry as ae}from"@weavecode/harness";import{TERMINAL_LOCATOR_ENV_KEYS as pe}from"@weavecode/core";import{startSessionSweeper as ce}from"../hooks/session-sweeper.js";import{startStatuslineCacheSweeper as me}from"../statusline/cache-sweeper.js";import{wireHookFilePipeline as le}from"./hook-pipeline.js";import{ensureBuiltinMarket as ue,builtinMarketDir as fe}from"../market/builtin.js";import{HookRuleRegistry as he}from"../hooks/registry.js";import{HookDispatcher as de}from"../hooks/dispatcher.js";import{HookEventBus as we}from"../hooks/bus.js";import{ResumeRunner as ge}from"../hooks/resume-runner.js";import{HeadlessRunner as Se}from"../hooks/headless-runner.js";import{MessageDeliverer as Re}from"../hooks/message-deliverer.js";import{QuestionTracker as ve}from"../hooks/question-tracker.js";import{startPromptFlusher as be}from"../hooks/prompt-flusher.js";import{SessionWatchRepository as ke}from"../repositories/session-watches.js";import{PushSubscriptionRepository as ye}from"../repositories/push-subscriptions.js";import{UploadRepository as De}from"../repositories/uploads.js";import{PushNotifier as Pe}from"../hooks/push-notify.js";import{SessionSequenceRepository as Ee}from"../repositories/session-sequences.js";import{WatchEngine as He}from"../hooks/watch-engine.js";import{SequenceEngine as Te}from"../hooks/sequence-engine.js";import{loadAllPlugins as Ce}from"../hooks/plugin-loader.js";import{ToolkitService as Ie}from"../hooks/toolkit.js";import{WatchService as Ae}from"../watch/watch-service.js";import{SyncScheduler as qe}from"../watch/sync-scheduler.js";import{FingerprintCache as Le}from"../install/fingerprint.js";import{detectProjectUpdateCounts as _e}from"../install/updates.js";import{weaveRequestHandler as Me}from"./server.js";import{startTlsServer as Ne}from"./tls.js";import{DataBus as Oe}from"./data-bus.js";import{TerminalTopologyRefresher as Be}from"./terminal-topology-refresher.js";import{SnapshotRefresher as K}from"./snapshot-refresher.js";import{SessionProbe as We,dbTranscriptPathResolver as Fe}from"./session-probe.js";import{InflightCountsRefresher as Ue}from"./inflight-counts-refresher.js";import{ProjectUpdatesRefresher as je}from"./project-updates-refresher.js";import{claudeLivenessById as $e,pidAliveOf as xe}from"./claude-liveness.js";import{promptTerminalChannel as Ge,readTerminalCounts as Ve}from"./opener.js";import{DEFAULT_BIND_HOST as Ke}from"./port.js";import{readDaemonState as Qe,writeDaemonState as Ye}from"./state.js";import{readDaemonSettingsSync as M,setDaemonSettingsDb as ze,DEFAULT_SERVER_SETTINGS as Je}from"./settings.js";import{AuthService as Xe}from"./dashboard-auth.js";import{syncLaunchOnLogin as Ze}from"./auto-start.js";import{resolveStaticDir as es}from"./static.js";delete process.env.CLAUDE_CODE_CHILD_SESSION;for(const m of pe)delete process.env[m];export function startDaemon(){const m=Qe();m||(console.error("Daemon state not found. Run `weave daemon start` first."),process.exit(1));const s=se();ze(s);const R=M().server?.bindHost??Ke,v=M().server?.tlsPort??Je.tlsPort,b=new Xe;b.initialPassword&&console.log(`[weave] initial dashboard password: ${b.initialPassword}`);const t=new oe(s),u=new te(s),a=new re(s),k=ae(),Q=k.byCapability("events").flatMap(e=>e.events??[]),f=new he(new V(s)),h=new ne(s),r=new ie(s),n=new we,y={getHandler:()=>{},getConfig:()=>({})};let l;const D={list:()=>l?.list()??[],setPluginEnabled:(e,o)=>l?.setPluginEnabled(e,o)??!1,reloadAll:async()=>{await l?.reloadAll()},rescan:async()=>{await l?.rescanRoots(t.list(),a)}},Y=new Ie({projects:t,states:new S(s),plugins:D,libraries:a}),N=new de({registry:f,dispatches:h,bus:n,projects:t,sessions:r,plugins:y,pluginStates:new S(s)});ue({libraries:a}).then(e=>(e.error?console.error(`[weave] builtin market unavailable: ${e.error}`):e.changed&&console.log(`[weave] builtin market ${e.form==="link"?"linked":"copied"} -> ${fe(a.dataDir)}`),Ce({rules:new V(s),registry:f,states:new S(s),bus:n,libraries:a},t.list()))).then(({loader:e})=>{l=e,y.getHandler=(o,c)=>e.getHandler(o,c),y.getConfig=o=>e.getConfig(o),e.watchRoots()});const P=new Se,z=new ge({dispatches:h,sessions:r,projects:t,bus:n,resumeSpec:k.get("claude")?.resume,headless:P}),p=new Re({sessions:r,projects:t,hookEvents:u,bus:n,headless:P,terminal:Ge(()=>M().terminal)});be(p);const E=new ke(s),H=new He({watches:E,deliverer:p,sessions:r,bus:n}),O=new ye(s),T=new De(s),J=new Pe({subscriptions:O,sessions:r,bus:n}),C=new Ee(s),d=new Te({sequences:C,deliverer:p,sessions:r,bus:n});d.rearm();const w=new ve({sessions:r,hookEvents:u,onPending:e=>{n.emit({kind:"question.pending",sessionId:e.sessionId,harness:e.harness,count:e.questions.length,at:e.at})}});w.seedFromDb();const I=new Ae(t);I.start();const A=new Le,i=new Oe,g=new We(Fe(u)),B=new je(()=>_e(t.list(),a.list(),A),i,n,()=>i.hasSubscribers()),W=new qe(t,a,{cache:A,plugins:D,onSynced:()=>{B.refreshNow(!0)}});W.start();const q=new Be(async()=>({counts:await Ve(t.list()),terminals:await p.sessionTerminals()}),i,{shouldRun:()=>i.hasSubscribers(),graceMs:1e4});q.start();const L=new K(()=>{const e=$e(),o={};for(const c of r.listWithCounts()){const G=xe(c,e);G!==null&&(o[c.sessionId]=G)}return{alive:o}},i,{key:"sessionLiveness",shouldRun:()=>i.hasSubscribers()});L.start();const _=new K(()=>{const e={};for(const o of r.listWithCounts()){if(o.turnOpen!==!0)continue;const c=g.interruptedAt(o.sessionId,o.lastSeenAt);c!==null&&(e[o.sessionId]=c)}return{interrupted:e}},i,{key:"sessionInterrupt",intervalMs:5e3,shouldRun:()=>i.hasSubscribers()});_.start();const X=new Ue(()=>p.listInflightCounts(),i,n);ce({sessions:r,events:u,dispatches:h,deliverer:p,watches:E,sequences:C,watchEngine:H,sequenceEngine:d,questions:w,probe:g,uploads:T}),me();const F=le({projects:t,rules:f,sessions:r,bus:n,dispatcher:N,watchEngine:H,sequenceEngine:d,messagePipe:p,questionTracker:w,sessionProbe:g,uploads:T}),Z=es(),U=Me({projects:t,port:m.port,tlsPort:v,watch:I,hookEvents:u,adapters:Q,harnesses:k,libraries:a,fingerprintCache:A,staticDir:Z,hookRegistry:f,hookDispatches:h,hookSessions:r,hookBus:n,dataBus:i,terminalRefresher:q,interruptRefresher:_,livenessRefresher:L,sessionProbe:g,inflightRefresher:X,updatesRefresher:B,hookDispatcher:N,hookRunner:z,messageDeliverer:p,uploads:T,questionTracker:w,sessionWatches:E,watchEngine:H,sessionSequences:C,sequenceEngine:d,pushSubscriptions:O,pushNotifier:J,hookPlugins:D,hookMirror:F.mirror,pluginStates:new S(s),toolkit:Y,auth:b}),j=ee.createServer(U);let $=null;Ne({port:v,bindHost:R,handler:U}).then(e=>{$=e});const x=()=>{l?.stopWatching(),q.stop(),L.stop(),_.stop(),W.stop(),I.stop(),P.killAll(),F.stop(),j.close(),$?.server.close(),process.exit(0)};process.on("SIGTERM",x),process.on("SIGINT",x),j.listen(m.port,R,()=>{Ye({...m,pid:process.pid,host:R,tlsPort:v}),Ze()})}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{existsSync as r,mkdirSync as n,readFileSync as
|
|
2
|
-
`,"utf-8")}export function clearDaemonState(){const t=e();r(t)&&
|
|
1
|
+
import{existsSync as r,mkdirSync as n,readFileSync as i,rmSync as a,writeFileSync as o}from"node:fs";import{getDataDir as c,getDaemonStatePath as e}from"../db/paths.js";export function readDaemonState(){const t=e();if(!r(t))return null;try{return JSON.parse(i(t,"utf-8"))}catch{return null}}export function writeDaemonState(t){n(c(),{recursive:!0}),o(e(),JSON.stringify(t,null,2)+`
|
|
2
|
+
`,"utf-8")}export function clearDaemonState(){const t=e();r(t)&&a(t)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as o}from"node:fs";import{fileURLToPath as i}from"node:url";import t from"node:path";export function resolveStaticDir(){const e=t.dirname(i(import.meta.url)),r=t.resolve(e,"../../web/dist");return o(r)?r:void 0}
|
|
@@ -16,7 +16,10 @@ import type { DataBus } from './data-bus.js';
|
|
|
16
16
|
export interface TerminalTopology {
|
|
17
17
|
/** projectId → 本项目已开终端窗口数(项目卡角标)。 */
|
|
18
18
|
counts: Record<number, number>;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* sessionId → 所在可见屏幕;`null` = 确认不在了(pane 已关 / 换了 mux / 整个
|
|
21
|
+
* GUI 没了),缺 = 这轮没探到或没上报过定位——web 据此保留上次分块,不摘行。
|
|
22
|
+
*/
|
|
20
23
|
terminals: Record<string, SessionTerminal | null>;
|
|
21
24
|
}
|
|
22
25
|
export interface TerminalTopologyRefresherOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import w from"node:https";import f from"node:os";import l from"node:path";import{existsSync as u,mkdirSync as d,readFileSync as m,writeFileSync as h}from"node:fs";import{X509Certificate as S,createPrivateKey as k}from"node:crypto";import{generate as D}from"selfsigned";import{getDataDir as $}from"../db/paths.js";export function daemonCertsDir(){return l.join($(),"certs")}export function lanIps(){const t=new Set;for(const e of Object.values(f.networkInterfaces()))for(const r of e??[])r.family==="IPv4"&&!r.internal&&t.add(r.address);return[...t].sort()}export function accessUrls(t,e){const r=[{url:`http://localhost:${t}`,protocol:"http",scope:"local"}];e>0&&r.push({url:`https://localhost:${e}`,protocol:"https",scope:"local"});for(const o of lanIps())r.push({url:`http://${o}:${t}`,protocol:"http",scope:"lan"}),e>0&&r.push({url:`https://${o}:${e}`,protocol:"https",scope:"lan"});return r}function x(t){const e=t.subjectAltName??"",r=new Set;for(const o of e.split(",")){const n=o.trim().match(/^IP Address:(.+)$/);n&&r.add(n[1])}return r}export async function ensureDaemonCert(t=daemonCertsDir(),e={}){const r=e.ips??["127.0.0.1",...lanIps()],o=e.hostname??f.hostname(),n=e.now??new Date,s=l.join(t,"host.key"),a=l.join(t,"host.crt");if(u(s)&&u(a))try{const i=m(s,"utf-8"),p=new S(m(a,"utf-8")),y=r.every(v=>x(p).has(v));if(p.checkPrivateKey(k(i))&&Date.parse(p.validTo)>n.getTime()+7*864e5&&y)return{key:i,cert:m(a,"utf-8")}}catch{}const c=await D([{name:"commonName",value:"weave-daemon"}],{keySize:2048,notAfterDate:new Date(n.getTime()+825*864e5),extensions:[{name:"subjectAltName",altNames:[{type:2,value:"localhost"},{type:2,value:o},...r.map(i=>({type:7,ip:i}))]}]});return d(t,{recursive:!0}),h(s,c.private,{mode:384}),h(a,c.cert),{key:c.private,cert:c.cert}}export async function startTlsServer(t){if(t.port<=0)return null;try{const{key:e,cert:r}=await ensureDaemonCert(t.certDir),o=w.createServer({key:e,cert:r},t.handler);return await new Promise((n,s)=>{o.once("error",s),o.listen(t.port,t.bindHost,()=>{o.off("error",s),n()})}),{server:o,port:t.port}}catch(e){return console.warn(`[weave] https listener disabled (port ${t.port}): ${e instanceof Error?e.message:String(e)}`),null}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{sendJson as e}from"./http.js";import{ToolkitError as h}from"../hooks/toolkit.js";export async function handleToolkitRoutes(
|
|
1
|
+
import{sendJson as e}from"./http.js";import{ToolkitError as h}from"../hooks/toolkit.js";export async function handleToolkitRoutes(a,o,r,i,m){if(!i.includes("/toolkit"))return!1;if(!r.toolkit)return e(o,503,{error:"Toolkit unavailable"}),!0;const l=t=>{if(t instanceof h){e(o,t.code==="not-found"?404:400,{error:t.message,code:t.code});return}e(o,400,{error:t instanceof Error?t.message:"Toolkit operation failed"})},s=i.match(/^\/projects\/(\d+)\/toolkit$/);if(s){if(a.method!=="GET")return e(o,405,{error:"Method not allowed"}),!0;try{e(o,200,await r.toolkit.list(Number(s[1])))}catch(t){l(t)}return!0}const n=i.match(/^\/projects\/(\d+)\/toolkit\/([^/]+)\/(enable|disable|uninstall)$/);if(n){if(a.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;const t=Number(n[1]),c=decodeURIComponent(n[2]),k=n[3],u=m.searchParams.get("source");try{const d=k==="enable"?await r.toolkit.enable(t,c,u??void 0):k==="disable"?await r.toolkit.disable(t,c,u??void 0):await r.toolkit.uninstall(t,c,u??void 0);r.dataBus?.emit({key:"toolkit"}),e(o,200,d)}catch(d){l(d)}return!0}const f=i.match(/^\/projects\/(\d+)\/toolkit\/legacy-copies\/cleanup$/);if(f){if(a.method!=="POST")return e(o,405,{error:"Method not allowed"}),!0;try{const t=await r.toolkit.cleanupLegacyCopies(Number(f[1]));r.dataBus?.emit({key:"toolkit"}),e(o,200,t)}catch(t){l(t)}return!0}return!1}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{mkdirSync as
|
|
1
|
+
import{mkdirSync as i}from"node:fs";import o from"node:path";import{DatabaseSync as L}from"node:sqlite";import{getDbPath as a}from"./paths.js";import{projectKey as r}from"../repositories/projects.js";const n=`
|
|
2
2
|
CREATE TABLE IF NOT EXISTS projects (
|
|
3
3
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4
4
|
path TEXT NOT NULL UNIQUE,
|
|
@@ -131,4 +131,22 @@ CREATE TABLE IF NOT EXISTS push_subscriptions (
|
|
|
131
131
|
user_agent TEXT,
|
|
132
132
|
created_at TEXT NOT NULL
|
|
133
133
|
);
|
|
134
|
-
|
|
134
|
+
|
|
135
|
+
-- \u4F1A\u8BDD\u56FE\u7247\u4E0A\u4F20\uFF1A\u5185\u5BB9\u5BFB\u5740 id = sha256\uFF08\u5929\u7136\u53BB\u91CD\uFF09\uFF0C\u6587\u4EF6\u843D <dataDir>/uploads/\u3002
|
|
136
|
+
-- \u4E0A\u4F20 \u2260 \u6295\u9012\uFF08\u8D44\u6E90\u4E09\u5C42\u91CC\u7684\u300C\u88C5\u5230\u76EE\u6807\u4F4D\u300D\uFF09\uFF1B\u4E0E\u4F1A\u8BDD\u7684\u5173\u7CFB\u7ECF event_images\u3002
|
|
137
|
+
CREATE TABLE IF NOT EXISTS uploads (
|
|
138
|
+
id TEXT PRIMARY KEY,
|
|
139
|
+
media_type TEXT NOT NULL,
|
|
140
|
+
name TEXT NOT NULL,
|
|
141
|
+
size INTEGER NOT NULL,
|
|
142
|
+
created_at TEXT NOT NULL
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
-- \u6D88\u606F\u968F\u9644\u7684\u56FE\uFF08\u5BF9\u8BDD\u6C14\u6CE1\u7684\u7F29\u7565\u56FE\uFF09\uFF1A\u6302\u5728**\u5F00\u8F6E\u4E8B\u4EF6**\u4E0A\u2014\u2014\u6D88\u606F\u57DF\u4E0D\u843D\u5E93\uFF0C
|
|
146
|
+
-- \u56FE\u7684\u5F52\u5BBF\u662F\u4F1A\u8BDD\u81EA\u5DF1\u7684\u8F6C\u5F55\u4E8B\u4EF6\uFF0C\u8FD9\u91CC\u53EA\u5B58\u6307\u9488\u3002\u968F hook_events \u7EA7\u8054\u5220\u3002
|
|
147
|
+
CREATE TABLE IF NOT EXISTS event_images (
|
|
148
|
+
event_id INTEGER NOT NULL REFERENCES hook_events(id) ON DELETE CASCADE,
|
|
149
|
+
upload_id TEXT NOT NULL,
|
|
150
|
+
PRIMARY KEY (event_id, upload_id)
|
|
151
|
+
);
|
|
152
|
+
`;export function openDatabase(e=a()){e!==":memory:"&&i(o.dirname(e),{recursive:!0});const T=new L(e);return T.exec("PRAGMA busy_timeout = 5000"),T.exec("PRAGMA journal_mode = WAL"),T.exec("PRAGMA foreign_keys = ON"),T.exec(n),T.exec("DROP TABLE IF EXISTS session_messages"),O(T),d(T),_(T),A(T),T}function _(e){const T=e.prepare("SELECT id, path FROM projects ORDER BY id").all(),E=new Set(T.map(s=>s.path)),N=e.prepare("UPDATE projects SET path = ? WHERE id = ?");for(const s of T){const t=r(s.path);t===s.path||E.has(t)||(E.delete(s.path),E.add(t),N.run(t,s.id))}}function A(e){const T=new Set(e.prepare("PRAGMA table_info(session_watches)").all().map(E=>String(E.name)));T.size!==0&&(T.has("on_events")||e.exec("ALTER TABLE session_watches ADD COLUMN on_events TEXT"),T.has("remaining")||(e.exec("ALTER TABLE session_watches ADD COLUMN remaining INTEGER"),e.exec("UPDATE session_watches SET remaining = 1")))}function d(e){const T=new Set(e.prepare("PRAGMA table_info(projects)").all().map(E=>String(E.name)));T.size!==0&&(T.has("sort_order")||e.exec("ALTER TABLE projects ADD COLUMN sort_order INTEGER"),T.has("archived_at")||e.exec("ALTER TABLE projects ADD COLUMN archived_at TEXT"))}function O(e){const T=new Set(e.prepare("PRAGMA table_info(hook_rules)").all().map(E=>String(E.name)));T.size!==0&&(T.has("origin")||e.exec("ALTER TABLE hook_rules ADD COLUMN origin TEXT NOT NULL DEFAULT 'user'"),T.has("plugin_id")||e.exec("ALTER TABLE hook_rules ADD COLUMN plugin_id TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_hook_rules_plugin ON hook_rules(plugin_id)"))}
|
|
@@ -12,3 +12,7 @@ export declare function getInitialPasswordPath(): string;
|
|
|
12
12
|
export declare function getAiKeyPath(): string;
|
|
13
13
|
/** Absolute path to the Web Push VAPID keypair file (`{ publicKey, privateKey }`, 0600). */
|
|
14
14
|
export declare function getPushKeysPath(): string;
|
|
15
|
+
/** 会话图片上传的落盘根(内容寻址 `<sha256>.<ext>`;绝对路径由 harness 引用)。 */
|
|
16
|
+
export declare function getUploadsDir(): string;
|
|
17
|
+
/** 接口日志根(按小时 JSONL:`api-YYYY-MM-DDTHH.jsonl`,见 daemon/api-log.ts)。 */
|
|
18
|
+
export declare function getApiLogsDir(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"node:path";import{detectPlatform as n}from"@weavecode/core";export function getDataDir(){return t.join(n().configDir,"weave")}export function getDbPath(){return t.join(getDataDir(),"weave.db")}export function getDaemonStatePath(){return t.join(getDataDir(),"daemon.json")}export function getAuthPath(){return t.join(getDataDir(),"auth.json")}export function getInitialPasswordPath(){return t.join(getDataDir(),"initial-password")}export function getAiKeyPath(){return t.join(getDataDir(),"ai.json")}export function getPushKeysPath(){return t.join(getDataDir(),"push.json")}
|
|
1
|
+
import t from"node:path";import{detectPlatform as n}from"@weavecode/core";export function getDataDir(){return t.join(n().configDir,"weave")}export function getDbPath(){return t.join(getDataDir(),"weave.db")}export function getDaemonStatePath(){return t.join(getDataDir(),"daemon.json")}export function getAuthPath(){return t.join(getDataDir(),"auth.json")}export function getInitialPasswordPath(){return t.join(getDataDir(),"initial-password")}export function getAiKeyPath(){return t.join(getDataDir(),"ai.json")}export function getPushKeysPath(){return t.join(getDataDir(),"push.json")}export function getUploadsDir(){return t.join(getDataDir(),"uploads")}export function getApiLogsDir(){return t.join(getDataDir(),"logs","api")}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const p=" ";export function composeAnswerAtoms(i,l){if(i.every(e=>e.options.length===0))return{ok:!1,error:"Question face has no answerable options"};const f=new Map(l.map(e=>[e.questionKey,e]));for(const e of f.keys())if(!i.some(s=>s.key===e))return{ok:!1,error:`Unknown question: ${e}`};const n=[];for(const e of i){const s=f.get(e.key),t=(s?.options??[]).map(o=>e.options[o]);if(t.some(o=>!o))return{ok:!1,error:`Invalid option index: ${e.key}`};if(e.submit&&t.length!==1)return{ok:!1,error:"Submit choice required to finish the call"};const c=t.filter(o=>!o.input);if(!e.multiSelect&&c.length>1)return{ok:!1,error:`Single-select question got ${c.length} options: ${e.key}`};const u=s?.text?.trim()??"",r=t.find(o=>o.input);if(r&&!u)return{ok:!1,error:`Text required for this option: ${e.key}`};for(const o of t)n.push(...o.keys);if(r)n.push(...r.textFocus??[],u,...r.textTail??["\r"]);else for(const o of t)n.push(...o.commit??[]);if(e.submit||t.some(o=>o.chat))break;!r&&(e.multiSelect||t.length===0)&&n.push(" ")}return{ok:!0,atoms:n}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter as
|
|
1
|
+
import{EventEmitter as e}from"node:events";export class HookEventBus{emitter=new e;constructor(){this.emitter.setMaxListeners(100)}emit(t){this.emitter.emit("change",t)}subscribe(t){return this.emitter.on("change",t),()=>this.emitter.off("change",t)}}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{INJECTABLE_EVENTS as I,TITLE_EFFECTIVE_EVENTS as y,hookSourceHarness as
|
|
2
|
-
${
|
|
3
|
-
${
|
|
1
|
+
import{INJECTABLE_EVENTS as I,TITLE_EFFECTIVE_EVENTS as y,hookSourceHarness as P}from"@weavecode/core";import{createPluginLogger as b}from"./plugin-loader.js";import{readHooksEnabled as S}from"../daemon/settings.js";import{effective as k,pluginsStateOf as v}from"./plugin-project-state.js";import{runWebhook as w}from"./handlers/webhook.js";import{DISPATCH_MARKER as c,extractFilePath as h,isCrossProjectPath as j,matchesAnyGlob as T,projectLabel as D,renderTemplate as E,templateVars as W}from"./match.js";const g=6e4,N=4,_=4,O=3e3;export class HookDispatcher{deps;runningWebhooks=new Set;recentPool=new Map;activeWebhooks=0;pendingWebhooks=[];activePlugins=0;pendingPlugins=[];constructor(e){this.deps=e}async onIngest(e){try{if(!S())return{};this.deps.plugins?.notifyEvent?.(e.payload.eventType,e.payload,e.sessionId);const t={};if(e.sessionId){const s=C(e.payload);s!==null&&this.deps.sessions.applyReportedTitle(e.sessionId,s)&&this.deps.bus.emit({kind:"session.renamed",sessionId:e.sessionId,title:s,at:new Date().toISOString()});const o=this.deps.sessions.getBySessionId(e.sessionId)?.pendingTitle;if(o){t.sessionTitle=o;const l=y[e.source].includes(e.payload.eventType);(e.deliveredTitle===o&&l||s!==null)&&this.deps.sessions.confirmPendingTitle(e.sessionId,o)&&this.deps.bus.emit({kind:"session.renamed",sessionId:e.sessionId,title:o,at:new Date().toISOString()})}}const r=this.match(e);if(r.length===0)return t;const n=[],i=[],a=Date.now(),d=a+O;for(const s of r)if(this.deps.bus.emit({kind:"rule.matched",ruleId:s.id,eventId:e.eventId,sessionId:e.sessionId,at:new Date(a).toISOString()}),s.handler.type!=="log"){if(s.handler.type==="manual"||s.handler.type==="inject"){if(this.dedupe(s,e,a))continue;const o=E(s.handler.template,W({event:e.payload.eventType,tool:e.payload.toolName,filePath:h(e.payload.toolInput),cwd:e.payload.cwd,session:e.sessionId,project:D(e.project.path),rule:s.name}))+`
|
|
2
|
+
${c}`,l=s.handler.type==="inject"?"injected":"pending";this.createDispatch(s,e,{prompt:o,status:l,mode:s.handler.type==="inject"?"auto":"manual"}),s.handler.type==="inject"&&(s.filter.crossProjectOnly?i.push(o):n.push(o));continue}if(s.handler.type==="webhook"){if(this.runningWebhooks.has(s.id))continue;this.runningWebhooks.add(s.id);const o=this.createDispatch(s,e,{prompt:`webhook ${s.handler.url}`,status:"running",mode:"auto"});this.deps.bus.emit({kind:"dispatch.started",ruleId:s.id,dispatchId:o.id,sessionId:e.sessionId,at:new Date().toISOString()}),this.runWebhookAsync(s,this.summary(s,e),o.id);continue}if(s.handler.type==="plugin"){const o=this.deps.plugins;if(!o)continue;const l=o.getHandler(s.handler.pluginId,s.handler.handlerType);if(!l||this.dedupe(s,e,a))continue;if(!this.injectable(e)){this.runPluginDetached(s,e,o,l);continue}const u=d-Date.now();if(u<=0)continue;const p=await this.runPluginHandler(s,e,o,l,u);if(!p)continue;p.prompt&&this.createDispatch(s,e,{prompt:p.prompt+`
|
|
3
|
+
${c}`,status:"pending",mode:"auto"}),p.additionalContext&&i.push(p.additionalContext)}}return(n.length>0||i.length>0)&&(t.additionalContext=[...n,...i].join(`
|
|
4
4
|
|
|
5
|
-
`)),i.length>0&&(
|
|
5
|
+
`)),i.length>0&&(t.deferred=i.join(`
|
|
6
6
|
|
|
7
|
-
`)),
|
|
8
|
-
${
|
|
7
|
+
`)),t}catch{return{}}}createDispatch(e,t,r){const n=this.deps.dispatches.insert({ruleId:e.id,eventId:t.eventId,sessionId:t.sessionId,...r});return this.deps.bus.emit({kind:"dispatch.created",ruleId:e.id,dispatchId:n.id,status:r.status,mode:n.mode,sessionId:t.sessionId,at:n.startedAt}),n}dedupe(e,t,r){const n=`${e.id}:${t.sessionId??""}`,i=this.recentPool.get(n);return i!==void 0&&r-i<g?!0:(this.recentPool.set(n,r),this.trimDedupe(r),!1)}match(e){const t=this.deps.pluginStates,r=t?v(e.project.meta).enabled:null;let n=null;return this.deps.registry.candidates(e.payload.eventType,t?{includeDisabled:!0}:void 0).filter(i=>{const a=P(i.source);if(a!==null&&a!=="any"&&a!==e.source||i.projectId!==null&&i.projectId!==e.project.id)return!1;if(i.pluginId!==null){if(!i.enabled&&r?.[i.pluginId]!==!0||t&&!k(e.project,i.pluginId,{states:t}))return!1}else if(!i.enabled)return!1;const d=i.filter;if(d.toolNames?.length&&(!e.payload.toolName||!d.toolNames.includes(e.payload.toolName)))return!1;if(d.pathGlobs?.length){const s=h(e.payload.toolInput);if(!s||!T(s,d.pathGlobs))return!1}if(d.crossProjectOnly){const s=h(e.payload.toolInput)??e.payload.cwd;if(!s||(n??=this.deps.projects.list().map(o=>o.path).filter(o=>o!==e.project.path),!j(s,e.project.path,n)))return!1}return!0})}injectable(e){const t=e.payload.eventType;return t!==null&&I[e.source].includes(t)}async runPluginHandler(e,t,r,n,i){if(e.handler.type!=="plugin")return;const{pluginId:a}=e.handler,d=b(a),s=i===void 0?e.timeoutMs:Math.min(e.timeoutMs,i);let o;try{const l=(async()=>{await this.acquirePluginSlot();try{return await n.execute({event:t.payload,rule:e,config:r.getConfig(a),logger:d})}finally{this.releasePluginSlot()}})(),u=await Promise.race([l,new Promise((p,m)=>{o=setTimeout(()=>m(new Error("plugin handler timeout")),s)})]);return u&&typeof u=="object"?u:void 0}catch{return}finally{o&&clearTimeout(o)}}async runPluginDetached(e,t,r,n){try{const i=await this.runPluginHandler(e,t,r,n);if(!i?.prompt)return;this.createDispatch(e,t,{prompt:i.prompt+`
|
|
8
|
+
${c}`,status:"pending",mode:"auto"})}catch{}}summary(e,t){return{ruleId:e.id,ruleName:e.name,projectId:t.project.id,sessionId:t.sessionId,event:t.payload.eventType,toolName:t.payload.toolName,filePath:h(t.payload.toolInput),cwd:t.payload.cwd,at:new Date().toISOString()}}async runWebhookAsync(e,t,r){await this.acquireWebhookSlot();try{const n=await w(e,t,this.deps.fetchImpl);this.deps.dispatches.updateStatus(r,{status:n.status,output:n.output??null,error:n.error??null,finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:r,status:n.status,sessionId:t.sessionId,at:new Date().toISOString()})}catch(n){this.deps.dispatches.updateStatus(r,{status:"failed",error:String(n),finished:!0}),this.deps.bus.emit({kind:"dispatch.finished",ruleId:e.id,dispatchId:r,status:"failed",sessionId:t.sessionId,at:new Date().toISOString()})}finally{this.runningWebhooks.delete(e.id),this.releaseWebhookSlot()}}acquireWebhookSlot(){return this.activeWebhooks<N?(this.activeWebhooks++,Promise.resolve()):new Promise(e=>{this.pendingWebhooks.push(()=>{this.activeWebhooks++,e()})})}releaseWebhookSlot(){this.activeWebhooks--;const e=this.pendingWebhooks.shift();e&&e()}acquirePluginSlot(){return this.activePlugins<_?(this.activePlugins++,Promise.resolve()):new Promise(e=>{this.pendingPlugins.push(()=>{this.activePlugins++,e()})})}releasePluginSlot(){this.activePlugins--;const e=this.pendingPlugins.shift();e&&e()}trimDedupe(e){if(!(this.recentPool.size<1e3))for(const[t,r]of this.recentPool)e-r>=g&&this.recentPool.delete(t)}}function C(f){const e=f.raw;if(typeof e!="object"||e===null)return null;const t=e.session_title;return typeof t=="string"&&t.length>0?t:null}
|