openclaw-hybrid-memory 2026.5.310 → 2026.6.10
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/api/plugin-runtime.ts +2 -0
- package/backends/facts-db/contradictions.ts +1 -1
- package/cli/cmd-extract-directives.ts +225 -11
- package/cli/cmd-extract-proposals.ts +5 -6
- package/cli/cmd-extract-reinforcement.ts +71 -0
- package/cli/cmd-feedback.ts +15 -9
- package/cli/commands/manage/register-reflection-pipeline.ts +247 -13
- package/cli/commands/manage/register-storage-maintenance.ts +224 -15
- package/cli/commands/manage/storage-stats-helpers.ts +13 -2
- package/cli/context.ts +9 -19
- package/cli/distill.ts +31 -1
- package/cli/register.ts +28 -38
- package/dist/api/plugin-runtime.js.map +1 -1
- package/dist/backends/agent-health-store.js.map +1 -1
- package/dist/backends/apitap-store.js.map +1 -1
- package/dist/backends/audit-store.js.map +1 -1
- package/dist/backends/base-sqlite-store.js.map +1 -1
- package/dist/backends/cost-tracker.js.map +1 -1
- package/dist/backends/credentials-db.js +2 -3
- package/dist/backends/credentials-db.js.map +1 -1
- package/dist/backends/crystallization-store.js.map +1 -1
- package/dist/backends/edict-store.js.map +1 -1
- package/dist/backends/event-bus.js.map +1 -1
- package/dist/backends/event-log.js.map +1 -1
- package/dist/backends/facts-db/cache-manager.js.map +1 -1
- package/dist/backends/facts-db/clusters.js.map +1 -1
- package/dist/backends/facts-db/contradictions.js +1 -1
- package/dist/backends/facts-db/contradictions.js.map +1 -1
- package/dist/backends/facts-db/crud.js.map +1 -1
- package/dist/backends/facts-db/db-connection.js.map +1 -1
- package/dist/backends/facts-db/entity-autolink.js.map +1 -1
- package/dist/backends/facts-db/entity-layer.js.map +1 -1
- package/dist/backends/facts-db/episodes.js.map +1 -1
- package/dist/backends/facts-db/fact-queries.js.map +1 -1
- package/dist/backends/facts-db/fact-read-queries.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer1.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer2.js.map +1 -1
- package/dist/backends/facts-db/facts-db-layer3.js.map +1 -1
- package/dist/backends/facts-db/fts-text.js.map +1 -1
- package/dist/backends/facts-db/generated-skills/policy.js.map +1 -1
- package/dist/backends/facts-db/generated-skills.js.map +1 -1
- package/dist/backends/facts-db/housekeeping.js.map +1 -1
- package/dist/backends/facts-db/links.js.map +1 -1
- package/dist/backends/facts-db/maintenance.js.map +1 -1
- package/dist/backends/facts-db/procedures/crud.js.map +1 -1
- package/dist/backends/facts-db/procedures/internal.js.map +1 -1
- package/dist/backends/facts-db/procedures/promotion.js.map +1 -1
- package/dist/backends/facts-db/procedures/search.js.map +1 -1
- package/dist/backends/facts-db/procedures/stats.js.map +1 -1
- package/dist/backends/facts-db/reinforcement.js.map +1 -1
- package/dist/backends/facts-db/row-mapper.js.map +1 -1
- package/dist/backends/facts-db/scan-cursors.js.map +1 -1
- package/dist/backends/facts-db/schema-bootstrap.js.map +1 -1
- package/dist/backends/facts-db/scope-sql.js.map +1 -1
- package/dist/backends/facts-db/search.js.map +1 -1
- package/dist/backends/facts-db/stats.js.map +1 -1
- package/dist/backends/facts-db/types.js.map +1 -1
- package/dist/backends/facts-db/variants.js.map +1 -1
- package/dist/backends/identity-reflection-store.js.map +1 -1
- package/dist/backends/issue-store.js.map +1 -1
- package/dist/backends/learnings-db.js.map +1 -1
- package/dist/backends/migrations/facts-migrations.js.map +1 -1
- package/dist/backends/migrations/procedures.js.map +1 -1
- package/dist/backends/narratives-db.js.map +1 -1
- package/dist/backends/persona-state-store.js.map +1 -1
- package/dist/backends/proposals-db.js.map +1 -1
- package/dist/backends/scope-filter-sql.js.map +1 -1
- package/dist/backends/sqlite-schema-meta.js.map +1 -1
- package/dist/backends/tool-proposal-store.js.map +1 -1
- package/dist/backends/vector-db/constants.js.map +1 -1
- package/dist/backends/vector-db/path-utils.js.map +1 -1
- package/dist/backends/vector-db/runtime-locks.js.map +1 -1
- package/dist/backends/vector-db/vector-db-class.js.map +1 -1
- package/dist/backends/wal.js.map +1 -1
- package/dist/backends/workflow-store.js.map +1 -1
- package/dist/benchmark/shadow-eval.js.map +1 -1
- package/dist/cli/active-tasks.js.map +1 -1
- package/dist/cli/backup.js.map +1 -1
- package/dist/cli/benchmark.js.map +1 -1
- package/dist/cli/cmd-backfill.js.map +1 -1
- package/dist/cli/cmd-config.js.map +1 -1
- package/dist/cli/cmd-credentials.js.map +1 -1
- package/dist/cli/cmd-demo.js.map +1 -1
- package/dist/cli/cmd-distill.js.map +1 -1
- package/dist/cli/cmd-doctor.js.map +1 -1
- package/dist/cli/cmd-examples.js.map +1 -1
- package/dist/cli/cmd-extract-daily.js.map +1 -1
- package/dist/cli/cmd-extract-directives.js +141 -10
- package/dist/cli/cmd-extract-directives.js.map +1 -1
- package/dist/cli/cmd-extract-procedures.js.map +1 -1
- package/dist/cli/cmd-extract-proposals.js +3 -2
- package/dist/cli/cmd-extract-proposals.js.map +1 -1
- package/dist/cli/cmd-extract-reinforcement.js +39 -0
- package/dist/cli/cmd-extract-reinforcement.js.map +1 -1
- package/dist/cli/cmd-extract-sessions.js.map +1 -1
- package/dist/cli/cmd-feedback.js +9 -4
- package/dist/cli/cmd-feedback.js.map +1 -1
- package/dist/cli/cmd-health.js.map +1 -1
- package/dist/cli/cmd-providers.js.map +1 -1
- package/dist/cli/cmd-selfcorrection.js.map +1 -1
- package/dist/cli/cmd-setup.js.map +1 -1
- package/dist/cli/cmd-status.js.map +1 -1
- package/dist/cli/cmd-store.js.map +1 -1
- package/dist/cli/cmd-user-friendly.js.map +1 -1
- package/dist/cli/cmd-verify.js.map +1 -1
- package/dist/cli/commands/manage/bindings.js.map +1 -1
- package/dist/cli/commands/manage/dream-cycle-followup.js.map +1 -1
- package/dist/cli/commands/manage/maintenance-heartbeat.js.map +1 -1
- package/dist/cli/commands/manage/register-agents-audit-runall.js.map +1 -1
- package/dist/cli/commands/manage/register-analyze-maintenance-logs.js.map +1 -1
- package/dist/cli/commands/manage/register-budget-proposals.js.map +1 -1
- package/dist/cli/commands/manage/register-config-cli.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections-and-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-corrections.js.map +1 -1
- package/dist/cli/commands/manage/register-council.js.map +1 -1
- package/dist/cli/commands/manage/register-credentials-scope.js.map +1 -1
- package/dist/cli/commands/manage/register-digest.js.map +1 -1
- package/dist/cli/commands/manage/register-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-procedure-lifecycle.js.map +1 -1
- package/dist/cli/commands/manage/register-reconcile-cron-ledgers.js.map +1 -1
- package/dist/cli/commands/manage/register-reflection-pipeline.js +144 -7
- package/dist/cli/commands/manage/register-reflection-pipeline.js.map +1 -1
- package/dist/cli/commands/manage/register-self-correction-feedback.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-and-stats.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-entities-decay.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-graph-audit.js.map +1 -1
- package/dist/cli/commands/manage/register-storage-maintenance.js +152 -9
- package/dist/cli/commands/manage/register-storage-maintenance.js.map +1 -1
- package/dist/cli/commands/manage/register-validate-cron-exit.js.map +1 -1
- package/dist/cli/commands/manage/storage-stats-helpers.js +10 -3
- package/dist/cli/commands/manage/storage-stats-helpers.js.map +1 -1
- package/dist/cli/commands/register-manage-commands.js.map +1 -1
- package/dist/cli/config-feature-summaries.js.map +1 -1
- package/dist/cli/config-output-sink.js.map +1 -1
- package/dist/cli/distill-session-jsonl.js.map +1 -1
- package/dist/cli/distill.js +10 -1
- package/dist/cli/distill.js.map +1 -1
- package/dist/cli/global-verbose.js.map +1 -1
- package/dist/cli/goals.js.map +1 -1
- package/dist/cli/hybrid-mem-commander-utils.js.map +1 -1
- package/dist/cli/install/config-merge.js.map +1 -1
- package/dist/cli/install/cron-jobs.js.map +1 -1
- package/dist/cli/install/embedding-detect.js.map +1 -1
- package/dist/cli/install/run-install.js.map +1 -1
- package/dist/cli/install/workspace.js.map +1 -1
- package/dist/cli/proposals.js.map +1 -1
- package/dist/cli/register.js.map +1 -1
- package/dist/cli/shared.js.map +1 -1
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/task-queue-status.js.map +1 -1
- package/dist/cli/verified.js.map +1 -1
- package/dist/cli/verify/fact-count.js.map +1 -1
- package/dist/cli/verify/openclaw-config.js.map +1 -1
- package/dist/cli/verify/plugin-config-credentials.js.map +1 -1
- package/dist/cli/verify/sections/config-cron.js.map +1 -1
- package/dist/cli/verify/sections/embeddings.js.map +1 -1
- package/dist/cli/verify/sections/infrastructure.js.map +1 -1
- package/dist/cli/verify/sections/llm-models.js.map +1 -1
- package/dist/cli/verify/sections/reconcile.js.map +1 -1
- package/dist/cli/verify/verify-run-state.js.map +1 -1
- package/dist/cli/verify-llm-azure-auth.js.map +1 -1
- package/dist/cli/verify.js.map +1 -1
- package/dist/config/hybrid-schema.js.map +1 -1
- package/dist/config/index.js.map +1 -1
- package/dist/config/maintenance-fallback-policy.js.map +1 -1
- package/dist/config/parsers/capture.js.map +1 -1
- package/dist/config/parsers/core.js.map +1 -1
- package/dist/config/parsers/features.js.map +1 -1
- package/dist/config/parsers/index.js.map +1 -1
- package/dist/config/parsers/maintenance.js.map +1 -1
- package/dist/config/parsers/retrieval.js.map +1 -1
- package/dist/config/parsers/sensors.js.map +1 -1
- package/dist/config/skill-sections.js.map +1 -1
- package/dist/config/skill-size-limits.js.map +1 -1
- package/dist/config/types/agents.js.map +1 -1
- package/dist/config/types/bootstrap.js.map +1 -1
- package/dist/config/types/core.js.map +1 -1
- package/dist/config/types/index.js.map +1 -1
- package/dist/config/utils.js.map +1 -1
- package/dist/index-help.js.map +1 -1
- package/dist/index-testing-exports.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/lifecycle/hook-resolution-api.js.map +1 -1
- package/dist/lifecycle/hooks.js +0 -1
- package/dist/lifecycle/hooks.js.map +1 -1
- package/dist/lifecycle/resolve-agent-id.js.map +1 -1
- package/dist/lifecycle/session-state.js.map +1 -1
- package/dist/lifecycle/stage-active-task.js.map +1 -1
- package/dist/lifecycle/stage-auth-failure.js.map +1 -1
- package/dist/lifecycle/stage-capture/run-capture.js.map +1 -1
- package/dist/lifecycle/stage-capture.js.map +1 -1
- package/dist/lifecycle/stage-cleanup.js.map +1 -1
- package/dist/lifecycle/stage-credential-hint.js.map +1 -1
- package/dist/lifecycle/stage-frustration.js.map +1 -1
- package/dist/lifecycle/stage-goal-stewardship.js.map +1 -1
- package/dist/lifecycle/stage-goal-subagent.js.map +1 -1
- package/dist/lifecycle/stage-injection.js +1 -1
- package/dist/lifecycle/stage-injection.js.map +1 -1
- package/dist/lifecycle/stage-recall/run-recall.js.map +1 -1
- package/dist/lifecycle/stage-recall.js.map +1 -1
- package/dist/lifecycle/stage-setup.js.map +1 -1
- package/dist/routes/dashboard/collectors.js.map +1 -1
- package/dist/routes/dashboard/html.js.map +1 -1
- package/dist/routes/dashboard/server.js.map +1 -1
- package/dist/routes/dashboard-graph.js.map +1 -1
- package/dist/routes/graphql-resolvers.js.map +1 -1
- package/dist/routes/graphql-server.js.map +1 -1
- package/dist/services/active-task-checkpoint.js.map +1 -1
- package/dist/services/active-task-injection.js.map +1 -1
- package/dist/services/active-task.js.map +1 -1
- package/dist/services/adaptive-catch-up-pacing.js +25 -0
- package/dist/services/adaptive-catch-up-pacing.js.map +1 -0
- package/dist/services/adaptive-maintenance-llm.js.map +1 -1
- package/dist/services/adaptive-model-limits.js.map +1 -1
- package/dist/services/ambient-retrieval.js.map +1 -1
- package/dist/services/apitap-service.js.map +1 -1
- package/dist/services/audit-health-exit-info.js.map +1 -1
- package/dist/services/audit-health-json.js.map +1 -1
- package/dist/services/auth-failure-detect.js.map +1 -1
- package/dist/services/auto-capture.js.map +1 -1
- package/dist/services/auto-classifier.js.map +1 -1
- package/dist/services/auto-skills-audit.js.map +1 -1
- package/dist/services/bootstrap-optional.js.map +1 -1
- package/dist/services/bootstrap-priority.js.map +1 -1
- package/dist/services/bootstrap.js.map +1 -1
- package/dist/services/capture-provenance.js.map +1 -1
- package/dist/services/capture-utils.js.map +1 -1
- package/dist/services/chat.js +22 -3
- package/dist/services/chat.js.map +1 -1
- package/dist/services/classification-scope.js.map +1 -1
- package/dist/services/classification.js.map +1 -1
- package/dist/services/cli-sql-dump.js.map +1 -1
- package/dist/services/consolidation.js.map +1 -1
- package/dist/services/context-audit.js +1 -1
- package/dist/services/context-audit.js.map +1 -1
- package/dist/services/context-budget.js.map +1 -1
- package/dist/services/context-engine.js.map +1 -1
- package/dist/services/contextual-variants.js.map +1 -1
- package/dist/services/continuous-verifier.js.map +1 -1
- package/dist/services/contradiction-adjudicator.js.map +1 -1
- package/dist/services/cost-context.js.map +1 -1
- package/dist/services/cost-feature-labels.js.map +1 -1
- package/dist/services/credential-migration.js.map +1 -1
- package/dist/services/credential-scanner.js.map +1 -1
- package/dist/services/credential-validation.js.map +1 -1
- package/dist/services/cron-exit-validator.js.map +1 -1
- package/dist/services/cron-guard.js.map +1 -1
- package/dist/services/cron-job-bash-harness.js +52 -5
- package/dist/services/cron-job-bash-harness.js.map +1 -1
- package/dist/services/cron-maintenance-reconciler.js +1 -3
- package/dist/services/cron-maintenance-reconciler.js.map +1 -1
- package/dist/services/cross-agent-learning.js.map +1 -1
- package/dist/services/crystallization-proposer.js.map +1 -1
- package/dist/services/dedupe-policy.js.map +1 -1
- package/dist/services/deprecated-cron-commands.js.map +1 -1
- package/dist/services/directive-extract.js.map +1 -1
- package/dist/services/document-chunker.js.map +1 -1
- package/dist/services/document-grader.js.map +1 -1
- package/dist/services/dream-cycle.js.map +1 -1
- package/dist/services/embedding-migration.js.map +1 -1
- package/dist/services/embedding-registry.js.map +1 -1
- package/dist/services/embeddings/chain-provider.js.map +1 -1
- package/dist/services/embeddings/factory.js.map +1 -1
- package/dist/services/embeddings/fallback-provider.js.map +1 -1
- package/dist/services/embeddings/ollama-provider.js.map +1 -1
- package/dist/services/embeddings/onnx-provider.js.map +1 -1
- package/dist/services/embeddings/openai-provider.js.map +1 -1
- package/dist/services/embeddings/shared.js +3 -3
- package/dist/services/embeddings/shared.js.map +1 -1
- package/dist/services/embeddings/types.js.map +1 -1
- package/dist/services/entity-enrichment-adaptive.js +128 -0
- package/dist/services/entity-enrichment-adaptive.js.map +1 -0
- package/dist/services/entity-enrichment-cli.js +389 -42
- package/dist/services/entity-enrichment-cli.js.map +1 -1
- package/dist/services/entity-enrichment.js +31 -5
- package/dist/services/entity-enrichment.js.map +1 -1
- package/dist/services/error-reporter/noisy-errors.js.map +1 -1
- package/dist/services/error-reporter/sanitize.js.map +1 -1
- package/dist/services/error-reporter.js.map +1 -1
- package/dist/services/event-hub-repair.js.map +1 -1
- package/dist/services/export-memory.js.map +1 -1
- package/dist/services/fact-extraction.js.map +1 -1
- package/dist/services/feedback-effectiveness.js.map +1 -1
- package/dist/services/find-duplicates.js.map +1 -1
- package/dist/services/frustration-detector.js.map +1 -1
- package/dist/services/fts-search.js.map +1 -1
- package/dist/services/gap-detector.js.map +1 -1
- package/dist/services/generated-skill-lifecycle.js.map +1 -1
- package/dist/services/generated-skill-validation.js.map +1 -1
- package/dist/services/goal-active-task-mirror.js.map +1 -1
- package/dist/services/goal-circuit-breaker.js.map +1 -1
- package/dist/services/goal-health.js.map +1 -1
- package/dist/services/goal-registry.js.map +1 -1
- package/dist/services/goal-stewardship-heartbeat.js.map +1 -1
- package/dist/services/goal-stewardship-llm-triage.js.map +1 -1
- package/dist/services/goal-stewardship-verify-cron.js.map +1 -1
- package/dist/services/goal-stewardship.js.map +1 -1
- package/dist/services/goal-subagent.js.map +1 -1
- package/dist/services/graph-retrieval.js.map +1 -1
- package/dist/services/humanizer-score.js.map +1 -1
- package/dist/services/hybrid-mem-cron-default-job-steps.js.map +1 -1
- package/dist/services/hyde-helper.js.map +1 -1
- package/dist/services/identity-reflection.js.map +1 -1
- package/dist/services/implicit-feedback-extract.js.map +1 -1
- package/dist/services/index.js.map +1 -1
- package/dist/services/ingest-utils.js.map +1 -1
- package/dist/services/intent-template.js.map +1 -1
- package/dist/services/json-array-parser.js.map +1 -1
- package/dist/services/knowledge-gaps.js.map +1 -1
- package/dist/services/language-keywords-build.js.map +1 -1
- package/dist/services/lifecycle/github-adapter.js.map +1 -1
- package/dist/services/llm-rate-limit-headers.js +1 -2
- package/dist/services/llm-rate-limit-headers.js.map +1 -1
- package/dist/services/maintenance-auto-fix.js.map +1 -1
- package/dist/services/maintenance-log-analyzer.js +7 -1
- package/dist/services/maintenance-log-analyzer.js.map +1 -1
- package/dist/services/maintenance-timestamp.js.map +1 -1
- package/dist/services/memory-diagnostics.js.map +1 -1
- package/dist/services/memory-index.js.map +1 -1
- package/dist/services/merge-results.js.map +1 -1
- package/dist/services/model-capabilities.js.map +1 -1
- package/dist/services/model-pricing.js.map +1 -1
- package/dist/services/narrative-recall.js.map +1 -1
- package/dist/services/openclaw-session-artifact.js.map +1 -1
- package/dist/services/passive-observer.js.map +1 -1
- package/dist/services/pattern-detector-hash.js.map +1 -1
- package/dist/services/pattern-detector.js.map +1 -1
- package/dist/services/pending-autopilot/foundation.js.map +1 -1
- package/dist/services/pending-autopilot/redaction.js.map +1 -1
- package/dist/services/pending-autopilot/store.js.map +1 -1
- package/dist/services/pending-autopilot/types.js.map +1 -1
- package/dist/services/pending-digest-autopilot-cron.js.map +1 -1
- package/dist/services/pending-digest-autopilot.js.map +1 -1
- package/dist/services/pending-review-digest.js.map +1 -1
- package/dist/services/persona-proposal-triage.js.map +1 -1
- package/dist/services/persona-state-promotion.js.map +1 -1
- package/dist/services/post-compaction-recall.js.map +1 -1
- package/dist/services/pre-consolidation-flush.js.map +1 -1
- package/dist/services/pre-finalization-guard.js.map +1 -1
- package/dist/services/procedure-cluster.js.map +1 -1
- package/dist/services/procedure-extractor.js.map +1 -1
- package/dist/services/procedure-promotion/duplicate-skill-cache.js.map +1 -1
- package/dist/services/procedure-promotion-policy.js.map +1 -1
- package/dist/services/procedure-selection-metrics.js.map +1 -1
- package/dist/services/procedure-skill-eval.js.map +1 -1
- package/dist/services/procedure-skill-generator.js.map +1 -1
- package/dist/services/procedure-skill-recipe.js.map +1 -1
- package/dist/services/procedure-skill-shrink.js.map +1 -1
- package/dist/services/procedure-skill-workflow.js.map +1 -1
- package/dist/services/provenance.js.map +1 -1
- package/dist/services/public-export-bundle.js.map +1 -1
- package/dist/services/python-bridge.js.map +1 -1
- package/dist/services/query-expander.js.map +1 -1
- package/dist/services/query-validator.js.map +1 -1
- package/dist/services/recall-pipeline.js.map +1 -1
- package/dist/services/recall-timing.js.map +1 -1
- package/dist/services/recent-http-attempts.js.map +1 -1
- package/dist/services/reflection/shared.js.map +1 -1
- package/dist/services/reflection.js.map +1 -1
- package/dist/services/reinforcement-extract.js.map +1 -1
- package/dist/services/reranker.js.map +1 -1
- package/dist/services/responses-adapter.js.map +1 -1
- package/dist/services/retrieval-aliases.js.map +1 -1
- package/dist/services/retrieval-mode-policy.js.map +1 -1
- package/dist/services/retrieval-orchestrator/packing.js.map +1 -1
- package/dist/services/retrieval-orchestrator.d.ts +2 -3
- package/dist/services/retrieval-orchestrator.js.map +1 -1
- package/dist/services/rrf-fusion.js.map +1 -1
- package/dist/services/self-correction-extract.js.map +1 -1
- package/dist/services/session-observability.js.map +1 -1
- package/dist/services/session-pre-filter.js.map +1 -1
- package/dist/services/shortest-path.js.map +1 -1
- package/dist/services/skill-allowed-tools.js.map +1 -1
- package/dist/services/skill-creator-validator.js.map +1 -1
- package/dist/services/skill-crystallizer-helpers.js.map +1 -1
- package/dist/services/skill-crystallizer.js.map +1 -1
- package/dist/services/skill-description-builder.js.map +1 -1
- package/dist/services/skill-eval-synthesizer.js.map +1 -1
- package/dist/services/skill-examples-builder.js.map +1 -1
- package/dist/services/skill-frontmatter.js.map +1 -1
- package/dist/services/skill-name-validator.js.map +1 -1
- package/dist/services/skill-prompt-injection.js.map +1 -1
- package/dist/services/skill-reference-sidecar.js.map +1 -1
- package/dist/services/skill-script-bundler.js.map +1 -1
- package/dist/services/skill-validator.js.map +1 -1
- package/dist/services/startup-memory-attribution.js.map +1 -1
- package/dist/services/task-hygiene.js.map +1 -1
- package/dist/services/task-ledger/canonical.js.map +1 -1
- package/dist/services/task-ledger-facts.js.map +1 -1
- package/dist/services/task-queue-leases.js.map +1 -1
- package/dist/services/task-queue-watchdog.js.map +1 -1
- package/dist/services/tool-effectiveness.js.map +1 -1
- package/dist/services/tool-proposer.js.map +1 -1
- package/dist/services/tools-md-section.js.map +1 -1
- package/dist/services/topic-clusters.js.map +1 -1
- package/dist/services/trajectory-tracker.js.map +1 -1
- package/dist/services/vector-backend-observability.js.map +1 -1
- package/dist/services/vector-lifecycle-audit.js.map +1 -1
- package/dist/services/vector-maintenance.js.map +1 -1
- package/dist/services/vector-search.js.map +1 -1
- package/dist/services/verification-store.js.map +1 -1
- package/dist/services/verified-fact-triage.js.map +1 -1
- package/dist/services/wal-helpers.js.map +1 -1
- package/dist/services/workflow-tracker.js.map +1 -1
- package/dist/setup/bootstrap-databases.js.map +1 -1
- package/dist/setup/cli-context/cli-services.js.map +1 -1
- package/dist/setup/cli-context/help-text.js.map +1 -1
- package/dist/setup/cli-context/metadata.js.map +1 -1
- package/dist/setup/cli-context/register-cli-with-help.js.map +1 -1
- package/dist/setup/cli-context/register-full.js.map +1 -1
- package/dist/setup/cli-context/register-help.js.map +1 -1
- package/dist/setup/cost-instrumentation.js.map +1 -1
- package/dist/setup/hybrid-memory-generation-state.js.map +1 -1
- package/dist/setup/hybrid-memory-reload-coordinator.js +13 -13
- package/dist/setup/hybrid-memory-reload-coordinator.js.map +1 -1
- package/dist/setup/plugin-service.js.map +1 -1
- package/dist/setup/provider-router.js.map +1 -1
- package/dist/setup/register-context-engine.js.map +1 -1
- package/dist/setup/register-hooks.js.map +1 -1
- package/dist/setup/register-plugin.js +25 -21
- package/dist/setup/register-plugin.js.map +1 -1
- package/dist/setup/register-tools.js.map +1 -1
- package/dist/setup/reregister-policy.js +2 -2
- package/dist/setup/reregister-policy.js.map +1 -1
- package/dist/setup/tool-installers.js.map +1 -1
- package/dist/setup/workspace-bootstrap.js.map +1 -1
- package/dist/src/worker/narratives.js.map +1 -1
- package/dist/tools/apitap-tools.js.map +1 -1
- package/dist/tools/credential-tools.js.map +1 -1
- package/dist/tools/crystallization-tools.js.map +1 -1
- package/dist/tools/dashboard-routes.js.map +1 -1
- package/dist/tools/document-tools.js.map +1 -1
- package/dist/tools/goal-tools.js.map +1 -1
- package/dist/tools/graph-tools.js.map +1 -1
- package/dist/tools/issue-tools.js.map +1 -1
- package/dist/tools/memory/build-runtime.js.map +1 -1
- package/dist/tools/memory/helpers.js.map +1 -1
- package/dist/tools/memory/register-checkpoint-tools.js.map +1 -1
- package/dist/tools/memory/register-directory-tools.js.map +1 -1
- package/dist/tools/memory/register-edict-tools.js.map +1 -1
- package/dist/tools/memory/register-episode-tools.js.map +1 -1
- package/dist/tools/memory/register-recall-tools.js.map +1 -1
- package/dist/tools/memory/register-store-tools.js.map +1 -1
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/persona-tools.js.map +1 -1
- package/dist/tools/provenance-tools.js.map +1 -1
- package/dist/tools/public-api-routes.js.map +1 -1
- package/dist/tools/safe-register-http-route.js.map +1 -1
- package/dist/tools/self-extension-tools.js.map +1 -1
- package/dist/tools/task-hygiene-tools.js.map +1 -1
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/verification-tools.js.map +1 -1
- package/dist/tools/workflow-tools.js.map +1 -1
- package/dist/types/issue-types.js.map +1 -1
- package/dist/types/learnings-types.js.map +1 -1
- package/dist/types/memory.js.map +1 -1
- package/dist/utils/apim-gateway-fetch.js.map +1 -1
- package/dist/utils/atomic-write.js.map +1 -1
- package/dist/utils/auth-failover.js.map +1 -1
- package/dist/utils/auth.js.map +1 -1
- package/dist/utils/compaction-model-watchdog.js.map +1 -1
- package/dist/utils/consolidation-controls.js.map +1 -1
- package/dist/utils/constants.js.map +1 -1
- package/dist/utils/date-detector.js.map +1 -1
- package/dist/utils/dates.js.map +1 -1
- package/dist/utils/decay.js.map +1 -1
- package/dist/utils/duration.js.map +1 -1
- package/dist/utils/embed-call.js.map +1 -1
- package/dist/utils/entity-lookup-resolve.js.map +1 -1
- package/dist/utils/entity-mention-quality.js.map +1 -1
- package/dist/utils/entity-stopwords.js.map +1 -1
- package/dist/utils/env-manager.js.map +1 -1
- package/dist/utils/error-tracking.js.map +1 -1
- package/dist/utils/event-loop-yield.js.map +1 -1
- package/dist/utils/extract-last-user-message.js.map +1 -1
- package/dist/utils/extraction-from-template.js.map +1 -1
- package/dist/utils/fact-embeddings.js.map +1 -1
- package/dist/utils/file-snapshot.js.map +1 -1
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/fs.js.map +1 -1
- package/dist/utils/gh-repo-arg.js.map +1 -1
- package/dist/utils/hybrid-mem-json-cli.js.map +1 -1
- package/dist/utils/language-keywords.js.map +1 -1
- package/dist/utils/lifecycle-generation.js.map +1 -1
- package/dist/utils/llm-json-array.js.map +1 -1
- package/dist/utils/llm-selection.js.map +1 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/model-provider-family.js.map +1 -1
- package/dist/utils/model-tier.js.map +1 -1
- package/dist/utils/openclaw-agent-defaults.js.map +1 -1
- package/dist/utils/path.js.map +1 -1
- package/dist/utils/plugin-root.js.map +1 -1
- package/dist/utils/plugin-update-check.js.map +1 -1
- package/dist/utils/procedure-risk.js.map +1 -1
- package/dist/utils/progress-indicators.js.map +1 -1
- package/dist/utils/prompt-loader.js.map +1 -1
- package/dist/utils/provenance.js.map +1 -1
- package/dist/utils/provider-detection.js.map +1 -1
- package/dist/utils/registration-superseded.js.map +1 -1
- package/dist/utils/salience.js.map +1 -1
- package/dist/utils/sanitize-messages.js.map +1 -1
- package/dist/utils/scope-filter.js.map +1 -1
- package/dist/utils/skill-discovery.js.map +1 -1
- package/dist/utils/sqlite-file-perms.js.map +1 -1
- package/dist/utils/sqlite-outcome-compat.js.map +1 -1
- package/dist/utils/sqlite-transaction.js.map +1 -1
- package/dist/utils/stable-stringify.js.map +1 -1
- package/dist/utils/subagent-ended-utils.js.map +1 -1
- package/dist/utils/tags.js.map +1 -1
- package/dist/utils/text.js.map +1 -1
- package/dist/utils/timeout.js.map +1 -1
- package/dist/utils/typebox.js.map +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/dist/utils/wal-replay.js.map +1 -1
- package/dist/versionInfo.js.map +1 -1
- package/index.ts +2 -2
- package/lifecycle/hooks.ts +0 -1
- package/npm-shrinkwrap.json +487 -186
- package/openclaw.plugin.json +1 -1
- package/package.json +2 -2
- package/services/adaptive-catch-up-pacing.ts +28 -0
- package/services/chat.ts +34 -1
- package/services/cron-job-bash-harness.ts +52 -5
- package/services/embeddings/shared.ts +5 -2
- package/services/entity-enrichment-adaptive.ts +245 -0
- package/services/entity-enrichment-cli.ts +553 -47
- package/services/entity-enrichment.ts +43 -2
- package/services/llm-rate-limit-headers.ts +1 -4
- package/services/maintenance-log-analyzer.ts +13 -9
- package/services/reinforcement-extract.ts +19 -0
- package/setup/hybrid-memory-reload-coordinator.ts +26 -0
- package/setup/register-plugin.ts +62 -32
- package/setup/reregister-policy.ts +10 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-install.js","names":[],"sources":["../../../cli/install/run-install.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { getEnv } from \"../../utils/env-manager.js\";\nimport { findPluginRoot } from \"../../utils/plugin-root.js\";\n\nimport { type CronModelConfig, getCronModelConfig } from \"../../config.js\";\nimport { parseDigestWeeklyDeliveryOnly } from \"../../config/parsers/features.js\";\nimport { capturePluginError } from \"../../services/error-reporter.js\";\nimport { ensureWorkspaceBootstrap } from \"../../setup/workspace-bootstrap.js\";\nimport { PLUGIN_ID } from \"../../utils/constants.js\";\nimport type { HandlerContext } from \"../handlers.js\";\nimport type { InstallCliResult, UninstallCliResult, UpgradeCliResult } from \"../types.js\";\nimport {\n buildInstallDefaults,\n deepMerge,\n getPluginEntryConfig,\n inspectExistingEmbeddingSetup,\n} from \"./config-merge.js\";\nimport { applyDetectedEmbeddingSetup, detectRecommendedEmbeddingSetup, getDashboardUrl } from \"./embedding-detect.js\";\nimport { ensureMaintenanceCronJobs } from \"./cron-jobs.js\";\nimport {\n applyHybridMemoryToolsMd,\n assertSafeRequestedVersionArg,\n installHybridMemoryWorkspaceSkill,\n isPathInsideDir,\n npxExecutable,\n PLUGIN_JOB_ID_PREFIX,\n resolveAgentWorkspaceRoot,\n} from \"./workspace.js\";\n\nexport function runInstallForCli(opts: { dryRun: boolean }): InstallCliResult {\n const openclawDir = join(homedir(), \".openclaw\");\n const configPath = join(openclawDir, \"openclaw.json\");\n const fullDefaults = buildInstallDefaults();\n const pluginRootDir = findPluginRoot(import.meta.url);\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>;\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runInstallForCli:read-config\" });\n return { ok: false, error: `Could not read ${configPath}: ${e}` };\n }\n }\n const existingEmbedding = inspectExistingEmbeddingSetup(config);\n const detectedEmbedding = detectRecommendedEmbeddingSetup(config, pluginRootDir);\n const existingApiKey =\n (config?.plugins as Record<string, unknown>)?.entries &&\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)?.[PLUGIN_ID] &&\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n )?.config &&\n (\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n ).config as Record<string, unknown>\n )?.embedding &&\n (\n (\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n ).config as Record<string, unknown>\n ).embedding as Record<string, unknown>\n )?.apiKey;\n const isRealKey =\n typeof existingApiKey === \"string\" &&\n existingApiKey.length >= 10 &&\n existingApiKey !== \"YOUR_OPENAI_API_KEY\" &&\n existingApiKey !== \"<OPENAI_API_KEY>\";\n\n if (!config.plugins || typeof config.plugins !== \"object\") config.plugins = {};\n if (!(config.agents && typeof config.agents === \"object\")) config.agents = { defaults: {} };\n deepMerge(config, fullDefaults as unknown as Record<string, unknown>);\n if (isRealKey) {\n const entries = (config.plugins as Record<string, unknown>).entries as Record<string, unknown>;\n const mh = entries[PLUGIN_ID] as Record<string, unknown>;\n const cfg = mh?.config as Record<string, unknown>;\n const emb = cfg?.embedding as Record<string, unknown>;\n if (emb) emb.apiKey = existingApiKey;\n }\n const embeddingPatch = applyDetectedEmbeddingSetup(config, detectedEmbedding, existingEmbedding);\n const after = JSON.stringify(config, null, 2);\n const workspaceRoot = resolveAgentWorkspaceRoot(config);\n const dashboardUrl = getDashboardUrl(config);\n\n if (opts.dryRun) {\n const skillPreview = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: true,\n });\n const toolsPreview = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: true,\n });\n let bootstrapPreview = { workspaceRoot, directories: [], files: [] } as ReturnType<typeof ensureWorkspaceBootstrap>;\n let bootstrapPreviewError: string | undefined;\n try {\n bootstrapPreview = ensureWorkspaceBootstrap({ workspaceRoot, dryRun: true });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:workspace-bootstrap:dry-run\" });\n bootstrapPreview = { workspaceRoot, directories: [], files: [] };\n bootstrapPreviewError = String(err);\n }\n const previewDone: string[] = [\n \"Would write or repair the hybrid-memory plugin config block.\",\n \"Would refresh the workspace skill.\",\n \"Would refresh the managed TOOLS.md section.\",\n `Would ensure workspace starter layout under ${workspaceRoot}.`,\n `Would point you to Mission Control at ${dashboardUrl}.`,\n ];\n if (embeddingPatch.changed) {\n previewDone.push(\n `Would prefill embedding defaults with ${detectedEmbedding.provider}/${detectedEmbedding.model} (${detectedEmbedding.source}).`,\n );\n }\n if (bootstrapPreviewError) {\n previewDone.push(`Workspace bootstrap check would warn: ${bootstrapPreviewError}`);\n }\n const previewRemaining: string[] = [];\n if (detectedEmbedding.provider === \"openai\" && !detectedEmbedding.envKey && !existingEmbedding.hasUsableApiKey) {\n previewRemaining.push(\"Add an OpenAI-compatible embedding API key, then restart the gateway.\");\n } else if (detectedEmbedding.provider === \"google\" && !existingEmbedding.hasUsableApiKey) {\n previewRemaining.push(\n \"Add llm.providers.google.apiKey (or export GOOGLE_API_KEY / GEMINI_API_KEY), then restart.\",\n );\n } else if (detectedEmbedding.provider === \"ollama\") {\n previewRemaining.push(\"Make sure Ollama is running locally before verify.\");\n }\n previewRemaining.push(\"Restart the gateway after applying the config.\");\n previewRemaining.push(\"Run `openclaw hybrid-mem verify` to confirm the install.\");\n return {\n ok: true,\n configPath,\n dryRun: true,\n written: false,\n configJson: after,\n pluginId: PLUGIN_ID,\n workspaceSkillPath: skillPreview.path,\n workspaceSkillError: skillPreview.error,\n workspaceToolsMdPath: toolsPreview.path,\n workspaceToolsMdError: toolsPreview.error,\n workspaceToolsMdUpdated: toolsPreview.updated,\n workspaceRoot,\n dashboardUrl,\n detectedEmbedding,\n bootstrapDirectoriesCreated: bootstrapPreview.directories.filter((entry) => entry.created).length,\n bootstrapFilesCreated: bootstrapPreview.files.filter((entry) => entry.created).length,\n completed: previewDone,\n remaining: previewRemaining,\n };\n }\n\n try {\n mkdirSync(openclawDir, { recursive: true });\n mkdirSync(join(openclawDir, \"memory\"), { recursive: true });\n writeFileSync(configPath, after, \"utf-8\");\n const skillInstall = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: false,\n });\n const toolsMdInstall = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: false,\n });\n let bootstrapInstall = { workspaceRoot, directories: [], files: [] } as ReturnType<typeof ensureWorkspaceBootstrap>;\n let bootstrapInstallError: string | undefined;\n try {\n bootstrapInstall = ensureWorkspaceBootstrap({ workspaceRoot, dryRun: false });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:workspace-bootstrap\" });\n bootstrapInstallError = String(err);\n // non-fatal: workspace bootstrap should not fail a successful config install\n }\n let cronSummary: { added: string[]; normalized: string[] } | undefined;\n try {\n const pluginCfg = getPluginEntryConfig(config);\n const pluginConfig = pluginCfg as CronModelConfig | undefined;\n const dreamCycleRaw = pluginCfg?.nightlyCycle as Record<string, unknown> | undefined;\n const dreamCycleSchedule =\n typeof dreamCycleRaw?.schedule === \"string\" && (dreamCycleRaw.schedule as string).trim().length > 0\n ? (dreamCycleRaw.schedule as string).trim()\n : undefined;\n const sensorSweepRaw = pluginCfg?.sensorSweep as Record<string, unknown> | undefined;\n const sensorSweepSchedule =\n typeof sensorSweepRaw?.schedule === \"string\" && (sensorSweepRaw.schedule as string).trim().length > 0\n ? (sensorSweepRaw.schedule as string).trim()\n : undefined;\n const installScheduleOverrides: Record<string, string> = {};\n if (dreamCycleSchedule)\n installScheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}nightly-dream-cycle`] = dreamCycleSchedule;\n if (sensorSweepSchedule) installScheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}sensor-sweep`] = sensorSweepSchedule;\n cronSummary = ensureMaintenanceCronJobs(openclawDir, pluginConfig, {\n normalizeExisting: false,\n reEnableDisabled: false,\n scheduleOverrides: Object.keys(installScheduleOverrides).length > 0 ? installScheduleOverrides : undefined,\n featureGates: {\n \"sensorSweep.enabled\": (sensorSweepRaw?.enabled as boolean | undefined) === true,\n \"nightlyCycle.enabled\": (dreamCycleRaw?.enabled as boolean | undefined) === true,\n },\n digestWeeklyDelivery: parseDigestWeeklyDeliveryOnly(getPluginEntryConfig(config) ?? {}),\n });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:cron-setup\" });\n // non-fatal: cron jobs optional on install\n }\n const completed: string[] = [\n `Wrote hybrid-memory config to ${configPath}.`,\n `Installed workspace skill at ${skillInstall.path}${skillInstall.error ? ` (warning: ${skillInstall.error})` : \"\"}.`,\n `Checked TOOLS.md managed block at ${toolsMdInstall.path}${toolsMdInstall.updated ? \" (updated)\" : \" (already current)\"}.`,\n bootstrapInstallError\n ? `Workspace starter layout warning in ${workspaceRoot}: ${bootstrapInstallError}.`\n : `Ensured workspace starter layout in ${workspaceRoot} (${bootstrapInstall.directories.filter((entry) => entry.created).length} dirs, ${bootstrapInstall.files.filter((entry) => entry.created).length} files created).`,\n `Dashboard home: ${dashboardUrl}`,\n ];\n if (embeddingPatch.changed) {\n completed.push(\n `Prefilled embedding defaults with ${detectedEmbedding.provider}/${detectedEmbedding.model} (${detectedEmbedding.source}).`,\n );\n } else {\n completed.push(`Kept existing embedding setup (${detectedEmbedding.provider}/${detectedEmbedding.model}).`);\n }\n if (cronSummary) {\n completed.push(\n cronSummary.added.length > 0\n ? `Ensured maintenance cron jobs (${cronSummary.added.length} added).`\n : \"Checked maintenance cron jobs.\",\n );\n }\n for (const note of embeddingPatch.notes) completed.push(note);\n const remaining: string[] = [];\n if (detectedEmbedding.provider === \"openai\" && !existingEmbedding.hasUsableApiKey && !detectedEmbedding.envKey) {\n remaining.push('Set plugins.entries[\"openclaw-hybrid-memory\"].config.embedding.apiKey to a real key.');\n }\n if (detectedEmbedding.provider === \"google\" && !existingEmbedding.hasUsableApiKey) {\n remaining.push(\"Set llm.providers.google.apiKey (or export GOOGLE_API_KEY / GEMINI_API_KEY).\");\n }\n if (detectedEmbedding.provider === \"ollama\") {\n remaining.push(\"Keep Ollama running locally before using semantic recall.\");\n }\n remaining.push(\"Restart the gateway so the new config and workspace files are picked up.\");\n remaining.push(\"Run `openclaw hybrid-mem verify` for the beginner-friendly health check.\");\n return {\n ok: true,\n configPath,\n dryRun: false,\n written: true,\n pluginId: PLUGIN_ID,\n workspaceSkillPath: skillInstall.path,\n workspaceSkillError: skillInstall.error,\n workspaceToolsMdPath: toolsMdInstall.path,\n workspaceToolsMdError: toolsMdInstall.error,\n workspaceToolsMdUpdated: toolsMdInstall.updated,\n workspaceRoot,\n dashboardUrl,\n detectedEmbedding,\n bootstrapDirectoriesCreated: bootstrapInstall.directories.filter((entry) => entry.created).length,\n bootstrapFilesCreated: bootstrapInstall.files.filter((entry) => entry.created).length,\n completed,\n remaining,\n };\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:write-config\" });\n return { ok: false, error: `Could not write config: ${err}` };\n }\n}\n\nexport function runUninstallForCli(\n ctx: HandlerContext,\n opts: { cleanAll: boolean; leaveConfig: boolean },\n): UninstallCliResult {\n const { resolvedSqlitePath, resolvedLancePath } = ctx;\n const openclawDir = join(homedir(), \".openclaw\");\n const openclawMemoryDir = join(openclawDir, \"memory\");\n const dangerousUninstallEnabled = getEnv(\"OPENCLAW_HYBRID_MEM_UNINSTALL_DANGEROUS\") === \"1\";\n const configPath = join(openclawDir, \"openclaw.json\");\n const cleaned: string[] = [];\n let outcome: UninstallCliResult[\"outcome\"];\n let error = \"\";\n\n if (!opts.leaveConfig && existsSync(configPath)) {\n try {\n const raw = readFileSync(configPath, \"utf-8\");\n const config = JSON.parse(raw) as Record<string, unknown>;\n if (!config.plugins || typeof config.plugins !== \"object\") config.plugins = {};\n const plugins = config.plugins as Record<string, unknown>;\n if (!plugins.slots || typeof plugins.slots !== \"object\") plugins.slots = {};\n (plugins.slots as Record<string, string>).memory = \"memory-core\";\n if (!plugins.entries || typeof plugins.entries !== \"object\") plugins.entries = {};\n const entries = plugins.entries as Record<string, unknown>;\n if (!entries[PLUGIN_ID] || typeof entries[PLUGIN_ID] !== \"object\") entries[PLUGIN_ID] = {};\n (entries[PLUGIN_ID] as Record<string, boolean>).enabled = false;\n writeFileSync(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n outcome = \"config_updated\";\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:update-config\" });\n outcome = \"config_error\";\n error = String(e);\n }\n } else if (!opts.leaveConfig) {\n outcome = \"config_not_found\";\n } else {\n outcome = \"leave_config\";\n }\n\n if (opts.cleanAll) {\n if (\n existsSync(resolvedSqlitePath) &&\n (dangerousUninstallEnabled || isPathInsideDir(openclawMemoryDir, resolvedSqlitePath))\n ) {\n try {\n rmSync(resolvedSqlitePath, { force: true });\n cleaned.push(resolvedSqlitePath);\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:remove-sqlite\" });\n }\n }\n if (\n existsSync(resolvedLancePath) &&\n (dangerousUninstallEnabled || isPathInsideDir(openclawMemoryDir, resolvedLancePath))\n ) {\n try {\n rmSync(resolvedLancePath, { recursive: true, force: true });\n cleaned.push(resolvedLancePath);\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:remove-lance\" });\n }\n }\n }\n\n const base = { pluginId: PLUGIN_ID, cleaned };\n if (outcome === \"config_error\") return { ...base, outcome, error };\n return { ...base, outcome } as UninstallCliResult;\n}\n\nexport async function runUpgradeForCli(ctx: HandlerContext, requestedVersion?: string): Promise<UpgradeCliResult> {\n const { cfg, logger } = ctx;\n const extDir = findPluginRoot(import.meta.url);\n const { spawnSync } = await import(\"node:child_process\");\n const version = requestedVersion?.trim() || \"latest\";\n try {\n assertSafeRequestedVersionArg(version);\n } catch (e) {\n return { ok: false, error: `Invalid requested version: ${e instanceof Error ? e.message : String(e)}` };\n }\n\n const manifestPath = join(extDir, \"openclaw.plugin.json\");\n const pkgPath = join(extDir, \"package.json\");\n if (!existsSync(manifestPath) || !existsSync(pkgPath)) {\n return { ok: false, error: `Refusing to upgrade: plugin directory does not look valid: ${extDir}` };\n }\n\n const backupDir = join(dirname(extDir), `${basename(extDir)}.bak-${Date.now()}`);\n try {\n renameSync(extDir, backupDir);\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:move-dir\" });\n return {\n ok: false,\n error: `Could not move plugin directory for upgrade: ${e}. Use standalone installer: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n // Use standalone installer so upgrade works even when config is invalid (plugin missing).\n const npxArgs = [\"-y\", \"openclaw-hybrid-memory-install\", version];\n const r = spawnSync(npxExecutable(), npxArgs, {\n stdio: \"inherit\",\n cwd: homedir(),\n shell: false,\n });\n if (r.status !== 0) {\n // Best-effort rollback: restore original plugin directory.\n try {\n if (existsSync(extDir)) {\n // Installer might have created a partial directory; avoid clobbering it.\n const failedDir = join(dirname(extDir), `${basename(extDir)}.failed-${Date.now()}`);\n try {\n renameSync(extDir, failedDir);\n } catch {\n rmSync(extDir, { recursive: true, force: true });\n }\n }\n renameSync(backupDir, extDir);\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:rollback\" });\n return {\n ok: false,\n error: `Install failed (exit ${r.status}). Rollback also failed: ${e}. Run manually: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n return {\n ok: false,\n error: `Install failed (exit ${r.status}). Run manually: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n try {\n rmSync(backupDir, { recursive: true, force: true });\n } catch (e) {\n // Non-fatal; backup cleanup failure shouldn't block upgrade.\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:cleanup-backup\" });\n }\n let installedVersion = version;\n try {\n const pkgAfterPath = join(extDir, \"package.json\");\n if (existsSync(pkgAfterPath)) {\n const pkg = JSON.parse(readFileSync(pkgAfterPath, \"utf-8\")) as { version?: string };\n installedVersion = pkg.version ?? installedVersion;\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:read-version\" });\n }\n // Ensure maintenance cron jobs exist (add missing, normalize existing; never re-enable disabled)\n try {\n const openclawDir = join(homedir(), \".openclaw\");\n const pluginConfig = getCronModelConfig(cfg);\n const scheduleOverrides: Record<string, string> = {};\n if (typeof cfg.nightlyCycle?.schedule === \"string\" && cfg.nightlyCycle.schedule.trim().length > 0) {\n scheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}nightly-dream-cycle`] = cfg.nightlyCycle.schedule;\n }\n if (typeof cfg.sensorSweep?.schedule === \"string\" && cfg.sensorSweep.schedule.trim().length > 0) {\n scheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}sensor-sweep`] = cfg.sensorSweep.schedule;\n }\n const { added, normalized } = ensureMaintenanceCronJobs(openclawDir, pluginConfig, {\n normalizeExisting: true,\n reEnableDisabled: false,\n scheduleOverrides: Object.keys(scheduleOverrides).length > 0 ? scheduleOverrides : undefined,\n featureGates: {\n \"sensorSweep.enabled\": cfg.sensorSweep?.enabled === true,\n \"nightlyCycle.enabled\": cfg.nightlyCycle?.enabled === true,\n },\n digestWeeklyDelivery: cfg.digest.weekly.delivery,\n });\n if (added.length > 0 || normalized.length > 0) {\n logger?.info?.(\n `memory-hybrid: upgrade — cron jobs: ${added.length} added, ${normalized.length} normalized (disabled jobs left as-is). Run openclaw hybrid-mem verify to confirm.`,\n );\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:ensure-cron-jobs\" });\n // non-fatal: user can run verify --fix later\n }\n let mergedConfig: Record<string, unknown> = {};\n try {\n const cfgPath = join(homedir(), \".openclaw\", \"openclaw.json\");\n if (existsSync(cfgPath)) {\n mergedConfig = JSON.parse(readFileSync(cfgPath, \"utf-8\")) as Record<string, unknown>;\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:read-config-for-skill\" });\n }\n const skillAfterUpgrade = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: mergedConfig,\n pluginRootDir: extDir,\n dryRun: false,\n });\n if (skillAfterUpgrade.error) {\n logger?.warn?.(`memory-hybrid: could not refresh workspace skill: ${skillAfterUpgrade.error}`);\n } else {\n logger?.info?.(`memory-hybrid: workspace skill updated at ${skillAfterUpgrade.path}`);\n }\n const toolsAfterUpgrade = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: mergedConfig,\n pluginRootDir: extDir,\n dryRun: false,\n });\n if (toolsAfterUpgrade.error) {\n logger?.warn?.(`memory-hybrid: could not refresh TOOLS.md block: ${toolsAfterUpgrade.error}`);\n } else if (toolsAfterUpgrade.updated) {\n logger?.info?.(`memory-hybrid: TOOLS.md hybrid block updated at ${toolsAfterUpgrade.path}`);\n }\n return {\n ok: true,\n version: installedVersion,\n pluginDir: extDir,\n workspaceSkillPath: skillAfterUpgrade.path,\n workspaceSkillError: skillAfterUpgrade.error,\n workspaceToolsMdPath: toolsAfterUpgrade.path,\n workspaceToolsMdError: toolsAfterUpgrade.error,\n workspaceToolsMdUpdated: toolsAfterUpgrade.updated,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run-install.js","names":[],"sources":["../../../cli/install/run-install.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, join } from \"node:path\";\n\nimport { getEnv } from \"../../utils/env-manager.js\";\nimport { findPluginRoot } from \"../../utils/plugin-root.js\";\n\nimport { type CronModelConfig, getCronModelConfig } from \"../../config.js\";\nimport { parseDigestWeeklyDeliveryOnly } from \"../../config/parsers/features.js\";\nimport { capturePluginError } from \"../../services/error-reporter.js\";\nimport { ensureWorkspaceBootstrap } from \"../../setup/workspace-bootstrap.js\";\nimport { PLUGIN_ID } from \"../../utils/constants.js\";\nimport type { HandlerContext } from \"../handlers.js\";\nimport type { InstallCliResult, UninstallCliResult, UpgradeCliResult } from \"../types.js\";\nimport {\n buildInstallDefaults,\n deepMerge,\n getPluginEntryConfig,\n inspectExistingEmbeddingSetup,\n} from \"./config-merge.js\";\nimport { applyDetectedEmbeddingSetup, detectRecommendedEmbeddingSetup, getDashboardUrl } from \"./embedding-detect.js\";\nimport { ensureMaintenanceCronJobs } from \"./cron-jobs.js\";\nimport {\n applyHybridMemoryToolsMd,\n assertSafeRequestedVersionArg,\n installHybridMemoryWorkspaceSkill,\n isPathInsideDir,\n npxExecutable,\n PLUGIN_JOB_ID_PREFIX,\n resolveAgentWorkspaceRoot,\n} from \"./workspace.js\";\n\nexport function runInstallForCli(opts: { dryRun: boolean }): InstallCliResult {\n const openclawDir = join(homedir(), \".openclaw\");\n const configPath = join(openclawDir, \"openclaw.json\");\n const fullDefaults = buildInstallDefaults();\n const pluginRootDir = findPluginRoot(import.meta.url);\n\n let config: Record<string, unknown> = {};\n if (existsSync(configPath)) {\n try {\n config = JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>;\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runInstallForCli:read-config\" });\n return { ok: false, error: `Could not read ${configPath}: ${e}` };\n }\n }\n const existingEmbedding = inspectExistingEmbeddingSetup(config);\n const detectedEmbedding = detectRecommendedEmbeddingSetup(config, pluginRootDir);\n const existingApiKey =\n (config?.plugins as Record<string, unknown>)?.entries &&\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)?.[PLUGIN_ID] &&\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n )?.config &&\n (\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n ).config as Record<string, unknown>\n )?.embedding &&\n (\n (\n (\n ((config.plugins as Record<string, unknown>).entries as Record<string, unknown>)[PLUGIN_ID] as Record<\n string,\n unknown\n >\n ).config as Record<string, unknown>\n ).embedding as Record<string, unknown>\n )?.apiKey;\n const isRealKey =\n typeof existingApiKey === \"string\" &&\n existingApiKey.length >= 10 &&\n existingApiKey !== \"YOUR_OPENAI_API_KEY\" &&\n existingApiKey !== \"<OPENAI_API_KEY>\";\n\n if (!config.plugins || typeof config.plugins !== \"object\") config.plugins = {};\n if (!(config.agents && typeof config.agents === \"object\")) config.agents = { defaults: {} };\n deepMerge(config, fullDefaults as unknown as Record<string, unknown>);\n if (isRealKey) {\n const entries = (config.plugins as Record<string, unknown>).entries as Record<string, unknown>;\n const mh = entries[PLUGIN_ID] as Record<string, unknown>;\n const cfg = mh?.config as Record<string, unknown>;\n const emb = cfg?.embedding as Record<string, unknown>;\n if (emb) emb.apiKey = existingApiKey;\n }\n const embeddingPatch = applyDetectedEmbeddingSetup(config, detectedEmbedding, existingEmbedding);\n const after = JSON.stringify(config, null, 2);\n const workspaceRoot = resolveAgentWorkspaceRoot(config);\n const dashboardUrl = getDashboardUrl(config);\n\n if (opts.dryRun) {\n const skillPreview = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: true,\n });\n const toolsPreview = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: true,\n });\n let bootstrapPreview = { workspaceRoot, directories: [], files: [] } as ReturnType<typeof ensureWorkspaceBootstrap>;\n let bootstrapPreviewError: string | undefined;\n try {\n bootstrapPreview = ensureWorkspaceBootstrap({ workspaceRoot, dryRun: true });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:workspace-bootstrap:dry-run\" });\n bootstrapPreview = { workspaceRoot, directories: [], files: [] };\n bootstrapPreviewError = String(err);\n }\n const previewDone: string[] = [\n \"Would write or repair the hybrid-memory plugin config block.\",\n \"Would refresh the workspace skill.\",\n \"Would refresh the managed TOOLS.md section.\",\n `Would ensure workspace starter layout under ${workspaceRoot}.`,\n `Would point you to Mission Control at ${dashboardUrl}.`,\n ];\n if (embeddingPatch.changed) {\n previewDone.push(\n `Would prefill embedding defaults with ${detectedEmbedding.provider}/${detectedEmbedding.model} (${detectedEmbedding.source}).`,\n );\n }\n if (bootstrapPreviewError) {\n previewDone.push(`Workspace bootstrap check would warn: ${bootstrapPreviewError}`);\n }\n const previewRemaining: string[] = [];\n if (detectedEmbedding.provider === \"openai\" && !detectedEmbedding.envKey && !existingEmbedding.hasUsableApiKey) {\n previewRemaining.push(\"Add an OpenAI-compatible embedding API key, then restart the gateway.\");\n } else if (detectedEmbedding.provider === \"google\" && !existingEmbedding.hasUsableApiKey) {\n previewRemaining.push(\n \"Add llm.providers.google.apiKey (or export GOOGLE_API_KEY / GEMINI_API_KEY), then restart.\",\n );\n } else if (detectedEmbedding.provider === \"ollama\") {\n previewRemaining.push(\"Make sure Ollama is running locally before verify.\");\n }\n previewRemaining.push(\"Restart the gateway after applying the config.\");\n previewRemaining.push(\"Run `openclaw hybrid-mem verify` to confirm the install.\");\n return {\n ok: true,\n configPath,\n dryRun: true,\n written: false,\n configJson: after,\n pluginId: PLUGIN_ID,\n workspaceSkillPath: skillPreview.path,\n workspaceSkillError: skillPreview.error,\n workspaceToolsMdPath: toolsPreview.path,\n workspaceToolsMdError: toolsPreview.error,\n workspaceToolsMdUpdated: toolsPreview.updated,\n workspaceRoot,\n dashboardUrl,\n detectedEmbedding,\n bootstrapDirectoriesCreated: bootstrapPreview.directories.filter((entry) => entry.created).length,\n bootstrapFilesCreated: bootstrapPreview.files.filter((entry) => entry.created).length,\n completed: previewDone,\n remaining: previewRemaining,\n };\n }\n\n try {\n mkdirSync(openclawDir, { recursive: true });\n mkdirSync(join(openclawDir, \"memory\"), { recursive: true });\n writeFileSync(configPath, after, \"utf-8\");\n const skillInstall = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: false,\n });\n const toolsMdInstall = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: config,\n pluginRootDir,\n dryRun: false,\n });\n let bootstrapInstall = { workspaceRoot, directories: [], files: [] } as ReturnType<typeof ensureWorkspaceBootstrap>;\n let bootstrapInstallError: string | undefined;\n try {\n bootstrapInstall = ensureWorkspaceBootstrap({ workspaceRoot, dryRun: false });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:workspace-bootstrap\" });\n bootstrapInstallError = String(err);\n // non-fatal: workspace bootstrap should not fail a successful config install\n }\n let cronSummary: { added: string[]; normalized: string[] } | undefined;\n try {\n const pluginCfg = getPluginEntryConfig(config);\n const pluginConfig = pluginCfg as CronModelConfig | undefined;\n const dreamCycleRaw = pluginCfg?.nightlyCycle as Record<string, unknown> | undefined;\n const dreamCycleSchedule =\n typeof dreamCycleRaw?.schedule === \"string\" && (dreamCycleRaw.schedule as string).trim().length > 0\n ? (dreamCycleRaw.schedule as string).trim()\n : undefined;\n const sensorSweepRaw = pluginCfg?.sensorSweep as Record<string, unknown> | undefined;\n const sensorSweepSchedule =\n typeof sensorSweepRaw?.schedule === \"string\" && (sensorSweepRaw.schedule as string).trim().length > 0\n ? (sensorSweepRaw.schedule as string).trim()\n : undefined;\n const installScheduleOverrides: Record<string, string> = {};\n if (dreamCycleSchedule)\n installScheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}nightly-dream-cycle`] = dreamCycleSchedule;\n if (sensorSweepSchedule) installScheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}sensor-sweep`] = sensorSweepSchedule;\n cronSummary = ensureMaintenanceCronJobs(openclawDir, pluginConfig, {\n normalizeExisting: false,\n reEnableDisabled: false,\n scheduleOverrides: Object.keys(installScheduleOverrides).length > 0 ? installScheduleOverrides : undefined,\n featureGates: {\n \"sensorSweep.enabled\": (sensorSweepRaw?.enabled as boolean | undefined) === true,\n \"nightlyCycle.enabled\": (dreamCycleRaw?.enabled as boolean | undefined) === true,\n },\n digestWeeklyDelivery: parseDigestWeeklyDeliveryOnly(getPluginEntryConfig(config) ?? {}),\n });\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:cron-setup\" });\n // non-fatal: cron jobs optional on install\n }\n const completed: string[] = [\n `Wrote hybrid-memory config to ${configPath}.`,\n `Installed workspace skill at ${skillInstall.path}${skillInstall.error ? ` (warning: ${skillInstall.error})` : \"\"}.`,\n `Checked TOOLS.md managed block at ${toolsMdInstall.path}${toolsMdInstall.updated ? \" (updated)\" : \" (already current)\"}.`,\n bootstrapInstallError\n ? `Workspace starter layout warning in ${workspaceRoot}: ${bootstrapInstallError}.`\n : `Ensured workspace starter layout in ${workspaceRoot} (${bootstrapInstall.directories.filter((entry) => entry.created).length} dirs, ${bootstrapInstall.files.filter((entry) => entry.created).length} files created).`,\n `Dashboard home: ${dashboardUrl}`,\n ];\n if (embeddingPatch.changed) {\n completed.push(\n `Prefilled embedding defaults with ${detectedEmbedding.provider}/${detectedEmbedding.model} (${detectedEmbedding.source}).`,\n );\n } else {\n completed.push(`Kept existing embedding setup (${detectedEmbedding.provider}/${detectedEmbedding.model}).`);\n }\n if (cronSummary) {\n completed.push(\n cronSummary.added.length > 0\n ? `Ensured maintenance cron jobs (${cronSummary.added.length} added).`\n : \"Checked maintenance cron jobs.\",\n );\n }\n for (const note of embeddingPatch.notes) completed.push(note);\n const remaining: string[] = [];\n if (detectedEmbedding.provider === \"openai\" && !existingEmbedding.hasUsableApiKey && !detectedEmbedding.envKey) {\n remaining.push('Set plugins.entries[\"openclaw-hybrid-memory\"].config.embedding.apiKey to a real key.');\n }\n if (detectedEmbedding.provider === \"google\" && !existingEmbedding.hasUsableApiKey) {\n remaining.push(\"Set llm.providers.google.apiKey (or export GOOGLE_API_KEY / GEMINI_API_KEY).\");\n }\n if (detectedEmbedding.provider === \"ollama\") {\n remaining.push(\"Keep Ollama running locally before using semantic recall.\");\n }\n remaining.push(\"Restart the gateway so the new config and workspace files are picked up.\");\n remaining.push(\"Run `openclaw hybrid-mem verify` for the beginner-friendly health check.\");\n return {\n ok: true,\n configPath,\n dryRun: false,\n written: true,\n pluginId: PLUGIN_ID,\n workspaceSkillPath: skillInstall.path,\n workspaceSkillError: skillInstall.error,\n workspaceToolsMdPath: toolsMdInstall.path,\n workspaceToolsMdError: toolsMdInstall.error,\n workspaceToolsMdUpdated: toolsMdInstall.updated,\n workspaceRoot,\n dashboardUrl,\n detectedEmbedding,\n bootstrapDirectoriesCreated: bootstrapInstall.directories.filter((entry) => entry.created).length,\n bootstrapFilesCreated: bootstrapInstall.files.filter((entry) => entry.created).length,\n completed,\n remaining,\n };\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runInstallForCli:write-config\" });\n return { ok: false, error: `Could not write config: ${err}` };\n }\n}\n\nexport function runUninstallForCli(\n ctx: HandlerContext,\n opts: { cleanAll: boolean; leaveConfig: boolean },\n): UninstallCliResult {\n const { resolvedSqlitePath, resolvedLancePath } = ctx;\n const openclawDir = join(homedir(), \".openclaw\");\n const openclawMemoryDir = join(openclawDir, \"memory\");\n const dangerousUninstallEnabled = getEnv(\"OPENCLAW_HYBRID_MEM_UNINSTALL_DANGEROUS\") === \"1\";\n const configPath = join(openclawDir, \"openclaw.json\");\n const cleaned: string[] = [];\n let outcome: UninstallCliResult[\"outcome\"];\n let error = \"\";\n\n if (!opts.leaveConfig && existsSync(configPath)) {\n try {\n const raw = readFileSync(configPath, \"utf-8\");\n const config = JSON.parse(raw) as Record<string, unknown>;\n if (!config.plugins || typeof config.plugins !== \"object\") config.plugins = {};\n const plugins = config.plugins as Record<string, unknown>;\n if (!plugins.slots || typeof plugins.slots !== \"object\") plugins.slots = {};\n (plugins.slots as Record<string, string>).memory = \"memory-core\";\n if (!plugins.entries || typeof plugins.entries !== \"object\") plugins.entries = {};\n const entries = plugins.entries as Record<string, unknown>;\n if (!entries[PLUGIN_ID] || typeof entries[PLUGIN_ID] !== \"object\") entries[PLUGIN_ID] = {};\n (entries[PLUGIN_ID] as Record<string, boolean>).enabled = false;\n writeFileSync(configPath, JSON.stringify(config, null, 2), \"utf-8\");\n outcome = \"config_updated\";\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:update-config\" });\n outcome = \"config_error\";\n error = String(e);\n }\n } else if (!opts.leaveConfig) {\n outcome = \"config_not_found\";\n } else {\n outcome = \"leave_config\";\n }\n\n if (opts.cleanAll) {\n if (\n existsSync(resolvedSqlitePath) &&\n (dangerousUninstallEnabled || isPathInsideDir(openclawMemoryDir, resolvedSqlitePath))\n ) {\n try {\n rmSync(resolvedSqlitePath, { force: true });\n cleaned.push(resolvedSqlitePath);\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:remove-sqlite\" });\n }\n }\n if (\n existsSync(resolvedLancePath) &&\n (dangerousUninstallEnabled || isPathInsideDir(openclawMemoryDir, resolvedLancePath))\n ) {\n try {\n rmSync(resolvedLancePath, { recursive: true, force: true });\n cleaned.push(resolvedLancePath);\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUninstallForCli:remove-lance\" });\n }\n }\n }\n\n const base = { pluginId: PLUGIN_ID, cleaned };\n if (outcome === \"config_error\") return { ...base, outcome, error };\n return { ...base, outcome } as UninstallCliResult;\n}\n\nexport async function runUpgradeForCli(ctx: HandlerContext, requestedVersion?: string): Promise<UpgradeCliResult> {\n const { cfg, logger } = ctx;\n const extDir = findPluginRoot(import.meta.url);\n const { spawnSync } = await import(\"node:child_process\");\n const version = requestedVersion?.trim() || \"latest\";\n try {\n assertSafeRequestedVersionArg(version);\n } catch (e) {\n return { ok: false, error: `Invalid requested version: ${e instanceof Error ? e.message : String(e)}` };\n }\n\n const manifestPath = join(extDir, \"openclaw.plugin.json\");\n const pkgPath = join(extDir, \"package.json\");\n if (!existsSync(manifestPath) || !existsSync(pkgPath)) {\n return { ok: false, error: `Refusing to upgrade: plugin directory does not look valid: ${extDir}` };\n }\n\n const backupDir = join(dirname(extDir), `${basename(extDir)}.bak-${Date.now()}`);\n try {\n renameSync(extDir, backupDir);\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:move-dir\" });\n return {\n ok: false,\n error: `Could not move plugin directory for upgrade: ${e}. Use standalone installer: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n // Use standalone installer so upgrade works even when config is invalid (plugin missing).\n const npxArgs = [\"-y\", \"openclaw-hybrid-memory-install\", version];\n const r = spawnSync(npxExecutable(), npxArgs, {\n stdio: \"inherit\",\n cwd: homedir(),\n shell: false,\n });\n if (r.status !== 0) {\n // Best-effort rollback: restore original plugin directory.\n try {\n if (existsSync(extDir)) {\n // Installer might have created a partial directory; avoid clobbering it.\n const failedDir = join(dirname(extDir), `${basename(extDir)}.failed-${Date.now()}`);\n try {\n renameSync(extDir, failedDir);\n } catch {\n rmSync(extDir, { recursive: true, force: true });\n }\n }\n renameSync(backupDir, extDir);\n } catch (e) {\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:rollback\" });\n return {\n ok: false,\n error: `Install failed (exit ${r.status}). Rollback also failed: ${e}. Run manually: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n return {\n ok: false,\n error: `Install failed (exit ${r.status}). Run manually: npx -y openclaw-hybrid-memory-install ${version}`,\n };\n }\n try {\n rmSync(backupDir, { recursive: true, force: true });\n } catch (e) {\n // Non-fatal; backup cleanup failure shouldn't block upgrade.\n capturePluginError(e as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:cleanup-backup\" });\n }\n let installedVersion = version;\n try {\n const pkgAfterPath = join(extDir, \"package.json\");\n if (existsSync(pkgAfterPath)) {\n const pkg = JSON.parse(readFileSync(pkgAfterPath, \"utf-8\")) as { version?: string };\n installedVersion = pkg.version ?? installedVersion;\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:read-version\" });\n }\n // Ensure maintenance cron jobs exist (add missing, normalize existing; never re-enable disabled)\n try {\n const openclawDir = join(homedir(), \".openclaw\");\n const pluginConfig = getCronModelConfig(cfg);\n const scheduleOverrides: Record<string, string> = {};\n if (typeof cfg.nightlyCycle?.schedule === \"string\" && cfg.nightlyCycle.schedule.trim().length > 0) {\n scheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}nightly-dream-cycle`] = cfg.nightlyCycle.schedule;\n }\n if (typeof cfg.sensorSweep?.schedule === \"string\" && cfg.sensorSweep.schedule.trim().length > 0) {\n scheduleOverrides[`${PLUGIN_JOB_ID_PREFIX}sensor-sweep`] = cfg.sensorSweep.schedule;\n }\n const { added, normalized } = ensureMaintenanceCronJobs(openclawDir, pluginConfig, {\n normalizeExisting: true,\n reEnableDisabled: false,\n scheduleOverrides: Object.keys(scheduleOverrides).length > 0 ? scheduleOverrides : undefined,\n featureGates: {\n \"sensorSweep.enabled\": cfg.sensorSweep?.enabled === true,\n \"nightlyCycle.enabled\": cfg.nightlyCycle?.enabled === true,\n },\n digestWeeklyDelivery: cfg.digest.weekly.delivery,\n });\n if (added.length > 0 || normalized.length > 0) {\n logger?.info?.(\n `memory-hybrid: upgrade — cron jobs: ${added.length} added, ${normalized.length} normalized (disabled jobs left as-is). Run openclaw hybrid-mem verify to confirm.`,\n );\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:ensure-cron-jobs\" });\n // non-fatal: user can run verify --fix later\n }\n let mergedConfig: Record<string, unknown> = {};\n try {\n const cfgPath = join(homedir(), \".openclaw\", \"openclaw.json\");\n if (existsSync(cfgPath)) {\n mergedConfig = JSON.parse(readFileSync(cfgPath, \"utf-8\")) as Record<string, unknown>;\n }\n } catch (err) {\n capturePluginError(err as Error, { subsystem: \"cli\", operation: \"runUpgradeForCli:read-config-for-skill\" });\n }\n const skillAfterUpgrade = installHybridMemoryWorkspaceSkill({\n mergedOpenclawConfig: mergedConfig,\n pluginRootDir: extDir,\n dryRun: false,\n });\n if (skillAfterUpgrade.error) {\n logger?.warn?.(`memory-hybrid: could not refresh workspace skill: ${skillAfterUpgrade.error}`);\n } else {\n logger?.info?.(`memory-hybrid: workspace skill updated at ${skillAfterUpgrade.path}`);\n }\n const toolsAfterUpgrade = applyHybridMemoryToolsMd({\n mergedOpenclawConfig: mergedConfig,\n pluginRootDir: extDir,\n dryRun: false,\n });\n if (toolsAfterUpgrade.error) {\n logger?.warn?.(`memory-hybrid: could not refresh TOOLS.md block: ${toolsAfterUpgrade.error}`);\n } else if (toolsAfterUpgrade.updated) {\n logger?.info?.(`memory-hybrid: TOOLS.md hybrid block updated at ${toolsAfterUpgrade.path}`);\n }\n return {\n ok: true,\n version: installedVersion,\n pluginDir: extDir,\n workspaceSkillPath: skillAfterUpgrade.path,\n workspaceSkillError: skillAfterUpgrade.error,\n workspaceToolsMdPath: toolsAfterUpgrade.path,\n workspaceToolsMdError: toolsAfterUpgrade.error,\n workspaceToolsMdUpdated: toolsAfterUpgrade.updated,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.js","names":["pathResolve"],"sources":["../../../cli/install/workspace.ts"],"sourcesContent":["/**\n * CLI Install/Uninstall/Upgrade Command Handlers\n *\n * Contains all install-related functions extracted from handlers.ts:\n * - buildPreFilterConfig\n * - Cron constants and helpers (PLUGIN_JOB_ID_PREFIX, MIN_INTERVAL_MS,\n * MAINTENANCE_CRON_JOBS, LEGACY_JOB_MATCHERS, resolveCronJob,\n * ensureMaintenanceCronJobs, createProgressReporter)\n * - deepMerge\n * - runResetAuthBackoffForCli\n * - runInstallForCli\n * - runUninstallForCli\n * - runUpgradeForCli\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, resolve as pathResolve, relative } from \"node:path\";\n\nimport { getEnv } from \"../../utils/env-manager.js\";\nimport { expandTilde } from \"../../utils/path.js\";\n\nimport type { HybridMemoryConfig } from \"../../config.js\";\nimport { compileHeartbeatMatchers } from \"../../services/goal-stewardship-heartbeat.js\";\nimport type { PreFilterConfig } from \"../../services/session-pre-filter.js\";\n\n/** Subfolder under workspace `skills/` — OpenClaw loads this with highest precedence vs shared/bundled skills. */\nconst HYBRID_MEMORY_SKILL_DIR = \"hybrid-memory\";\n\n/** Returns a unique sibling temp-dir path under `skillsDir` for atomic rename into `destDir`. */\nfunction skillTmpDir(skillsDir: string): string {\n return join(skillsDir, `.${HYBRID_MEMORY_SKILL_DIR}-tmp-${randomBytes(6).toString(\"hex\")}`);\n}\n\nfunction resolvedPathOrFallback(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return pathResolve(path);\n }\n}\n\nexport function isPathInsideDir(rootDirAbs: string, candidatePath: string): boolean {\n const rootResolved = resolvedPathOrFallback(rootDirAbs);\n const candidateAbs = isAbsolute(candidatePath) ? candidatePath : pathResolve(candidatePath);\n const candidateResolved = resolvedPathOrFallback(candidateAbs);\n const rel = relative(rootResolved, candidateResolved);\n if (rel === \"\") return true;\n return !rel.startsWith(\"..\") && !isAbsolute(rel);\n}\n\nfunction hasNoWhitespace(s: string): boolean {\n return !/[\\s\\r\\n\\t]/.test(s);\n}\n\nexport function npxExecutable(): string {\n if (process.platform !== \"win32\") return \"npx\";\n const candidate = join(dirname(process.execPath), \"npx.cmd\");\n return existsSync(candidate) ? candidate : \"npx.cmd\";\n}\n\nexport function assertSafeRequestedVersionArg(version: string): void {\n const v = version.trim();\n if (!v) throw new Error(\"Upgrade version is empty\");\n if (!hasNoWhitespace(v)) throw new Error(\"Upgrade version contains whitespace\");\n if (v.startsWith(\"-\")) throw new Error(\"Upgrade version must not start with '-'\");\n}\n\n/** Reject empty paths and the literal strings \"undefined\"/\"null\" (common when env vars are set incorrectly). */\nfunction isUsableWorkspacePath(p: string): boolean {\n const t = p.trim();\n if (t.length === 0) return false;\n const lower = t.toLowerCase();\n if (lower === \"undefined\" || lower === \"null\") return false;\n return true;\n}\n\n/**\n * Resolve the agent workspace root (where `skills/`, `memory/`, MEMORY.md, etc. live).\n * Order: `OPENCLAW_WORKSPACE` (if valid), `agents.defaults.workspace`, `agent.workspace` (OpenClaw [agent workspace](https://docs.openclaw.ai/concepts/agent-workspace) shape), else `~/.openclaw/workspace`.\n */\nexport function resolveAgentWorkspaceRoot(config: Record<string, unknown>): string {\n const env = process.env.OPENCLAW_WORKSPACE?.trim();\n if (env && isUsableWorkspacePath(env)) return expandTilde(env);\n const agents = config.agents as Record<string, unknown> | undefined;\n const defaults = agents?.defaults as Record<string, unknown> | undefined;\n const ws = defaults?.workspace;\n if (typeof ws === \"string\" && isUsableWorkspacePath(ws)) return expandTilde(ws.trim());\n const agentBlock = config.agent as Record<string, unknown> | undefined;\n const legacyWs = agentBlock?.workspace;\n if (typeof legacyWs === \"string\" && isUsableWorkspacePath(legacyWs)) return expandTilde(legacyWs.trim());\n return join(homedir(), \".openclaw\", \"workspace\");\n}\n\nfunction bundledHybridMemorySkillDir(pluginRootDir: string): string {\n return join(pluginRootDir, \"skills\", HYBRID_MEMORY_SKILL_DIR);\n}\n\nfunction bundledHybridMemorySkillPath(pluginRootDir: string): string {\n return join(bundledHybridMemorySkillDir(pluginRootDir), \"SKILL.md\");\n}\n\n/** @internal Exported for tests — copies bundled `skills/hybrid-memory/` (SKILL.md + references/) into the workspace. */\nexport function installHybridMemoryWorkspaceSkill(opts: {\n mergedOpenclawConfig: Record<string, unknown>;\n pluginRootDir: string;\n dryRun: boolean;\n}): { path: string; error?: string } {\n const srcDir = bundledHybridMemorySkillDir(opts.pluginRootDir);\n const skillMd = bundledHybridMemorySkillPath(opts.pluginRootDir);\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const dest = join(workspaceRoot, \"skills\", HYBRID_MEMORY_SKILL_DIR, \"SKILL.md\");\n if (!existsSync(skillMd)) {\n return { path: dest, error: `Bundled skill missing at ${skillMd}` };\n }\n if (opts.dryRun) {\n return { path: dest };\n }\n try {\n const skillsDir = join(workspaceRoot, \"skills\");\n mkdirSync(skillsDir, { recursive: true });\n const destDir = join(skillsDir, HYBRID_MEMORY_SKILL_DIR);\n const tmpDir = skillTmpDir(skillsDir);\n let destRemoved = false;\n try {\n cpSync(srcDir, tmpDir, { recursive: true });\n if (existsSync(destDir)) {\n rmSync(destDir, { recursive: true, force: true });\n destRemoved = true;\n }\n renameSync(tmpDir, destDir);\n } catch (copyErr) {\n // Only clean up tmpDir if destDir wasn't removed — otherwise tmpDir is the only remaining copy\n if (!destRemoved) {\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n /* ignore temp-cleanup failure */\n }\n }\n throw copyErr;\n }\n return { path: dest };\n } catch (err) {\n return { path: dest, error: String(err) };\n }\n}\n\n/**\n * Path to merged OpenClaw config JSON for workspace resolution and skill bootstrap.\n * Order: `OPENCLAW_CONFIG`, `OPENCLAW_CONFIG_PATH`, then `{OPENCLAW_HOME}/openclaw.json`, else `~/.openclaw/openclaw.json`.\n */\nexport function resolveOpenclawJsonPathForWorkspace(): string {\n const explicit = getEnv(\"OPENCLAW_CONFIG\")?.trim() || getEnv(\"OPENCLAW_CONFIG_PATH\")?.trim();\n if (explicit) return expandTilde(explicit);\n const owHome = getEnv(\"OPENCLAW_HOME\")?.trim();\n if (owHome) return join(expandTilde(owHome), \"openclaw.json\");\n return join(homedir(), \".openclaw\", \"openclaw.json\");\n}\n\n/**\n * Load `openclaw.json` for workspace resolution (`agents.defaults.workspace`, etc.).\n * Returns `{}` if the file is missing or unreadable (caller still gets `OPENCLAW_WORKSPACE` via env in {@link resolveAgentWorkspaceRoot}).\n */\nexport function loadOpenclawRootForWorkspace(): Record<string, unknown> {\n const configPath = resolveOpenclawJsonPathForWorkspace();\n try {\n if (!existsSync(configPath)) return {};\n return JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Copy bundled `skills/hybrid-memory/` into the workspace **only when** `{workspace}/skills/hybrid-memory/SKILL.md`\n * is missing — so the skill appears without a manual `hybrid-mem install`, without overwriting operator edits on every restart.\n * Full overwrite (including references) remains the job of `installHybridMemoryWorkspaceSkill` from **`hybrid-mem install`**.\n */\nexport function ensureHybridMemoryWorkspaceSkillIfMissing(opts: {\n pluginRootDir: string;\n mergedOpenclawConfig: Record<string, unknown>;\n}): {\n path: string;\n deployed: boolean;\n skippedReason?: \"already_exists\" | \"bundled_missing\" | string;\n} {\n const skillMd = bundledHybridMemorySkillPath(opts.pluginRootDir);\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const destDir = join(workspaceRoot, \"skills\", HYBRID_MEMORY_SKILL_DIR);\n const dest = join(destDir, \"SKILL.md\");\n if (!existsSync(skillMd)) {\n return { path: dest, deployed: false, skippedReason: \"bundled_missing\" };\n }\n if (existsSync(dest)) {\n return { path: dest, deployed: false, skippedReason: \"already_exists\" };\n }\n // Avoid clobbering a partial or hand-edited tree when SKILL.md alone is missing.\n if (existsSync(destDir)) {\n return { path: dest, deployed: false, skippedReason: \"destination_dir_exists\" };\n }\n try {\n const skillsDir = join(workspaceRoot, \"skills\");\n mkdirSync(skillsDir, { recursive: true });\n const srcDir = bundledHybridMemorySkillDir(opts.pluginRootDir);\n const tmpDir = skillTmpDir(skillsDir);\n try {\n cpSync(srcDir, tmpDir, { recursive: true });\n renameSync(tmpDir, destDir);\n } catch (copyErr) {\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n /* ignore temp-cleanup failure */\n }\n throw copyErr;\n }\n return { path: dest, deployed: true };\n } catch (err) {\n return { path: dest, deployed: false, skippedReason: String(err) };\n }\n}\n\nconst TOOLS_MD_MANAGED_BEGIN = \"<!-- openclaw-hybrid-memory:managed-begin -->\";\nconst TOOLS_MD_MANAGED_END = \"<!-- openclaw-hybrid-memory:managed-end -->\";\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction getToolsMdManagedBlockRe(): RegExp {\n return new RegExp(`${escapeRegExp(TOOLS_MD_MANAGED_BEGIN)}[\\\\s\\\\S]*?${escapeRegExp(TOOLS_MD_MANAGED_END)}`);\n}\n\n/** True if applying the managed block would modify `existing` (append, replace, or replace with different body). */\nfunction toolsMdManagedBlockWouldChange(existing: string, newBlock: string): boolean {\n const re = getToolsMdManagedBlockRe();\n if (!re.test(existing)) return true;\n return existing.replace(re, newBlock) !== existing;\n}\n\nfunction buildHybridMemoryToolsMdManagedBlock(innerBody: string): string {\n const inner = innerBody.trimEnd();\n return [\n TOOLS_MD_MANAGED_BEGIN,\n \"\",\n \"## Hybrid memory (`openclaw-hybrid-memory`)\",\n \"\",\n \"_This section is refreshed by `openclaw hybrid-mem install` / `upgrade`. Add your own tool notes elsewhere in this file._\",\n \"\",\n inner,\n \"\",\n TOOLS_MD_MANAGED_END,\n ].join(\"\\n\");\n}\n\n/** @internal Merges or refreshes the managed Hybrid memory block in workspace `TOOLS.md`. */\nexport function applyHybridMemoryToolsMd(opts: {\n mergedOpenclawConfig: Record<string, unknown>;\n pluginRootDir: string;\n dryRun: boolean;\n}): { path: string; error?: string; updated: boolean } {\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const toolsPath = join(workspaceRoot, \"TOOLS.md\");\n const snippetPath = join(opts.pluginRootDir, \"workspace-snippets\", \"TOOLS-hybrid-memory-body.md\");\n if (!existsSync(snippetPath)) {\n return { path: toolsPath, error: `Bundled TOOLS snippet missing at ${snippetPath}`, updated: false };\n }\n let innerBody: string;\n try {\n innerBody = readFileSync(snippetPath, \"utf-8\");\n } catch (err) {\n return { path: toolsPath, error: String(err), updated: false };\n }\n const block = buildHybridMemoryToolsMdManagedBlock(innerBody);\n if (opts.dryRun) {\n let wouldChange = !existsSync(toolsPath);\n if (!wouldChange && existsSync(toolsPath)) {\n try {\n const cur = readFileSync(toolsPath, \"utf-8\");\n wouldChange = !cur.includes(TOOLS_MD_MANAGED_BEGIN) || toolsMdManagedBlockWouldChange(cur, block);\n } catch {\n wouldChange = true;\n }\n }\n return { path: toolsPath, updated: wouldChange };\n }\n const managedRe = getToolsMdManagedBlockRe();\n try {\n mkdirSync(workspaceRoot, { recursive: true });\n if (!existsSync(toolsPath)) {\n writeFileSync(toolsPath, `# TOOLS\\n\\n${block}\\n`, \"utf-8\");\n return { path: toolsPath, updated: true };\n }\n const existing = readFileSync(toolsPath, \"utf-8\");\n if (managedRe.test(existing)) {\n const next = existing.replace(managedRe, block);\n if (next !== existing) {\n writeFileSync(toolsPath, next, \"utf-8\");\n return { path: toolsPath, updated: true };\n }\n return { path: toolsPath, updated: false };\n }\n writeFileSync(toolsPath, `${existing.trimEnd()}\\n\\n${block}\\n`, \"utf-8\");\n return { path: toolsPath, updated: true };\n } catch (err) {\n return { path: toolsPath, error: String(err), updated: false };\n }\n}\n\n/**\n * Build a PreFilterConfig from the plugin config.\n * Resolves the Ollama endpoint from extraction.preFilter.endpoint,\n * then llm.providers.ollama.baseURL, then the default localhost URL.\n */\nexport function buildPreFilterConfig(cfg: HybridMemoryConfig): PreFilterConfig {\n const pf = cfg.extraction?.preFilter;\n const ollamaEndpoint = pf?.endpoint ?? cfg.llm?.providers?.ollama?.baseURL ?? \"http://localhost:11434\";\n return {\n enabled: pf?.enabled === true,\n model: pf?.model ?? \"qwen3:8b\",\n endpoint: ollamaEndpoint,\n maxCharsPerSession: pf?.maxCharsPerSession ?? 2000,\n };\n}\n// Re-export preFilterSessions so callers in other handler modules can import from here.\n\n// Shared cron job definitions used by install and verify --fix.\n// Canonical schedule per #86 (7 jobs, non-overlapping). Model is resolved dynamically from user config via getLLMModelPreference.\n// modelTier: \"default\" = standard LLM, \"heavy\" = larger context; resolved via getDefaultCronModel at install/verify time.\n// Order: daily 02:00 → daily 02:30 → Sun 03:00 → Sun 04:00 → Sat 04:00 → Sun 10:00 → 1st 05:00.\nexport const PLUGIN_JOB_ID_PREFIX = \"hybrid-mem:\";\nexport const GOAL_STEWARDSHIP_HEARTBEAT_JOB_ID = \"goal-stewardship-heartbeat\";\nexport const GOAL_STEWARDSHIP_HEARTBEAT_CRON_EXPR = \"*/30 * * * *\";\n\nfunction extractPlainHeartbeatPatternHints(patterns: string[]): string[] {\n const out: string[] = [];\n for (const rawPattern of patterns) {\n const raw = rawPattern.trim();\n if (!raw) continue;\n let hint: string | null = null;\n if (raw.startsWith(\"/\") && raw.lastIndexOf(\"/\") > 0) {\n const last = raw.lastIndexOf(\"/\");\n const body = raw.slice(1, last).trim().replace(/^\\^/, \"\").replace(/\\$$/, \"\").trim();\n if (/^[\\w -]+$/.test(body)) hint = body;\n } else if (/^[\\w -]+$/.test(raw)) {\n hint = raw;\n }\n if (!hint) continue;\n const normalized = hint.replace(/\\s+/g, \" \").trim();\n if (!normalized) continue;\n if (!out.includes(normalized)) out.push(normalized);\n }\n return out;\n}\n\nexport function selectGoalStewardshipHeartbeatMessage(heartbeatPatterns: string[]): string | null {\n const matchers = compileHeartbeatMatchers(heartbeatPatterns);\n const candidates = [\"cron heartbeat\"];\n for (const hint of extractPlainHeartbeatPatternHints(heartbeatPatterns)) {\n const candidate = `cron heartbeat ${hint}`.replace(/\\s+/g, \" \").trim();\n if (!candidates.includes(candidate)) candidates.push(candidate);\n if (!candidates.includes(hint)) candidates.push(hint);\n }\n return candidates.find((candidate) => matchers.some((re) => re.test(candidate))) ?? null;\n}\n\nfunction collectHeartbeatMessageCandidatesFromJob(job: Record<string, unknown>): string[] {\n const out: string[] = [];\n const payload =\n typeof job.payload === \"object\" && job.payload !== null && !Array.isArray(job.payload)\n ? (job.payload as Record<string, unknown>)\n : undefined;\n const candidates = [payload?.text, payload?.message, job.text, job.message];\n for (const raw of candidates) {\n if (typeof raw !== \"string\") continue;\n const normalized = raw.trim();\n if (!normalized || out.includes(normalized)) continue;\n out.push(normalized);\n }\n return out;\n}\n\nexport function selectExistingGoalStewardshipHeartbeatMessage(\n existing: Record<string, unknown> | undefined,\n heartbeatPatterns: string[],\n): string | null {\n if (!existing) return null;\n const matchers = compileHeartbeatMatchers(heartbeatPatterns);\n const candidates = collectHeartbeatMessageCandidatesFromJob(existing);\n return candidates.find((candidate) => matchers.some((re) => re.test(candidate))) ?? null;\n}\n\n/**\n * Ensure there is one enabled, heartbeat-shaped cron job for goal stewardship.\n * The job is intentionally simple and should be safe to run continuously.\n */\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workspace.js","names":["pathResolve"],"sources":["../../../cli/install/workspace.ts"],"sourcesContent":["/**\n * CLI Install/Uninstall/Upgrade Command Handlers\n *\n * Contains all install-related functions extracted from handlers.ts:\n * - buildPreFilterConfig\n * - Cron constants and helpers (PLUGIN_JOB_ID_PREFIX, MIN_INTERVAL_MS,\n * MAINTENANCE_CRON_JOBS, LEGACY_JOB_MATCHERS, resolveCronJob,\n * ensureMaintenanceCronJobs, createProgressReporter)\n * - deepMerge\n * - runResetAuthBackoffForCli\n * - runInstallForCli\n * - runUninstallForCli\n * - runUpgradeForCli\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { cpSync, existsSync, mkdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, resolve as pathResolve, relative } from \"node:path\";\n\nimport { getEnv } from \"../../utils/env-manager.js\";\nimport { expandTilde } from \"../../utils/path.js\";\n\nimport type { HybridMemoryConfig } from \"../../config.js\";\nimport { compileHeartbeatMatchers } from \"../../services/goal-stewardship-heartbeat.js\";\nimport type { PreFilterConfig } from \"../../services/session-pre-filter.js\";\n\n/** Subfolder under workspace `skills/` — OpenClaw loads this with highest precedence vs shared/bundled skills. */\nconst HYBRID_MEMORY_SKILL_DIR = \"hybrid-memory\";\n\n/** Returns a unique sibling temp-dir path under `skillsDir` for atomic rename into `destDir`. */\nfunction skillTmpDir(skillsDir: string): string {\n return join(skillsDir, `.${HYBRID_MEMORY_SKILL_DIR}-tmp-${randomBytes(6).toString(\"hex\")}`);\n}\n\nfunction resolvedPathOrFallback(path: string): string {\n try {\n return realpathSync(path);\n } catch {\n return pathResolve(path);\n }\n}\n\nexport function isPathInsideDir(rootDirAbs: string, candidatePath: string): boolean {\n const rootResolved = resolvedPathOrFallback(rootDirAbs);\n const candidateAbs = isAbsolute(candidatePath) ? candidatePath : pathResolve(candidatePath);\n const candidateResolved = resolvedPathOrFallback(candidateAbs);\n const rel = relative(rootResolved, candidateResolved);\n if (rel === \"\") return true;\n return !rel.startsWith(\"..\") && !isAbsolute(rel);\n}\n\nfunction hasNoWhitespace(s: string): boolean {\n return !/[\\s\\r\\n\\t]/.test(s);\n}\n\nexport function npxExecutable(): string {\n if (process.platform !== \"win32\") return \"npx\";\n const candidate = join(dirname(process.execPath), \"npx.cmd\");\n return existsSync(candidate) ? candidate : \"npx.cmd\";\n}\n\nexport function assertSafeRequestedVersionArg(version: string): void {\n const v = version.trim();\n if (!v) throw new Error(\"Upgrade version is empty\");\n if (!hasNoWhitespace(v)) throw new Error(\"Upgrade version contains whitespace\");\n if (v.startsWith(\"-\")) throw new Error(\"Upgrade version must not start with '-'\");\n}\n\n/** Reject empty paths and the literal strings \"undefined\"/\"null\" (common when env vars are set incorrectly). */\nfunction isUsableWorkspacePath(p: string): boolean {\n const t = p.trim();\n if (t.length === 0) return false;\n const lower = t.toLowerCase();\n if (lower === \"undefined\" || lower === \"null\") return false;\n return true;\n}\n\n/**\n * Resolve the agent workspace root (where `skills/`, `memory/`, MEMORY.md, etc. live).\n * Order: `OPENCLAW_WORKSPACE` (if valid), `agents.defaults.workspace`, `agent.workspace` (OpenClaw [agent workspace](https://docs.openclaw.ai/concepts/agent-workspace) shape), else `~/.openclaw/workspace`.\n */\nexport function resolveAgentWorkspaceRoot(config: Record<string, unknown>): string {\n const env = process.env.OPENCLAW_WORKSPACE?.trim();\n if (env && isUsableWorkspacePath(env)) return expandTilde(env);\n const agents = config.agents as Record<string, unknown> | undefined;\n const defaults = agents?.defaults as Record<string, unknown> | undefined;\n const ws = defaults?.workspace;\n if (typeof ws === \"string\" && isUsableWorkspacePath(ws)) return expandTilde(ws.trim());\n const agentBlock = config.agent as Record<string, unknown> | undefined;\n const legacyWs = agentBlock?.workspace;\n if (typeof legacyWs === \"string\" && isUsableWorkspacePath(legacyWs)) return expandTilde(legacyWs.trim());\n return join(homedir(), \".openclaw\", \"workspace\");\n}\n\nfunction bundledHybridMemorySkillDir(pluginRootDir: string): string {\n return join(pluginRootDir, \"skills\", HYBRID_MEMORY_SKILL_DIR);\n}\n\nfunction bundledHybridMemorySkillPath(pluginRootDir: string): string {\n return join(bundledHybridMemorySkillDir(pluginRootDir), \"SKILL.md\");\n}\n\n/** @internal Exported for tests — copies bundled `skills/hybrid-memory/` (SKILL.md + references/) into the workspace. */\nexport function installHybridMemoryWorkspaceSkill(opts: {\n mergedOpenclawConfig: Record<string, unknown>;\n pluginRootDir: string;\n dryRun: boolean;\n}): { path: string; error?: string } {\n const srcDir = bundledHybridMemorySkillDir(opts.pluginRootDir);\n const skillMd = bundledHybridMemorySkillPath(opts.pluginRootDir);\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const dest = join(workspaceRoot, \"skills\", HYBRID_MEMORY_SKILL_DIR, \"SKILL.md\");\n if (!existsSync(skillMd)) {\n return { path: dest, error: `Bundled skill missing at ${skillMd}` };\n }\n if (opts.dryRun) {\n return { path: dest };\n }\n try {\n const skillsDir = join(workspaceRoot, \"skills\");\n mkdirSync(skillsDir, { recursive: true });\n const destDir = join(skillsDir, HYBRID_MEMORY_SKILL_DIR);\n const tmpDir = skillTmpDir(skillsDir);\n let destRemoved = false;\n try {\n cpSync(srcDir, tmpDir, { recursive: true });\n if (existsSync(destDir)) {\n rmSync(destDir, { recursive: true, force: true });\n destRemoved = true;\n }\n renameSync(tmpDir, destDir);\n } catch (copyErr) {\n // Only clean up tmpDir if destDir wasn't removed — otherwise tmpDir is the only remaining copy\n if (!destRemoved) {\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n /* ignore temp-cleanup failure */\n }\n }\n throw copyErr;\n }\n return { path: dest };\n } catch (err) {\n return { path: dest, error: String(err) };\n }\n}\n\n/**\n * Path to merged OpenClaw config JSON for workspace resolution and skill bootstrap.\n * Order: `OPENCLAW_CONFIG`, `OPENCLAW_CONFIG_PATH`, then `{OPENCLAW_HOME}/openclaw.json`, else `~/.openclaw/openclaw.json`.\n */\nexport function resolveOpenclawJsonPathForWorkspace(): string {\n const explicit = getEnv(\"OPENCLAW_CONFIG\")?.trim() || getEnv(\"OPENCLAW_CONFIG_PATH\")?.trim();\n if (explicit) return expandTilde(explicit);\n const owHome = getEnv(\"OPENCLAW_HOME\")?.trim();\n if (owHome) return join(expandTilde(owHome), \"openclaw.json\");\n return join(homedir(), \".openclaw\", \"openclaw.json\");\n}\n\n/**\n * Load `openclaw.json` for workspace resolution (`agents.defaults.workspace`, etc.).\n * Returns `{}` if the file is missing or unreadable (caller still gets `OPENCLAW_WORKSPACE` via env in {@link resolveAgentWorkspaceRoot}).\n */\nexport function loadOpenclawRootForWorkspace(): Record<string, unknown> {\n const configPath = resolveOpenclawJsonPathForWorkspace();\n try {\n if (!existsSync(configPath)) return {};\n return JSON.parse(readFileSync(configPath, \"utf-8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\n/**\n * Copy bundled `skills/hybrid-memory/` into the workspace **only when** `{workspace}/skills/hybrid-memory/SKILL.md`\n * is missing — so the skill appears without a manual `hybrid-mem install`, without overwriting operator edits on every restart.\n * Full overwrite (including references) remains the job of `installHybridMemoryWorkspaceSkill` from **`hybrid-mem install`**.\n */\nexport function ensureHybridMemoryWorkspaceSkillIfMissing(opts: {\n pluginRootDir: string;\n mergedOpenclawConfig: Record<string, unknown>;\n}): {\n path: string;\n deployed: boolean;\n skippedReason?: \"already_exists\" | \"bundled_missing\" | string;\n} {\n const skillMd = bundledHybridMemorySkillPath(opts.pluginRootDir);\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const destDir = join(workspaceRoot, \"skills\", HYBRID_MEMORY_SKILL_DIR);\n const dest = join(destDir, \"SKILL.md\");\n if (!existsSync(skillMd)) {\n return { path: dest, deployed: false, skippedReason: \"bundled_missing\" };\n }\n if (existsSync(dest)) {\n return { path: dest, deployed: false, skippedReason: \"already_exists\" };\n }\n // Avoid clobbering a partial or hand-edited tree when SKILL.md alone is missing.\n if (existsSync(destDir)) {\n return { path: dest, deployed: false, skippedReason: \"destination_dir_exists\" };\n }\n try {\n const skillsDir = join(workspaceRoot, \"skills\");\n mkdirSync(skillsDir, { recursive: true });\n const srcDir = bundledHybridMemorySkillDir(opts.pluginRootDir);\n const tmpDir = skillTmpDir(skillsDir);\n try {\n cpSync(srcDir, tmpDir, { recursive: true });\n renameSync(tmpDir, destDir);\n } catch (copyErr) {\n try {\n rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n /* ignore temp-cleanup failure */\n }\n throw copyErr;\n }\n return { path: dest, deployed: true };\n } catch (err) {\n return { path: dest, deployed: false, skippedReason: String(err) };\n }\n}\n\nconst TOOLS_MD_MANAGED_BEGIN = \"<!-- openclaw-hybrid-memory:managed-begin -->\";\nconst TOOLS_MD_MANAGED_END = \"<!-- openclaw-hybrid-memory:managed-end -->\";\n\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction getToolsMdManagedBlockRe(): RegExp {\n return new RegExp(`${escapeRegExp(TOOLS_MD_MANAGED_BEGIN)}[\\\\s\\\\S]*?${escapeRegExp(TOOLS_MD_MANAGED_END)}`);\n}\n\n/** True if applying the managed block would modify `existing` (append, replace, or replace with different body). */\nfunction toolsMdManagedBlockWouldChange(existing: string, newBlock: string): boolean {\n const re = getToolsMdManagedBlockRe();\n if (!re.test(existing)) return true;\n return existing.replace(re, newBlock) !== existing;\n}\n\nfunction buildHybridMemoryToolsMdManagedBlock(innerBody: string): string {\n const inner = innerBody.trimEnd();\n return [\n TOOLS_MD_MANAGED_BEGIN,\n \"\",\n \"## Hybrid memory (`openclaw-hybrid-memory`)\",\n \"\",\n \"_This section is refreshed by `openclaw hybrid-mem install` / `upgrade`. Add your own tool notes elsewhere in this file._\",\n \"\",\n inner,\n \"\",\n TOOLS_MD_MANAGED_END,\n ].join(\"\\n\");\n}\n\n/** @internal Merges or refreshes the managed Hybrid memory block in workspace `TOOLS.md`. */\nexport function applyHybridMemoryToolsMd(opts: {\n mergedOpenclawConfig: Record<string, unknown>;\n pluginRootDir: string;\n dryRun: boolean;\n}): { path: string; error?: string; updated: boolean } {\n const workspaceRoot = resolveAgentWorkspaceRoot(opts.mergedOpenclawConfig);\n const toolsPath = join(workspaceRoot, \"TOOLS.md\");\n const snippetPath = join(opts.pluginRootDir, \"workspace-snippets\", \"TOOLS-hybrid-memory-body.md\");\n if (!existsSync(snippetPath)) {\n return { path: toolsPath, error: `Bundled TOOLS snippet missing at ${snippetPath}`, updated: false };\n }\n let innerBody: string;\n try {\n innerBody = readFileSync(snippetPath, \"utf-8\");\n } catch (err) {\n return { path: toolsPath, error: String(err), updated: false };\n }\n const block = buildHybridMemoryToolsMdManagedBlock(innerBody);\n if (opts.dryRun) {\n let wouldChange = !existsSync(toolsPath);\n if (!wouldChange && existsSync(toolsPath)) {\n try {\n const cur = readFileSync(toolsPath, \"utf-8\");\n wouldChange = !cur.includes(TOOLS_MD_MANAGED_BEGIN) || toolsMdManagedBlockWouldChange(cur, block);\n } catch {\n wouldChange = true;\n }\n }\n return { path: toolsPath, updated: wouldChange };\n }\n const managedRe = getToolsMdManagedBlockRe();\n try {\n mkdirSync(workspaceRoot, { recursive: true });\n if (!existsSync(toolsPath)) {\n writeFileSync(toolsPath, `# TOOLS\\n\\n${block}\\n`, \"utf-8\");\n return { path: toolsPath, updated: true };\n }\n const existing = readFileSync(toolsPath, \"utf-8\");\n if (managedRe.test(existing)) {\n const next = existing.replace(managedRe, block);\n if (next !== existing) {\n writeFileSync(toolsPath, next, \"utf-8\");\n return { path: toolsPath, updated: true };\n }\n return { path: toolsPath, updated: false };\n }\n writeFileSync(toolsPath, `${existing.trimEnd()}\\n\\n${block}\\n`, \"utf-8\");\n return { path: toolsPath, updated: true };\n } catch (err) {\n return { path: toolsPath, error: String(err), updated: false };\n }\n}\n\n/**\n * Build a PreFilterConfig from the plugin config.\n * Resolves the Ollama endpoint from extraction.preFilter.endpoint,\n * then llm.providers.ollama.baseURL, then the default localhost URL.\n */\nexport function buildPreFilterConfig(cfg: HybridMemoryConfig): PreFilterConfig {\n const pf = cfg.extraction?.preFilter;\n const ollamaEndpoint = pf?.endpoint ?? cfg.llm?.providers?.ollama?.baseURL ?? \"http://localhost:11434\";\n return {\n enabled: pf?.enabled === true,\n model: pf?.model ?? \"qwen3:8b\",\n endpoint: ollamaEndpoint,\n maxCharsPerSession: pf?.maxCharsPerSession ?? 2000,\n };\n}\n// Re-export preFilterSessions so callers in other handler modules can import from here.\n\n// Shared cron job definitions used by install and verify --fix.\n// Canonical schedule per #86 (7 jobs, non-overlapping). Model is resolved dynamically from user config via getLLMModelPreference.\n// modelTier: \"default\" = standard LLM, \"heavy\" = larger context; resolved via getDefaultCronModel at install/verify time.\n// Order: daily 02:00 → daily 02:30 → Sun 03:00 → Sun 04:00 → Sat 04:00 → Sun 10:00 → 1st 05:00.\nexport const PLUGIN_JOB_ID_PREFIX = \"hybrid-mem:\";\nexport const GOAL_STEWARDSHIP_HEARTBEAT_JOB_ID = \"goal-stewardship-heartbeat\";\nexport const GOAL_STEWARDSHIP_HEARTBEAT_CRON_EXPR = \"*/30 * * * *\";\n\nfunction extractPlainHeartbeatPatternHints(patterns: string[]): string[] {\n const out: string[] = [];\n for (const rawPattern of patterns) {\n const raw = rawPattern.trim();\n if (!raw) continue;\n let hint: string | null = null;\n if (raw.startsWith(\"/\") && raw.lastIndexOf(\"/\") > 0) {\n const last = raw.lastIndexOf(\"/\");\n const body = raw.slice(1, last).trim().replace(/^\\^/, \"\").replace(/\\$$/, \"\").trim();\n if (/^[\\w -]+$/.test(body)) hint = body;\n } else if (/^[\\w -]+$/.test(raw)) {\n hint = raw;\n }\n if (!hint) continue;\n const normalized = hint.replace(/\\s+/g, \" \").trim();\n if (!normalized) continue;\n if (!out.includes(normalized)) out.push(normalized);\n }\n return out;\n}\n\nexport function selectGoalStewardshipHeartbeatMessage(heartbeatPatterns: string[]): string | null {\n const matchers = compileHeartbeatMatchers(heartbeatPatterns);\n const candidates = [\"cron heartbeat\"];\n for (const hint of extractPlainHeartbeatPatternHints(heartbeatPatterns)) {\n const candidate = `cron heartbeat ${hint}`.replace(/\\s+/g, \" \").trim();\n if (!candidates.includes(candidate)) candidates.push(candidate);\n if (!candidates.includes(hint)) candidates.push(hint);\n }\n return candidates.find((candidate) => matchers.some((re) => re.test(candidate))) ?? null;\n}\n\nfunction collectHeartbeatMessageCandidatesFromJob(job: Record<string, unknown>): string[] {\n const out: string[] = [];\n const payload =\n typeof job.payload === \"object\" && job.payload !== null && !Array.isArray(job.payload)\n ? (job.payload as Record<string, unknown>)\n : undefined;\n const candidates = [payload?.text, payload?.message, job.text, job.message];\n for (const raw of candidates) {\n if (typeof raw !== \"string\") continue;\n const normalized = raw.trim();\n if (!normalized || out.includes(normalized)) continue;\n out.push(normalized);\n }\n return out;\n}\n\nexport function selectExistingGoalStewardshipHeartbeatMessage(\n existing: Record<string, unknown> | undefined,\n heartbeatPatterns: string[],\n): string | null {\n if (!existing) return null;\n const matchers = compileHeartbeatMatchers(heartbeatPatterns);\n const candidates = collectHeartbeatMessageCandidatesFromJob(existing);\n return candidates.find((candidate) => matchers.some((re) => re.test(candidate))) ?? null;\n}\n\n/**\n * Ensure there is one enabled, heartbeat-shaped cron job for goal stewardship.\n * The job is intentionally simple and should be safe to run continuously.\n */\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proposals.js","names":[],"sources":["../../cli/proposals.ts"],"sourcesContent":["import { getEnv } from \"../utils/env-manager.js\";\n/**\n * CLI commands for managing persona proposals (human-only operations)\n */\n\nimport { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join, relative } from \"node:path\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport type { IdentityFileType } from \"../config.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { spawnSync } from \"../utils/process-runner.js\";\n/** Resolve a proposal target file (e.g. SOUL.md) against the workspace directory. */\nfunction resolveProposalTarget(targetFile: string): string {\n const workspace = getEnv(\"OPENCLAW_WORKSPACE\") ?? join(homedir(), \".openclaw\", \"workspace\");\n return join(workspace, targetFile);\n}\nimport { getFileSnapshot } from \"../utils/file-snapshot.js\";\n\n/**\n * Audit trail logging for proposal actions\n */\nasync function auditProposal(\n action: string,\n proposalId: string,\n resolvedSqlitePath: string,\n details?: any,\n logger?: { warn?: (msg: string) => void; error?: (msg: string) => void },\n): Promise<void> {\n const auditDir = join(dirname(resolvedSqlitePath), \"decisions\");\n await mkdir(auditDir, { recursive: true });\n const timestamp = new Date().toISOString();\n const entry = {\n timestamp,\n action,\n proposalId,\n ...details,\n };\n const auditPath = join(auditDir, `proposal-${proposalId}.jsonl`);\n try {\n await writeFile(auditPath, `${JSON.stringify(entry)}\\n`, { flag: \"a\" });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"proposals-audit\",\n subsystem: \"proposals\",\n proposalId,\n });\n const msg = `Audit log write failed: ${err}`;\n if (logger?.warn) {\n logger.warn(`memory-hybrid: ${msg}`);\n } else if (logger?.error) {\n logger.error(msg);\n }\n }\n}\n\ntype ProposalChangeType = \"append\" | \"replace\";\n\nconst REPLACE_PREFIXES = [\n \"replace the entire file\",\n \"replace entire file\",\n \"replace the whole file\",\n \"replace whole file\",\n \"replace the file\",\n] as const;\n\nfunction stripOneLeadingSeparator(input: string): string {\n let out = input.trimStart();\n if (out.startsWith(\":\") || out.startsWith(\".\")) out = out.slice(1);\n return out.trimStart();\n}\n\nfunction stripReplaceContentLeadIn(input: string): string {\n const trimmed = input.trimStart();\n const lower = trimmed.toLowerCase();\n for (const leadIn of [\"with the following content\", \"with the following\", \"with\"] as const) {\n if (lower === leadIn) return \"\";\n if (lower.startsWith(leadIn)) {\n const afterLeadIn = trimmed.slice(leadIn.length);\n const trimmedAfter = afterLeadIn.trimStart();\n if (trimmedAfter.startsWith(\":\")) {\n const afterColon = trimmedAfter.slice(1);\n const afterColonTrimmed = afterColon.trimStart();\n if (\n afterColonTrimmed === \"\" ||\n afterColon.startsWith(\"\\n\") ||\n afterColon.startsWith(\"\\r\") ||\n afterColon.startsWith(\" \\n\") ||\n afterColon.startsWith(\" \\r\")\n ) {\n return stripOneLeadingSeparator(afterLeadIn);\n }\n }\n }\n }\n return input;\n}\n\nexport function parseSuggestedChange(suggestedChange: string): { changeType: ProposalChangeType; content: string } {\n const lines = suggestedChange.split(/\\r?\\n/);\n const firstLine = lines[0]?.trim() ?? \"\";\n const lowerFirstLine = firstLine.toLowerCase();\n const replacePrefix = REPLACE_PREFIXES.find((prefix) => {\n if (lowerFirstLine === prefix) return true;\n if (lowerFirstLine.startsWith(`${prefix}:`)) return true;\n if (lowerFirstLine.startsWith(`${prefix}.`)) return true;\n if (lowerFirstLine.startsWith(`${prefix} `)) return true;\n return false;\n });\n if (replacePrefix) {\n const remainder = stripOneLeadingSeparator(firstLine.slice(replacePrefix.length));\n const content = stripReplaceContentLeadIn([remainder, ...lines.slice(1)].join(\"\\n\"));\n return { changeType: \"replace\", content };\n }\n return { changeType: \"append\", content: suggestedChange };\n}\n\n/**\n * Apply confidence cap for replace-type proposals (issue #89).\n * SOUL.md replace is capped at 0.5; other file replace at 0.6; append unchanged.\n */\nexport function capProposalConfidence(confidence: number, targetFile: string, suggestedChange: string): number {\n const parsed = parseSuggestedChange(suggestedChange);\n if (parsed.changeType === \"replace\" && targetFile === \"SOUL.md\") {\n return Math.min(confidence, 0.5);\n }\n if (parsed.changeType === \"replace\") {\n return Math.min(confidence, 0.6);\n }\n return confidence;\n}\n\nfunction buildAppendBlock(proposalId: string, observation: string, suggestedChange: string, timestamp: string): string {\n const escapeHtmlComment = (text: string): string =>\n text\n // Neutralize both standard (-->) and lenient (--!>) HTML comment end markers.\n .replace(/--!?>/g, \"-- >\")\n // Prevent starting a new HTML comment inside the observation.\n .replace(/<!--/g, \"<! --\");\n const safeObservation = escapeHtmlComment(observation);\n return `\\n\\n<!-- Proposal ${proposalId} applied at ${timestamp} -->\\n<!-- Observation: ${safeObservation} -->\\n\\n${suggestedChange}\\n`;\n}\n\nexport function buildAppliedContent(\n original: string,\n proposal: { id: string; observation: string; suggestedChange: string },\n timestamp: string,\n): { changeType: ProposalChangeType; content: string } {\n const parsed = parseSuggestedChange(proposal.suggestedChange);\n if (parsed.changeType === \"replace\") {\n return { changeType: \"replace\", content: parsed.content };\n }\n return {\n changeType: \"append\",\n content: original + buildAppendBlock(proposal.id, proposal.observation, parsed.content, timestamp),\n };\n}\n\nexport function buildUnifiedDiff(currentContent: string, proposedContent: string, targetFile: string): string {\n const diffDir = mkdtempSync(join(tmpdir(), \"proposal-diff-\"));\n const currentPath = join(diffDir, \"current.txt\");\n const proposedPath = join(diffDir, \"proposed.txt\");\n try {\n writeFileSync(currentPath, currentContent, \"utf-8\");\n writeFileSync(proposedPath, proposedContent, \"utf-8\");\n const result = spawnSync(\n \"git\",\n [\n \"diff\",\n \"--no-index\",\n \"--label\",\n `${targetFile} (current)`,\n \"--label\",\n `${targetFile} (proposed)`,\n \"--\",\n currentPath,\n proposedPath,\n ],\n { encoding: \"utf-8\" },\n );\n if (result.status !== 0 && result.status !== 1) {\n throw new Error(result.stderr || result.stdout || \"git diff failed\");\n }\n const out = (result.stdout || \"\").trimEnd();\n return out || \"(no changes)\";\n } finally {\n rmSync(diffDir, { recursive: true, force: true });\n }\n}\n\n/** Returns true if the given path (or its directory) is inside a git repository. */\nfunction isGitRepo(dirOrFilePath: string): boolean {\n let dir: string;\n try {\n dir = statSync(dirOrFilePath).isDirectory() ? dirOrFilePath : dirname(dirOrFilePath);\n } catch {\n dir = dirname(dirOrFilePath);\n }\n const result = spawnSync(\"git\", [\"rev-parse\", \"--git-dir\"], { cwd: dir, encoding: \"utf-8\" });\n return result.status === 0 && !!result.stdout?.trim();\n}\n\nfunction commitProposalChange(\n targetPath: string,\n proposalId: string,\n targetFile: string,\n): { ok: true } | { ok: false; error: string } {\n const repoRoot = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { cwd: dirname(targetPath), encoding: \"utf-8\" });\n if (repoRoot.status !== 0 || !repoRoot.stdout.trim()) {\n return { ok: false, error: `Failed to resolve git repo root: ${repoRoot.stderr || repoRoot.stdout}` };\n }\n const cwd = repoRoot.stdout.trim();\n const relPath = relative(cwd, targetPath);\n const add = spawnSync(\"git\", [\"add\", \"--\", relPath], { cwd, encoding: \"utf-8\" });\n if (add.status !== 0) {\n return { ok: false, error: `git add failed: ${add.stderr || add.stdout}` };\n }\n const message = `chore: apply persona proposal ${proposalId} to ${targetFile}`;\n const commit = spawnSync(\"git\", [\"commit\", \"-m\", message, \"--\", relPath], { cwd, encoding: \"utf-8\" });\n if (commit.status !== 0) {\n return { ok: false, error: `git commit failed: ${commit.stderr || commit.stdout}` };\n }\n return { ok: true };\n}\n\ntype ApplyProposalContext = {\n proposalsDb: ProposalsDB;\n cfg: { personaProposals: { allowedFiles: string[] } };\n resolvedSqlitePath: string;\n api?: { logger?: { warn?: (msg: string) => void } };\n};\n\n/**\n * Apply an approved proposal to its target file and mark as applied.\n * Used by CLI \"apply\" and after \"approve\" so approval auto-applies (fixes #82).\n */\nexport async function applyApprovedProposal(\n ctx: ApplyProposalContext,\n proposalId: string,\n): Promise<\n { ok: true; targetFile: string; backupPath: string; suggestedChange: string } | { ok: false; error: string }\n> {\n const proposal = ctx.proposalsDb.get(proposalId);\n if (!proposal) {\n return { ok: false, error: `Proposal ${proposalId} not found` };\n }\n if (proposal.status !== \"approved\") {\n return {\n ok: false,\n error: `Proposal ${proposalId} is ${proposal.status}. Only approved proposals can be applied.`,\n };\n }\n if (!ctx.cfg.personaProposals.allowedFiles.includes(proposal.targetFile as IdentityFileType)) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} is no longer in allowedFiles. Current: ${ctx.cfg.personaProposals.allowedFiles.join(\", \")}`,\n };\n }\n if (proposal.targetFile.includes(\"..\") || proposal.targetFile.includes(\"/\") || proposal.targetFile.includes(\"\\\\\")) {\n return { ok: false, error: `Invalid target file path: ${proposal.targetFile}. Path traversal detected.` };\n }\n const targetPath = resolveProposalTarget(proposal.targetFile);\n if (!existsSync(targetPath)) {\n return { ok: false, error: `Target file ${proposal.targetFile} not found at ${targetPath}` };\n }\n const DANGEROUS_PATTERNS = /<script|<iframe|javascript:/i;\n if (DANGEROUS_PATTERNS.test(proposal.suggestedChange)) {\n return { ok: false, error: `Proposal ${proposalId} contains potentially dangerous content and cannot be applied.` };\n }\n try {\n const currentSnapshot = getFileSnapshot(targetPath);\n if (proposal.targetHash && currentSnapshot?.hash && proposal.targetHash !== currentSnapshot.hash) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} has changed since proposal creation (hash mismatch). Review and re-approve.`,\n };\n }\n if (\n !proposal.targetHash &&\n proposal.targetMtimeMs != null &&\n currentSnapshot?.mtimeMs != null &&\n proposal.targetMtimeMs !== currentSnapshot.mtimeMs\n ) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} has changed since proposal creation (mtime mismatch). Review and re-approve.`,\n };\n }\n const original = readFileSync(targetPath, \"utf-8\");\n const backupPath = `${targetPath}.backup-${Date.now()}`;\n writeFileSync(backupPath, original);\n const timestamp = new Date().toISOString();\n const applied = buildAppliedContent(original, proposal, timestamp);\n if (!applied.content.trim()) {\n return { ok: false, error: `Proposal ${proposalId} does not contain replacement content to apply.` };\n }\n writeFileSync(targetPath, applied.content);\n // Only attempt git commit when the target is inside a git repo (issue #90: non-git workspace can still apply).\n if (isGitRepo(targetPath)) {\n const commitResult = commitProposalChange(targetPath, proposalId, proposal.targetFile);\n if (!commitResult.ok) {\n writeFileSync(targetPath, original);\n const repoRoot = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { encoding: \"utf-8\" });\n if (repoRoot.status === 0 && repoRoot.stdout.trim()) {\n const cwd = repoRoot.stdout.trim();\n const relPath = relative(cwd, targetPath);\n spawnSync(\"git\", [\"reset\", \"HEAD\", \"--\", relPath], { cwd, encoding: \"utf-8\" });\n }\n return {\n ok: false,\n error: `Git commit failed; target file rolled back to original. Commit error: ${commitResult.error}`,\n };\n }\n }\n ctx.proposalsDb.markApplied(proposalId);\n await auditProposal(\n \"applied\",\n proposalId,\n ctx.resolvedSqlitePath,\n {\n targetFile: proposal.targetFile,\n targetPath,\n backupPath,\n timestamp,\n changeType: applied.changeType,\n },\n { error: console.error },\n );\n return {\n ok: true,\n targetFile: proposal.targetFile,\n backupPath,\n suggestedChange: proposal.suggestedChange,\n };\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"apply-proposal\",\n subsystem: \"proposals\",\n proposalId,\n });\n return { ok: false, error: `Failed to apply proposal: ${err}` };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"proposals.js","names":[],"sources":["../../cli/proposals.ts"],"sourcesContent":["import { getEnv } from \"../utils/env-manager.js\";\n/**\n * CLI commands for managing persona proposals (human-only operations)\n */\n\nimport { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir, tmpdir } from \"node:os\";\nimport { dirname, join, relative } from \"node:path\";\nimport type { ProposalsDB } from \"../backends/proposals-db.js\";\nimport type { IdentityFileType } from \"../config.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport { spawnSync } from \"../utils/process-runner.js\";\n/** Resolve a proposal target file (e.g. SOUL.md) against the workspace directory. */\nfunction resolveProposalTarget(targetFile: string): string {\n const workspace = getEnv(\"OPENCLAW_WORKSPACE\") ?? join(homedir(), \".openclaw\", \"workspace\");\n return join(workspace, targetFile);\n}\nimport { getFileSnapshot } from \"../utils/file-snapshot.js\";\n\n/**\n * Audit trail logging for proposal actions\n */\nasync function auditProposal(\n action: string,\n proposalId: string,\n resolvedSqlitePath: string,\n details?: any,\n logger?: { warn?: (msg: string) => void; error?: (msg: string) => void },\n): Promise<void> {\n const auditDir = join(dirname(resolvedSqlitePath), \"decisions\");\n await mkdir(auditDir, { recursive: true });\n const timestamp = new Date().toISOString();\n const entry = {\n timestamp,\n action,\n proposalId,\n ...details,\n };\n const auditPath = join(auditDir, `proposal-${proposalId}.jsonl`);\n try {\n await writeFile(auditPath, `${JSON.stringify(entry)}\\n`, { flag: \"a\" });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"proposals-audit\",\n subsystem: \"proposals\",\n proposalId,\n });\n const msg = `Audit log write failed: ${err}`;\n if (logger?.warn) {\n logger.warn(`memory-hybrid: ${msg}`);\n } else if (logger?.error) {\n logger.error(msg);\n }\n }\n}\n\ntype ProposalChangeType = \"append\" | \"replace\";\n\nconst REPLACE_PREFIXES = [\n \"replace the entire file\",\n \"replace entire file\",\n \"replace the whole file\",\n \"replace whole file\",\n \"replace the file\",\n] as const;\n\nfunction stripOneLeadingSeparator(input: string): string {\n let out = input.trimStart();\n if (out.startsWith(\":\") || out.startsWith(\".\")) out = out.slice(1);\n return out.trimStart();\n}\n\nfunction stripReplaceContentLeadIn(input: string): string {\n const trimmed = input.trimStart();\n const lower = trimmed.toLowerCase();\n for (const leadIn of [\"with the following content\", \"with the following\", \"with\"] as const) {\n if (lower === leadIn) return \"\";\n if (lower.startsWith(leadIn)) {\n const afterLeadIn = trimmed.slice(leadIn.length);\n const trimmedAfter = afterLeadIn.trimStart();\n if (trimmedAfter.startsWith(\":\")) {\n const afterColon = trimmedAfter.slice(1);\n const afterColonTrimmed = afterColon.trimStart();\n if (\n afterColonTrimmed === \"\" ||\n afterColon.startsWith(\"\\n\") ||\n afterColon.startsWith(\"\\r\") ||\n afterColon.startsWith(\" \\n\") ||\n afterColon.startsWith(\" \\r\")\n ) {\n return stripOneLeadingSeparator(afterLeadIn);\n }\n }\n }\n }\n return input;\n}\n\nexport function parseSuggestedChange(suggestedChange: string): { changeType: ProposalChangeType; content: string } {\n const lines = suggestedChange.split(/\\r?\\n/);\n const firstLine = lines[0]?.trim() ?? \"\";\n const lowerFirstLine = firstLine.toLowerCase();\n const replacePrefix = REPLACE_PREFIXES.find((prefix) => {\n if (lowerFirstLine === prefix) return true;\n if (lowerFirstLine.startsWith(`${prefix}:`)) return true;\n if (lowerFirstLine.startsWith(`${prefix}.`)) return true;\n if (lowerFirstLine.startsWith(`${prefix} `)) return true;\n return false;\n });\n if (replacePrefix) {\n const remainder = stripOneLeadingSeparator(firstLine.slice(replacePrefix.length));\n const content = stripReplaceContentLeadIn([remainder, ...lines.slice(1)].join(\"\\n\"));\n return { changeType: \"replace\", content };\n }\n return { changeType: \"append\", content: suggestedChange };\n}\n\n/**\n * Apply confidence cap for replace-type proposals (issue #89).\n * SOUL.md replace is capped at 0.5; other file replace at 0.6; append unchanged.\n */\nexport function capProposalConfidence(confidence: number, targetFile: string, suggestedChange: string): number {\n const parsed = parseSuggestedChange(suggestedChange);\n if (parsed.changeType === \"replace\" && targetFile === \"SOUL.md\") {\n return Math.min(confidence, 0.5);\n }\n if (parsed.changeType === \"replace\") {\n return Math.min(confidence, 0.6);\n }\n return confidence;\n}\n\nfunction buildAppendBlock(proposalId: string, observation: string, suggestedChange: string, timestamp: string): string {\n const escapeHtmlComment = (text: string): string =>\n text\n // Neutralize both standard (-->) and lenient (--!>) HTML comment end markers.\n .replace(/--!?>/g, \"-- >\")\n // Prevent starting a new HTML comment inside the observation.\n .replace(/<!--/g, \"<! --\");\n const safeObservation = escapeHtmlComment(observation);\n return `\\n\\n<!-- Proposal ${proposalId} applied at ${timestamp} -->\\n<!-- Observation: ${safeObservation} -->\\n\\n${suggestedChange}\\n`;\n}\n\nexport function buildAppliedContent(\n original: string,\n proposal: { id: string; observation: string; suggestedChange: string },\n timestamp: string,\n): { changeType: ProposalChangeType; content: string } {\n const parsed = parseSuggestedChange(proposal.suggestedChange);\n if (parsed.changeType === \"replace\") {\n return { changeType: \"replace\", content: parsed.content };\n }\n return {\n changeType: \"append\",\n content: original + buildAppendBlock(proposal.id, proposal.observation, parsed.content, timestamp),\n };\n}\n\nexport function buildUnifiedDiff(currentContent: string, proposedContent: string, targetFile: string): string {\n const diffDir = mkdtempSync(join(tmpdir(), \"proposal-diff-\"));\n const currentPath = join(diffDir, \"current.txt\");\n const proposedPath = join(diffDir, \"proposed.txt\");\n try {\n writeFileSync(currentPath, currentContent, \"utf-8\");\n writeFileSync(proposedPath, proposedContent, \"utf-8\");\n const result = spawnSync(\n \"git\",\n [\n \"diff\",\n \"--no-index\",\n \"--label\",\n `${targetFile} (current)`,\n \"--label\",\n `${targetFile} (proposed)`,\n \"--\",\n currentPath,\n proposedPath,\n ],\n { encoding: \"utf-8\" },\n );\n if (result.status !== 0 && result.status !== 1) {\n throw new Error(result.stderr || result.stdout || \"git diff failed\");\n }\n const out = (result.stdout || \"\").trimEnd();\n return out || \"(no changes)\";\n } finally {\n rmSync(diffDir, { recursive: true, force: true });\n }\n}\n\n/** Returns true if the given path (or its directory) is inside a git repository. */\nfunction isGitRepo(dirOrFilePath: string): boolean {\n let dir: string;\n try {\n dir = statSync(dirOrFilePath).isDirectory() ? dirOrFilePath : dirname(dirOrFilePath);\n } catch {\n dir = dirname(dirOrFilePath);\n }\n const result = spawnSync(\"git\", [\"rev-parse\", \"--git-dir\"], { cwd: dir, encoding: \"utf-8\" });\n return result.status === 0 && !!result.stdout?.trim();\n}\n\nfunction commitProposalChange(\n targetPath: string,\n proposalId: string,\n targetFile: string,\n): { ok: true } | { ok: false; error: string } {\n const repoRoot = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { cwd: dirname(targetPath), encoding: \"utf-8\" });\n if (repoRoot.status !== 0 || !repoRoot.stdout.trim()) {\n return { ok: false, error: `Failed to resolve git repo root: ${repoRoot.stderr || repoRoot.stdout}` };\n }\n const cwd = repoRoot.stdout.trim();\n const relPath = relative(cwd, targetPath);\n const add = spawnSync(\"git\", [\"add\", \"--\", relPath], { cwd, encoding: \"utf-8\" });\n if (add.status !== 0) {\n return { ok: false, error: `git add failed: ${add.stderr || add.stdout}` };\n }\n const message = `chore: apply persona proposal ${proposalId} to ${targetFile}`;\n const commit = spawnSync(\"git\", [\"commit\", \"-m\", message, \"--\", relPath], { cwd, encoding: \"utf-8\" });\n if (commit.status !== 0) {\n return { ok: false, error: `git commit failed: ${commit.stderr || commit.stdout}` };\n }\n return { ok: true };\n}\n\ntype ApplyProposalContext = {\n proposalsDb: ProposalsDB;\n cfg: { personaProposals: { allowedFiles: string[] } };\n resolvedSqlitePath: string;\n api?: { logger?: { warn?: (msg: string) => void } };\n};\n\n/**\n * Apply an approved proposal to its target file and mark as applied.\n * Used by CLI \"apply\" and after \"approve\" so approval auto-applies (fixes #82).\n */\nexport async function applyApprovedProposal(\n ctx: ApplyProposalContext,\n proposalId: string,\n): Promise<\n { ok: true; targetFile: string; backupPath: string; suggestedChange: string } | { ok: false; error: string }\n> {\n const proposal = ctx.proposalsDb.get(proposalId);\n if (!proposal) {\n return { ok: false, error: `Proposal ${proposalId} not found` };\n }\n if (proposal.status !== \"approved\") {\n return {\n ok: false,\n error: `Proposal ${proposalId} is ${proposal.status}. Only approved proposals can be applied.`,\n };\n }\n if (!ctx.cfg.personaProposals.allowedFiles.includes(proposal.targetFile as IdentityFileType)) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} is no longer in allowedFiles. Current: ${ctx.cfg.personaProposals.allowedFiles.join(\", \")}`,\n };\n }\n if (proposal.targetFile.includes(\"..\") || proposal.targetFile.includes(\"/\") || proposal.targetFile.includes(\"\\\\\")) {\n return { ok: false, error: `Invalid target file path: ${proposal.targetFile}. Path traversal detected.` };\n }\n const targetPath = resolveProposalTarget(proposal.targetFile);\n if (!existsSync(targetPath)) {\n return { ok: false, error: `Target file ${proposal.targetFile} not found at ${targetPath}` };\n }\n const DANGEROUS_PATTERNS = /<script|<iframe|javascript:/i;\n if (DANGEROUS_PATTERNS.test(proposal.suggestedChange)) {\n return { ok: false, error: `Proposal ${proposalId} contains potentially dangerous content and cannot be applied.` };\n }\n try {\n const currentSnapshot = getFileSnapshot(targetPath);\n if (proposal.targetHash && currentSnapshot?.hash && proposal.targetHash !== currentSnapshot.hash) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} has changed since proposal creation (hash mismatch). Review and re-approve.`,\n };\n }\n if (\n !proposal.targetHash &&\n proposal.targetMtimeMs != null &&\n currentSnapshot?.mtimeMs != null &&\n proposal.targetMtimeMs !== currentSnapshot.mtimeMs\n ) {\n return {\n ok: false,\n error: `Target file ${proposal.targetFile} has changed since proposal creation (mtime mismatch). Review and re-approve.`,\n };\n }\n const original = readFileSync(targetPath, \"utf-8\");\n const backupPath = `${targetPath}.backup-${Date.now()}`;\n writeFileSync(backupPath, original);\n const timestamp = new Date().toISOString();\n const applied = buildAppliedContent(original, proposal, timestamp);\n if (!applied.content.trim()) {\n return { ok: false, error: `Proposal ${proposalId} does not contain replacement content to apply.` };\n }\n writeFileSync(targetPath, applied.content);\n // Only attempt git commit when the target is inside a git repo (issue #90: non-git workspace can still apply).\n if (isGitRepo(targetPath)) {\n const commitResult = commitProposalChange(targetPath, proposalId, proposal.targetFile);\n if (!commitResult.ok) {\n writeFileSync(targetPath, original);\n const repoRoot = spawnSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], { encoding: \"utf-8\" });\n if (repoRoot.status === 0 && repoRoot.stdout.trim()) {\n const cwd = repoRoot.stdout.trim();\n const relPath = relative(cwd, targetPath);\n spawnSync(\"git\", [\"reset\", \"HEAD\", \"--\", relPath], { cwd, encoding: \"utf-8\" });\n }\n return {\n ok: false,\n error: `Git commit failed; target file rolled back to original. Commit error: ${commitResult.error}`,\n };\n }\n }\n ctx.proposalsDb.markApplied(proposalId);\n await auditProposal(\n \"applied\",\n proposalId,\n ctx.resolvedSqlitePath,\n {\n targetFile: proposal.targetFile,\n targetPath,\n backupPath,\n timestamp,\n changeType: applied.changeType,\n },\n { error: console.error },\n );\n return {\n ok: true,\n targetFile: proposal.targetFile,\n backupPath,\n suggestedChange: proposal.suggestedChange,\n };\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n operation: \"apply-proposal\",\n subsystem: \"proposals\",\n proposalId,\n });\n return { ok: false, error: `Failed to apply proposal: ${err}` };\n }\n}\n"],"mappings":"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"}
|
package/dist/cli/register.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","names":[],"sources":["../../cli/register.ts"],"sourcesContent":["// @ts-nocheck\n/**\n * Register hybrid-mem CLI subcommands.\n * Thin orchestrator that delegates to specialized command modules.\n */\n\nimport type { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { VectorDB } from \"../backends/vector-db.js\";\nimport type { WriteAheadLog } from \"../backends/wal.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport type { EmbeddingProvider } from \"../services/embeddings.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport type { mergeResults } from \"../services/merge-results.js\";\nimport type { AliasDB } from \"../services/retrieval-aliases.js\";\nimport { PLUGIN_ID } from \"../utils/constants.js\";\nimport { type ActiveTaskContext, registerActiveTaskCommands } from \"./active-tasks.js\";\nimport { registerBenchmarkCommands } from \"./benchmark.js\";\nimport { registerStatusCommands } from \"./cmd-status.js\";\nimport { type UserFriendlyContext, registerUserFriendlyCommands } from \"./cmd-user-friendly.js\";\nimport { type DistillContext, registerDistillCommands } from \"./distill.js\";\nimport { registerGoalCommands } from \"./goals.js\";\nimport { type ManageContext, registerManageCommands } from \"./manage.js\";\nimport { registerSkillsCommands } from \"./skills.js\";\nimport { registerTaskQueueStatusCommands } from \"./task-queue-status.js\";\nimport type {\n AnalyzeFeedbackPhrasesResult,\n BackfillCliResult,\n BackfillCliSink,\n ConfigCliResult,\n CredentialsAuditResult,\n CredentialsPruneResult,\n DistillCliResult,\n DistillCliSink,\n DistillWindowResult,\n ExtractDailyResult,\n ExtractDailySink,\n ExtractProceduresResult,\n FindDuplicatesResult,\n GenerateAutoSkillsResult,\n IngestFilesResult,\n IngestFilesSink,\n InstallCliResult,\n MigrateToVaultResult,\n RecordDistillResult,\n SelfCorrectionExtractResult,\n SelfCorrectionRunResult,\n StoreCliOpts,\n StoreCliResult,\n UninstallCliResult,\n UpgradeCliResult,\n VerifyCliSink,\n} from \"./types.js\";\nimport { registerVerifiedCommands } from \"./verified.js\";\nimport { type VerifyContext, registerVerifyCommands } from \"./verify.js\";\n\nexport type {\n FindDuplicatesResult,\n StoreCliOpts,\n StoreCliResult,\n InstallCliResult,\n VerifyCliSink,\n DistillWindowResult,\n RecordDistillResult,\n ExtractDailyResult,\n ExtractDailySink,\n ExtractProceduresResult,\n GenerateAutoSkillsResult,\n BackfillCliResult,\n BackfillCliSink,\n IngestFilesResult,\n IngestFilesSink,\n DistillCliResult,\n DistillCliSink,\n SelfCorrectionExtractResult,\n SelfCorrectionRunResult,\n AnalyzeFeedbackPhrasesResult,\n MigrateToVaultResult,\n CredentialsAuditResult,\n CredentialsPruneResult,\n UpgradeCliResult,\n UninstallCliResult,\n ConfigCliResult,\n};\nexport type { ActiveTaskContext };\n\nexport type HybridMemCliContext = {\n factsDb: FactsDB;\n vectorDb: VectorDB;\n wal?: WriteAheadLog | null;\n aliasDb?: AliasDB | null;\n crystallizationStore?: CrystallizationStore | null;\n versionInfo: {\n pluginVersion: string;\n memoryManagerVersion: string;\n schemaVersion: number;\n };\n embeddings: EmbeddingProvider;\n mergeResults: typeof mergeResults;\n parseSourceDate: (v: string | number | null | undefined) => number | null;\n getMemoryCategories: () => string[];\n cfg: HybridMemoryConfig;\n runStore: (opts: StoreCliOpts) => Promise<StoreCliResult>;\n runInstall: (opts: { dryRun: boolean }) => Promise<InstallCliResult>;\n runVerify: (\n opts: {\n fix: boolean;\n logFile?: string;\n testLlm?: boolean;\n reconcile?: boolean;\n reconcilePolicy?: \"conservative\" | \"balanced\" | \"aggressive\";\n reconcileMaxFixes?: number;\n },\n sink: VerifyCliSink,\n ) => Promise<void>;\n runDistillWindow: (opts: { json: boolean }) => Promise<DistillWindowResult>;\n runRecordDistill: () => Promise<RecordDistillResult>;\n runExtractDaily: (\n opts: { days: number; dryRun: boolean; verbose?: boolean },\n sink: ExtractDailySink,\n ) => Promise<ExtractDailyResult>;\n runExtractProcedures: (opts: {\n sessionDir?: string;\n days?: number;\n dryRun: boolean;\n verbose?: boolean;\n full?: boolean;\n }) => Promise<ExtractProceduresResult>;\n runGenerateAutoSkills: (opts: {\n dryRun: boolean;\n apply?: boolean;\n verbose?: boolean;\n max?: number;\n policy?: string;\n json?: boolean;\n bypassDuplicateSkillCache?: boolean;\n }) => Promise<GenerateAutoSkillsResult>;\n runSkillsSuggest: (opts: {\n dryRun?: boolean;\n apply?: boolean;\n days?: number;\n verbose?: boolean;\n }) => Promise<import(\"../services/memory-to-skills.js\").SkillsSuggestResult>;\n runBackfill: (\n opts: { dryRun: boolean; workspace?: string; limit?: number },\n sink: BackfillCliSink,\n ) => Promise<BackfillCliResult>;\n runIngestFiles: (\n opts: { dryRun: boolean; workspace?: string; paths?: string[] },\n sink: IngestFilesSink,\n ) => Promise<IngestFilesResult>;\n runDistill: (\n opts: {\n dryRun: boolean;\n all?: boolean;\n days?: number;\n since?: string;\n model?: string;\n verbose?: boolean;\n maxSessions?: number;\n maxSessionTokens?: number;\n full?: boolean;\n },\n sink: DistillCliSink,\n ) => Promise<DistillCliResult>;\n runMigrateToVault: () => Promise<MigrateToVaultResult | null>;\n runCredentialsList: () => Array<{\n service: string;\n type: string;\n url: string | null;\n }>;\n runCredentialsGet: (opts: { service: string; type?: string }) => {\n service: string;\n type: string;\n value: string;\n url: string | null;\n notes: string | null;\n } | null;\n runCredentialsAudit: () => CredentialsAuditResult;\n runCredentialsPrune: (opts: { dryRun: boolean; yes?: boolean; onlyFlags?: string[] }) => CredentialsPruneResult;\n runUninstall: (opts: { cleanAll: boolean; leaveConfig: boolean }) => Promise<UninstallCliResult>;\n runUpgrade: (version?: string) => Promise<UpgradeCliResult>;\n runConfigMode: (mode: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runConfigSet: (key: string, value: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runConfigSetHelp: (key: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runFindDuplicates: (opts: {\n threshold: number;\n includeStructured: boolean;\n limit: number;\n }) => Promise<FindDuplicatesResult>;\n runConsolidate: (opts: {\n threshold: number;\n includeStructured: boolean;\n dryRun: boolean;\n limit: number;\n model: string;\n }) => Promise<{ clustersFound: number; merged: number; deleted: number }>;\n runReflection: (opts: { window: number; dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n factsAnalyzed: number;\n patternsExtracted: number;\n patternsStored: number;\n window: number;\n }>;\n runReflectionRules: (opts: { dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n rulesExtracted: number;\n rulesStored: number;\n diagnostics?: {\n modelResponseChars: number;\n parseSuccess: boolean;\n parsedCandidates: number;\n rejectedDuplicates: number;\n rejectedLowConfidence: number;\n stored: number;\n zeroRulesReason?: string;\n status: \"ok\" | \"partial\" | \"degraded\";\n };\n }>;\n runReflectionMeta: (opts: { dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n metaExtracted: number;\n metaStored: number;\n }>;\n reflectionConfig: {\n enabled: boolean;\n defaultWindow: number;\n minObservations: number;\n model: string;\n };\n runDreamCycle: (opts?: { verbose?: boolean }) => Promise<import(\"../services/dream-cycle.js\").DreamCycleResult>;\n runContinuousVerification: (opts?: {\n verbose?: boolean;\n }) => Promise<import(\"../services/continuous-verifier.js\").VerificationCycleResult>;\n runResolveContradictions: () => Promise<{\n autoResolved: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n ambiguous: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n }>;\n runResolveContradictionsDryRun: () => Promise<{\n autoResolvable: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n ambiguous: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n }>;\n runResolveContradictionsProjectStateLww: (opts: {\n dryRun?: boolean;\n }) => Promise<import(\"../backends/facts-db/contradictions.js\").ProjectStateLwwResult>;\n runResolveContradictionsAuto: (\n opts: import(\"../backends/facts-db/contradictions.js\").ResolveContradictionsAutoOptions,\n ) => Promise<import(\"../backends/facts-db/contradictions.js\").ResolveContradictionsAutoResult>;\n runApplyContradictionReviewDecisions: (\n decisions: import(\"../backends/facts-db/contradictions.js\").ContradictionReviewDecision[],\n ) => Promise<import(\"../backends/facts-db/contradictions.js\").ApplyContradictionReviewResult>;\n runClassify: (opts: { dryRun: boolean; limit: number; model?: string }) => Promise<{\n reclassified: number;\n total: number;\n breakdown?: Record<string, number>;\n }>;\n autoClassifyConfig: {\n model: string;\n batchSize: number;\n suggestCategories?: boolean;\n };\n runCompaction: (opts?: { apply?: boolean }) => Promise<{\n hot: number;\n warm: number;\n cold: number;\n structural: number;\n changed?: number;\n examined?: number;\n apply?: boolean;\n }>;\n runBuildLanguageKeywords: (opts: {\n model?: string;\n dryRun?: boolean;\n }) => Promise<\n { ok: true; path: string; topLanguages: string[]; languagesAdded: number } | { ok: false; error: string }\n >;\n runEntityEnrichment: (opts: {\n limit: number;\n dryRun: boolean;\n model?: string;\n verbose?: boolean;\n all?: boolean;\n onProgress?: (progress: import(\"../services/entity-enrichment-cli.js\").EntityEnrichmentProgress) => void;\n }) => Promise<{\n pending: number;\n pendingTotal?: number;\n pendingByTier?: { hot: number; warm: number; structural: number; cold: number; unknown: number };\n processed: number;\n factsEnriched: number;\n mode?: \"bounded\" | \"all\";\n effectiveLimit?: number | \"all\";\n remainingTotal?: number;\n estimatedRunsRemaining?: number;\n mentions: number;\n accepted: number;\n rejected: number;\n duplicates: number;\n rejectReasons: Record<string, number>;\n skipped?: boolean;\n pendingFactIds?: string[];\n enrichedFacts?: import(\"../services/entity-enrichment-cli.js\").EntityEnrichmentVerboseFact[];\n }>;\n runSelfCorrectionExtract: (opts: {\n days?: number;\n outputPath?: string;\n verbose?: boolean;\n }) => Promise<SelfCorrectionExtractResult>;\n runSelfCorrectionRun: (opts: {\n extractPath?: string;\n incidents?: Array<{\n userMessage: string;\n precedingAssistant: string;\n followingAssistant: string;\n timestamp?: string;\n sessionFile: string;\n }>;\n workspace?: string;\n dryRun?: boolean;\n model?: string;\n approve?: boolean;\n applyTools?: boolean;\n full?: boolean;\n verbose?: boolean;\n }) => Promise<SelfCorrectionRunResult>;\n runAnalyzeFeedbackPhrases: (opts: {\n days?: number;\n model?: string;\n outputPath?: string;\n learn?: boolean;\n }) => Promise<AnalyzeFeedbackPhrasesResult>;\n runExtractDirectives: (opts: { days?: number; verbose?: boolean; dryRun?: boolean; full?: boolean }) => Promise<{\n incidents: Array<{\n userMessage: string;\n categories: string[];\n extractedRule: string;\n precedingAssistant: string;\n confidence: number;\n timestamp?: string;\n sessionFile: string;\n }>;\n sessionsScanned: number;\n skipped?: boolean;\n }>;\n runExtractReinforcement: (opts: { days?: number; verbose?: boolean; dryRun?: boolean; full?: boolean }) => Promise<{\n incidents: Array<{\n userMessage: string;\n agentBehavior: string;\n recalledMemoryIds: string[];\n toolCallSequence: string[];\n confidence: number;\n timestamp?: string;\n sessionFile: string;\n }>;\n sessionsScanned: number;\n skipped?: boolean;\n }>;\n runExtractImplicitFeedback?: (opts: {\n days?: number;\n verbose?: boolean;\n dryRun?: boolean;\n full?: boolean;\n includeTrajectories?: boolean;\n includeClosedLoop?: boolean;\n onProgress?: (snapshot: import(\"./cmd-feedback.js\").ExtractImplicitFeedbackProgressSnapshot) => void;\n }) => Promise<{\n signalsExtracted: number;\n positiveCount: number;\n negativeCount: number;\n trajectoriesBuilt: number;\n sessionsScanned: number;\n sessionsVisited: number;\n sessionsProcessed: number;\n sessionsSkipped: number;\n sessionsDeferred: number;\n backlogSessionsEstimate: number;\n backlogSignalsEstimate: number;\n backlogTrajectoriesEstimate: number;\n partial: boolean;\n partialReason?: import(\"./cmd-feedback.js\").ExtractImplicitFeedbackStopReason;\n closedLoopReport?: string;\n skipped?: boolean;\n }>;\n runGenerateProposals?: (opts: { dryRun: boolean; verbose?: boolean }) => Promise<{ created: number }>;\n runExport: (opts: {\n outputPath: string;\n excludeCredentials?: boolean;\n includeCredentials?: boolean;\n sources?: string[];\n mode?: \"replace\" | \"additive\";\n }) => Promise<{\n factsExported: number;\n proceduresExported: number;\n filesWritten: number;\n outputPath: string;\n }>;\n richStatsExtras?: {\n getCredentialsCount: () => number;\n getProposalsPending: () => number;\n getProposalsAvailable: () => boolean;\n getWalPending: () => Promise<number> | number;\n getLastRunTimestamps: () => {\n distill?: string;\n reflect?: string;\n compact?: string;\n vectordbOptimize?: string;\n };\n getStorageSizes: () => Promise<{\n sqliteBytes?: number;\n lanceBytes?: number;\n lanceBytesTimedOut?: boolean;\n }>;\n getCronJobsStatus?: () => Array<{\n name: string;\n pluginJobId: string;\n enabled: boolean;\n scheduleExpr: string | null;\n lastRunAtMs: number | null;\n }>;\n };\n listCommands?: {\n listProposals: (opts: { status?: string }) => Promise<\n Array<{\n id: string;\n title: string;\n targetFile: string;\n status: string;\n confidence: number;\n createdAt: number;\n }>\n >;\n proposalApprove: (id: string) => Promise<{ ok: boolean; error?: string }>;\n proposalReject: (id: string, reason?: string) => Promise<{ ok: boolean; error?: string }>;\n listCorrections: (opts: { workspace?: string }) => Promise<{\n reportPath: string | null;\n items: string[];\n }>;\n correctionsApproveAll: (opts: { workspace?: string }) => Promise<{\n applied: number;\n error?: string;\n }>;\n showItem: (id: string) => Promise<{ type: \"fact\" | \"proposal\"; data: unknown } | null>;\n triageProposals?: (opts: {\n dryRun?: boolean;\n apply?: boolean;\n policy?: string;\n max?: number;\n json?: boolean;\n stateDb?: string;\n workspace?: string;\n }) => Promise<import(\"../services/persona-proposal-triage.js\").PersonaProposalTriageResult>;\n };\n tieringEnabled: boolean;\n resolvedSqlitePath?: string;\n resolvePath?: (file: string) => string;\n /** Active task working memory context (required when activeTask.enabled = true) */\n activeTask?: ActiveTaskContext;\n runCrossAgentLearning?: (opts?: {\n verbose?: boolean;\n }) => Promise<import(\"../cli/handlers.js\").CrossAgentLearningCliResult>;\n runToolEffectiveness?: (opts?: { verbose?: boolean }) => Promise<string>;\n runCostReport?: (opts: import(\"../cli/handlers.js\").CostReportCliOpts, sink: { log: (msg: string) => void }) => void;\n pruneCostLog?: (retainDays?: number) => number;\n /** Resolved path to LanceDB vector store (for backup). */\n resolvedLancePath?: string;\n /** Create a point-in-time backup snapshot (Issue #276). */\n runBackup?: (opts?: { backupDir?: string }) => Promise<import(\"../cli/backup.js\").BackupCliResult>;\n /** Verify SQLite DB integrity without creating a backup (Issue #276). */\n runBackupVerify?: () => import(\"../cli/backup.js\").BackupVerifyResult;\n /** Cross-agent audit log (Issue #790). */\n auditStore?: import(\"../backends/audit-store.js\").AuditStore | null;\n agentHealthStore?: import(\"../backends/agent-health-store.js\").AgentHealthStore | null;\n};\n\n/** Chainable command type (Commander-style). */\ntype Chainable = {\n command(name: string): Chainable;\n description(desc: string): Chainable;\n action(fn: (...args: any[]) => void | Promise<void>): Chainable;\n option(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n requiredOption(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n argument?(name: string, desc?: string): Chainable;\n alias?(name: string): Chainable;\n};\n\nexport function registerHybridMemCli(mem: Chainable, ctx: HybridMemCliContext): void {\n const verifyContext: VerifyContext = {\n runVerify: ctx.runVerify,\n runInstall: ctx.runInstall,\n };\n try {\n registerVerifyCommands(mem, verifyContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:verify\",\n });\n throw err;\n }\n\n const distillContext: DistillContext = {\n runDistillWindow: ctx.runDistillWindow,\n runRecordDistill: ctx.runRecordDistill,\n runExtractDaily: ctx.runExtractDaily,\n runExtractProcedures: ctx.runExtractProcedures,\n runGenerateAutoSkills: ctx.runGenerateAutoSkills,\n runSkillsSuggest: ctx.runSkillsSuggest,\n runDistill: ctx.runDistill,\n runExtractDirectives: ctx.runExtractDirectives,\n runExtractReinforcement: ctx.runExtractReinforcement,\n runGenerateProposals: ctx.runGenerateProposals,\n };\n try {\n registerDistillCommands(mem, distillContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:distill\",\n });\n throw err;\n }\n\n const manageContext: ManageContext = ctx;\n try {\n registerManageCommands(mem, manageContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:manage\",\n });\n throw err;\n }\n\n try {\n registerSkillsCommands(mem, {\n crystallizationStore: ctx.crystallizationStore ?? null,\n cfg: ctx.cfg,\n factsDb: ctx.factsDb ?? null,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:skills\",\n });\n throw err;\n }\n\n try {\n registerTaskQueueStatusCommands(mem);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:task-queue-status\",\n });\n throw err;\n }\n\n try {\n registerStatusCommands(mem, {\n factsDb: ctx.factsDb,\n vectorDb: ctx.vectorDb,\n resolvedSqlitePath: ctx.resolvedSqlitePath,\n resolvedLancePath: ctx.resolvedLancePath,\n pluginId: PLUGIN_ID,\n cfg: ctx.cfg as unknown as Record<string, unknown>,\n costTracker: ctx.costTracker ?? null,\n auditStore: ctx.auditStore ?? null,\n agentHealthStore: ctx.agentHealthStore ?? null,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:status\",\n });\n throw err;\n }\n\n try {\n registerActiveTaskCommands(mem, ctx.cfg, ctx.activeTask);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:active-tasks\",\n });\n throw err;\n }\n\n try {\n registerGoalCommands(mem, ctx);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:goals\",\n });\n throw err;\n }\n\n try {\n registerVerifiedCommands(mem, {\n factsDb: ctx.factsDb,\n resolvedSqlitePath: ctx.resolvedSqlitePath,\n resolvePath: ctx.resolvePath,\n reverificationDays: ctx.cfg.verification?.reverificationDays,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:verified\",\n });\n throw err;\n }\n\n try {\n registerBenchmarkCommands(mem, ctx);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:benchmark\",\n });\n throw err;\n }\n\n // Register user-friendly commands (setup, demo, providers, health, doctor, examples)\n try {\n const userFriendlyContext: UserFriendlyContext = {\n cfg: ctx.cfg,\n factsDb: ctx.factsDb,\n vectorDb: ctx.vectorDb,\n wal: ctx.wal,\n embeddings: ctx.embeddings,\n runConfigSet: ctx.runConfigSet,\n };\n registerUserFriendlyCommands(mem, userFriendlyContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:user-friendly\",\n });\n throw err;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"register.js","names":[],"sources":["../../cli/register.ts"],"sourcesContent":["// @ts-nocheck\n/**\n * Register hybrid-mem CLI subcommands.\n * Thin orchestrator that delegates to specialized command modules.\n */\n\nimport type { CrystallizationStore } from \"../backends/crystallization-store.js\";\nimport type { FactsDB } from \"../backends/facts-db.js\";\nimport type { VectorDB } from \"../backends/vector-db.js\";\nimport type { WriteAheadLog } from \"../backends/wal.js\";\nimport type { HybridMemoryConfig } from \"../config.js\";\nimport type { EmbeddingProvider } from \"../services/embeddings.js\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\nimport type { mergeResults } from \"../services/merge-results.js\";\nimport type { AliasDB } from \"../services/retrieval-aliases.js\";\nimport { PLUGIN_ID } from \"../utils/constants.js\";\nimport { type ActiveTaskContext, registerActiveTaskCommands } from \"./active-tasks.js\";\nimport { registerBenchmarkCommands } from \"./benchmark.js\";\nimport { registerStatusCommands } from \"./cmd-status.js\";\nimport { registerUserFriendlyCommands, type UserFriendlyContext } from \"./cmd-user-friendly.js\";\nimport { type DistillContext, registerDistillCommands } from \"./distill.js\";\nimport { registerGoalCommands } from \"./goals.js\";\nimport { type ManageContext, registerManageCommands } from \"./manage.js\";\nimport { registerSkillsCommands } from \"./skills.js\";\nimport { registerTaskQueueStatusCommands } from \"./task-queue-status.js\";\nimport type {\n AnalyzeFeedbackPhrasesResult,\n BackfillCliResult,\n BackfillCliSink,\n ConfigCliResult,\n CredentialsAuditResult,\n CredentialsPruneResult,\n DistillCliResult,\n DistillCliSink,\n DistillWindowResult,\n ExtractDailyResult,\n ExtractDailySink,\n ExtractProceduresResult,\n FindDuplicatesResult,\n GenerateAutoSkillsResult,\n IngestFilesResult,\n IngestFilesSink,\n InstallCliResult,\n MigrateToVaultResult,\n RecordDistillResult,\n SelfCorrectionExtractResult,\n SelfCorrectionRunResult,\n StoreCliOpts,\n StoreCliResult,\n UninstallCliResult,\n UpgradeCliResult,\n VerifyCliSink,\n} from \"./types.js\";\nimport { registerVerifiedCommands } from \"./verified.js\";\nimport { registerVerifyCommands, type VerifyContext } from \"./verify.js\";\n\nexport type {\n ActiveTaskContext,\n AnalyzeFeedbackPhrasesResult,\n BackfillCliResult,\n BackfillCliSink,\n ConfigCliResult,\n CredentialsAuditResult,\n CredentialsPruneResult,\n DistillCliResult,\n DistillCliSink,\n DistillWindowResult,\n ExtractDailyResult,\n ExtractDailySink,\n ExtractProceduresResult,\n FindDuplicatesResult,\n GenerateAutoSkillsResult,\n IngestFilesResult,\n IngestFilesSink,\n InstallCliResult,\n MigrateToVaultResult,\n RecordDistillResult,\n SelfCorrectionExtractResult,\n SelfCorrectionRunResult,\n StoreCliOpts,\n StoreCliResult,\n UninstallCliResult,\n UpgradeCliResult,\n VerifyCliSink,\n};\n\nexport type HybridMemCliContext = {\n factsDb: FactsDB;\n vectorDb: VectorDB;\n wal?: WriteAheadLog | null;\n aliasDb?: AliasDB | null;\n crystallizationStore?: CrystallizationStore | null;\n versionInfo: {\n pluginVersion: string;\n memoryManagerVersion: string;\n schemaVersion: number;\n };\n embeddings: EmbeddingProvider;\n mergeResults: typeof mergeResults;\n parseSourceDate: (v: string | number | null | undefined) => number | null;\n getMemoryCategories: () => string[];\n cfg: HybridMemoryConfig;\n runStore: (opts: StoreCliOpts) => Promise<StoreCliResult>;\n runInstall: (opts: { dryRun: boolean }) => Promise<InstallCliResult>;\n runVerify: (\n opts: {\n fix: boolean;\n logFile?: string;\n testLlm?: boolean;\n reconcile?: boolean;\n reconcilePolicy?: \"conservative\" | \"balanced\" | \"aggressive\";\n reconcileMaxFixes?: number;\n },\n sink: VerifyCliSink,\n ) => Promise<void>;\n runDistillWindow: (opts: { json: boolean }) => Promise<DistillWindowResult>;\n runRecordDistill: () => Promise<RecordDistillResult>;\n runExtractDaily: (\n opts: { days: number; dryRun: boolean; verbose?: boolean },\n sink: ExtractDailySink,\n ) => Promise<ExtractDailyResult>;\n runExtractProcedures: (opts: {\n sessionDir?: string;\n days?: number;\n dryRun: boolean;\n verbose?: boolean;\n full?: boolean;\n }) => Promise<ExtractProceduresResult>;\n runGenerateAutoSkills: (opts: {\n dryRun: boolean;\n apply?: boolean;\n verbose?: boolean;\n max?: number;\n policy?: string;\n json?: boolean;\n bypassDuplicateSkillCache?: boolean;\n }) => Promise<GenerateAutoSkillsResult>;\n runSkillsSuggest: (opts: {\n dryRun?: boolean;\n apply?: boolean;\n days?: number;\n verbose?: boolean;\n }) => Promise<import(\"../services/memory-to-skills.js\").SkillsSuggestResult>;\n runBackfill: (\n opts: { dryRun: boolean; workspace?: string; limit?: number },\n sink: BackfillCliSink,\n ) => Promise<BackfillCliResult>;\n runIngestFiles: (\n opts: { dryRun: boolean; workspace?: string; paths?: string[] },\n sink: IngestFilesSink,\n ) => Promise<IngestFilesResult>;\n runDistill: (\n opts: {\n dryRun: boolean;\n all?: boolean;\n days?: number;\n since?: string;\n model?: string;\n verbose?: boolean;\n maxSessions?: number;\n maxSessionTokens?: number;\n full?: boolean;\n },\n sink: DistillCliSink,\n ) => Promise<DistillCliResult>;\n runMigrateToVault: () => Promise<MigrateToVaultResult | null>;\n runCredentialsList: () => Array<{\n service: string;\n type: string;\n url: string | null;\n }>;\n runCredentialsGet: (opts: { service: string; type?: string }) => {\n service: string;\n type: string;\n value: string;\n url: string | null;\n notes: string | null;\n } | null;\n runCredentialsAudit: () => CredentialsAuditResult;\n runCredentialsPrune: (opts: { dryRun: boolean; yes?: boolean; onlyFlags?: string[] }) => CredentialsPruneResult;\n runUninstall: (opts: { cleanAll: boolean; leaveConfig: boolean }) => Promise<UninstallCliResult>;\n runUpgrade: (version?: string) => Promise<UpgradeCliResult>;\n runConfigMode: (mode: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runConfigSet: (key: string, value: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runConfigSetHelp: (key: string) => ConfigCliResult | Promise<ConfigCliResult>;\n runFindDuplicates: (opts: {\n threshold: number;\n includeStructured: boolean;\n limit: number;\n }) => Promise<FindDuplicatesResult>;\n runConsolidate: (opts: {\n threshold: number;\n includeStructured: boolean;\n dryRun: boolean;\n limit: number;\n model: string;\n }) => Promise<{ clustersFound: number; merged: number; deleted: number }>;\n runReflection: (opts: { window: number; dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n factsAnalyzed: number;\n patternsExtracted: number;\n patternsStored: number;\n window: number;\n }>;\n runReflectionRules: (opts: { dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n rulesExtracted: number;\n rulesStored: number;\n diagnostics?: {\n modelResponseChars: number;\n parseSuccess: boolean;\n parsedCandidates: number;\n rejectedDuplicates: number;\n rejectedLowConfidence: number;\n stored: number;\n zeroRulesReason?: string;\n status: \"ok\" | \"partial\" | \"degraded\";\n };\n }>;\n runReflectionMeta: (opts: { dryRun: boolean; model: string; verbose?: boolean }) => Promise<{\n metaExtracted: number;\n metaStored: number;\n }>;\n reflectionConfig: {\n enabled: boolean;\n defaultWindow: number;\n minObservations: number;\n model: string;\n };\n runDreamCycle: (opts?: { verbose?: boolean }) => Promise<import(\"../services/dream-cycle.js\").DreamCycleResult>;\n runContinuousVerification: (opts?: {\n verbose?: boolean;\n }) => Promise<import(\"../services/continuous-verifier.js\").VerificationCycleResult>;\n runResolveContradictions: () => Promise<{\n autoResolved: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n ambiguous: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n }>;\n runResolveContradictionsDryRun: () => Promise<{\n autoResolvable: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n ambiguous: Array<{\n contradictionId: string;\n factIdNew: string;\n factIdOld: string;\n }>;\n }>;\n runResolveContradictionsProjectStateLww: (opts: {\n dryRun?: boolean;\n }) => Promise<import(\"../backends/facts-db/contradictions.js\").ProjectStateLwwResult>;\n runResolveContradictionsAuto: (\n opts: import(\"../backends/facts-db/contradictions.js\").ResolveContradictionsAutoOptions,\n ) => Promise<import(\"../backends/facts-db/contradictions.js\").ResolveContradictionsAutoResult>;\n runApplyContradictionReviewDecisions: (\n decisions: import(\"../backends/facts-db/contradictions.js\").ContradictionReviewDecision[],\n ) => Promise<import(\"../backends/facts-db/contradictions.js\").ApplyContradictionReviewResult>;\n runClassify: (opts: { dryRun: boolean; limit: number; model?: string }) => Promise<{\n reclassified: number;\n total: number;\n breakdown?: Record<string, number>;\n }>;\n autoClassifyConfig: {\n model: string;\n batchSize: number;\n suggestCategories?: boolean;\n };\n runCompaction: (opts?: { apply?: boolean }) => Promise<{\n hot: number;\n warm: number;\n cold: number;\n structural: number;\n changed?: number;\n examined?: number;\n apply?: boolean;\n }>;\n runBuildLanguageKeywords: (opts: {\n model?: string;\n dryRun?: boolean;\n }) => Promise<\n { ok: true; path: string; topLanguages: string[]; languagesAdded: number } | { ok: false; error: string }\n >;\n runEntityEnrichment: (opts: {\n limit: number;\n dryRun: boolean;\n model?: string;\n verbose?: boolean;\n all?: boolean;\n adaptiveCatchUp?: boolean;\n batchSize?: number;\n batchDelayMs?: number;\n timeBudgetSec?: number;\n targetDurationSec?: number;\n maxConcurrency?: number;\n providerPressureBudget?: number;\n onProgress?: (progress: import(\"../services/entity-enrichment-cli.js\").EntityEnrichmentProgress) => void;\n onAdaptivePacing?: (state: import(\"../services/entity-enrichment-cli.js\").EntityEnrichmentAdaptivePacing) => void;\n }) => Promise<import(\"../services/entity-enrichment-cli.js\").EntityEnrichmentCliResult>;\n runSelfCorrectionExtract: (opts: {\n days?: number;\n outputPath?: string;\n verbose?: boolean;\n }) => Promise<SelfCorrectionExtractResult>;\n runSelfCorrectionRun: (opts: {\n extractPath?: string;\n incidents?: Array<{\n userMessage: string;\n precedingAssistant: string;\n followingAssistant: string;\n timestamp?: string;\n sessionFile: string;\n }>;\n workspace?: string;\n dryRun?: boolean;\n model?: string;\n approve?: boolean;\n applyTools?: boolean;\n full?: boolean;\n verbose?: boolean;\n }) => Promise<SelfCorrectionRunResult>;\n runAnalyzeFeedbackPhrases: (opts: {\n days?: number;\n model?: string;\n outputPath?: string;\n learn?: boolean;\n }) => Promise<AnalyzeFeedbackPhrasesResult>;\n runExtractDirectives: (opts: { days?: number; verbose?: boolean; dryRun?: boolean; full?: boolean }) => Promise<{\n incidents: Array<{\n userMessage: string;\n categories: string[];\n extractedRule: string;\n precedingAssistant: string;\n confidence: number;\n timestamp?: string;\n sessionFile: string;\n }>;\n sessionsScanned: number;\n skipped?: boolean;\n }>;\n runExtractReinforcement: (opts: { days?: number; verbose?: boolean; dryRun?: boolean; full?: boolean }) => Promise<{\n incidents: Array<{\n userMessage: string;\n agentBehavior: string;\n recalledMemoryIds: string[];\n toolCallSequence: string[];\n confidence: number;\n timestamp?: string;\n sessionFile: string;\n }>;\n sessionsScanned: number;\n skipped?: boolean;\n }>;\n runExtractImplicitFeedback?: (opts: {\n days?: number;\n verbose?: boolean;\n dryRun?: boolean;\n full?: boolean;\n includeTrajectories?: boolean;\n includeClosedLoop?: boolean;\n onProgress?: (snapshot: import(\"./cmd-feedback.js\").ExtractImplicitFeedbackProgressSnapshot) => void;\n }) => Promise<{\n signalsExtracted: number;\n positiveCount: number;\n negativeCount: number;\n trajectoriesBuilt: number;\n sessionsScanned: number;\n sessionsVisited: number;\n sessionsProcessed: number;\n sessionsSkipped: number;\n sessionsDeferred: number;\n backlogSessionsEstimate: number;\n backlogSignalsEstimate: number;\n backlogTrajectoriesEstimate: number;\n partial: boolean;\n partialReason?: import(\"./cmd-feedback.js\").ExtractImplicitFeedbackStopReason;\n closedLoopReport?: string;\n skipped?: boolean;\n }>;\n runGenerateProposals?: (opts: { dryRun: boolean; verbose?: boolean }) => Promise<{ created: number }>;\n runExport: (opts: {\n outputPath: string;\n excludeCredentials?: boolean;\n includeCredentials?: boolean;\n sources?: string[];\n mode?: \"replace\" | \"additive\";\n }) => Promise<{\n factsExported: number;\n proceduresExported: number;\n filesWritten: number;\n outputPath: string;\n }>;\n richStatsExtras?: {\n getCredentialsCount: () => number;\n getProposalsPending: () => number;\n getProposalsAvailable: () => boolean;\n getWalPending: () => Promise<number> | number;\n getLastRunTimestamps: () => {\n distill?: string;\n reflect?: string;\n compact?: string;\n vectordbOptimize?: string;\n };\n getStorageSizes: () => Promise<{\n sqliteBytes?: number;\n lanceBytes?: number;\n lanceBytesTimedOut?: boolean;\n }>;\n getCronJobsStatus?: () => Array<{\n name: string;\n pluginJobId: string;\n enabled: boolean;\n scheduleExpr: string | null;\n lastRunAtMs: number | null;\n }>;\n };\n listCommands?: {\n listProposals: (opts: { status?: string }) => Promise<\n Array<{\n id: string;\n title: string;\n targetFile: string;\n status: string;\n confidence: number;\n createdAt: number;\n }>\n >;\n proposalApprove: (id: string) => Promise<{ ok: boolean; error?: string }>;\n proposalReject: (id: string, reason?: string) => Promise<{ ok: boolean; error?: string }>;\n listCorrections: (opts: { workspace?: string }) => Promise<{\n reportPath: string | null;\n items: string[];\n }>;\n correctionsApproveAll: (opts: { workspace?: string }) => Promise<{\n applied: number;\n error?: string;\n }>;\n showItem: (id: string) => Promise<{ type: \"fact\" | \"proposal\"; data: unknown } | null>;\n triageProposals?: (opts: {\n dryRun?: boolean;\n apply?: boolean;\n policy?: string;\n max?: number;\n json?: boolean;\n stateDb?: string;\n workspace?: string;\n }) => Promise<import(\"../services/persona-proposal-triage.js\").PersonaProposalTriageResult>;\n };\n tieringEnabled: boolean;\n resolvedSqlitePath?: string;\n resolvePath?: (file: string) => string;\n /** Active task working memory context (required when activeTask.enabled = true) */\n activeTask?: ActiveTaskContext;\n runCrossAgentLearning?: (opts?: {\n verbose?: boolean;\n }) => Promise<import(\"../cli/handlers.js\").CrossAgentLearningCliResult>;\n runToolEffectiveness?: (opts?: { verbose?: boolean }) => Promise<string>;\n runCostReport?: (opts: import(\"../cli/handlers.js\").CostReportCliOpts, sink: { log: (msg: string) => void }) => void;\n pruneCostLog?: (retainDays?: number) => number;\n /** Resolved path to LanceDB vector store (for backup). */\n resolvedLancePath?: string;\n /** Create a point-in-time backup snapshot (Issue #276). */\n runBackup?: (opts?: { backupDir?: string }) => Promise<import(\"../cli/backup.js\").BackupCliResult>;\n /** Verify SQLite DB integrity without creating a backup (Issue #276). */\n runBackupVerify?: () => import(\"../cli/backup.js\").BackupVerifyResult;\n /** Cross-agent audit log (Issue #790). */\n auditStore?: import(\"../backends/audit-store.js\").AuditStore | null;\n agentHealthStore?: import(\"../backends/agent-health-store.js\").AgentHealthStore | null;\n};\n\n/** Chainable command type (Commander-style). */\ntype Chainable = {\n command(name: string): Chainable;\n description(desc: string): Chainable;\n action(fn: (...args: any[]) => void | Promise<void>): Chainable;\n option(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n requiredOption(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n argument?(name: string, desc?: string): Chainable;\n alias?(name: string): Chainable;\n};\n\nexport function registerHybridMemCli(mem: Chainable, ctx: HybridMemCliContext): void {\n const verifyContext: VerifyContext = {\n runVerify: ctx.runVerify,\n runInstall: ctx.runInstall,\n };\n try {\n registerVerifyCommands(mem, verifyContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:verify\",\n });\n throw err;\n }\n\n const distillContext: DistillContext = {\n runDistillWindow: ctx.runDistillWindow,\n runRecordDistill: ctx.runRecordDistill,\n runExtractDaily: ctx.runExtractDaily,\n runExtractProcedures: ctx.runExtractProcedures,\n runGenerateAutoSkills: ctx.runGenerateAutoSkills,\n runSkillsSuggest: ctx.runSkillsSuggest,\n runDistill: ctx.runDistill,\n runExtractDirectives: ctx.runExtractDirectives,\n runExtractReinforcement: ctx.runExtractReinforcement,\n runGenerateProposals: ctx.runGenerateProposals,\n };\n try {\n registerDistillCommands(mem, distillContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:distill\",\n });\n throw err;\n }\n\n const manageContext: ManageContext = ctx;\n try {\n registerManageCommands(mem, manageContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:manage\",\n });\n throw err;\n }\n\n try {\n registerSkillsCommands(mem, {\n crystallizationStore: ctx.crystallizationStore ?? null,\n cfg: ctx.cfg,\n factsDb: ctx.factsDb ?? null,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:skills\",\n });\n throw err;\n }\n\n try {\n registerTaskQueueStatusCommands(mem);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:task-queue-status\",\n });\n throw err;\n }\n\n try {\n registerStatusCommands(mem, {\n factsDb: ctx.factsDb,\n vectorDb: ctx.vectorDb,\n resolvedSqlitePath: ctx.resolvedSqlitePath,\n resolvedLancePath: ctx.resolvedLancePath,\n pluginId: PLUGIN_ID,\n cfg: ctx.cfg as unknown as Record<string, unknown>,\n costTracker: ctx.costTracker ?? null,\n auditStore: ctx.auditStore ?? null,\n agentHealthStore: ctx.agentHealthStore ?? null,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:status\",\n });\n throw err;\n }\n\n try {\n registerActiveTaskCommands(mem, ctx.cfg, ctx.activeTask);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:active-tasks\",\n });\n throw err;\n }\n\n try {\n registerGoalCommands(mem, ctx);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:goals\",\n });\n throw err;\n }\n\n try {\n registerVerifiedCommands(mem, {\n factsDb: ctx.factsDb,\n resolvedSqlitePath: ctx.resolvedSqlitePath,\n resolvePath: ctx.resolvePath,\n reverificationDays: ctx.cfg.verification?.reverificationDays,\n });\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:verified\",\n });\n throw err;\n }\n\n try {\n registerBenchmarkCommands(mem, ctx);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:benchmark\",\n });\n throw err;\n }\n\n // Register user-friendly commands (setup, demo, providers, health, doctor, examples)\n try {\n const userFriendlyContext: UserFriendlyContext = {\n cfg: ctx.cfg,\n factsDb: ctx.factsDb,\n vectorDb: ctx.vectorDb,\n wal: ctx.wal,\n embeddings: ctx.embeddings,\n runConfigSet: ctx.runConfigSet,\n };\n registerUserFriendlyCommands(mem, userFriendlyContext);\n } catch (err) {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"registration\",\n operation: \"register-cli:user-friendly\",\n });\n throw err;\n }\n}\n"],"mappings":"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"}
|
package/dist/cli/shared.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.js","names":[],"sources":["../../cli/shared.ts"],"sourcesContent":["/**\n * Shared CLI utilities\n *\n * Contains concurrency lock infrastructure and other utilities shared across\n * multiple CLI command modules.\n */\n\nimport { basename } from \"node:path\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\n\n/**\n * Format a timestamp in milliseconds as a human-readable relative time string.\n * e.g. \"in 3h\", \"5m ago\", \"just now\"\n */\nexport function relativeTime(ms: number): string {\n const diff = ms - Date.now();\n const abs = Math.abs(diff);\n const future = diff > 0;\n if (abs < 60000) return future ? \"in <1m\" : \"just now\";\n if (abs < 3600000) {\n const m = Math.floor(abs / 60000);\n return future ? `in ${m}m` : `${m}m ago`;\n }\n if (abs < 86400000) {\n const h = Math.floor(abs / 3600000);\n return future ? `in ${h}h` : `${h}h ago`;\n }\n const d = Math.floor(abs / 86400000);\n return future ? `in ${d}d` : `${d}d ago`;\n}\n\nexport type Chainable = {\n command(name: string): Chainable;\n description(desc: string): Chainable;\n action(fn: (...args: any[]) => void | Promise<void>): Chainable;\n option(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n requiredOption(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n argument?(name: string, desc?: string): Chainable;\n alias?(name: string): Chainable;\n};\n\nfunction isStandaloneCliProcess(argv = process.argv): boolean {\n const executable = basename(argv[1] ?? \"\");\n return executable === \"openclaw\" || executable === \"hybrid-mem\";\n}\n\n/** Wrap async action to exit on completion (only for standalone CLI). */\nexport const withExit =\n <A extends unknown[], R>(fn: (...args: A) => Promise<R>) =>\n (...args: A) => {\n const isStandaloneCli = isStandaloneCliProcess();\n return Promise.resolve(fn(...args)).then(\n () => {\n if (isStandaloneCli) process.exit(process.exitCode ?? 0);\n },\n (err: unknown) => {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"cli\",\n operation: \"cli-command\",\n });\n console.error(err);\n if (isStandaloneCli) process.exit(1);\n else throw err;\n },\n );\n };\n\n/** In-memory concurrency lock: prevents two simultaneous scans of the same type. */\nconst SCAN_IN_PROGRESS = new Map<string, boolean>();\n\n/** 23-hour threshold for startup guard (milliseconds). */\nexport const SCAN_MIN_INTERVAL_MS = 23 * 60 * 60 * 1000;\n\n/**\n * Apply the 23h startup guard and concurrency lock for a scan type.\n * Returns a skip reason string if the scan should be skipped, or null if it can proceed.\n * If it can proceed, marks the scan as in-progress (caller must call clearScanLock when done).\n */\nexport function acquireScanSlot(\n scanType: string,\n lastRunAt: number | undefined,\n logger: { info?: (s: string) => void },\n): string | null {\n if (SCAN_IN_PROGRESS.get(scanType)) {\n const msg = `Skipping ${scanType}: already running`;\n logger.info?.(msg);\n return msg;\n }\n if (lastRunAt !== undefined && lastRunAt !== 0 && Date.now() - lastRunAt < SCAN_MIN_INTERVAL_MS) {\n const hoursAgo = ((Date.now() - lastRunAt) / 3_600_000).toFixed(1);\n const msg = `Skipping ${scanType}: last run was ${hoursAgo}h ago (threshold: 23h). Use --full to override.`;\n logger.info?.(msg);\n return msg;\n }\n SCAN_IN_PROGRESS.set(scanType, true);\n return null;\n}\n\nexport function clearScanLock(scanType: string): void {\n SCAN_IN_PROGRESS.delete(scanType);\n}\n\n/**\n * Approximate run interval for \"stale\" detection per cron expression.\n * Returns interval in milliseconds, or null if not recognized.\n */\nexport function approxIntervalMs(cron?: string | null): number | null {\n if (!cron) return null;\n const t = cron.trim();\n if (/^\\d+\\s+\\d+\\s+\\*\\s+\\*\\s+\\*$/.test(t)) return 24 * 60 * 60 * 1000;\n if (/^\\d+\\s+\\d+\\s+\\*\\s+\\*\\s+[0-7]$/.test(t)) return 7 * 24 * 60 * 60 * 1000;\n if (/^\\d+\\s+\\d+\\s+\\d+\\s+\\*\\s+\\*$/.test(t)) return 30 * 24 * 60 * 60 * 1000;\n const everyN = /^\\d+\\s+\\*\\/(\\d+)\\s+\\*\\s+\\*\\s+\\*$/.exec(t);\n if (everyN) return Number(everyN[1]) * 60 * 60 * 1000;\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,OAAO,KAAK,KAAK,
|
|
1
|
+
{"version":3,"file":"shared.js","names":[],"sources":["../../cli/shared.ts"],"sourcesContent":["/**\n * Shared CLI utilities\n *\n * Contains concurrency lock infrastructure and other utilities shared across\n * multiple CLI command modules.\n */\n\nimport { basename } from \"node:path\";\nimport { capturePluginError } from \"../services/error-reporter.js\";\n\n/**\n * Format a timestamp in milliseconds as a human-readable relative time string.\n * e.g. \"in 3h\", \"5m ago\", \"just now\"\n */\nexport function relativeTime(ms: number): string {\n const diff = ms - Date.now();\n const abs = Math.abs(diff);\n const future = diff > 0;\n if (abs < 60000) return future ? \"in <1m\" : \"just now\";\n if (abs < 3600000) {\n const m = Math.floor(abs / 60000);\n return future ? `in ${m}m` : `${m}m ago`;\n }\n if (abs < 86400000) {\n const h = Math.floor(abs / 3600000);\n return future ? `in ${h}h` : `${h}h ago`;\n }\n const d = Math.floor(abs / 86400000);\n return future ? `in ${d}d` : `${d}d ago`;\n}\n\nexport type Chainable = {\n command(name: string): Chainable;\n description(desc: string): Chainable;\n action(fn: (...args: any[]) => void | Promise<void>): Chainable;\n option(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n requiredOption(flags: string, desc?: string, defaultValue?: unknown): Chainable;\n argument?(name: string, desc?: string): Chainable;\n alias?(name: string): Chainable;\n};\n\nfunction isStandaloneCliProcess(argv = process.argv): boolean {\n const executable = basename(argv[1] ?? \"\");\n return executable === \"openclaw\" || executable === \"hybrid-mem\";\n}\n\n/** Wrap async action to exit on completion (only for standalone CLI). */\nexport const withExit =\n <A extends unknown[], R>(fn: (...args: A) => Promise<R>) =>\n (...args: A) => {\n const isStandaloneCli = isStandaloneCliProcess();\n return Promise.resolve(fn(...args)).then(\n () => {\n if (isStandaloneCli) process.exit(process.exitCode ?? 0);\n },\n (err: unknown) => {\n capturePluginError(err instanceof Error ? err : new Error(String(err)), {\n subsystem: \"cli\",\n operation: \"cli-command\",\n });\n console.error(err);\n if (isStandaloneCli) process.exit(1);\n else throw err;\n },\n );\n };\n\n/** In-memory concurrency lock: prevents two simultaneous scans of the same type. */\nconst SCAN_IN_PROGRESS = new Map<string, boolean>();\n\n/** 23-hour threshold for startup guard (milliseconds). */\nexport const SCAN_MIN_INTERVAL_MS = 23 * 60 * 60 * 1000;\n\n/**\n * Apply the 23h startup guard and concurrency lock for a scan type.\n * Returns a skip reason string if the scan should be skipped, or null if it can proceed.\n * If it can proceed, marks the scan as in-progress (caller must call clearScanLock when done).\n */\nexport function acquireScanSlot(\n scanType: string,\n lastRunAt: number | undefined,\n logger: { info?: (s: string) => void },\n): string | null {\n if (SCAN_IN_PROGRESS.get(scanType)) {\n const msg = `Skipping ${scanType}: already running`;\n logger.info?.(msg);\n return msg;\n }\n if (lastRunAt !== undefined && lastRunAt !== 0 && Date.now() - lastRunAt < SCAN_MIN_INTERVAL_MS) {\n const hoursAgo = ((Date.now() - lastRunAt) / 3_600_000).toFixed(1);\n const msg = `Skipping ${scanType}: last run was ${hoursAgo}h ago (threshold: 23h). Use --full to override.`;\n logger.info?.(msg);\n return msg;\n }\n SCAN_IN_PROGRESS.set(scanType, true);\n return null;\n}\n\nexport function clearScanLock(scanType: string): void {\n SCAN_IN_PROGRESS.delete(scanType);\n}\n\n/**\n * Approximate run interval for \"stale\" detection per cron expression.\n * Returns interval in milliseconds, or null if not recognized.\n */\nexport function approxIntervalMs(cron?: string | null): number | null {\n if (!cron) return null;\n const t = cron.trim();\n if (/^\\d+\\s+\\d+\\s+\\*\\s+\\*\\s+\\*$/.test(t)) return 24 * 60 * 60 * 1000;\n if (/^\\d+\\s+\\d+\\s+\\*\\s+\\*\\s+[0-7]$/.test(t)) return 7 * 24 * 60 * 60 * 1000;\n if (/^\\d+\\s+\\d+\\s+\\d+\\s+\\*\\s+\\*$/.test(t)) return 30 * 24 * 60 * 60 * 1000;\n const everyN = /^\\d+\\s+\\*\\/(\\d+)\\s+\\*\\s+\\*\\s+\\*$/.exec(t);\n if (everyN) return Number(everyN[1]) * 60 * 60 * 1000;\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;AAcA,SAAgB,aAAa,IAAoB;CAC/C,MAAM,OAAO,KAAK,KAAK,IAAI;CAC3B,MAAM,MAAM,KAAK,IAAI,IAAI;CACzB,MAAM,SAAS,OAAO;CACtB,IAAI,MAAM,KAAO,OAAO,SAAS,WAAW;CAC5C,IAAI,MAAM,MAAS;EACjB,MAAM,IAAI,KAAK,MAAM,MAAM,GAAK;EAChC,OAAO,SAAS,MAAM,EAAE,KAAK,GAAG,EAAE;CACpC;CACA,IAAI,MAAM,OAAU;EAClB,MAAM,IAAI,KAAK,MAAM,MAAM,IAAO;EAClC,OAAO,SAAS,MAAM,EAAE,KAAK,GAAG,EAAE;CACpC;CACA,MAAM,IAAI,KAAK,MAAM,MAAM,KAAQ;CACnC,OAAO,SAAS,MAAM,EAAE,KAAK,GAAG,EAAE;AACpC;AAYA,SAAS,uBAAuB,OAAO,QAAQ,MAAe;CAC5D,MAAM,aAAa,SAAS,KAAK,MAAM,EAAE;CACzC,OAAO,eAAe,cAAc,eAAe;AACrD;;AAGA,MAAa,YACc,QACxB,GAAG,SAAY;CACd,MAAM,kBAAkB,uBAAuB;CAC/C,OAAO,QAAQ,QAAQ,GAAG,GAAG,IAAI,CAAC,EAAE,WAC5B;EACJ,IAAI,iBAAiB,QAAQ,KAAK,QAAQ,YAAY,CAAC;CACzD,IACC,QAAiB;EAChB,mBAAmB,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,GAAG,CAAC,GAAG;GACtE,WAAW;GACX,WAAW;EACb,CAAC;EACD,QAAQ,MAAM,GAAG;EACjB,IAAI,iBAAiB,QAAQ,KAAK,CAAC;OAC9B,MAAM;CACb,CACF;AACF;;AAGF,MAAM,mCAAmB,IAAI,IAAqB;;AAGlD,MAAa,uBAAuB,OAAU,KAAK;;;;;;AAOnD,SAAgB,gBACd,UACA,WACA,QACe;CACf,IAAI,iBAAiB,IAAI,QAAQ,GAAG;EAClC,MAAM,MAAM,YAAY,SAAS;EACjC,OAAO,OAAO,GAAG;EACjB,OAAO;CACT;CACA,IAAI,cAAc,KAAA,KAAa,cAAc,KAAK,KAAK,IAAI,IAAI,YAAA,OAAkC;EAE/F,MAAM,MAAM,YAAY,SAAS,mBADd,KAAK,IAAI,IAAI,aAAa,MAAW,QAAQ,CACP,EAAE;EAC3D,OAAO,OAAO,GAAG;EACjB,OAAO;CACT;CACA,iBAAiB,IAAI,UAAU,IAAI;CACnC,OAAO;AACT;AAEA,SAAgB,cAAc,UAAwB;CACpD,iBAAiB,OAAO,QAAQ;AAClC;;;;;AAMA,SAAgB,iBAAiB,MAAqC;CACpE,IAAI,CAAC,MAAM,OAAO;CAClB,MAAM,IAAI,KAAK,KAAK;CACpB,IAAI,6BAA6B,KAAK,CAAC,GAAG,OAAO,OAAU,KAAK;CAChE,IAAI,gCAAgC,KAAK,CAAC,GAAG,OAAO,QAAc,KAAK;CACvE,IAAI,8BAA8B,KAAK,CAAC,GAAG,OAAO,MAAU,KAAK,KAAK;CACtE,MAAM,SAAS,mCAAmC,KAAK,CAAC;CACxD,IAAI,QAAQ,OAAO,OAAO,OAAO,EAAE,IAAI,KAAK,KAAK;CACjD,OAAO;AACT"}
|