@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,3 +1,4 @@
|
|
|
1
|
-
import{randomUUID as w}from"node:crypto";import{tmpdir as b}from"node:os";import{WEAVE_INJECTION_MARKER as D,isHarness as x}from"@weavecode/core";import{messagingSurfaceFor as j}from"../surfaces.js";import{normalizeDirKey as g}from"../daemon/opener.js";import{HeadlessRunner as E}from"./headless-runner.js";import{appendOutbox as O,hooksRoot as P}from"./mirror.js";import{InboxSocketRegistry as A,deliverViaInboxSocket as B}from"./inbox-socket.js";import{appendPromptbox as C,readAllPromptbox as W,readPromptbox as m,removePromptboxBySession as M,removePromptboxEntries as c,scanQueuedSessionIds as q}from"./promptbox.js";const R=()=>b(),T=5,y=1e3,$=6e4,F=12e4,K=8,N=200,S=/^(?:[1-9]|n|\t|\r|\x1b\[B)$/,H=/^[^\x00-\x1f\x7f]*$/,_="\x1B",V=120,L=D;function k(u){return u.replace(/<\/?cross-session-message[^>]*>/g,"").replace(/\s+/g," ").trim()}const v=u=>new Promise(s=>setTimeout(s,u));export class MessageDeliverer{deps;headless;hooksDir;memory=new Map;queuedSessions;inboxSockets=new A;paneEnvs=new Map;flushScheduled=new Set;flushing=new Set;stalled=new Map;dismissedIds=new Set;constructor(s){this.deps=s,this.headless=s.headless??new E({spawnImpl:s.spawnImpl,killImpl:s.killImpl}),this.hooksDir=s.hooksDir??P(),this.queuedSessions=q(this.hooksDir)}async send(s){const t=this.deps.sessions.getBySessionId(s.toSessionId);if(!t)return{ok:!1,status:404,error:"Session not found"};const e=this.surfaceOfSession(s.toSessionId);if(!e)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const n=this.resolveChannel(s.mode,s.toSessionId,e);if(typeof n!="string")return{ok:!1,status:409,error:n.reason};if(t.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const o=this.deps.projects.getById(t.projectId);if(!o)return{ok:!1,status:404,error:"Project not found"};if(n==="headless"&&this.headless.isBusy(s.toSessionId))return{ok:!1,status:409,error:"Session already has a running run"};const i={fromLabel:s.fromKind==="session"?`session ${s.fromSessionId??"unknown"}`:s.fromKind,at:new Date().toISOString(),mode:n},r={id:w(),sessionId:s.toSessionId,text:s.text,mode:s.mode,oneWay:s.oneWay===!0,channel:n,status:"pending",at:i.at},a=n==="inject"?this.deliverInject(r,o.token,i,e):n==="headless"?this.deliverHeadless(r,o.path,i,e):await this.deliverPrompt(r,t,o,e);return this.bus({kind:"message.created",messageId:r.id,sessionId:r.sessionId,mode:r.mode,at:r.at}),a}getMessage(s){return this.memory.get(s)??null}listVisible(s){const t=this.deps.visibleTtlMs??$,e=Date.now(),n=[],o=this.deps.sessions.getBySessionId(s);if(o?.projectId!=null){const i=this.deps.projects.getById(o.projectId);if(i)for(const r of m(this.hooksDir,i.token))r.sessionId===s&&n.push({id:r.id,sessionId:s,text:r.text,mode:"prompt",oneWay:r.oneWay===!0,channel:"prompt",status:"pending",at:r.at})}for(const i of this.memory.values()){if(i.sessionId!==s)continue;if(i.stalled===!0||i.status==="delivering"||i.status==="running"){n.push(i);continue}if(i.status==="failed"||i.status==="timeout"){n.push(i);continue}const r=i.settledAt?Date.parse(i.settledAt):NaN;!Number.isNaN(r)&&e-r<t&&n.push(i)}return n.sort((i,r)=>i.at<r.at?-1:1)}hasQueued(s){return this.queuedSessions.has(s)}listInflightCounts(){const s=new Map,t=e=>{s.set(e,(s.get(e)??0)+1)};for(const e of W(this.hooksDir))t(e.sessionId);for(const e of this.memory.values())(e.status==="delivering"||e.status==="running")&&t(e.sessionId);return s}hasTerminalChannel(){return this.terminalChannel()!=null}scheduleFlushContinuation(s){this.flushScheduled.has(s)||(this.flushScheduled.add(s),setTimeout(()=>{this.flushScheduled.delete(s),this.flushSession(s)},this.deps.flushGapMs??y).unref?.())}noteInboxSocket(s,t){this.inboxSockets.set(s,t)}notePaneEnv(s,t){this.paneEnvs.set(s,t)}async sessionTerminals(){const s=this.terminalChannel();return!s?.locateScreens||this.paneEnvs.size===0?{}:s.locateScreens(Object.fromEntries(this.paneEnvs))}onSessionPrompt(s,t){const e=k(t);if(e)for(const n of[...this.memory.values()].reverse()){if(n.sessionId!==s||n.acked||n.mode!=="prompt")continue;const o=k(n.text);if(!(!o||o.length<K||!e.includes(o))){this.memory.set(n.id,{...n,acked:!0,stalled:!1}),this.stalled.get(s)?.messageId===n.id&&(this.stalled.delete(s),this.queuedSessions.has(s)&&this.scheduleFlushContinuation(s)),this.bus({kind:"message.acknowledged",messageId:n.id,sessionId:s,at:new Date().toISOString()});return}}}armAckWatch(s){setTimeout(()=>{const t=this.memory.get(s.id);!t||t.acked||t.status!=="delivered"||this.stall(t.sessionId,t,"unacked")},this.deps.ackStallMs??F).unref?.()}stall(s,t,e){this.stalled.set(s,{messageId:t.id,reason:e});const n=this.memory.get(t.id);n&&this.memory.set(t.id,{...n,stalled:!0}),this.bus({kind:"message.stalled",messageId:t.id,sessionId:s,reason:e,at:new Date().toISOString()})}async answer(s,t){if(t.length===0||!S.test(t[0])||t.some(n=>!S.test(n)&&!H.test(n)))return{ok:!1,status:400,error:"Invalid answer keys"};const e=await this.sessionKeysTarget(s,"Answering");if(!e.ok)return e;try{for(const[n,o]of t.entries())n>0&&await v(V),await e.terminal.sendKeys(e.paneId,o);return{ok:!0}}catch(n){return{ok:!1,status:409,error:n instanceof Error?n.message:String(n)}}}async interrupt(s){const t=await this.sessionKeysTarget(s,"Interrupting");if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,_),{ok:!0}}catch(e){return{ok:!1,status:409,error:e instanceof Error?e.message:String(e)}}}async sessionKeysTarget(s,t){const e=this.deps.sessions.getBySessionId(s);if(!e)return{ok:!1,status:404,error:"Session not found"};if(e.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const n=this.deps.projects.getById(e.projectId);if(!n)return{ok:!1,status:404,error:"Project not found"};const o=this.terminalChannel();if(!o)return{ok:!1,status:409,error:`${t} needs a text-capable terminal (pick wezterm in settings)`};const i=await this.terminalPaneFor(e,n);return i?{ok:!0,terminal:o,paneId:i.id}:{ok:!1,status:409,error:"Session pane not found \u2014 is the session window open?"}}async resend(s){const t=this.memory.get(s);if(!t)return{ok:!1,status:404,error:"Message not found"};if(!(t.channel==="prompt"&&(t.status==="failed"||t.status==="delivered"&&!t.acked)))return{ok:!1,status:409,error:"Message is not resendable"};const e=this.deps.sessions.getBySessionId(t.sessionId);if(!e)return{ok:!1,status:404,error:"Session not found"};if(e.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const n=this.deps.projects.getById(e.projectId);if(!n)return{ok:!1,status:404,error:"Project not found"};const o=this.surfaceOfSession(t.sessionId);if(!o)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};this.stalled.get(t.sessionId)?.messageId===s&&this.stalled.delete(t.sessionId),this.memory.delete(s);const i={...t,status:"pending",stalled:!1,acked:!1,settledAt:null},r=await this.deliverPrompt(i,e,n,o);return this.bus({kind:"message.created",messageId:i.id,sessionId:i.sessionId,mode:i.mode,at:new Date().toISOString()}),r}dismiss(s,t){const e=this.memory.get(t);if(e){if(e.status==="delivering"||e.status==="running")return{ok:!1,status:409,error:"Message is still in flight"};this.memory.delete(t),this.stalled.get(e.sessionId)?.messageId===t&&(this.stalled.delete(e.sessionId),this.queuedSessions.has(e.sessionId)&&this.scheduleFlushContinuation(e.sessionId))}else if(!this.dropQueued(s,t))return{ok:!1,status:404,error:"Message not found"};return this.bus({kind:"message.dismissed",messageId:t,sessionId:s,at:new Date().toISOString()}),{ok:!0}}dropQueued(s,t){const e=this.deps.sessions.getBySessionId(s);if(e?.projectId==null)return!1;const n=this.deps.projects.getById(e.projectId);if(!n)return!1;const o=m(this.hooksDir,n.token);if(!o.some(i=>i.id===t&&i.sessionId===s))return!1;for(c(this.hooksDir,n.token,new Set([t])),this.dismissedIds.add(t);this.dismissedIds.size>N;){const i=this.dismissedIds.values().next().value;if(i===void 0)break;this.dismissedIds.delete(i)}return o.some(i=>i.sessionId===s&&i.id!==t)||this.queuedSessions.delete(s),!0}async flushSession(s){if(!this.stalled.has(s)&&!this.flushing.has(s)&&this.queuedSessions.has(s)){this.flushing.add(s);try{await this.flushSessionInner(s)}catch{}finally{this.flushing.delete(s)}}}async flushSessionInner(s){const t=this.deps.sessions.getBySessionId(s);if(t?.projectId==null)return;const e=this.deps.projects.getById(t.projectId);if(!e)return;const n=m(this.hooksDir,e.token).filter(a=>a.sessionId===s);if(n.length===0){this.queuedSessions.delete(s);return}const o=this.surfaceOfSession(s),i=o?.prompt??null;let r=0;for(const a of n){if(this.stalled.has(s))return;if(this.dismissedIds.has(a.id))continue;if(r>=T){this.scheduleFlushContinuation(s);return}r>0&&await v(this.deps.flushGapMs??y);const d={id:a.id,sessionId:s,text:a.text,mode:"prompt",oneWay:a.oneWay===!0,via:"socket",channel:"prompt",status:"pending",at:a.at};if(o&&await this.tryInboxDeliver(d,o)){c(this.hooksDir,e.token,new Set([a.id])),r++;continue}const l=i?.resolve(s)??null,h=d.oneWay===!0?["terminal","relay"]:["relay","terminal"];let p=!1;for(const f of h){if(f==="relay"&&i&&l){if(this.memory.set(d.id,{...d,status:"delivering",via:"relay"}),!this.runRelay(d,i,l.name)){this.memory.delete(d.id);return}c(this.hooksDir,e.token,new Set([a.id])),r++,p=!0;break}if(f==="terminal"&&this.terminalChannel()){const I=await this.terminalPaneFor(t,e);if(I){c(this.hooksDir,e.token,new Set([a.id])),this.memory.set(d.id,{...d,via:"terminal",status:"delivering"}),await this.runTerminalPrompt(d.id,I.id,d.text),r++,p=!0;break}}}if(!p)return}m(this.hooksDir,e.token).filter(a=>a.sessionId===s).length===0&&this.queuedSessions.delete(s)}async flushAll(){for(const s of[...this.queuedSessions])await this.flushSession(s)}forgetSession(s){let t=0;for(const[e,n]of this.memory)n.sessionId===s&&(this.memory.delete(e),t++);return t+=M(this.hooksDir,s),this.queuedSessions.delete(s),this.stalled.delete(s),this.inboxSockets.forget(s),this.paneEnvs.delete(s),t}forgetProject(s){let t=0;for(const[e,n]of this.memory)this.deps.sessions.getBySessionId(n.sessionId)?.projectId===s&&(this.memory.delete(e),this.inboxSockets.forget(n.sessionId),this.paneEnvs.delete(n.sessionId),this.stalled.delete(n.sessionId),t++);for(const e of[...this.queuedSessions])this.deps.sessions.getBySessionId(e)?.projectId===s&&(t+=this.forgetSession(e));return t}surfaceOfSession(s){const t=this.deps.hookEvents.listBySession(s,1),e=t[t.length-1]?.source;return x(e)?this.deps.surfaceFor?.(e)??j(e):null}resolveChannel(s,t,e){if(s==="prompt")return e.prompt||this.terminalChannel()?"prompt":{reason:e.unsupportedReasons?.prompt??`Harness "${e.harness}" has no native prompt channel and the configured terminal cannot inject text`};if(s==="inject"||s==="headless")return(s==="inject"?e.inject:e.headless)?s:{reason:this.unsupportedReason(e,s)};const n=this.deps.sessions.turnOpenOf(t)?"inject":"headless";return(n==="inject"?e.inject:e.headless)?n:{reason:this.unsupportedReason(e,n)}}unsupportedReason(s,t){return s.unsupportedReasons?.[t]??`Harness "${s.harness}" does not support the ${t} messaging channel`}async terminalPaneFor(s,t){const e=this.terminalChannel();if(!e)return null;const n=this.paneEnvs.get(s.sessionId);if(n){const d=await e.locatePane?.(n).catch(()=>null);if(d)return{id:d}}if(!s.title)return null;const o=s.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,""),i=g(t.path,process.platform);let r;try{r=await e.listPanes()}catch{return null}const a=r.filter(d=>d.title!=null&&d.cwd!=null&&i!=null&&d.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,"")===o&&g(d.cwd,process.platform)===i);return a.length===1?a[0]:null}terminalChannel(){const s=this.deps.terminal;return s&&s.available()?s:null}async deliverPrompt(s,t,e,n){const o=await this.tryInboxDeliver(s,n);if(o)return{ok:!0,messageId:s.id,status:"delivered",message:o};const i=n.prompt,r=i?.resolve(s.sessionId)??null,a=s.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const l of a){if(l==="relay"&&i&&r){if(this.memory.set(s.id,{...s,status:"delivering",via:"relay"}),this.runRelay(s,i,r.name))return{ok:!0,messageId:s.id,status:"delivering",message:this.memory.get(s.id)};this.memory.delete(s.id)}if(l==="terminal"&&this.terminalChannel()){const h=await this.terminalPaneFor(t,e);if(h)return this.memory.set(s.id,{...s,status:"delivering",via:"terminal"}),this.runTerminalPrompt(s.id,h.id,s.text),{ok:!0,messageId:s.id,status:"delivering",message:this.memory.get(s.id)}}}this.queueEntry(s,e.token);const d={...s,status:"pending"};return{ok:!0,messageId:s.id,status:"pending",message:d}}async tryInboxDeliver(s,t){const e=t.promptInbox,n=this.inboxSockets.get(s.sessionId);if(!e||s.oneWay!==!0||!n)return null;this.memory.set(s.id,{...s,status:"delivering",via:"socket"});try{await B(e,n,`${L}${s.text}`)}catch{return this.memory.delete(s.id),null}const o={...this.memory.get(s.id),status:"delivered",via:"socket",settledAt:new Date().toISOString()};return this.memory.set(s.id,o),this.armAckWatch(o),this.bus({kind:"message.delivered",messageId:s.id,sessionId:s.sessionId,at:new Date().toISOString()}),o}queueEntry(s,t){C(this.hooksDir,t,[{id:s.id,sessionId:s.sessionId,text:s.text,oneWay:s.oneWay===!0}]),this.queuedSessions.add(s.sessionId)}runRelay(s,t,e){try{return this.headless.run({sessionId:`prompt-relay:${s.sessionId}`,cwd:R(),prompt:t.instruction(e,s.text,{oneWay:s.oneWay===!0}),spec:{supported:!0,bin:t.bin,args:()=>[...t.args],promptStdin:!0},bin:this.deps.bin??process.env.WEAVE_CLAUDE_BIN??t.bin,timeoutMs:this.deps.relayTimeoutMs??0,detached:!1,onSettle:n=>this.settleRelay(s.id,n)})}catch(n){return this.settleRelay(s.id,{status:"failed",output:null,error:n instanceof Error?n.message:String(n)}),!0}}settleRelay(s,t){const e=this.memory.get(s);if(!e)return;if(t.status==="succeeded"){this.queuedSessions.has(e.sessionId)&&this.scheduleFlushContinuation(e.sessionId);const o={...e,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(s,o),this.armAckWatch(o),this.bus({kind:"message.delivered",messageId:s,sessionId:e.sessionId,at:new Date().toISOString()});return}const n={...e,status:"failed",error:t.error??`prompt relay ${t.status}`,settledAt:new Date().toISOString()};this.memory.set(s,n),this.stall(e.sessionId,n,"failed"),this.bus({kind:"message.finished",messageId:s,sessionId:e.sessionId,status:"failed",at:new Date().toISOString()})}async runTerminalPrompt(s,t,e){const n=this.memory.get(s);if(!n)return;const o=this.terminalChannel();if(o)try{await o.sendText(t,e);const i={...n,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(s,i),this.armAckWatch(i),this.bus({kind:"message.delivered",messageId:s,sessionId:n.sessionId,at:new Date().toISOString()})}catch(i){const r={...n,status:"failed",error:i instanceof Error?i.message:String(i),settledAt:new Date().toISOString()};this.memory.set(s,r),this.stall(n.sessionId,r,"failed"),this.bus({kind:"message.finished",messageId:s,sessionId:n.sessionId,status:"failed",at:new Date().toISOString()})}}deliverInject(s,t,e,n){const o=this.renderEnvelope(s.text,e,n);O(this.hooksDir,t,[{sessionId:s.sessionId,text:o}]);const i={...s,status:"injected",settledAt:new Date().toISOString()};return this.memory.set(i.id,i),this.bus({kind:"message.delivered",messageId:i.id,sessionId:i.sessionId,at:new Date().toISOString()}),{ok:!0,messageId:i.id,status:"injected",message:i}}deliverHeadless(s,t,e,n){const o=n.headless,i={...s,status:"running"};this.memory.set(i.id,i);const r={settled:!1};try{this.headless.run({sessionId:i.sessionId,cwd:t,prompt:this.renderEnvelope(i.text,e,n),spec:o,bin:this.deps.bin??process.env.WEAVE_CLAUDE_BIN??o.bin,timeoutMs:this.deps.timeoutMs,onSettle:a=>this.settle(i,r,a)})||this.settle(i,r,{status:"failed",output:null,error:"Session already has a running run"})}catch(a){this.settle(i,r,{status:"failed",output:null,error:a instanceof Error?a.message:String(a)})}return{ok:!0,messageId:i.id,status:"running",message:this.memory.get(i.id)}}renderEnvelope(s,t,e){return e.renderEnvelope?.(s,t)??`[weave message] from=${t.fromLabel} at=${t.at} mode=${t.mode}
|
|
1
|
+
import{randomUUID as A}from"node:crypto";import{chmodSync as D,mkdirSync as j,readFileSync as T,renameSync as P,writeFileSync as M}from"node:fs";import{tmpdir as _}from"node:os";import{dirname as B,join as p}from"node:path";import{WEAVE_INJECTION_MARKER as C,isHarness as R}from"@weavecode/core";import{messagingSurfaceFor as W}from"../surfaces.js";import{claudeLivenessById as g,pidAliveOf as v}from"../daemon/claude-liveness.js";import{normalizeDirKey as I}from"../daemon/opener.js";import{HeadlessRunner as F}from"./headless-runner.js";import{appendOutbox as q,hooksRoot as N}from"./mirror.js";import{INBOX_TARGETS_FILE as $,InboxSocketRegistry as K,deliverViaInboxSocket as L}from"./inbox-socket.js";import{appendPromptbox as Q,readAllPromptbox as H,readPromptbox as m,removePromptboxBySession as J,removePromptboxEntries as f,scanQueuedSessionIds as G}from"./promptbox.js";const U=()=>_(),V=1e3,X=6e4,z=12e4,Z=8,Y="Session is not running",ee=200,w=/^(?:[1-9]|n|\t|\r|\x1b\[B)$/,se=/^[^\x00-\x1f\x7f]*$/,te="\x1B",ie="\x1B[Z",ne=/^[^\s\x00-\x1f\x7f]{1,128}$/,re=u=>`/model ${u}`,oe=120,k=C;function y(u){return u.replace(/<\/?cross-session-message[^>]*>/g,"").replace(/\s+/g," ").trim()}function ae(u){const e=u.trimStart();return e.startsWith(k)?e.slice(k.length):e}function b(u){return u.replace(/\s+/g,"")}const O="pane-envs.json";function de(u){try{const e=JSON.parse(T(u,"utf8"));if(typeof e!="object"||e===null)return{};const t={};for(const[s,i]of Object.entries(e)){if(typeof i!="object"||i===null)continue;const n={};for(const[r,o]of Object.entries(i))typeof o=="string"&&o&&(n[r]=o);Object.keys(n).length>0&&(t[s]=n)}return t}catch{return{}}}const le=u=>new Promise(e=>setTimeout(e,u));export class MessageDeliverer{deps;headless;hooksDir;memory=new Map;queuedSessions;inboxSockets;paneEnvs;persistedPaneEnvs;flushScheduled=new Set;flushing=new Set;stalled=new Map;awaitingAck=new Map;dismissedIds=new Set;constructor(e){this.deps=e,this.headless=e.headless??new F({spawnImpl:e.spawnImpl,killImpl:e.killImpl}),this.hooksDir=e.hooksDir??N(),this.inboxSockets=new K(p(this.hooksDir,$));const t=de(p(this.hooksDir,O));this.paneEnvs=new Map(Object.entries(t)),this.persistedPaneEnvs=JSON.stringify(t),this.queuedSessions=G(this.hooksDir)}async send(e){const t=this.deps.sessions.getBySessionId(e.toSessionId);if(!t)return{ok:!1,status:404,error:"Session not found"};const s=this.surfaceOfSession(e.toSessionId);if(!s)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};const i=e.images?[...e.images]:[];if(i.length>0&&!s.imageAttach)return{ok:!1,status:409,error:"This harness cannot receive images"};const n=this.resolveChannel(e.mode,e.toSessionId,s);if(typeof n!="string")return{ok:!1,status:409,error:n.reason};if(t.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const r=this.deps.projects.getById(t.projectId);if(!r)return{ok:!1,status:404,error:"Project not found"};if(n==="headless"&&this.headless.isBusy(e.toSessionId))return{ok:!1,status:409,error:"Session already has a running run"};const o={fromLabel:e.fromKind==="session"?`session ${e.fromSessionId??"unknown"}`:e.fromKind,at:new Date().toISOString(),mode:n},a={id:A(),sessionId:e.toSessionId,text:e.text,...i.length>0?{images:i}:{},mode:e.mode,oneWay:e.oneWay===!0,...e.forceTerminal===!0?{forceTerminal:!0}:{},channel:n,status:"pending",at:o.at},d=n==="prompt"&&this.blockedAhead(a.sessionId);d&&(this.queueEntry(a,r.token),this.scheduleFlushContinuation(a.sessionId));const l=d?{ok:!0,messageId:a.id,status:"pending",message:a}:n==="inject"?this.deliverInject(a,r.token,o,s):n==="headless"?this.deliverHeadless(a,r.path,o,s):await this.deliverPrompt(a,t,r,s);return this.bus({kind:"message.created",messageId:a.id,sessionId:a.sessionId,mode:a.mode,at:a.at}),l}getMessage(e){return this.memory.get(e)??null}listVisible(e){const t=this.deps.visibleTtlMs??X,s=Date.now(),i=[],n=this.deps.sessions.getBySessionId(e);if(n?.projectId!=null){const r=this.deps.projects.getById(n.projectId);if(r)for(const o of m(this.hooksDir,r.token))o.sessionId===e&&i.push({id:o.id,sessionId:e,text:o.text,...o.images&&o.images.length>0?{images:o.images}:{},mode:"prompt",oneWay:o.oneWay===!0,...o.forceTerminal===!0?{forceTerminal:!0}:{},channel:"prompt",status:"pending",at:o.at})}for(const r of this.memory.values()){if(r.sessionId!==e)continue;if(r.stalled===!0||r.status==="delivering"||r.status==="running"){i.push(r);continue}if(r.status==="failed"||r.status==="timeout"){i.push(r);continue}const o=r.settledAt?Date.parse(r.settledAt):NaN;(r.status==="delivered"&&r.acked!==!0||!Number.isNaN(o)&&s-o<t)&&i.push(r)}return i.sort((r,o)=>r.at<o.at?-1:1)}hasQueued(e){return this.queuedSessions.has(e)}listInflightCounts(){const e=new Map,t=s=>{e.set(s,(e.get(s)??0)+1)};for(const s of H(this.hooksDir))t(s.sessionId);for(const s of this.memory.values())(s.status==="delivering"||s.status==="running")&&t(s.sessionId);return e}hasTerminalChannel(){return this.terminalChannel()!=null}scheduleFlushContinuation(e){if(this.flushScheduled.has(e))return;this.flushScheduled.add(e),setTimeout(()=>{this.flushScheduled.delete(e),this.flushSession(e)},this.deps.flushGapMs??V).unref?.()}ackGateOpen(e){const t=this.awaitingAck.get(e);if(t===void 0)return!0;const s=this.memory.get(t);return s&&s.acked!==!0&&s.status!=="failed"&&s.status!=="timeout"?!1:(this.awaitingAck.delete(e),!0)}blockedAhead(e){return this.ackGateOpen(e)?this.queuedSessions.has(e)||this.flushing.has(e):!0}noteInboxSocket(e,t){this.inboxSockets.set(e,t)}notePaneEnv(e,t){this.paneEnvs.set(e,t),this.persistPaneEnvs()}persistPaneEnvs(){const e=JSON.stringify(Object.fromEntries(this.paneEnvs));if(e===this.persistedPaneEnvs)return;const t=p(this.hooksDir,O);try{j(B(t),{recursive:!0});const s=`${t}.tmp`;M(s,`${e}
|
|
2
|
+
`,{encoding:"utf8",mode:384}),P(s,t),D(t,384),this.persistedPaneEnvs=e}catch{}}sessionExited(e){this.inboxSockets.forget(e),this.paneEnvs.delete(e),this.persistPaneEnvs(),this.awaitingAck.delete(e);const t=this.deps.sessions.getBySessionId(e),s=t?.projectId==null?null:this.deps.projects.getById(t.projectId);if(!s)return;const i=m(this.hooksDir,s.token).filter(n=>n.sessionId===e);this.failQueuedOffline(e,i.filter(n=>!this.dismissedIds.has(n.id)))}async sessionTerminals(){const e=this.terminalChannel();if(!e?.locateScreens||this.paneEnvs.size===0)return{};const t={},s=this.deps.livenessOf?.()??g();for(const[i,n]of this.paneEnvs){if(this.sessionJudgedDead(i,s)){this.paneEnvs.delete(i),this.persistPaneEnvs();continue}t[i]=n}return e.locateScreens(t)}diagnose(e){const t=this.surfaceOfSession(e),s=this.deps.sessions.livenessRowOf(e),i=s?v(s,this.deps.livenessOf?.()??g()):null,n=t?.promptInbox??null,r=this.inboxSockets.get(e),o=n?r?n.requiresAuthOn(process.platform)&&!r.token?{status:"unavailable",reason:"auth-token-required"}:{status:"ready",reason:null}:{status:"unavailable",reason:"no-credentials"}:{status:"unavailable",reason:"no-mechanism"},a=t?.prompt?.resolve(e)??null,d=t?.prompt?a?{status:"ready",reason:null}:{status:"unavailable",reason:"no-peer-name"}:{status:"unavailable",reason:"no-mechanism"},l=this.paneEnvs.has(e),h=this.terminalChannel()?l?{status:"ready",reason:null}:{status:"unknown",reason:"no-pane-env"}:{status:"unavailable",reason:"no-backend"},c=this.deps.sessions.getBySessionId(e),S=c?.projectId==null?null:this.deps.projects.getById(c.projectId),E=S?m(this.hooksDir,S.token).filter(x=>x.sessionId===e).length:0;return{alive:i,inbox:o,relay:d,terminal:h,paneEnvReported:l,pending:E,stalled:this.stalled.has(e)}}onSessionPrompt(e,t,s){const i=y(ae(t)),n=i.replace(/\[Image #\d+\]/gi,"").trim(),r=[];let o=!1;for(const a of[...this.memory.values()].reverse()){if(a.sessionId!==e||a.acked||a.mode!=="prompt")continue;const d=y(a.text),l=!!d&&(d.length>=Z?i.includes(d):i===d),h=(a.images?.length??0)>0&&(d?b(i).includes(b(d)):n.length===0);!l&&!h||(o=!0,this.memory.set(a.id,{...a,acked:!0,stalled:!1,...s===void 0?{}:{ackedEventId:s}}),this.stalled.get(e)?.messageId===a.id&&this.stalled.delete(e),this.awaitingAck.get(e)===a.id&&this.awaitingAck.delete(e),r.push(...a.images?.map(c=>c.id)??[]),this.bus({kind:"message.acknowledged",messageId:a.id,sessionId:e,at:new Date().toISOString()}))}return o&&this.queuedSessions.has(e)&&this.scheduleFlushContinuation(e),r}armAckWatch(e){setTimeout(()=>{const s=this.memory.get(e.id);!s||s.acked||s.status!=="delivered"||this.stall(s.sessionId,s,"unacked")},this.deps.ackStallMs??z).unref?.()}stall(e,t,s){this.stalled.set(e,{messageId:t.id,reason:s});const i=this.memory.get(t.id);i&&this.memory.set(t.id,{...i,stalled:!0}),this.bus({kind:"message.stalled",messageId:t.id,sessionId:e,reason:s,at:new Date().toISOString()})}async answer(e,t){if(t.length===0||!w.test(t[0])||t.some(i=>!w.test(i)&&!se.test(i)))return{ok:!1,status:400,error:"Invalid answer keys"};const s=await this.sessionKeysTarget(e);if(!s.ok)return s;try{for(const[i,n]of t.entries())i>0&&await le(oe),await s.terminal.sendKeys(s.paneId,n);return{ok:!0}}catch(i){return{ok:!1,status:409,error:i instanceof Error?i.message:String(i)}}}async interrupt(e){const t=await this.sessionKeysTarget(e);if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,te),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async closePane(e){const t=await this.sessionKeysTarget(e,"\u5173\u95ED");if(!t.ok)return t;try{return await t.terminal.closePane(t.paneId),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async cycleMode(e){const t=await this.sessionKeysTarget(e);if(!t.ok)return t;try{return await t.terminal.sendKeys(t.paneId,ie),{ok:!0}}catch(s){return{ok:!1,status:409,error:s instanceof Error?s.message:String(s)}}}async setModel(e,t){const s=t.trim();if(!ne.test(s))return{ok:!1,status:400,error:"\u6A21\u578B\u540D\u5F62\u6001\u4E0D\u5408\u6CD5\uFF08\u4E0D\u542B\u7A7A\u767D\u4E0E\u63A7\u5236\u5B57\u7B26\uFF0C\u2264128 \u5B57\u7B26\uFF09"};const i=await this.sessionKeysTarget(e);if(!i.ok)return i;try{return await i.terminal.sendText(i.paneId,re(s)),{ok:!0}}catch(n){return{ok:!1,status:409,error:n instanceof Error?n.message:String(n)}}}async sessionKeysTarget(e,t="\u51FB\u952E"){const s=this.deps.sessions.getBySessionId(e);if(!s)return{ok:!1,status:404,error:"Session not found"};if(s.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const i=this.deps.projects.getById(s.projectId);if(!i)return{ok:!1,status:404,error:"Project not found"};const n=this.terminalChannel();if(!n)return{ok:!1,status:409,error:`\u7EC8\u7AEF\u901A\u9053\u672A\u88C5\u914D\uFF0C\u65E0\u6CD5\u8FDC\u7A0B${t}`};const r=await this.terminalPaneFor(s,i);return r?{ok:!0,terminal:n,paneId:r.id}:{ok:!1,status:409,error:`\u627E\u4E0D\u5230\u4F1A\u8BDD\u6240\u5728\u7684\u7EC8\u7AEF\u7A97\u53E3\u2014\u2014\u8FD9\u4E2A\u4F1A\u8BDD\u6240\u5728\u7EC8\u7AEF\u6CA1\u6709\u53EF\u7528\u7684\u8FDC\u7A0B${t}\u901A\u9053`}}async resend(e){const t=this.memory.get(e);if(!t)return{ok:!1,status:404,error:"Message not found"};if(!(t.channel==="prompt"&&(t.status==="failed"||t.status==="delivered"&&!t.acked)))return{ok:!1,status:409,error:"Message is not resendable"};const i=this.deps.sessions.getBySessionId(t.sessionId);if(!i)return{ok:!1,status:404,error:"Session not found"};if(i.projectId==null)return{ok:!1,status:400,error:"Session is not bound to a project"};const n=this.deps.projects.getById(i.projectId);if(!n)return{ok:!1,status:404,error:"Project not found"};const r=this.surfaceOfSession(t.sessionId);if(!r)return{ok:!1,status:400,error:"Session has no hook events to determine its harness"};if(this.stalled.get(t.sessionId)?.messageId===e&&this.stalled.delete(t.sessionId),t.status==="delivered"&&t.via==="terminal"&&this.terminalChannel()){const d=await this.terminalPaneFor(i,n);if(d)return this.memory.set(e,{...t,status:"delivering",stalled:!1,settledAt:null}),this.runTerminalSubmit(e,d.id),this.bus({kind:"message.created",messageId:e,sessionId:t.sessionId,mode:t.mode,at:new Date().toISOString()}),{ok:!0,messageId:e,status:"delivering",message:this.memory.get(e)}}this.memory.delete(e);const o={...t,status:"pending",stalled:!1,acked:!1,settledAt:null},a=await this.deliverPrompt(o,i,n,r);return this.bus({kind:"message.created",messageId:o.id,sessionId:o.sessionId,mode:o.mode,at:new Date().toISOString()}),a}dismiss(e,t){const s=this.memory.get(t);if(s){if(s.status==="delivering"||s.status==="running")return{ok:!1,status:409,error:"Message is still in flight"};this.memory.delete(t),this.stalled.get(s.sessionId)?.messageId===t&&this.stalled.delete(s.sessionId),this.awaitingAck.get(s.sessionId)===t&&this.awaitingAck.delete(s.sessionId),this.queuedSessions.has(s.sessionId)&&this.scheduleFlushContinuation(s.sessionId)}else if(!this.dropQueued(e,t))return{ok:!1,status:404,error:"Message not found"};return this.bus({kind:"message.dismissed",messageId:t,sessionId:e,at:new Date().toISOString()}),{ok:!0}}dropQueued(e,t){const s=this.deps.sessions.getBySessionId(e);if(s?.projectId==null)return!1;const i=this.deps.projects.getById(s.projectId);if(!i)return!1;const n=m(this.hooksDir,i.token);if(!n.some(r=>r.id===t&&r.sessionId===e))return!1;for(f(this.hooksDir,i.token,new Set([t])),this.dismissedIds.add(t);this.dismissedIds.size>ee;){const r=this.dismissedIds.values().next().value;if(r===void 0)break;this.dismissedIds.delete(r)}return n.some(r=>r.sessionId===e&&r.id!==t)||this.queuedSessions.delete(e),!0}async flushSession(e){if(!this.stalled.has(e)&&!this.flushing.has(e)&&this.queuedSessions.has(e)){this.flushing.add(e);try{await this.flushSessionInner(e)}catch{}finally{this.flushing.delete(e)}}}async flushSessionInner(e){if(!this.ackGateOpen(e))return;const t=this.deps.sessions.getBySessionId(e);if(t?.projectId==null)return;const s=this.deps.projects.getById(t.projectId);if(!s)return;const i=m(this.hooksDir,s.token).filter(o=>o.sessionId===e);if(i.length===0){this.queuedSessions.delete(e);return}if(this.sessionJudgedDead(e)){this.failQueuedOffline(e,i.filter(o=>!this.dismissedIds.has(o.id)));return}const n=this.surfaceOfSession(e),r=n?.prompt??null;for(const o of i){if(this.stalled.has(e))return;if(this.dismissedIds.has(o.id))continue;const a={id:o.id,sessionId:e,text:o.text,...o.images&&o.images.length>0?{images:o.images}:{},mode:"prompt",oneWay:o.oneWay===!0,...o.forceTerminal===!0?{forceTerminal:!0}:{},via:"socket",channel:"prompt",status:"pending",at:o.at};if(this.hasImages(a)&&this.terminalChannel()){const h=await this.terminalPaneFor(t,s);if(h){f(this.hooksDir,s.token,new Set([o.id])),this.memory.set(a.id,{...a,via:"terminal",status:"delivering"}),this.awaitingAck.set(e,a.id),await this.runTerminalPrompt(a.id,h.id,this.wireTextOf(a)),this.settleQueueIndex(e,s.token);return}}if(n&&await this.tryInboxDeliver(a,n)){f(this.hooksDir,s.token,new Set([o.id])),this.settleQueueIndex(e,s.token);return}const d=r?.resolve(e)??null,l=a.forceTerminal===!0?["terminal"]:a.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const h of l){if(h==="relay"&&r&&d){if(this.memory.set(a.id,{...a,status:"delivering",via:"relay"}),!this.runRelay(a,r,d.name)){this.memory.delete(a.id);return}this.awaitingAck.set(e,a.id),f(this.hooksDir,s.token,new Set([o.id]));break}if(h==="terminal"&&this.terminalChannel()){const c=await this.terminalPaneFor(t,s);if(c){f(this.hooksDir,s.token,new Set([o.id])),this.memory.set(a.id,{...a,via:"terminal",status:"delivering"}),this.awaitingAck.set(e,a.id),await this.runTerminalPrompt(a.id,c.id,this.wireTextOf(a));break}}}if(this.awaitingAck.get(e)===a.id){this.settleQueueIndex(e,s.token);return}return}this.settleQueueIndex(e,s.token)}settleQueueIndex(e,t){m(this.hooksDir,t).every(s=>s.sessionId!==e)&&this.queuedSessions.delete(e)}async flushAll(){for(const e of[...this.queuedSessions])await this.flushSession(e)}forgetSession(e){let t=0;for(const[s,i]of this.memory)i.sessionId===e&&(this.memory.delete(s),t++);return t+=J(this.hooksDir,e),this.queuedSessions.delete(e),this.stalled.delete(e),this.awaitingAck.delete(e),this.inboxSockets.forget(e),this.paneEnvs.delete(e),this.persistPaneEnvs(),t}forgetProject(e){let t=0;for(const[s,i]of this.memory)this.deps.sessions.getBySessionId(i.sessionId)?.projectId===e&&(this.memory.delete(s),this.inboxSockets.forget(i.sessionId),this.paneEnvs.delete(i.sessionId),this.stalled.delete(i.sessionId),this.awaitingAck.delete(i.sessionId),t++);for(const s of[...this.queuedSessions])this.deps.sessions.getBySessionId(s)?.projectId===e&&(t+=this.forgetSession(s));return this.persistPaneEnvs(),t}surfaceOfSession(e){const t=this.deps.hookEvents.listBySession(e,1),s=t[t.length-1]?.source;return R(s)?this.deps.surfaceFor?.(s)??W(s):null}resolveChannel(e,t,s){if(e==="prompt")return s.prompt||this.terminalChannel()?"prompt":{reason:s.unsupportedReasons?.prompt??`Harness "${s.harness}" has no native prompt channel and the configured terminal cannot inject text`};if(e==="inject"||e==="headless")return(e==="inject"?s.inject:s.headless)?e:{reason:this.unsupportedReason(s,e)};const n=this.deps.sessions.turnOpenOf(t)?"inject":"headless";return(n==="inject"?s.inject:s.headless)?n:{reason:this.unsupportedReason(s,n)}}unsupportedReason(e,t){return e.unsupportedReasons?.[t]??`Harness "${e.harness}" does not support the ${t} messaging channel`}async terminalPaneFor(e,t){const s=this.terminalChannel();if(!s)return null;const i=this.paneEnvs.get(e.sessionId);if(i){const d=await s.locatePane?.(i).catch(()=>null);if(d)return{id:d}}if(!e.title)return null;const n=e.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,""),r=I(t.path,process.platform);let o;try{o=await s.listPanes()}catch{return null}const a=o.filter(d=>d.title!=null&&d.cwd!=null&&r!=null&&d.title.replace(/^[✻✽✶✳✢⋅◦✦✧∘◐◑◒◓*]+\s*/,"")===n&&I(d.cwd,process.platform)===r);return a.length===1?a[0]:null}terminalChannel(){const e=this.deps.terminal;return e&&e.available()?e:null}async deliverPrompt(e,t,s,i){if(this.sessionJudgedDead(e.sessionId))return{ok:!0,messageId:e.id,status:"failed",message:this.failOffline(e)};if(this.hasImages(e)&&this.terminalChannel()){const l=await this.terminalPaneFor(t,s);if(l)return this.memory.set(e.id,{...e,status:"delivering",via:"terminal"}),this.awaitingAck.set(e.sessionId,e.id),this.runTerminalPrompt(e.id,l.id,this.wireTextOf(e)),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)}}const n=await this.tryInboxDeliver(e,i);if(n)return{ok:!0,messageId:e.id,status:"delivered",message:n};const r=i.prompt,o=r?.resolve(e.sessionId)??null,a=e.forceTerminal===!0?["terminal"]:e.oneWay===!0?["terminal","relay"]:["relay","terminal"];for(const l of a){if(l==="relay"&&r&&o){if(this.memory.set(e.id,{...e,status:"delivering",via:"relay"}),this.runRelay(e,r,o.name))return this.awaitingAck.set(e.sessionId,e.id),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)};this.memory.delete(e.id)}if(l==="terminal"&&this.terminalChannel()){const h=await this.terminalPaneFor(t,s);if(h)return this.memory.set(e.id,{...e,status:"delivering",via:"terminal"}),this.awaitingAck.set(e.sessionId,e.id),this.runTerminalPrompt(e.id,h.id,this.wireTextOf(e)),{ok:!0,messageId:e.id,status:"delivering",message:this.memory.get(e.id)}}}if(this.sessionJudgedDead(e.sessionId))return{ok:!0,messageId:e.id,status:"failed",message:this.failOffline(e)};this.queueEntry(e,s.token);const d={...e,status:"pending"};return{ok:!0,messageId:e.id,status:"pending",message:d}}async tryInboxDeliver(e,t){const s=t.promptInbox,i=this.inboxSockets.get(e.sessionId);if(!s||e.oneWay!==!0||!i||e.forceTerminal===!0)return null;this.memory.set(e.id,{...e,status:"delivering",via:"socket"});try{await L(s,i,`${k}${this.wireTextOf(e)}`)}catch{return this.memory.delete(e.id),null}const n={...this.memory.get(e.id),status:"delivered",via:"socket",settledAt:new Date().toISOString()};return this.memory.set(e.id,n),this.awaitingAck.set(e.sessionId,e.id),this.armAckWatch(n),this.bus({kind:"message.delivered",messageId:e.id,sessionId:e.sessionId,at:new Date().toISOString()}),n}queueEntry(e,t){Q(this.hooksDir,t,[{id:e.id,sessionId:e.sessionId,text:e.text,oneWay:e.oneWay===!0,...e.forceTerminal===!0?{forceTerminal:!0}:{},...e.images&&e.images.length>0?{images:e.images}:{}}]),this.queuedSessions.add(e.sessionId)}sessionJudgedDead(e,t=this.deps.livenessOf?.()??g()){const s=this.deps.sessions.livenessRowOf(e);return s?v(s,t)===!1:!1}failOffline(e){const t=new Date().toISOString(),s={...e,status:"failed",reason:"offline",error:Y,settledAt:t};return this.memory.set(e.id,s),this.bus({kind:"message.finished",messageId:e.id,sessionId:e.sessionId,status:"failed",at:t}),s}failQueuedOffline(e,t){const s=this.deps.sessions.getBySessionId(e),i=s?.projectId==null?null:this.deps.projects.getById(s.projectId);if(!(!i||t.length===0)){for(const n of t)this.failOffline({id:n.id,sessionId:e,text:n.text,...n.images&&n.images.length>0?{images:n.images}:{},mode:"prompt",oneWay:n.oneWay===!0,channel:"prompt",status:"pending",at:n.at});f(this.hooksDir,i.token,new Set(t.map(n=>n.id))),this.queuedSessions.delete(e)}}runRelay(e,t,s){try{return this.headless.run({sessionId:`prompt-relay:${e.sessionId}`,cwd:U(),prompt:t.instruction(s,this.wireTextOf(e),{oneWay:e.oneWay===!0}),spec:{supported:!0,bin:t.bin,args:()=>[...t.args],promptStdin:!0},bin:this.deps.bin??process.env.WEAVE_CLAUDE_BIN??t.bin,timeoutMs:this.deps.relayTimeoutMs??0,detached:!1,onSettle:i=>this.settleRelay(e.id,i)})}catch(i){return this.settleRelay(e.id,{status:"failed",output:null,error:i instanceof Error?i.message:String(i)}),!0}}settleRelay(e,t){const s=this.memory.get(e);if(!s)return;if(t.status==="succeeded"){this.queuedSessions.has(s.sessionId)&&this.scheduleFlushContinuation(s.sessionId);const n={...s,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(e,n),this.armAckWatch(n),this.bus({kind:"message.delivered",messageId:e,sessionId:s.sessionId,at:new Date().toISOString()});return}if(s.acked===!0){const n=new Date().toISOString();this.memory.set(e,{...s,status:"delivered",settledAt:n}),this.bus({kind:"message.delivered",messageId:e,sessionId:s.sessionId,at:n});return}const i={...s,status:"failed",error:t.error??`prompt relay ${t.status}`,settledAt:new Date().toISOString()};this.memory.set(e,i),this.stall(s.sessionId,i,"failed"),this.bus({kind:"message.finished",messageId:e,sessionId:s.sessionId,status:"failed",at:new Date().toISOString()})}async runTerminalPrompt(e,t,s){await this.runTerminal(e,i=>i.sendText(t,s))}async runTerminalSubmit(e,t){await this.runTerminal(e,s=>s.sendKeys(t,"\r"))}async runTerminal(e,t){const s=this.memory.get(e);if(!s)return;const i=this.terminalChannel();if(i)try{await t(i);const r={...this.memory.get(e)??s,status:"delivered",settledAt:new Date().toISOString()};this.memory.set(e,r),this.armAckWatch(r),this.bus({kind:"message.delivered",messageId:e,sessionId:s.sessionId,at:new Date().toISOString()})}catch(n){const r=this.memory.get(e)??s;if(r.acked===!0){const a=new Date().toISOString();this.memory.set(e,{...r,status:"delivered",settledAt:a}),this.bus({kind:"message.delivered",messageId:e,sessionId:r.sessionId,at:a});return}const o={...r,status:"failed",error:n instanceof Error?n.message:String(n),settledAt:new Date().toISOString()};this.memory.set(e,o),this.stall(s.sessionId,o,"failed"),this.bus({kind:"message.finished",messageId:e,sessionId:s.sessionId,status:"failed",at:new Date().toISOString()})}}wireTextOf(e){const t=e.images;return!t||t.length===0?e.text:this.surfaceOfSession(e.sessionId)?.imageAttach?.composePrompt(e.text,t)??e.text}hasImages(e){return(e.images?.length??0)>0}deliverInject(e,t,s,i){const n=this.renderEnvelope(this.wireTextOf(e),s,i);q(this.hooksDir,t,[{sessionId:e.sessionId,text:n}]);const r={...e,status:"injected",settledAt:new Date().toISOString()};return this.memory.set(r.id,r),this.bus({kind:"message.delivered",messageId:r.id,sessionId:r.sessionId,at:new Date().toISOString()}),{ok:!0,messageId:r.id,status:"injected",message:r}}deliverHeadless(e,t,s,i){const n=i.headless,r={...e,status:"running"};this.memory.set(r.id,r);const o={settled:!1};try{this.headless.run({sessionId:r.sessionId,cwd:t,prompt:this.renderEnvelope(this.wireTextOf(r),s,i),spec:n,bin:this.deps.bin??process.env.WEAVE_CLAUDE_BIN??n.bin,timeoutMs:this.deps.timeoutMs,onSettle:d=>this.settle(r,o,d)})||this.settle(r,o,{status:"failed",output:null,error:"Session already has a running run"})}catch(a){this.settle(r,o,{status:"failed",output:null,error:a instanceof Error?a.message:String(a)})}return{ok:!0,messageId:r.id,status:"running",message:this.memory.get(r.id)}}renderEnvelope(e,t,s){return s.renderEnvelope?.(e,t)??`[weave message] from=${t.fromLabel} at=${t.at} mode=${t.mode}
|
|
2
3
|
|
|
3
|
-
${
|
|
4
|
+
${e}`}settle(e,t,s){if(t.settled)return;t.settled=!0;const i=this.memory.get(e.id);if(i)try{this.memory.set(e.id,{...i,status:s.status,output:s.output,error:s.error,settledAt:new Date().toISOString()}),this.bus({kind:"message.finished",messageId:e.id,sessionId:e.sessionId,status:s.status,at:new Date().toISOString()})}catch{}}bus(e){try{this.deps.bus?.emit(e)}catch{}}}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{createHash as
|
|
2
|
-
`,{flag:"a"})}export function appendOutbox(
|
|
3
|
-
`).filter(c=>c.trim())}catch{t=[]}for(const c of e)t.push(JSON.stringify({...c,at:new Date().toISOString()}));const
|
|
1
|
+
import{createHash as h}from"node:crypto";import{mkdirSync as a,readFileSync as u,renameSync as d,writeFileSync as p}from"node:fs";import{join as n}from"node:path";import{hookSourceHarness as m}from"@weavecode/core";import{getDataDir as l}from"../db/paths.js";import{projectLabel as y}from"./match.js";export const MIRROR_VERSION=1,OUTBOX_MAX_LINES=200;export function hookShardId(i){return h("sha256").update(i).digest("hex").slice(0,16)}export function hooksRoot(i=l()){return n(i,"hooks")}export function mirrorPathOf(i,r){return n(i,"mirror",`${r}.json`)}export function outboxPathOf(i,r){return n(i,"outbox",`${r}.jsonl`)}export function buildMirrorDoc(i,r,e){const o=r.filter(t=>!(t.source.kind!=="hook-event"||m(t.source)!=="claude"||t.handler.type!=="inject"||!t.enabled||t.projectId!==null&&t.projectId!==i.id||t.filter.crossProjectOnly)).sort((t,s)=>s.priority-t.priority).map(t=>({id:t.id,name:t.name,events:[t.source.kind==="hook-event"?t.source.event:""],tools:t.filter.toolNames?.length?[...t.filter.toolNames]:null,globs:t.filter.pathGlobs?.length?[...t.filter.pathGlobs]:null,template:t.handler.type==="inject"?t.handler.template:""}));return{version:MIRROR_VERSION,project:y(i.path),pendingTitles:e,rules:o}}export class MirrorWriter{deps;dataDir;constructor(r){this.deps=r,this.dataDir=r.dataDir??l()}syncAll(){for(const r of this.deps.projects.list())this.syncProject(r.id)}syncProject(r){const e=this.deps.projects.getById(r);if(!e||e.archivedAt)return;const o={};for(const t of this.deps.sessions.list(r))t.pendingTitle&&(o[t.sessionId]=t.pendingTitle);this.write(e.token,buildMirrorDoc(e,this.deps.rules.list(),o))}write(r,e){try{const o=mirrorPathOf(hooksRoot(this.dataDir),hookShardId(r));a(n(hooksRoot(this.dataDir),"mirror"),{recursive:!0});const t=`${o}.tmp`;p(t,JSON.stringify(e)),d(t,o)}catch{}}attachToBus(r){r.subscribe(e=>{if(e.kind!=="session.renamed"||!e.sessionId)return;const o=this.deps.sessions.getBySessionId(e.sessionId);o?.projectId!=null&&this.syncProject(o.projectId)})}}export function appendInbox(i,r,e){const o=n(i,"inbox");a(o,{recursive:!0}),p(n(o,`${hookShardId(r)}.jsonl`),JSON.stringify({v:1,token:r,report:e})+`
|
|
2
|
+
`,{flag:"a"})}export function appendOutbox(i,r,e){if(e.length!==0)try{const o=outboxPathOf(i,hookShardId(r));a(n(i,"outbox"),{recursive:!0});let t=[];try{t=u(o,"utf8").split(`
|
|
3
|
+
`).filter(c=>c.trim())}catch{t=[]}for(const c of e)t.push(JSON.stringify({...c,at:new Date().toISOString()}));const s=t.slice(-OUTBOX_MAX_LINES),f=`${o}.tmp`;p(f,s.length?s.join(`
|
|
4
4
|
`)+`
|
|
5
|
-
`:""),d(
|
|
5
|
+
`:""),d(f,o)}catch{}}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{cp as j,mkdir as p,readFile as
|
|
2
|
-
`,"utf8")}async function
|
|
3
|
-
`,"utf8")}export async function searchPlugins(
|
|
1
|
+
import{cp as j,mkdir as p,readFile as g,readdir as D,rm as m,writeFile as P}from"node:fs/promises";import{existsSync as v}from"node:fs";import s from"node:path";import{spawn as F}from"node:child_process";import{WEAVE_PLUGIN_MANIFEST as x,WeavePluginManifestSchema as J}from"@weavecode/core";import{getDataDir as A}from"../db/paths.js";export function globalPluginRoot(){return s.join(A(),"plugins")}function E(t){return s.join(t??globalPluginRoot(),"installed.json")}async function N(t){try{const r=JSON.parse(await g(E(t),"utf8"));return Array.isArray(r)?r:[]}catch{return[]}}async function O(t,r){const i=r??globalPluginRoot();await p(i,{recursive:!0}),await P(E(r),JSON.stringify(t,null,2)+`
|
|
2
|
+
`,"utf8")}async function S(t){try{const r=JSON.parse(await g(s.join(t,x),"utf8"));return J.safeParse(r).success?r:null}catch{return null}}async function T(t){const r=[],i=await S(t);if(i)return[{dir:t,manifest:i}];let o;try{o=await D(t)}catch{return r}for(const a of o){const e=s.join(t,a),n=await S(e);n&&r.push({dir:e,manifest:n})}return r}function W(t,r,i,o=6e4){return new Promise((a,e)=>{const n=F(t,r,{cwd:i,windowsHide:!0,stdio:["ignore","pipe","pipe"]});let u="";const l=setTimeout(()=>{n.kill(),e(new Error(`${t} ${r.join(" ")} \u8D85\u65F6\uFF08${o}ms\uFF09`))},o);n.stderr?.on("data",c=>u+=c.toString()),n.on("error",c=>{clearTimeout(l),e(c)}),n.on("close",c=>{clearTimeout(l),c===0?a():e(new Error(`${t} \u9000\u51FA\u7801 ${c}: ${u.slice(0,500)}`))})})}export function isGitSource(t){return/^(https?:\/\/|git@|ssh:\/\/|git:\/\/)/.test(t)||t.endsWith(".git")}export async function installPlugin(t,r){const i=[];let o,a;if(isGitSource(t)){i.push(`\u4ECE ${t} \u5B89\u88C5\u7684\u63D2\u4EF6\u672A\u7ECF\u6C99\u7BB1\u9694\u79BB\uFF0C\u8BF7\u786E\u8BA4\u6765\u6E90\u53EF\u4FE1`);const e=s.join(A(),"tmp",`install-${Date.now()}`);await p(e,{recursive:!0}),await W("git",["clone","--depth","1",t,s.join(e,"repo")]),o=s.join(e,"repo"),a=()=>m(e,{recursive:!0,force:!0})}else if(o=s.resolve(t),!v(o))throw new Error(`\u672C\u5730\u8DEF\u5F84\u4E0D\u5B58\u5728: ${o}`);try{const e=await T(o);if(e.length===0)throw new Error(`\u672A\u627E\u5230 ${x}\uFF08src \u6216\u5176\u4E00\u7EA7\u5B50\u76EE\u5F55\uFF09`);const n=r?.root??globalPluginRoot();await p(n,{recursive:!0});const u=await N(r?.root),l=[];for(const{dir:c,manifest:y}of e){const f=String(y.id),h=s.join(n,f);s.resolve(h).startsWith(s.resolve(n)+s.sep)&&(await m(h,{recursive:!0,force:!0}),await j(c,h,{recursive:!0,filter:w=>!w.includes("node_modules")&&!w.includes(`${s.sep}.git`)}));const d={id:f,name:String(y.name??f),version:String(y.version??"0.0.0"),source:t,dir:f,installedAt:new Date().toISOString()},$=u.findIndex(w=>w.id===f);$>=0?u[$]=d:u.push(d),l.push({id:f,name:d.name,version:d.version,dir:f})}return await O(u,r?.root),{installed:l,warnings:i}}finally{a&&await a()}}export async function uninstallPlugin(t,r){const i=r?.root??globalPluginRoot(),o=await N(r?.root),a=o.find(n=>n.id===t),e=a?s.join(i,a.dir):s.join(i,t);return v(e)?(await m(e,{recursive:!0,force:!0}),a&&await O(o.filter(n=>n.id!==t),r?.root),!0):!1}export async function exportPlugin(t,r,i){const o=s.join(i?.root??globalPluginRoot(),t);if(!v(o))throw new Error(`\u63D2\u4EF6\u76EE\u5F55\u4E0D\u5B58\u5728: ${o}`);if(!await S(o))throw new Error(`\u63D2\u4EF6\u7F3A\u5C11\u5408\u6CD5 ${x}: ${t}`);const e=s.join(s.resolve(r),t);return await m(e,{recursive:!0,force:!0}),await j(o,e,{recursive:!0,filter:n=>!n.includes("node_modules")&&!n.includes(`${s.sep}.git`)}),e}function _(t){return s.join(t??globalPluginRoot(),"sources.json")}export function parseSources(t){if(Array.isArray(t))return{indexes:t.filter(r=>typeof r=="string")};if(t&&typeof t=="object"){const r=t.indexes;return{indexes:Array.isArray(r)?r.filter(i=>typeof i=="string"):[]}}return{indexes:[]}}export async function readSourcesFile(t){try{return parseSources(JSON.parse(await g(_(t),"utf8")))}catch{return{indexes:[]}}}export async function writeSourcesFile(t,r){const i=r??globalPluginRoot();await p(i,{recursive:!0}),await P(_(r),JSON.stringify(t,null,2)+`
|
|
3
|
+
`,"utf8")}export async function searchPlugins(t){const{indexes:r}=await readSourcesFile(),i=[];for(const o of r)try{const a=await fetch(o,{signal:AbortSignal.timeout(1e4)});if(!a.ok)continue;const e=await a.json();for(const n of e.plugins??[]){const u=`${n.id} ${n.name} ${n.description??""}`.toLowerCase();(!t||u.includes(t.toLowerCase()))&&i.push(n)}}catch{}return i}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as I}from"node:fs";import{readFile as S,readdir as A}from"node:fs/promises";import c from"node:path";import{pathToFileURL as P}from"node:url";import{watch as M}from"chokidar";import{builtinRulesDir as O}from"../market/builtin.js";import{HARNESS_EVENT_UNION as W,HookRuleSchema as x,PluginRuleEntrySchema as H,WEAVE_PLUGIN_MANIFEST as j,WeavePluginManifestSchema as L}from"@weavecode/core";import{getDataDir as T}from"../db/paths.js";import{marketLibraryRoots as N}from"../market/resolve.js";import{validateHandler as C}from"./registry.js";import{builtinToolkitRoot as U,discoverToolkitSources as _,discoverWeavePackDirs as B}from"./toolkit-scan.js";export function createPluginLogger(l){return{debug:e=>console.debug(`[plugin:${l}] ${e}`),info:e=>console.info(`[plugin:${l}] ${e}`),warn:e=>console.warn(`[plugin:${l}] ${e}`),error:e=>console.error(`[plugin:${l}] ${e}`)}}const D="@file:";function F(){return c.resolve(U())}export class WeavePluginLoader{deps;handlers=new Map;configs=new Map;plugins=new Map;subscribers=new Map;roots=new Map;watchStop;constructor(e){this.deps=e}list(){return[...this.plugins.values()]}getHandler(e,s){return this.handlers.get(`${e}:${s}`)}getConfig(e){return this.configs.get(e)??{}}async loadRoot(e,s,o){const n=c.resolve(e);this.roots.set(n,{scope:s,projectId:o});let i;try{i=await A(n)}catch{return[]}const t=this.priorIdsUnder(n),u=[];for(const f of i){const d=c.join(n,f);if(this.roots.has(c.resolve(d))||c.resolve(d)===F())continue;const g=await this.loadOne(d,s,o,f);this.plugins.set(g.id,g),u.push(g)}return this.finalizeScan(t,u)}async loadToolkitRoot(e,s,o){const n=c.resolve(e);this.roots.set(n,{scope:s,projectId:o,deep:!0});const i=await B(n),t=this.priorIdsUnder(n),u=[];for(const f of i){await this.ensureToolkitDefaultDisabled(f);const d=await this.loadOne(f,s,o,c.basename(f));this.plugins.set(d.id,d),u.push(d)}return this.finalizeScan(t,u)}async ensureToolkitDefaultDisabled(e){try{const s=JSON.parse(await S(c.join(e,j),"utf8"));typeof s.id=="string"&&!this.deps.states.get(s.id)&&this.deps.states.setEnabled(s.id,!1)}catch{}}priorIdsUnder(e){const s=[...this.roots.keys()].filter(o=>o!==e&&o.startsWith(e+c.sep));return new Set([...this.plugins.values()].filter(o=>o.dir.startsWith(e+c.sep)?!s.some(n=>o.dir.startsWith(n+c.sep)):!1).map(o=>o.id))}finalizeScan(e,s){const o=new Set(s.map(i=>i.id));let n=!1;for(const i of e)o.has(i)||(this.deps.rules.removeByPlugin(i),this.unloadHandlers(i),this.configs.delete(i),this.plugins.delete(i),n=!0,this.emitReload({pluginId:i,status:"rejected",ruleCount:0,removed:!0}));(n||s.length>0)&&this.deps.registry.load();for(const i of s)this.emitReload({pluginId:i.id,status:i.status,ruleCount:i.ruleCount,at:new Date().toISOString()});return s}watchRoots(e=1e3){if(this.watchStop)return this.watchStop;const s=new Map,o=[...this.roots.entries()].filter(([n])=>I(n)).map(([n,i])=>{const t=i.deep?6:i.projectId!==null?3:2,u=M(n,{ignoreInitial:!0,depth:t});return u.on("all",()=>{const f=s.get(n);f&&clearTimeout(f),s.set(n,setTimeout(()=>{s.delete(n);const d=this.roots.get(n);if(!d)return;(d.deep?this.loadToolkitRoot(n,d.scope,d.projectId):this.loadRoot(n,d.scope,d.projectId)).catch(()=>{})},e))}),u.on("error",()=>{}),u});return this.watchStop=()=>{for(const n of s.values())clearTimeout(n);s.clear();for(const n of o)n.close();this.watchStop=void 0},this.watchStop}async reloadAll(){for(const[e,s]of[...this.roots])await(s.deep?this.loadToolkitRoot(e,s.scope,s.projectId):this.loadRoot(e,s.scope,s.projectId)).catch(()=>{})}stopWatching(){this.watchStop?.()}async rescanRoots(e,s){await registerPluginRoots(this,{libraries:s},e),this.stopWatching(),await this.reloadAll(),this.watchRoots()}setPluginEnabled(e,s){const o=this.plugins.get(e);if(!o)return!1;this.deps.states.setEnabled(e,s);for(const i of this.deps.rules.listByPlugin(e))this.deps.rules.setEnabled(i.id,s);this.deps.registry.load();const n=s?o.error?"rejected":"active":"disabled";return this.plugins.set(e,{...o,status:n}),this.deps.bus?.emit({kind:"plugin.toggled",pluginId:e,enabled:s,at:new Date().toISOString()}),!0}unloadHandlers(e){for(const s of[...this.handlers.keys()])s.startsWith(`${e}:`)&&this.handlers.delete(s);this.subscribers.delete(e)}notifyEvent(e,s,o){for(const[n,i]of this.subscribers){if(!i.events.has(e))continue;const t=this.configs.get(n)??{};(async()=>{await i.sub.onEvent({eventType:e,payload:s,sessionId:o,config:t,logger:createPluginLogger(n)})})().catch(()=>{})}}emitReload(e){this.deps.bus?.emit({kind:"plugin.reloaded",at:new Date().toISOString(),...e})}async loadOne(e,s,o,n){const i=(r,a,v=n,h="0.0.0")=>{const w=this.plugins.get(r);return w&&w.dir===e&&(this.deps.rules.removeByPlugin(r),this.unloadHandlers(r),this.configs.delete(r)),{id:r,name:v,version:h,dir:e,scope:s,projectId:o,status:"rejected",error:a,ruleCount:0}};let t;try{const r=JSON.parse(await S(c.join(e,j),"utf8")),a=L.safeParse(r);if(!a.success)return i(n,`manifest \u6821\u9A8C\u5931\u8D25: ${a.error.issues[0]?.message??""}`);t=a.data}catch(r){return i(n,`manifest \u8BFB\u53D6\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`)}if(s!=="builtin"&&t.id.startsWith("weave-"))return i(t.id,"id \u4EE5 weave- \u5F00\u5934\u4E3A\u5185\u7F6E\u9884\u8BBE\u547D\u540D\u7A7A\u95F4\u4FDD\u7559",t.name,t.version);const u=this.plugins.get(t.id);if(u&&u.status!=="rejected"&&u.dir!==e)return i(t.id,`\u91CD\u590D\u7684\u63D2\u4EF6 id\uFF08\u5DF2\u7531 ${u.dir} \u6CE8\u518C\uFF09`,t.name,t.version);const d=(t.requires?.events??[]).filter(r=>!W.includes(r));if(d.length>0)return i(t.id,`requires.events \u542B\u672A\u77E5\u4E8B\u4EF6: ${d.join(", ")}`,t.name,t.version);const g=[];for(const r of t.rules)try{const a=JSON.parse(await S(this.resolveWithin(e,r),"utf8"));if(!Array.isArray(a))throw new Error(`${r} \u4E0D\u662F\u6570\u7EC4`);g.push(...a)}catch(a){return i(t.id,`\u89C4\u5219\u6587\u4EF6 ${r}: ${a instanceof Error?a.message:String(a)}`,t.name,t.version)}const E=new Map;for(const r of t.handlers)try{const a=this.resolveWithin(e,r.entry),h=(await import(`${P(a).href}?t=${Date.now()}`)).default;if(!h||typeof h.execute!="function")throw new Error(`${r.entry} \u7684 default \u5BFC\u51FA\u7F3A\u5C11 execute \u51FD\u6570`);if(h.type!==r.type)throw new Error(`${r.entry} \u5BFC\u51FA type="${h.type}" \u4E0E manifest \u58F0\u660E "${r.type}" \u4E0D\u7B26`);E.set(`${t.id}:${r.type}`,h)}catch(a){return i(t.id,`handler ${r.type} \u52A0\u8F7D\u5931\u8D25: ${a instanceof Error?a.message:String(a)}`,t.name,t.version)}let R;if(t.subscribe){const r=t.subscribe.events.filter(a=>!W.includes(a));if(r.length>0)return i(t.id,`subscribe.events \u542B\u672A\u77E5\u4E8B\u4EF6: ${r.join(", ")}`,t.name,t.version);try{const a=this.resolveWithin(e,t.subscribe.entry),h=(await import(`${P(a).href}?t=${Date.now()}`)).default;if(!h||typeof h.onEvent!="function")throw new Error(`${t.subscribe.entry} \u7684 default \u5BFC\u51FA\u7F3A\u5C11 onEvent \u51FD\u6570`);R={events:new Set(t.subscribe.events),sub:h}}catch(a){return i(t.id,`subscriber \u52A0\u8F7D\u5931\u8D25: ${a instanceof Error?a.message:String(a)}`,t.name,t.version)}}const k=[];for(let r=0;r<g.length;r++){const a=g[r],v=typeof a=="object"&&a!==null&&"handler"in a?{...a,handler:q(a.handler,t.id)}:a,h=H.safeParse(v);if(!h.success)return i(t.id,`\u89C4\u5219 #${r} \u6821\u9A8C\u5931\u8D25: ${h.error.issues[0]?.message??""}`,t.name,t.version);const w=h.data;let p=w.handler;if(p.type==="plugin"&&!E.has(`${t.id}:${p.handlerType}`))return i(t.id,`\u89C4\u5219 #${r} \u5F15\u7528\u672A\u58F0\u660E\u7684 handler "${p.handlerType}"`,t.name,t.version);if((p.type==="inject"||p.type==="manual")&&p.template.startsWith(D)){const y=p.template.slice(D.length);try{const b=await S(this.resolveWithin(e,y),"utf8");p={...p,template:b}}catch(b){return i(t.id,`\u89C4\u5219 #${r} \u6A21\u677F ${y}: ${b instanceof Error?b.message:String(b)}`,t.name,t.version)}}let $;try{$=x.parse({...w,handler:p,id:`plugin:${t.id}:${r}`,projectId:o,enabled:w.enabled??!0,priority:w.priority??0,origin:s==="builtin"?"builtin":"plugin",pluginId:t.id}),C($.source,$.handler)}catch(y){return i(t.id,`\u89C4\u5219 #${r}: ${y instanceof Error?y.message:String(y)}`,t.name,t.version)}k.push($)}const m=this.deps.states.get(t.id);try{for(const r of k)this.deps.rules.upsertPluginRule(r)}catch(r){return this.deps.rules.removeByPlugin(t.id),i(t.id,`\u89C4\u5219\u5165\u5E93\u5931\u8D25: ${r instanceof Error?r.message:String(r)}`,t.name,t.version)}if(m&&!m.enabled)for(const r of this.deps.rules.listByPlugin(t.id))this.deps.rules.setEnabled(r.id,!1);for(const[r,a]of E)this.handlers.set(r,a);return this.configs.set(t.id,{...t.config??{},...m?.config??{}}),R&&!(m&&!m.enabled)&&this.subscribers.set(t.id,R),{id:t.id,name:t.name,version:t.version,dir:e,scope:s,projectId:o,status:m&&!m.enabled?"disabled":"active",ruleCount:k.length}}resolveWithin(e,s){const o=c.resolve(e),n=c.resolve(o,s);if(n!==o&&!n.startsWith(o+c.sep))throw new Error(`\u8DEF\u5F84\u8D8A\u51FA\u63D2\u4EF6\u76EE\u5F55: ${s}`);return n}}function q(l,e){if(typeof l!="object"||l===null)return l;const s=l;return s.type!=="plugin"||s.pluginId!==void 0?l:{...s,pluginId:e}}export async function registerPluginRoots(l,e,s){const o=[],n=_();if(e.libraries)for(const t of N(e.libraries))n.push({root:t,provenance:"market"});const i=new Set;for(const t of n){const u=c.resolve(t.root);i.has(u)||(i.add(u),o.push(...await l.loadToolkitRoot(t.root,t.provenance==="builtin"?"builtin":"user",null)))}o.push(...await l.loadRoot(O(T()),"builtin",null)),o.push(...await l.loadRoot(c.join(T(),"plugins"),"user",null));for(const t of s)o.push(...await l.loadRoot(c.join(t.path,".weave","plugins"),"project",t.id));return o}export async function loadAllPlugins(l,e){const s=new WeavePluginLoader(l),o=await registerPluginRoots(s,l,e);return{loader:s,loaded:o}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function pluginsStateOf(
|
|
1
|
+
export function pluginsStateOf(s){const e={syncedAt:null,enabled:{}};if(s==null)return e;try{const t=JSON.parse(s);if(!t||typeof t!="object"||Array.isArray(t))return e;const n=t.plugins;if(!n||typeof n!="object"||Array.isArray(n))return e;const r=n,a=r.enabled,c={};if(a&&typeof a=="object"&&!Array.isArray(a))for(const[l,o]of Object.entries(a))typeof o=="boolean"&&(c[l]=o);return{syncedAt:typeof r.syncedAt=="string"?r.syncedAt:null,enabled:c}}catch{return e}}export function effective(s,e,t){const n=pluginsStateOf(s.meta);return Object.hasOwn(n.enabled,e)?n.enabled[e]:n.syncedAt!==null?!1:t.states.get(e)?.enabled??t.defaultEnabled??!0}export function setProjectEnabled(s,e,t,n){const r=pluginsStateOf(s.meta);n.projects.setMeta(s.id,{plugins:{syncedAt:r.syncedAt,enabled:{...r.enabled,[e]:t}}})}export function syncPlugins(s,e,t){const r={...pluginsStateOf(s.meta).enabled};for(const c of e)Object.hasOwn(r,c)||(r[c]=!1);const a=t.now??new Date().toISOString();return t.projects.setMeta(s.id,{plugins:{syncedAt:a,enabled:r}}),a}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PROMPT_FLUSH_INTERVAL_MS=15e3;export function startPromptFlusher(
|
|
1
|
+
export const PROMPT_FLUSH_INTERVAL_MS=15e3;export function startPromptFlusher(r){const t=setInterval(()=>{r.flushAll()},15e3);return t.unref?.(),()=>clearInterval(t)}
|
|
@@ -5,6 +5,13 @@
|
|
|
5
5
|
* shard 与 outbox 同算法(项目 token 哈希前缀);送达即删行,无 DB。
|
|
6
6
|
*/
|
|
7
7
|
export declare const PROMPTBOX_MAX_LINES = 200;
|
|
8
|
+
/** 队列行的随附图(引用上传件;路径也落盘,重启后冲洗才能重合成投递文本)。 */
|
|
9
|
+
export interface PromptboxImage {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
mediaType: string;
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
8
15
|
/** 队列行:id = 管道发号(MessageDeliverer 的 uuid),daemon 重启后仍可追溯。 */
|
|
9
16
|
export interface PromptboxEntry {
|
|
10
17
|
id: string;
|
|
@@ -12,6 +19,10 @@ export interface PromptboxEntry {
|
|
|
12
19
|
text: string;
|
|
13
20
|
/** 单向注入(手动面)——随行落盘,重启后冲洗仍带「无需回复」注记。 */
|
|
14
21
|
oneWay?: boolean;
|
|
22
|
+
/** 发送人强制走层② 终端(下拉选的通道)——随行落盘,冲洗时同样不回落直投/中继。 */
|
|
23
|
+
forceTerminal?: boolean;
|
|
24
|
+
/** 随附图:`text` 恒为用户原文,投递文本由 harness `imageAttach` 现合成。 */
|
|
25
|
+
images?: PromptboxImage[];
|
|
15
26
|
at: string;
|
|
16
27
|
}
|
|
17
28
|
export declare function promptboxPathOf(hooksDir: string, shardId: string): string;
|
|
@@ -21,6 +32,8 @@ export declare function appendPromptbox(hooksDir: string, token: string, entries
|
|
|
21
32
|
sessionId: string;
|
|
22
33
|
text: string;
|
|
23
34
|
oneWay?: boolean;
|
|
35
|
+
forceTerminal?: boolean;
|
|
36
|
+
images?: PromptboxImage[];
|
|
24
37
|
}>): void;
|
|
25
38
|
/** 读一个项目的全部待递送行。 */
|
|
26
39
|
export declare function readPromptbox(hooksDir: string, token: string): PromptboxEntry[];
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import{mkdirSync as
|
|
2
|
-
`))if(
|
|
3
|
-
`).filter(
|
|
1
|
+
import{mkdirSync as g,readFileSync as u,readdirSync as h,renameSync as l,writeFileSync as m}from"node:fs";import{join as a}from"node:path";import{hookShardId as y}from"./mirror.js";export const PROMPTBOX_MAX_LINES=200;export function promptboxPathOf(n,e){return a(n,"promptbox",`${e}.jsonl`)}function d(n){const e=[];for(const o of n.split(`
|
|
2
|
+
`))if(o.trim())try{const t=JSON.parse(o);if(typeof t.id=="string"&&typeof t.sessionId=="string"&&typeof t.text=="string"){const r=Array.isArray(t.images)?t.images.filter(i=>typeof i?.id=="string"&&typeof i?.name=="string"&&typeof i?.mediaType=="string"&&typeof i?.path=="string"):[];e.push({id:t.id,sessionId:t.sessionId,text:t.text,oneWay:t.oneWay===!0,...t.forceTerminal===!0?{forceTerminal:!0}:{},...r.length>0?{images:r}:{},at:typeof t.at=="string"?t.at:""})}}catch{}return e}export function appendPromptbox(n,e,o){if(o.length!==0)try{const t=promptboxPathOf(n,y(e));g(a(n,"promptbox"),{recursive:!0});let r=[];try{r=u(t,"utf8").split(`
|
|
3
|
+
`).filter(p=>p.trim())}catch{r=[]}const i=new Date().toISOString();for(const p of o)r.push(JSON.stringify({...p,at:i}));const c=r.slice(-PROMPTBOX_MAX_LINES),s=`${t}.tmp`;m(s,c.length?c.join(`
|
|
4
4
|
`)+`
|
|
5
|
-
`:""),l(s,t)}catch{}}export function readPromptbox(
|
|
6
|
-
`).filter(s=>s.trim())}catch{return}const
|
|
5
|
+
`:""),l(s,t)}catch{}}export function readPromptbox(n,e){try{return d(u(promptboxPathOf(n,y(e)),"utf8"))}catch{return[]}}export function removePromptboxEntries(n,e,o){if(o.size!==0)try{const t=promptboxPathOf(n,y(e));let r;try{r=u(t,"utf8").split(`
|
|
6
|
+
`).filter(s=>s.trim())}catch{return}const i=r.filter(s=>{try{return!o.has(JSON.parse(s).id??"")}catch{return!1}}),c=`${t}.tmp`;m(c,i.length?i.join(`
|
|
7
7
|
`)+`
|
|
8
|
-
`:""),l(
|
|
9
|
-
`).filter(
|
|
8
|
+
`:""),l(c,t)}catch{}}export function readAllPromptbox(n){const e=a(n,"promptbox");let o;try{o=h(e)}catch{return[]}const t=[];for(const r of o)if(r.endsWith(".jsonl"))try{t.push(...d(u(a(e,r),"utf8")))}catch{continue}return t}export function scanQueuedSessionIds(n){return new Set(readAllPromptbox(n).map(e=>e.sessionId))}export function removePromptboxBySession(n,e){const o=a(n,"promptbox");let t;try{t=h(o)}catch{return 0}let r=0;for(const i of t){if(!i.endsWith(".jsonl"))continue;const c=a(o,i);let s;try{s=u(c,"utf8").split(`
|
|
9
|
+
`).filter(f=>f.trim())}catch{continue}const p=s.filter(f=>{try{return JSON.parse(f).sessionId!==e}catch{return!1}});if(p.length!==s.length){r+=s.length-p.length;try{const f=`${c}.tmp`;m(f,p.length?p.join(`
|
|
10
10
|
`)+`
|
|
11
|
-
`:""),l(
|
|
11
|
+
`:""),l(f,c)}catch{}}}return r}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{chmodSync as
|
|
2
|
-
`,{encoding:"utf8",mode:384}),d(
|
|
1
|
+
import{chmodSync as a,existsSync as u,mkdirSync as p,readFileSync as c,renameSync as d,writeFileSync as l}from"node:fs";import y from"node:path";import n from"web-push";import{getPushKeysPath as h}from"../db/paths.js";import{watchReasonPhrase as f}from"./watch-engine.js";export class PushNotifier{deps;vapid;constructor(t){this.deps=t,this.vapid=w(t.keysPath??h()),t.bus.subscribe(e=>this.onBus(e))}publicKey(){return this.vapid.publicKey}onBus(t){const e=this.payloadFor(t);if(!e)return;const i=this.deps.subscriptions.list();i.length!==0&&this.pushAll(i,JSON.stringify(e))}payloadFor(t){return t.kind==="watch.fired"?t.watcherSessionId!==null?null:{title:"weave",body:`Session ${this.labelOf(t.targetSessionId)} ${f(t.reason)}`,tag:`weave-watch-${t.targetSessionId}`,url:"/"}:t.kind==="question.pending"?{title:"weave",body:`Session ${this.labelOf(t.sessionId)} is waiting for your answer`,tag:`weave-question-${t.sessionId}`,url:"/"}:null}labelOf(t){return this.deps.sessions.getBySessionId(t)?.title??t.slice(0,8)}async pushAll(t,e){for(const i of t)try{await(this.deps.send??b)(i,e,this.vapid)}catch(o){const r=o.statusCode;(r===404||r===410)&&this.deps.subscriptions.deleteByEndpoint(i.endpoint)}}}async function b(s,t,e){n.setVapidDetails("mailto:weave@localhost",e.publicKey,e.privateKey),await n.sendNotification({endpoint:s.endpoint,keys:{p256dh:s.p256dh,auth:s.auth}},t,{TTL:3600})}function w(s){if(u(s))try{const i=JSON.parse(c(s,"utf8"));if(typeof i.publicKey=="string"&&i.publicKey&&typeof i.privateKey=="string"&&i.privateKey)return{publicKey:i.publicKey,privateKey:i.privateKey}}catch{}const t=n.generateVAPIDKeys();p(y.dirname(s),{recursive:!0});const e=`${s}.tmp`;l(e,`${JSON.stringify(t,null,2)}
|
|
2
|
+
`,{encoding:"utf8",mode:384}),d(e,s);try{a(s,384)}catch{}return t}
|
|
@@ -9,9 +9,11 @@ import type { NormalizedHookPayload } from './types.js';
|
|
|
9
9
|
* 作答。为什么不走 hookBus 帧:帧域不带 toolName(frameFacts 只提 agent 事实),
|
|
10
10
|
* 挂点必须在 handleIngestedRecords(解析后的 payload 在手)。
|
|
11
11
|
*
|
|
12
|
-
* 置位:PreToolUse(阻塞工具) / Notification(permission_prompt)
|
|
12
|
+
* 置位:PreToolUse(阻塞工具) / Notification(permission_prompt) / 事件弹框
|
|
13
|
+
* (`spec.eventQuestion` 认出来的,如 claude 的「Switch model?」);
|
|
13
14
|
* 清除:PostToolUse(同名阻塞工具) 与 UserPromptSubmit/Stop(question 态),
|
|
14
|
-
* permission 态由任意后续非 Notification
|
|
15
|
+
* permission 与 switch 态由任意后续非 Notification 事件清(对话框了结必有下文;
|
|
16
|
+
* switch 的落定笔是 PostModelSwitch——答「No, go back」不发任何事件,留待下文清)。
|
|
15
17
|
* daemon 重启由 seedFromDb 按最近事件窗口重放重建。
|
|
16
18
|
*
|
|
17
19
|
* 例外:卡在阻塞工具里时,该工具自己补发的 permission_prompt 不改写问题面——
|
|
@@ -30,8 +32,8 @@ import type { NormalizedHookPayload } from './types.js';
|
|
|
30
32
|
export interface PendingQuestionEntry {
|
|
31
33
|
sessionId: string;
|
|
32
34
|
harness: Harness;
|
|
33
|
-
/** question = 阻塞工具(问答/计划确认);permission =
|
|
34
|
-
kind: 'question' | 'permission';
|
|
35
|
+
/** question = 阻塞工具(问答/计划确认);permission = 权限确认;switch = 模型切换确认。 */
|
|
36
|
+
kind: 'question' | 'permission' | 'switch';
|
|
35
37
|
questions: BlockingQuestion[];
|
|
36
38
|
at: string;
|
|
37
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isHarness as
|
|
1
|
+
import{isHarness as c}from"@weavecode/core";import{blockingPromptFor as f}from"../surfaces.js";const h=12;export class QuestionTracker{deps;pending=new Map;lastPreTool=new Map;permissionMode=new Map;seeding=!1;constructor(e){this.deps=e}specOf(e){return c(e)?this.deps.surfaceFor?.(e)??f(e):null}onEvent(e){const s=e.payload;if(!s)return;const n=this.specOf(e.source);if(!n)return;const t=e.sessionId,r=typeof s.toolName=="string"?s.toolName:null,p=g(s.raw);if(p&&this.permissionMode.set(t,p),s.eventType==="PreToolUse"){if(r&&this.lastPreTool.set(t,{toolName:r,toolInput:s.toolInput}),r&&n.blockingTools.includes(r)){const l=this.pending.get(t),i={sessionId:t,harness:this.harnessOf(e.source),kind:"question",questions:n.parseQuestions(r,s.toolInput),at:new Date().toISOString()};this.pending.set(t,i),!this.seeding&&l?.kind!=="question"&&this.deps.onPending?.(i)}return}if(s.eventType==="Notification"){if(n.permissionNotificationType&&y(s.raw)===n.permissionNotificationType){const l=this.permissionMode.get(t);if(l!=null&&n.silentPermissionModes.includes(l))return;const i=this.lastPreTool.get(t);if(this.pending.get(t)?.kind==="question"&&i!=null&&n.blockingTools.includes(i.toolName))return;const a=this.lastPreTool.get(t)??{toolName:null,toolInput:null};this.pending.set(t,{sessionId:t,harness:this.harnessOf(e.source),kind:"permission",questions:[n.permissionQuestion({...a,message:m(s.raw),permissionMode:l??null})],at:new Date().toISOString()})}return}const d=n.eventQuestion(s.eventType,s.raw);if(d){const l=this.pending.get(t),i={sessionId:t,harness:this.harnessOf(e.source),kind:"switch",questions:[d],at:new Date().toISOString()};this.pending.set(t,i),!this.seeding&&l?.kind!=="switch"&&this.deps.onPending?.(i);return}const u=this.pending.get(t);if(!u)return;if(u.kind!=="question"){this.pending.delete(t),this.lastPreTool.delete(t);return}(s.eventType==="PostToolUse"&&r!=null&&n.blockingTools.includes(r)||s.eventType==="UserPromptSubmit"||s.eventType==="Stop")&&(this.pending.delete(t),this.lastPreTool.delete(t))}seedFromDb(){this.seeding=!0;try{for(const e of this.deps.sessions.list())for(const s of this.deps.hookEvents.listBySession(e.sessionId,h)){let n=null;try{n=JSON.parse(s.payload)}catch{n=null}this.onEvent({sessionId:e.sessionId,source:s.source,payload:n})}}finally{this.seeding=!1}}snapshot(){return[...this.pending.values()].sort((e,s)=>e.at<s.at?1:-1)}get(e){return this.pending.get(e)??null}markAnswered(e){this.pending.delete(e)}forgetSession(e){this.pending.delete(e),this.lastPreTool.delete(e),this.permissionMode.delete(e)}harnessOf(e){return e}}function g(o){if(!o||typeof o!="object")return null;const e=o.permission_mode;return typeof e=="string"&&e?e:null}function m(o){if(!o||typeof o!="object")return null;const e=o.message;return typeof e=="string"&&e.trim()?e:null}function y(o){if(!o||typeof o!="object")return null;const e=o.notification_type;return typeof e=="string"&&e?e:null}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{INJECTABLE_EVENTS as
|
|
1
|
+
import{INJECTABLE_EVENTS as l,hookSourceHarness as u,normalizeHookRuleSource as s}from"@weavecode/core";export class HookRuleRegistry{repo;byEvent=new Map;all=[];onChange;constructor(e){this.repo=e,this.load()}load(){this.all=this.repo.list().map(e=>({...e,source:s(e.source)})),this.byEvent=new Map;for(const e of this.all){if(e.source.kind!=="hook-event")continue;const t=this.byEvent.get(e.source.event);t?t.push(e):this.byEvent.set(e.source.event,[e])}this.onChange?.()}list(e){return(e===void 0?this.all:this.repo.list(e)).map(n=>({...n,source:s(n.source)}))}get(e){return this.all.find(t=>t.id===e)}candidates(e,t){const n=this.byEvent.get(e)??[];return t?.includeDisabled?[...n]:n.filter(o=>o.enabled)}create(e){const t=s(e.source);validateHandler(t,e.handler);const n=this.repo.create({...e,source:t});return this.load(),n}update(e,t){const n=this.get(e);if(!n)return;const o=t.source?s(t.source):n.source;validateHandler(o,t.handler??n.handler);const i=this.repo.update(e,t.source?{...t,source:o}:t);return i&&this.load(),i}setEnabled(e,t){const n=this.repo.setEnabled(e,t);return n&&this.load(),n}remove(e){const t=this.repo.remove(e);return t&&this.load(),t}}export function validateHandler(r,e){const t=u(r);if(e.type==="inject"){if(t===null||t==="any")throw new Error('inject handler requires source.kind = "hook-event" with a concrete harness (legacy "claude-event" accepted; "any" rejected)');const n=l[t],o=r.kind==="claude-event"||r.kind==="hook-event"?r.event:"";if(!n.includes(o))throw new Error(`inject handler is not supported on event "${o}" (allowed: ${n.join(", ")})`);return}if(e.type==="plugin"&&t===null)throw new Error('plugin handler requires source.kind = "hook-event"')}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CLAUDE_RESUME as
|
|
1
|
+
import{CLAUDE_RESUME as o}from"@weavecode/harness";import{HeadlessRunner as l}from"./headless-runner.js";export class ResumeRunner{deps;headless;claudeBin;resumeSpec;timeoutMs;constructor(t){this.deps=t,this.headless=t.headless??new l({spawnImpl:t.spawnImpl,killImpl:t.killImpl}),this.resumeSpec=t.resumeSpec??o,this.claudeBin=t.claudeBin??process.env.WEAVE_CLAUDE_BIN??this.resumeSpec.bin,this.timeoutMs=t.timeoutMs}async run(t,e){const s=this.deps.dispatches.getById(t);if(!s)return{ok:!1,status:404,error:"Dispatch not found"};if(s.status!=="pending"&&s.status!=="injected")return{ok:!1,status:409,error:`Dispatch is ${s.status}`};const r=this.deps.sessions.getBySessionId(e);if(!r)return{ok:!1,status:404,error:"Session not found"};if(r.projectId==null)return{ok:!1,status:400,error:"Session has no project"};const a=this.deps.projects.getById(r.projectId);if(!a)return{ok:!1,status:400,error:"Project not found for session"};if(this.headless.isBusy(e))return{ok:!1,status:409,error:"Session already has a running dispatch"};const u={settled:!1};try{this.deps.dispatches.updateStatus(t,{status:"running"}),this.deps.bus?.emit({kind:"dispatch.started",ruleId:s.ruleId,dispatchId:t,sessionId:e,at:new Date().toISOString()}),this.headless.run({sessionId:e,cwd:a.path,prompt:s.prompt,spec:this.resumeSpec,bin:this.claudeBin,timeoutMs:this.timeoutMs,onSettle:n=>this.settle(s,e,u,n)})||this.settle(s,e,u,{status:"failed",output:null,error:"Session already has a running dispatch"})}catch(i){this.settle(s,e,u,{status:"failed",output:null,error:i instanceof Error?i.message:String(i)})}return{ok:!0,dispatchId:t}}settle(t,e,s,r){if(!s.settled){s.settled=!0;try{this.deps.dispatches.updateStatus(t.id,{status:r.status,output:r.output,error:r.error,finished:!0}),this.deps.bus?.emit({kind:"dispatch.finished",ruleId:t.ruleId,dispatchId:t.id,status:r.status,sessionId:e,at:new Date().toISOString()})}catch{}}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{messagingSurfaceFor as
|
|
1
|
+
import{messagingSurfaceFor as d}from"../surfaces.js";import{claudeLivenessById as u,pidAliveOf as a}from"../daemon/claude-liveness.js";export const SEQUENCE_HOP_LIMIT=3;export class SequenceEngine{deps;constructor(s){this.deps=s,this.deps.bus.subscribe(t=>this.onBus(t))}async trigger(s){await this.fire(s.id,s.cursor)}cancel(s){return this.finish(s,"cancelled")}rearm(){try{for(const s of this.deps.sequences.listRunning()){const t=s.steps[s.cursor];if(!t){this.finish(s.id,"done");continue}if(t.messageId==null){this.finish(s.id,"failed",`step ${s.cursor+1} interrupted \u2014 daemon restarted, not re-sent`);continue}const e=this.deps.deliverer.getMessage(t.messageId);if(!(e?.status==="injected"||e?.status==="delivered")){if(e?.status==="running"){this.finish(s.id,"failed","daemon restarted during headless step");continue}e?.status==="succeeded"?this.advance(s):this.finish(s.id,"failed",`step ${s.cursor+1} ${e?.status??"message missing"}`)}}}catch{}}onEvent(s){try{if(!(this.deps.surfaceFor?.(s.source)??d(s.source)).idleSignals.includes(s.eventType))return;for(const e of this.deps.sequences.listRunning()){const i=e.steps[e.cursor];if(!i||i.to!==s.sessionId||i.messageId==null)continue;const n=this.deps.deliverer.getMessage(i.messageId);(n?.status==="injected"||n?.status==="delivered")&&this.advance(e)}}catch{}}onBus(s){if(s.kind==="message.finished")try{for(const t of this.deps.sequences.listRunning())t.steps[t.cursor]?.messageId===s.messageId&&(s.status==="succeeded"?this.advance(t):this.finish(t.id,"failed",`step ${t.cursor+1} ${s.status}`))}catch{}}advance(s){if(s.cursor+1>=s.steps.length){this.finish(s.id,"done");return}this.deps.sequences.advanceCursor(s.id,s.cursor,s.cursor+1)&&this.fire(s.id,s.cursor+1)}async fire(s,t){try{const e=this.deps.sequences.getById(s);if(!e||e.status!=="running"||e.cursor!==t)return;const i=e.steps[t];if(!i)return;this.deps.bus.emit({kind:"sequence.step",sequenceId:s,cursor:t,at:new Date().toISOString()});const n=await this.deps.deliverer.send({toSessionId:i.to,text:i.text,mode:i.mode,fromKind:"dashboard"});if(!n.ok){this.finish(s,"failed",`step ${t+1} rejected: ${n.error}`);return}if(this.deps.sequences.setStepMessage(s,t,n.messageId),n.status==="running"){const r=this.deps.deliverer.getMessage(n.messageId);if(r?.status==="succeeded"||r?.status==="failed"||r?.status==="timeout")if(r.status==="succeeded"){const c=this.deps.sequences.getById(s);c&&this.advance(c)}else this.finish(s,"failed",`step ${t+1} ${r.status}`)}}catch(e){this.finish(s,"failed",e instanceof Error?e.message:String(e))}}finish(s,t,e=null){return this.deps.sequences.finish(s,t,e)?(this.deps.bus.emit({kind:"sequence.finished",sequenceId:s,status:t,error:e,at:new Date().toISOString()}),!0):!1}sweepTerminated(){try{const s=this.deps.livenessOf?.()??u(),t=new Map(this.deps.sessions.listWithCounts().map(i=>[i.sessionId,i]));let e=0;for(const i of this.deps.sequences.listRunning()){const n=i.steps[i.cursor];if(!n)continue;const r=t.get(n.to);r&&a(r,s)!==!1||this.finish(i.id,"failed",`target session ${n.to} terminated`)&&e++}return e}catch{return 0}}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function purgeSession(e,
|
|
1
|
+
export function purgeSession(e,t){const n=e.events.deleteBySession(t);e.uploads?.pruneUnreferenced();const r=e.dispatches?.deleteBySession(t)??0,o=e.deliverer?.forgetSession(t)??0;return e.watches?.deleteBySession(t),e.sequences?.deleteMentioning(new Set([t])),e.questions?.forgetSession(t),e.probe?.forget(t),e.sessions.remove(t),{events:n,dispatches:r,messages:o}}
|
|
@@ -3,15 +3,12 @@ import type { WatchEngine } from './watch-engine.js';
|
|
|
3
3
|
import type { SequenceEngine } from './sequence-engine.js';
|
|
4
4
|
export declare const SWEEP_INTERVAL_MS: number;
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* `listWithCounts`(`autoDeleteAt` 计算列)——本清扫器只做「过期即清」;
|
|
10
|
-
* 收到过 prompt 的会话 autoDeleteAt 为 null,永不自动删(遵循全局事件保留期)。
|
|
6
|
+
* 定时清过期会话:判据与期限的单一事实源 = sessions 仓储的 `listWithCounts`
|
|
7
|
+
* (`autoDeleteAt` 计算列,两档——没等到用户 prompt 的新会话 1 小时快过期、
|
|
8
|
+
* 收到过 prompt 的走 settings `sessions.idleDays` 闲置窗),本清扫器只做「过期即清」。
|
|
11
9
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* 遗留存量行。
|
|
10
|
+
* 注:入库路径对**每个**首现 sessionId 都建档(含仅一条 SessionStart 的新会话
|
|
11
|
+
* ——新建会话要马上出现在列表),期限倒计时随行展示,看得见它还剩多久。
|
|
15
12
|
*/
|
|
16
13
|
export declare class SessionSweeper {
|
|
17
14
|
private readonly deps;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{purgeSession as r}from"./session-purge.js";export const SWEEP_INTERVAL_MS=5*6e4;export class SessionSweeper{deps;now;constructor(e,s=Date.now){this.deps=e,this.now=s}sweep(){const e=this.now();let s=0;for(const t of this.deps.sessions.listWithCounts()){const o=t.autoDeleteAt==null?null:Date.parse(t.autoDeleteAt);o==null||e<o||(r(this.deps,t.sessionId),s++)}return this.deps.watchEngine?.sweepTerminated(),this.deps.sequenceEngine?.sweepTerminated(),s}start(){this.sweep();const e=setInterval(()=>this.sweep(),SWEEP_INTERVAL_MS);return e.unref(),e}}export function startSessionSweeper(n){return new SessionSweeper(n).start()}
|
|
1
|
+
import{purgeSession as r}from"./session-purge.js";export const SWEEP_INTERVAL_MS=5*6e4;export class SessionSweeper{deps;now;constructor(e,s=Date.now){this.deps=e,this.now=s}sweep(){const e=this.now();let s=0;for(const t of this.deps.sessions.listWithCounts()){const o=t.autoDeleteAt==null?null:Date.parse(t.autoDeleteAt);o==null||e<o||(r(this.deps,t.sessionId),s++)}return this.deps.uploads?.pruneUnreferenced(),this.deps.watchEngine?.sweepTerminated(),this.deps.sequenceEngine?.sweepTerminated(),s}start(){this.sweep();const e=setInterval(()=>this.sweep(),SWEEP_INTERVAL_MS);return e.unref(),e}}export function startSessionSweeper(n){return new SessionSweeper(n).start()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFile as
|
|
1
|
+
import{readFile as L,readdir as h,stat as w}from"node:fs/promises";import e from"node:path";import{WEAVE_PLUGIN_MANIFEST as y,WeavePluginManifestSchema as R,HARNESS_KEYS as I}from"@weavecode/core";import{builtinPacksDir as W}from"../market/builtin.js";import{getDataDir as J}from"../db/paths.js";import{hasNonEmptyModules as E}from"../watch/plugin-mods.js";const S=".claude-plugin",v="plugin.json",K="weave.json",D=2,O=10,_=["claude"];export function builtinToolkitRoot(){return e.resolve(W(J()))}async function d(t){try{return(await w(t)).isDirectory()}catch{return!1}}async function p(t){try{const n=JSON.parse(await L(t,"utf8"));return n&&typeof n=="object"&&!Array.isArray(n)?n:null}catch{return null}}export async function isToolkitPackDir(t){return await N(t)?!0:await d(e.join(t,"skills"))||await d(e.join(t,"commands"))||await d(e.join(t,"agents"))}async function N(t){if(await p(e.join(t,S,v)))return!0;try{return await w(e.join(t,y)),!0}catch{}return E(await p(e.join(t,"hooks","hooks.json")))}async function V(t){try{return(await h(t,{withFileTypes:!0})).filter(o=>o.isDirectory()).map(o=>o.name).sort()}catch{return[]}}async function P(t){try{return(await h(t,{withFileTypes:!0})).filter(o=>o.isFile()&&o.name.endsWith(".md")).map(o=>o.name.replace(/\.md$/,"")).sort()}catch{return[]}}function G(t){if(!Array.isArray(t)||t.length===0)return _;const n=t.filter(o=>I.includes(o));return n.length>0?n:_}export async function parseToolkitPack(t,n,o){const i=e.basename(t),a=await p(e.join(t,S,v)),s=await p(e.join(t,y)),r=await p(e.join(t,K)),m=await V(e.join(t,"skills")),g=await P(e.join(t,"commands")),c=await P(e.join(t,"agents")),f=await p(e.join(t,"hooks","hooks.json")),j=E(f),T=!!f&&typeof f.hooks=="object"&&f.hooks!==null,u=[];if(m.length>0&&u.push("skill"),g.length>0&&u.push("command"),c.length>0&&u.push("agent"),j?u.push("mod"):T&&u.push("hook"),s&&u.push("rule"),u.length===0)return null;const k=typeof r?.kind=="string"?r.kind:null,F=k&&["skill","hook","mod","rule","surface"].includes(k)?k:j?"mod":T?"hook":s&&!a?"rule":m.length>0?"skill":"surface",l=s?R.safeParse(s):null,C=l?.success?l.data.id:i,b=(typeof a?.name=="string"?a.name:void 0)??(l?.success?l.data.name:void 0)??i,x=(l?.success?l.data.version:void 0)??(typeof a?.version=="string"?a.version:void 0)??"0.0.0",A=(typeof a?.description=="string"?a.description:void 0)??(l?.success?l.data.description:void 0);return{id:C,name:b,version:x,...A?{description:A}:{},scope:o,dir:t,provenance:n.provenance,sourceRoot:n.root,targets:G(r?.targets),kind:F,components:u,ccPack:!!a,weavePack:!!s,skills:m}}function M(t){return t==="node_modules"||t.startsWith(".")}export async function discoverToolkitPacks(t){const n=t.provenance==="market",o=n?O:D,i=async(a,s,r)=>{if(await isToolkitPackDir(a)&&!(s===0&&n&&!await N(a))){const f=await parseToolkitPack(a,t,r);return f?[f]:[]}if(s>=o)return[];let m;try{m=await h(a,{withFileTypes:!0})}catch{return[]}return(await Promise.all(m.filter(c=>c.isDirectory()&&!M(c.name)).map(c=>i(e.join(a,c.name),s+1,s===0?c.name:r)))).flat()};return i(t.root,0,"")}export function discoverToolkitSources(){return[{root:builtinToolkitRoot(),provenance:"builtin"}]}export async function discoverWeavePackDirs(t){const n=[],o=async(i,a)=>{try{await w(e.join(i,y)),n.push(i);return}catch{}if(a>=D)return;let s;try{s=await h(i,{withFileTypes:!0})}catch{return}for(const r of s)!r.isDirectory()||M(r.name)||await o(e.join(i,r.name),a+1)};return await o(t,0),n}
|
|
@@ -105,9 +105,17 @@ export interface ToolkitServiceDeps {
|
|
|
105
105
|
}
|
|
106
106
|
export declare class ToolkitService {
|
|
107
107
|
private readonly deps;
|
|
108
|
+
private packsCache;
|
|
108
109
|
constructor(deps: ToolkitServiceDeps);
|
|
109
110
|
/** 扫描源:内置根(测试可覆盖)+ managed 市场资源根。 */
|
|
110
111
|
private sources;
|
|
112
|
+
/**
|
|
113
|
+
* 各扫描源并行发现(市场源要下钻 10 层,一个一个来就是把最慢的那个乘上根数)。
|
|
114
|
+
*
|
|
115
|
+
* 盘上清单只在装/卸/导入市场时才变,而 `list` 是面板每次打开都要打的一发
|
|
116
|
+
* (实测 ~200ms)——10s 内复用上一次的扫描结果,在飞请求共用同一个 Promise
|
|
117
|
+
* (单飞)。缓存键带扫描根集合:导入/移除市场换了根即重扫,不等 TTL。
|
|
118
|
+
*/
|
|
111
119
|
private allPacks;
|
|
112
120
|
/**
|
|
113
121
|
* 包清单 + 启用态(读侧以落盘/级联校验),顺带把 meta 索引自愈到事实、
|