principles-disciple 1.8.1 → 1.8.2
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/ADVANCED_CONFIG_ZH.md +97 -0
- package/AGENT_INSTALL.md +173 -0
- package/AGENT_INSTALL_EN.md +173 -0
- package/INSTALL.md +256 -0
- package/SKILL.md +63 -0
- package/docs/COMMAND_REFERENCE.md +76 -0
- package/docs/COMMAND_REFERENCE_EN.md +79 -0
- package/esbuild.config.js +75 -0
- package/openclaw.plugin.json +4 -4
- package/package.json +11 -13
- package/scripts/build-web.mjs +46 -0
- package/scripts/install-dependencies.cjs +47 -0
- package/scripts/sync-plugin.mjs +802 -0
- package/scripts/verify-build.mjs +109 -0
- package/src/agents/nocturnal-dreamer.md +152 -0
- package/src/agents/nocturnal-philosopher.md +138 -0
- package/src/agents/nocturnal-reflector.md +126 -0
- package/src/agents/nocturnal-scribe.md +164 -0
- package/src/commands/capabilities.ts +85 -0
- package/{dist/commands/context.js → src/commands/context.ts} +78 -38
- package/src/commands/evolution-status.ts +146 -0
- package/src/commands/export.ts +111 -0
- package/src/commands/focus.ts +533 -0
- package/src/commands/nocturnal-review.ts +311 -0
- package/src/commands/nocturnal-rollout.ts +763 -0
- package/src/commands/nocturnal-train.ts +1002 -0
- package/{dist/commands/pain.js → src/commands/pain.ts} +68 -49
- package/src/commands/principle-rollback.ts +27 -0
- package/{dist/commands/rollback.js → src/commands/rollback.ts} +44 -12
- package/src/commands/samples.ts +60 -0
- package/src/commands/strategy.ts +38 -0
- package/{dist/commands/thinking-os.js → src/commands/thinking-os.ts} +59 -36
- package/src/commands/workflow-debug.ts +128 -0
- package/{dist/config/defaults/runtime.js → src/config/defaults/runtime.ts} +12 -5
- package/src/config/errors.ts +163 -0
- package/{dist/config/index.d.ts → src/config/index.ts} +2 -1
- package/src/constants/diagnostician.ts +66 -0
- package/src/constants/tools.ts +62 -0
- package/src/core/adaptive-thresholds.ts +476 -0
- package/{dist/core/config-service.js → src/core/config-service.ts} +7 -4
- package/{dist/core/config.js → src/core/config.ts} +158 -46
- package/src/core/control-ui-db.ts +435 -0
- package/{dist/core/detection-funnel.js → src/core/detection-funnel.ts} +36 -21
- package/{dist/core/detection-service.js → src/core/detection-service.ts} +7 -4
- package/{dist/core/dictionary-service.js → src/core/dictionary-service.ts} +7 -4
- package/{dist/core/dictionary.js → src/core/dictionary.ts} +57 -34
- package/src/core/empathy-keyword-matcher.ts +327 -0
- package/src/core/empathy-types.ts +218 -0
- package/src/core/event-log.ts +544 -0
- package/src/core/evolution-engine.ts +612 -0
- package/src/core/evolution-logger.ts +353 -0
- package/src/core/evolution-migration.ts +77 -0
- package/src/core/evolution-reducer.ts +731 -0
- package/src/core/evolution-types.ts +456 -0
- package/src/core/external-training-contract.ts +527 -0
- package/src/core/focus-history.ts +1458 -0
- package/src/core/hygiene/tracker.ts +117 -0
- package/{dist/core/init.js → src/core/init.ts} +39 -26
- package/src/core/local-worker-routing.ts +617 -0
- package/{dist/core/migration.js → src/core/migration.ts} +18 -11
- package/src/core/model-deployment-registry.ts +722 -0
- package/src/core/model-training-registry.ts +813 -0
- package/src/core/nocturnal-arbiter.ts +706 -0
- package/src/core/nocturnal-candidate-scoring.ts +392 -0
- package/src/core/nocturnal-compliance.ts +1075 -0
- package/src/core/nocturnal-dataset.ts +668 -0
- package/src/core/nocturnal-executability.ts +428 -0
- package/src/core/nocturnal-export.ts +390 -0
- package/{dist/core/nocturnal-paths.js → src/core/nocturnal-paths.ts} +49 -23
- package/src/core/nocturnal-trajectory-extractor.ts +484 -0
- package/src/core/nocturnal-trinity.ts +1384 -0
- package/src/core/pain.ts +122 -0
- package/{dist/core/path-resolver.js → src/core/path-resolver.ts} +157 -36
- package/{dist/core/paths.js → src/core/paths.ts} +13 -4
- package/src/core/principle-training-state.ts +450 -0
- package/src/core/profile.ts +226 -0
- package/src/core/promotion-gate.ts +822 -0
- package/{dist/core/risk-calculator.js → src/core/risk-calculator.ts} +42 -16
- package/{dist/core/session-tracker.js → src/core/session-tracker.ts} +175 -62
- package/src/core/shadow-observation-registry.ts +534 -0
- package/{dist/core/system-logger.js → src/core/system-logger.ts} +9 -5
- package/src/core/thinking-models.ts +217 -0
- package/src/core/training-program.ts +630 -0
- package/src/core/trajectory-types.ts +243 -0
- package/src/core/trajectory.ts +1673 -0
- package/{dist/core/workspace-context.js → src/core/workspace-context.ts} +57 -32
- package/src/hooks/bash-risk.ts +171 -0
- package/src/hooks/edit-verification.ts +295 -0
- package/src/hooks/gate-block-helper.ts +160 -0
- package/src/hooks/gate.ts +210 -0
- package/src/hooks/gfi-gate.ts +177 -0
- package/src/hooks/lifecycle.ts +326 -0
- package/{dist/hooks/llm.js → src/hooks/llm.ts} +160 -80
- package/src/hooks/message-sanitize.ts +45 -0
- package/src/hooks/pain.ts +384 -0
- package/src/hooks/progressive-trust-gate.ts +174 -0
- package/src/hooks/prompt.ts +920 -0
- package/src/hooks/subagent.ts +207 -0
- package/src/hooks/thinking-checkpoint.ts +73 -0
- package/src/hooks/trajectory-collector.ts +290 -0
- package/src/http/principles-console-route.ts +716 -0
- package/src/i18n/commands.ts +117 -0
- package/src/index.ts +694 -0
- package/src/service/central-database.ts +831 -0
- package/src/service/control-ui-query-service.ts +888 -0
- package/src/service/evolution-query-service.ts +405 -0
- package/src/service/evolution-worker.ts +1646 -0
- package/src/service/health-query-service.ts +836 -0
- package/{dist/service/nocturnal-runtime.js → src/service/nocturnal-runtime.ts} +235 -79
- package/src/service/nocturnal-service.ts +1015 -0
- package/src/service/nocturnal-target-selector.ts +532 -0
- package/src/service/phase3-input-filter.ts +237 -0
- package/src/service/runtime-summary-service.ts +757 -0
- package/src/service/subagent-workflow/deep-reflect-workflow-manager.ts +513 -0
- package/{dist/service/subagent-workflow/empathy-observer-workflow-manager.js → src/service/subagent-workflow/empathy-observer-workflow-manager.ts} +240 -117
- package/src/service/subagent-workflow/index.ts +51 -0
- package/src/service/subagent-workflow/nocturnal-workflow-manager.ts +856 -0
- package/src/service/subagent-workflow/runtime-direct-driver.ts +166 -0
- package/{dist/service/subagent-workflow/types.d.ts → src/service/subagent-workflow/types.ts} +137 -18
- package/src/service/subagent-workflow/workflow-store.ts +328 -0
- package/src/service/trajectory-service.ts +15 -0
- package/{dist/tools/critique-prompt.js → src/tools/critique-prompt.ts} +25 -8
- package/src/tools/deep-reflect.ts +349 -0
- package/{dist/tools/model-index.js → src/tools/model-index.ts} +33 -17
- package/src/types/event-types.ts +453 -0
- package/src/types/hygiene-types.ts +31 -0
- package/src/types/principle-tree-schema.ts +244 -0
- package/src/types/runtime-summary.ts +49 -0
- package/src/types.ts +74 -0
- package/src/utils/file-lock.ts +391 -0
- package/{dist/utils/glob-match.js → src/utils/glob-match.ts} +21 -20
- package/{dist/utils/hashing.js → src/utils/hashing.ts} +6 -4
- package/src/utils/io.ts +110 -0
- package/{dist/utils/nlp.js → src/utils/nlp.ts} +19 -12
- package/{dist/utils/plugin-logger.js → src/utils/plugin-logger.ts} +33 -8
- package/src/utils/subagent-probe.ts +94 -0
- package/templates/langs/zh/skills/pd-diagnostician/SKILL.md +70 -1
- package/templates/pain_settings.json +2 -1
- package/tests/README.md +120 -0
- package/tests/build-artifacts.test.ts +111 -0
- package/tests/commands/evolution-status.test.ts +222 -0
- package/tests/commands/evolver.test.ts +22 -0
- package/tests/commands/export.test.ts +78 -0
- package/tests/commands/nocturnal-review.test.ts +448 -0
- package/tests/commands/nocturnal-train.test.ts +97 -0
- package/tests/commands/pain.test.ts +108 -0
- package/tests/commands/samples.test.ts +65 -0
- package/tests/commands/strategy.test.ts +34 -0
- package/tests/commands/thinking-os.test.ts +88 -0
- package/tests/core/adaptive-thresholds.test.ts +261 -0
- package/tests/core/config-service.test.ts +89 -0
- package/tests/core/config.test.ts +90 -0
- package/tests/core/control-ui-db.test.ts +75 -0
- package/tests/core/core-template-guidance.test.ts +21 -0
- package/tests/core/detection-funnel.test.ts +63 -0
- package/tests/core/detection-service.test.ts +50 -0
- package/tests/core/dictionary-service.test.ts +116 -0
- package/tests/core/dictionary.test.ts +168 -0
- package/tests/core/empathy-keyword-matcher.test.ts +209 -0
- package/tests/core/event-log.test.ts +181 -0
- package/tests/core/evolution-e2e.test.ts +58 -0
- package/tests/core/evolution-engine-gate-integration.test.ts +543 -0
- package/tests/core/evolution-engine.test.ts +562 -0
- package/tests/core/evolution-logger.test.ts +148 -0
- package/tests/core/evolution-migration.test.ts +50 -0
- package/tests/core/evolution-paths.test.ts +21 -0
- package/tests/core/evolution-reducer.detector-metadata.test.ts +602 -0
- package/tests/core/evolution-reducer.test.ts +180 -0
- package/tests/core/evolution-types-loop.test.ts +48 -0
- package/tests/core/evolution-user-stories.e2e.test.ts +249 -0
- package/tests/core/external-training-contract.test.ts +463 -0
- package/tests/core/focus-history.test.ts +682 -0
- package/tests/core/init-flatten.test.ts +69 -0
- package/tests/core/init-refactor.test.ts +87 -0
- package/tests/core/init-v1.3.test.ts +46 -0
- package/tests/core/init.test.ts +190 -0
- package/tests/core/local-worker-routing.test.ts +757 -0
- package/tests/core/migration.test.ts +84 -0
- package/tests/core/model-deployment-registry.test.ts +845 -0
- package/tests/core/model-training-registry.test.ts +889 -0
- package/tests/core/nocturnal-arbiter.test.ts +494 -0
- package/tests/core/nocturnal-candidate-scoring.test.ts +400 -0
- package/tests/core/nocturnal-compliance.test.ts +646 -0
- package/tests/core/nocturnal-dataset.test.ts +892 -0
- package/tests/core/nocturnal-executability.test.ts +357 -0
- package/tests/core/nocturnal-export.test.ts +462 -0
- package/tests/core/nocturnal-reviewed-subset-comparison.test.ts +428 -0
- package/tests/core/nocturnal-trajectory-extractor.test.ts +634 -0
- package/tests/core/nocturnal-trinity.test.ts +953 -0
- package/tests/core/pain.test.ts +33 -0
- package/tests/core/path-resolver.test.ts +57 -0
- package/tests/core/paths-refactor.test.ts +42 -0
- package/tests/core/phase7-rollout-integration.test.ts +477 -0
- package/tests/core/principle-training-state.test.ts +712 -0
- package/tests/core/profile.test.ts +56 -0
- package/tests/core/promotion-gate.test.ts +556 -0
- package/tests/core/risk-calculator.test.ts +168 -0
- package/tests/core/session-tracker.test.ts +191 -0
- package/tests/core/training-program.test.ts +472 -0
- package/tests/core/trajectory.test.ts +265 -0
- package/tests/core/workspace-context-factory.test.ts +18 -0
- package/tests/core/workspace-context.test.ts +134 -0
- package/tests/fixtures/nocturnal-reviewed-subset.json +183 -0
- package/tests/fixtures/production-compatibility.test.ts +147 -0
- package/tests/fixtures/production-mock-generator.ts +282 -0
- package/tests/hooks/bash-risk-integration.test.ts +137 -0
- package/tests/hooks/bash-risk.test.ts +81 -0
- package/tests/hooks/edit-verification.test.ts +678 -0
- package/tests/hooks/gate-edit-verification-p1.test.ts +632 -0
- package/tests/hooks/gate-edit-verification.test.ts +435 -0
- package/tests/hooks/gate-pipeline-integration.test.ts +404 -0
- package/tests/hooks/gate.test.ts +271 -0
- package/tests/hooks/gfi-gate-unit.test.ts +422 -0
- package/tests/hooks/gfi-gate.test.ts +669 -0
- package/tests/hooks/lifecycle.test.ts +248 -0
- package/tests/hooks/llm.test.ts +308 -0
- package/tests/hooks/message-sanitize.test.ts +36 -0
- package/tests/hooks/pain.test.ts +141 -0
- package/tests/hooks/progressive-trust-gate.test.ts +277 -0
- package/tests/hooks/prompt.test.ts +1411 -0
- package/tests/hooks/subagent.test.ts +467 -0
- package/tests/hooks/thinking-gate.test.ts +313 -0
- package/tests/http/principles-console-route.test.ts +140 -0
- package/tests/hygiene-tracker.test.ts +77 -0
- package/tests/index.integration.test.ts +179 -0
- package/tests/index.shadow-routing.integration.test.ts +140 -0
- package/tests/index.test.ts +9 -0
- package/tests/integration/empathy-workflow-integration.test.ts +627 -0
- package/tests/service/control-ui-query-service.test.ts +121 -0
- package/tests/service/empathy-observer-workflow-manager.test.ts +176 -0
- package/tests/service/evolution-worker.test.ts +585 -0
- package/tests/service/nocturnal-runtime.test.ts +470 -0
- package/tests/service/nocturnal-service.test.ts +577 -0
- package/tests/service/nocturnal-target-selector.test.ts +615 -0
- package/tests/service/nocturnal-workflow-manager.test.ts +439 -0
- package/tests/service/phase3-input-filter.test.ts +289 -0
- package/tests/service/runtime-summary-service.test.ts +919 -0
- package/tests/task-compliance.test.ts +166 -0
- package/tests/test-utils.ts +48 -0
- package/tests/tools/critique-prompt.test.ts +260 -0
- package/tests/tools/deep-reflect.test.ts +232 -0
- package/tests/tools/model-index.test.ts +246 -0
- package/tests/ui/app.test.tsx +114 -0
- package/tests/utils/file-lock.test.ts +407 -0
- package/tests/utils/hashing.test.ts +32 -0
- package/tests/utils/io.test.ts +39 -0
- package/tests/utils/nlp.test.ts +53 -0
- package/tests/utils/plugin-logger.test.ts +156 -0
- package/tsconfig.json +16 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/ui/src/App.tsx +45 -0
- package/ui/src/api.ts +216 -0
- package/ui/src/charts.tsx +586 -0
- package/ui/src/components/ErrorState.tsx +6 -0
- package/ui/src/components/Loading.tsx +13 -0
- package/ui/src/components/ProtectedRoute.tsx +12 -0
- package/ui/src/components/Shell.tsx +91 -0
- package/ui/src/components/WorkspaceConfig.tsx +146 -0
- package/ui/src/components/index.ts +5 -0
- package/ui/src/context/auth.tsx +80 -0
- package/ui/src/context/theme.tsx +66 -0
- package/ui/src/hooks/useAutoRefresh.ts +39 -0
- package/ui/src/i18n/ui.ts +363 -0
- package/ui/src/main.tsx +16 -0
- package/ui/src/pages/EvolutionPage.tsx +352 -0
- package/ui/src/pages/FeedbackPage.tsx +140 -0
- package/ui/src/pages/GateMonitorPage.tsx +136 -0
- package/ui/src/pages/LoginPage.tsx +88 -0
- package/ui/src/pages/OverviewPage.tsx +238 -0
- package/ui/src/pages/SamplesPage.tsx +174 -0
- package/ui/src/pages/ThinkingModelsPage.tsx +127 -0
- package/ui/src/styles.css +1661 -0
- package/ui/src/types.ts +368 -0
- package/ui/src/utils/format.ts +15 -0
- package/vitest.config.ts +23 -0
- package/dist/commands/capabilities.d.ts +0 -3
- package/dist/commands/capabilities.js +0 -73
- package/dist/commands/context.d.ts +0 -5
- package/dist/commands/evolution-status.d.ts +0 -4
- package/dist/commands/evolution-status.js +0 -117
- package/dist/commands/evolver.d.ts +0 -9
- package/dist/commands/evolver.js +0 -26
- package/dist/commands/export.d.ts +0 -2
- package/dist/commands/export.js +0 -98
- package/dist/commands/focus.d.ts +0 -14
- package/dist/commands/focus.js +0 -457
- package/dist/commands/nocturnal-review.d.ts +0 -24
- package/dist/commands/nocturnal-review.js +0 -265
- package/dist/commands/nocturnal-rollout.d.ts +0 -27
- package/dist/commands/nocturnal-rollout.js +0 -671
- package/dist/commands/nocturnal-train.d.ts +0 -25
- package/dist/commands/nocturnal-train.js +0 -919
- package/dist/commands/pain.d.ts +0 -5
- package/dist/commands/principle-rollback.d.ts +0 -4
- package/dist/commands/principle-rollback.js +0 -22
- package/dist/commands/rollback.d.ts +0 -19
- package/dist/commands/samples.d.ts +0 -2
- package/dist/commands/samples.js +0 -55
- package/dist/commands/strategy.d.ts +0 -3
- package/dist/commands/strategy.js +0 -29
- package/dist/commands/thinking-os.d.ts +0 -2
- package/dist/config/defaults/runtime.d.ts +0 -40
- package/dist/config/errors.d.ts +0 -84
- package/dist/config/errors.js +0 -94
- package/dist/config/index.js +0 -7
- package/dist/constants/diagnostician.d.ts +0 -12
- package/dist/constants/diagnostician.js +0 -56
- package/dist/constants/tools.d.ts +0 -17
- package/dist/constants/tools.js +0 -54
- package/dist/core/adaptive-thresholds.d.ts +0 -186
- package/dist/core/adaptive-thresholds.js +0 -300
- package/dist/core/config-service.d.ts +0 -15
- package/dist/core/config.d.ts +0 -129
- package/dist/core/control-ui-db.d.ts +0 -95
- package/dist/core/control-ui-db.js +0 -292
- package/dist/core/detection-funnel.d.ts +0 -33
- package/dist/core/detection-service.d.ts +0 -15
- package/dist/core/dictionary-service.d.ts +0 -15
- package/dist/core/dictionary.d.ts +0 -38
- package/dist/core/event-log.d.ts +0 -82
- package/dist/core/event-log.js +0 -463
- package/dist/core/evolution-engine.d.ts +0 -118
- package/dist/core/evolution-engine.js +0 -464
- package/dist/core/evolution-logger.d.ts +0 -137
- package/dist/core/evolution-logger.js +0 -256
- package/dist/core/evolution-migration.d.ts +0 -5
- package/dist/core/evolution-migration.js +0 -65
- package/dist/core/evolution-reducer.d.ts +0 -98
- package/dist/core/evolution-reducer.js +0 -465
- package/dist/core/evolution-types.d.ts +0 -287
- package/dist/core/evolution-types.js +0 -78
- package/dist/core/external-training-contract.d.ts +0 -276
- package/dist/core/external-training-contract.js +0 -269
- package/dist/core/focus-history.d.ts +0 -210
- package/dist/core/focus-history.js +0 -1185
- package/dist/core/hygiene/tracker.d.ts +0 -22
- package/dist/core/hygiene/tracker.js +0 -106
- package/dist/core/init.d.ts +0 -12
- package/dist/core/local-worker-routing.d.ts +0 -175
- package/dist/core/local-worker-routing.js +0 -525
- package/dist/core/migration.d.ts +0 -6
- package/dist/core/model-deployment-registry.d.ts +0 -218
- package/dist/core/model-deployment-registry.js +0 -503
- package/dist/core/model-training-registry.d.ts +0 -295
- package/dist/core/model-training-registry.js +0 -475
- package/dist/core/nocturnal-arbiter.d.ts +0 -159
- package/dist/core/nocturnal-arbiter.js +0 -534
- package/dist/core/nocturnal-candidate-scoring.d.ts +0 -137
- package/dist/core/nocturnal-candidate-scoring.js +0 -266
- package/dist/core/nocturnal-compliance.d.ts +0 -175
- package/dist/core/nocturnal-compliance.js +0 -824
- package/dist/core/nocturnal-dataset.d.ts +0 -224
- package/dist/core/nocturnal-dataset.js +0 -443
- package/dist/core/nocturnal-executability.d.ts +0 -85
- package/dist/core/nocturnal-executability.js +0 -331
- package/dist/core/nocturnal-export.d.ts +0 -124
- package/dist/core/nocturnal-export.js +0 -275
- package/dist/core/nocturnal-paths.d.ts +0 -124
- package/dist/core/nocturnal-trajectory-extractor.d.ts +0 -242
- package/dist/core/nocturnal-trajectory-extractor.js +0 -307
- package/dist/core/nocturnal-trinity.d.ts +0 -311
- package/dist/core/nocturnal-trinity.js +0 -880
- package/dist/core/pain.d.ts +0 -4
- package/dist/core/pain.js +0 -70
- package/dist/core/path-resolver.d.ts +0 -46
- package/dist/core/paths.d.ts +0 -65
- package/dist/core/principle-training-state.d.ts +0 -121
- package/dist/core/principle-training-state.js +0 -321
- package/dist/core/profile.d.ts +0 -62
- package/dist/core/profile.js +0 -210
- package/dist/core/promotion-gate.d.ts +0 -238
- package/dist/core/promotion-gate.js +0 -529
- package/dist/core/risk-calculator.d.ts +0 -22
- package/dist/core/session-tracker.d.ts +0 -101
- package/dist/core/shadow-observation-registry.d.ts +0 -217
- package/dist/core/shadow-observation-registry.js +0 -308
- package/dist/core/system-logger.d.ts +0 -8
- package/dist/core/thinking-models.d.ts +0 -38
- package/dist/core/thinking-models.js +0 -170
- package/dist/core/training-program.d.ts +0 -233
- package/dist/core/training-program.js +0 -433
- package/dist/core/trajectory.d.ts +0 -411
- package/dist/core/trajectory.js +0 -1307
- package/dist/core/workspace-context.d.ts +0 -71
- package/dist/hooks/bash-risk.d.ts +0 -57
- package/dist/hooks/bash-risk.js +0 -137
- package/dist/hooks/edit-verification.d.ts +0 -62
- package/dist/hooks/edit-verification.js +0 -256
- package/dist/hooks/gate-block-helper.d.ts +0 -44
- package/dist/hooks/gate-block-helper.js +0 -119
- package/dist/hooks/gate.d.ts +0 -24
- package/dist/hooks/gate.js +0 -173
- package/dist/hooks/gfi-gate.d.ts +0 -40
- package/dist/hooks/gfi-gate.js +0 -113
- package/dist/hooks/lifecycle.d.ts +0 -5
- package/dist/hooks/lifecycle.js +0 -284
- package/dist/hooks/llm.d.ts +0 -13
- package/dist/hooks/message-sanitize.d.ts +0 -3
- package/dist/hooks/message-sanitize.js +0 -37
- package/dist/hooks/pain.d.ts +0 -5
- package/dist/hooks/pain.js +0 -301
- package/dist/hooks/progressive-trust-gate.d.ts +0 -52
- package/dist/hooks/progressive-trust-gate.js +0 -134
- package/dist/hooks/prompt.d.ts +0 -49
- package/dist/hooks/prompt.js +0 -905
- package/dist/hooks/subagent.d.ts +0 -10
- package/dist/hooks/subagent.js +0 -387
- package/dist/hooks/thinking-checkpoint.d.ts +0 -37
- package/dist/hooks/thinking-checkpoint.js +0 -51
- package/dist/hooks/trajectory-collector.d.ts +0 -32
- package/dist/hooks/trajectory-collector.js +0 -256
- package/dist/http/principles-console-route.d.ts +0 -9
- package/dist/http/principles-console-route.js +0 -681
- package/dist/i18n/commands.d.ts +0 -26
- package/dist/i18n/commands.js +0 -116
- package/dist/index.d.ts +0 -7
- package/dist/index.js +0 -581
- package/dist/service/central-database.d.ts +0 -104
- package/dist/service/central-database.js +0 -649
- package/dist/service/control-ui-query-service.d.ts +0 -221
- package/dist/service/control-ui-query-service.js +0 -543
- package/dist/service/empathy-observer-manager.d.ts +0 -88
- package/dist/service/empathy-observer-manager.js +0 -414
- package/dist/service/evolution-query-service.d.ts +0 -155
- package/dist/service/evolution-query-service.js +0 -258
- package/dist/service/evolution-worker.d.ts +0 -101
- package/dist/service/evolution-worker.js +0 -975
- package/dist/service/health-query-service.d.ts +0 -170
- package/dist/service/health-query-service.js +0 -662
- package/dist/service/nocturnal-runtime.d.ts +0 -183
- package/dist/service/nocturnal-service.d.ts +0 -163
- package/dist/service/nocturnal-service.js +0 -787
- package/dist/service/nocturnal-target-selector.d.ts +0 -145
- package/dist/service/nocturnal-target-selector.js +0 -315
- package/dist/service/phase3-input-filter.d.ts +0 -73
- package/dist/service/phase3-input-filter.js +0 -172
- package/dist/service/runtime-summary-service.d.ts +0 -122
- package/dist/service/runtime-summary-service.js +0 -485
- package/dist/service/subagent-workflow/empathy-observer-workflow-manager.d.ts +0 -48
- package/dist/service/subagent-workflow/index.d.ts +0 -4
- package/dist/service/subagent-workflow/index.js +0 -3
- package/dist/service/subagent-workflow/runtime-direct-driver.d.ts +0 -77
- package/dist/service/subagent-workflow/runtime-direct-driver.js +0 -75
- package/dist/service/subagent-workflow/types.js +0 -11
- package/dist/service/subagent-workflow/workflow-store.d.ts +0 -26
- package/dist/service/subagent-workflow/workflow-store.js +0 -165
- package/dist/service/trajectory-service.d.ts +0 -2
- package/dist/service/trajectory-service.js +0 -15
- package/dist/tools/critique-prompt.d.ts +0 -14
- package/dist/tools/deep-reflect.d.ts +0 -39
- package/dist/tools/deep-reflect.js +0 -350
- package/dist/tools/model-index.d.ts +0 -9
- package/dist/types/event-types.d.ts +0 -306
- package/dist/types/event-types.js +0 -106
- package/dist/types/hygiene-types.d.ts +0 -20
- package/dist/types/hygiene-types.js +0 -12
- package/dist/types/runtime-summary.d.ts +0 -47
- package/dist/types/runtime-summary.js +0 -1
- package/dist/types.d.ts +0 -50
- package/dist/types.js +0 -22
- package/dist/utils/file-lock.d.ts +0 -71
- package/dist/utils/file-lock.js +0 -309
- package/dist/utils/glob-match.d.ts +0 -28
- package/dist/utils/hashing.d.ts +0 -9
- package/dist/utils/io.d.ts +0 -6
- package/dist/utils/io.js +0 -106
- package/dist/utils/nlp.d.ts +0 -9
- package/dist/utils/plugin-logger.d.ts +0 -39
- package/dist/utils/subagent-probe.d.ts +0 -34
- package/dist/utils/subagent-probe.js +0 -81
|
@@ -1,44 +1,64 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
import {
|
|
3
|
+
import { PluginHookLlmOutputEvent, PluginHookAgentContext } from '../openclaw-sdk.js';
|
|
4
|
+
import { trackFriction, trackLlmOutput, recordThinkingCheckpoint, resetFriction } from '../core/session-tracker.js';
|
|
4
5
|
import { writePainFlag } from '../core/pain.js';
|
|
5
6
|
import { ControlUiDatabase } from '../core/control-ui-db.js';
|
|
6
7
|
import { DetectionService } from '../core/detection-service.js';
|
|
7
8
|
import { detectThinkingModelMatches, deriveThinkingScenarios } from '../core/thinking-models.js';
|
|
8
9
|
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
9
10
|
import { sanitizeAssistantText } from './message-sanitize.js';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
|
|
12
|
+
export interface EmpathySignal {
|
|
13
|
+
detected: boolean;
|
|
14
|
+
severity: 'mild' | 'moderate' | 'severe';
|
|
15
|
+
confidence: number;
|
|
16
|
+
reason?: string;
|
|
17
|
+
mode?: 'structured' | 'legacy_tag';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type EmpathyRateState = {
|
|
21
|
+
turnScore: number;
|
|
22
|
+
hourScore: number;
|
|
23
|
+
hourWindowStart: number;
|
|
24
|
+
lastRunId?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const empathyDedupState = new Map<string, number>();
|
|
28
|
+
const empathyRateState = new Map<string, EmpathyRateState>();
|
|
29
|
+
|
|
30
|
+
function clamp(value: number, min: number, max: number): number {
|
|
13
31
|
return Math.max(min, Math.min(max, value));
|
|
14
32
|
}
|
|
15
|
-
|
|
33
|
+
|
|
34
|
+
function normalizeSeverity(input?: string): 'mild' | 'moderate' | 'severe' {
|
|
16
35
|
const normalized = (input || '').toLowerCase();
|
|
17
|
-
if (normalized === 'severe' || normalized === 'high')
|
|
18
|
-
|
|
19
|
-
if (normalized === 'moderate' || normalized === 'medium')
|
|
20
|
-
return 'moderate';
|
|
36
|
+
if (normalized === 'severe' || normalized === 'high') return 'severe';
|
|
37
|
+
if (normalized === 'moderate' || normalized === 'medium') return 'moderate';
|
|
21
38
|
return 'mild';
|
|
22
39
|
}
|
|
23
|
-
|
|
40
|
+
|
|
41
|
+
function parseConfidence(raw?: string): number {
|
|
24
42
|
const parsed = Number(raw);
|
|
25
|
-
if (!Number.isFinite(parsed))
|
|
26
|
-
return 1;
|
|
43
|
+
if (!Number.isFinite(parsed)) return 1;
|
|
27
44
|
return clamp(parsed, 0, 1);
|
|
28
45
|
}
|
|
29
|
-
|
|
46
|
+
|
|
47
|
+
function parseTrustedLegacyTag(text: string): RegExpMatchArray | null {
|
|
30
48
|
return text.match(/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i);
|
|
31
49
|
}
|
|
50
|
+
|
|
32
51
|
/**
|
|
33
52
|
* 检测标签是否是被用户诱导/引用输出的(回显),而非 LLM 主动输出的情绪信号
|
|
34
53
|
*/
|
|
35
|
-
function isEchoedTag(text, tagMatch) {
|
|
54
|
+
function isEchoedTag(text: string, tagMatch: RegExpMatchArray): boolean {
|
|
36
55
|
const tagIndex = tagMatch.index ?? 0;
|
|
37
56
|
const before = text.substring(Math.max(0, tagIndex - 100), tagIndex).toLowerCase();
|
|
57
|
+
|
|
38
58
|
// 1. 检查是否在引号内(用户引用)
|
|
39
59
|
const quotesBefore = (before.match(/["'\u300c\u300d\u201c\u201d`]/g) || []).length;
|
|
40
|
-
if (quotesBefore % 2 === 1)
|
|
41
|
-
|
|
60
|
+
if (quotesBefore % 2 === 1) return true;
|
|
61
|
+
|
|
42
62
|
// 2. Strong patterns: 用户指令关键词(任意位置匹配)
|
|
43
63
|
const strongPatterns = [
|
|
44
64
|
/用户(说|让|要求|让我输出)/,
|
|
@@ -48,9 +68,9 @@ function isEchoedTag(text, tagMatch) {
|
|
|
48
68
|
/你让我输出/,
|
|
49
69
|
];
|
|
50
70
|
for (const pattern of strongPatterns) {
|
|
51
|
-
if (pattern.test(before))
|
|
52
|
-
return true;
|
|
71
|
+
if (pattern.test(before)) return true;
|
|
53
72
|
}
|
|
73
|
+
|
|
54
74
|
// 3. Weak patterns: 仅在标签 15 字符内触发
|
|
55
75
|
const weakPatterns = [
|
|
56
76
|
{ pattern: /echo/, window: 15 },
|
|
@@ -59,19 +79,21 @@ function isEchoedTag(text, tagMatch) {
|
|
|
59
79
|
];
|
|
60
80
|
for (const { pattern, window } of weakPatterns) {
|
|
61
81
|
const nearTag = text.substring(Math.max(0, tagIndex - window), tagIndex).toLowerCase();
|
|
62
|
-
if (pattern.test(nearTag))
|
|
63
|
-
return true;
|
|
82
|
+
if (pattern.test(nearTag)) return true;
|
|
64
83
|
}
|
|
84
|
+
|
|
65
85
|
// 4. 检查是否在代码块内
|
|
66
86
|
const codeBlocksBefore = (before.match(/```/g) || []).length;
|
|
67
|
-
if (codeBlocksBefore % 2 === 1)
|
|
68
|
-
|
|
87
|
+
if (codeBlocksBefore % 2 === 1) return true;
|
|
88
|
+
|
|
69
89
|
return false;
|
|
70
90
|
}
|
|
71
|
-
|
|
91
|
+
|
|
92
|
+
export function extractEmpathySignal(text: string): EmpathySignal {
|
|
72
93
|
if (!text || typeof text !== 'string') {
|
|
73
94
|
return { detected: false, severity: 'mild', confidence: 1 };
|
|
74
95
|
}
|
|
96
|
+
|
|
75
97
|
const xmlMatch = text.match(/<empathy\s+([^>]*)\/?>(?:<\/empathy>)?/i);
|
|
76
98
|
if (xmlMatch?.[1]) {
|
|
77
99
|
const attrs = xmlMatch[1];
|
|
@@ -83,11 +105,14 @@ export function extractEmpathySignal(text) {
|
|
|
83
105
|
return { detected: true, severity, confidence, reason, mode: 'structured' };
|
|
84
106
|
}
|
|
85
107
|
}
|
|
108
|
+
|
|
86
109
|
const jsonMatch = text.match(/"empathy"\s*:\s*\{[\s\S]*?\}/i);
|
|
87
110
|
if (jsonMatch) {
|
|
88
111
|
const jsonText = `{${jsonMatch[0]}}`;
|
|
89
112
|
try {
|
|
90
|
-
const parsed = JSON.parse(jsonText)
|
|
113
|
+
const parsed = JSON.parse(jsonText) as {
|
|
114
|
+
empathy?: { damageDetected?: boolean; severity?: string; confidence?: number; reason?: string };
|
|
115
|
+
};
|
|
91
116
|
if (parsed.empathy?.damageDetected === true) {
|
|
92
117
|
return {
|
|
93
118
|
detected: true,
|
|
@@ -97,11 +122,11 @@ export function extractEmpathySignal(text) {
|
|
|
97
122
|
mode: 'structured'
|
|
98
123
|
};
|
|
99
124
|
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
125
|
+
} catch {
|
|
102
126
|
// ignore malformed snippet
|
|
103
127
|
}
|
|
104
128
|
}
|
|
129
|
+
|
|
105
130
|
const tagMatch = parseTrustedLegacyTag(text);
|
|
106
131
|
if (tagMatch) {
|
|
107
132
|
if (isEchoedTag(text, tagMatch)) {
|
|
@@ -114,22 +139,25 @@ export function extractEmpathySignal(text) {
|
|
|
114
139
|
mode: 'legacy_tag'
|
|
115
140
|
};
|
|
116
141
|
}
|
|
142
|
+
|
|
117
143
|
return { detected: false, severity: 'mild', confidence: 1 };
|
|
118
144
|
}
|
|
119
|
-
|
|
145
|
+
|
|
146
|
+
function mapSeverityToPenalty(severity: 'mild' | 'moderate' | 'severe', config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']): number {
|
|
120
147
|
const mild = Number(config.get('empathy_engine.penalties.mild') ?? 10);
|
|
121
148
|
const moderate = Number(config.get('empathy_engine.penalties.moderate') ?? 25);
|
|
122
149
|
const severe = Number(config.get('empathy_engine.penalties.severe') ?? 40);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (severity === 'moderate')
|
|
126
|
-
return moderate;
|
|
150
|
+
|
|
151
|
+
if (severity === 'severe') return severe;
|
|
152
|
+
if (severity === 'moderate') return moderate;
|
|
127
153
|
return mild;
|
|
128
154
|
}
|
|
129
|
-
|
|
155
|
+
|
|
156
|
+
function dedupeKey(sessionId: string, runId: string, signal: EmpathySignal): string {
|
|
130
157
|
return `${sessionId}:${runId}:${signal.severity}:${(signal.reason || '').slice(0, 80)}`;
|
|
131
158
|
}
|
|
132
|
-
|
|
159
|
+
|
|
160
|
+
function shouldDedupe(sessionId: string, runId: string, signal: EmpathySignal, windowMs: number): boolean {
|
|
133
161
|
const key = dedupeKey(sessionId, runId, signal);
|
|
134
162
|
const now = Date.now();
|
|
135
163
|
const last = empathyDedupState.get(key);
|
|
@@ -139,69 +167,88 @@ function shouldDedupe(sessionId, runId, signal, windowMs) {
|
|
|
139
167
|
empathyDedupState.set(key, now);
|
|
140
168
|
return false;
|
|
141
169
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
170
|
+
|
|
171
|
+
function resolveCalibrationFactor(
|
|
172
|
+
event: PluginHookLlmOutputEvent,
|
|
173
|
+
config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']
|
|
174
|
+
): number {
|
|
175
|
+
const table = config.get('empathy_engine.model_calibration') as Record<string, number> | undefined;
|
|
176
|
+
if (!table || typeof table !== 'object') return 1;
|
|
177
|
+
|
|
146
178
|
const modelKey = `${event.provider}/${event.model}`;
|
|
147
179
|
const factor = Number(table[modelKey] ?? 1);
|
|
148
|
-
if (!Number.isFinite(factor))
|
|
149
|
-
return 1;
|
|
180
|
+
if (!Number.isFinite(factor)) return 1;
|
|
150
181
|
return clamp(factor, 0.1, 3);
|
|
151
182
|
}
|
|
152
|
-
|
|
183
|
+
|
|
184
|
+
function applyRateLimit(
|
|
185
|
+
sessionId: string,
|
|
186
|
+
runId: string,
|
|
187
|
+
score: number,
|
|
188
|
+
config: ReturnType<typeof WorkspaceContext.fromHookContext>['config']
|
|
189
|
+
): number {
|
|
153
190
|
const maxPerTurn = Number(config.get('empathy_engine.rate_limit.max_per_turn') ?? 40);
|
|
154
191
|
const maxPerHour = Number(config.get('empathy_engine.rate_limit.max_per_hour') ?? 120);
|
|
155
192
|
const now = Date.now();
|
|
193
|
+
|
|
156
194
|
const prev = empathyRateState.get(sessionId) ?? {
|
|
157
195
|
turnScore: 0,
|
|
158
196
|
hourScore: 0,
|
|
159
197
|
hourWindowStart: now,
|
|
160
198
|
lastRunId: runId,
|
|
161
199
|
};
|
|
200
|
+
|
|
162
201
|
if (prev.lastRunId !== runId) {
|
|
163
202
|
prev.turnScore = 0;
|
|
164
203
|
prev.lastRunId = runId;
|
|
165
204
|
}
|
|
205
|
+
|
|
166
206
|
if (now - prev.hourWindowStart >= 60 * 60 * 1000) {
|
|
167
207
|
prev.hourScore = 0;
|
|
168
208
|
prev.hourWindowStart = now;
|
|
169
209
|
}
|
|
210
|
+
|
|
170
211
|
const byTurn = Math.max(0, maxPerTurn - prev.turnScore);
|
|
171
212
|
const byHour = Math.max(0, maxPerHour - prev.hourScore);
|
|
172
213
|
const allowed = Math.max(0, Math.min(score, byTurn, byHour));
|
|
214
|
+
|
|
173
215
|
prev.turnScore += allowed;
|
|
174
216
|
prev.hourScore += allowed;
|
|
175
217
|
empathyRateState.set(sessionId, prev);
|
|
218
|
+
|
|
176
219
|
return allowed;
|
|
177
220
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
export function isEmpathyAuditPayload(text: string): boolean {
|
|
224
|
+
if (!text || typeof text !== 'string') return false;
|
|
181
225
|
const trimmed = text.trim();
|
|
182
|
-
if (/^\{[\s\S]*"damageDetected"[\s\S]*\}$/.test(trimmed))
|
|
183
|
-
|
|
184
|
-
if (
|
|
185
|
-
return true;
|
|
186
|
-
if (/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i.test(trimmed))
|
|
187
|
-
return true;
|
|
226
|
+
if (/^\{[\s\S]*"damageDetected"[\s\S]*\}$/.test(trimmed)) return true;
|
|
227
|
+
if (/^<empathy\s+([^>]*)\/?>/i.test(trimmed)) return true;
|
|
228
|
+
if (/^\s*\[EMOTIONAL_DAMAGE_DETECTED(?::(mild|moderate|severe))?\]\s*$/i.test(trimmed)) return true;
|
|
188
229
|
return false;
|
|
189
230
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
231
|
+
|
|
232
|
+
export function handleLlmOutput(
|
|
233
|
+
event: PluginHookLlmOutputEvent,
|
|
234
|
+
ctx: PluginHookAgentContext & { workspaceDir?: string }
|
|
235
|
+
): void {
|
|
236
|
+
if (!ctx.workspaceDir || !ctx.sessionId) return;
|
|
237
|
+
|
|
193
238
|
const wctx = WorkspaceContext.fromHookContext(ctx);
|
|
194
239
|
const config = wctx.config;
|
|
195
240
|
const eventLog = wctx.eventLog;
|
|
241
|
+
|
|
196
242
|
// Track this turn in the core session memory
|
|
197
243
|
const state = trackLlmOutput(ctx.sessionId, event.usage, config, ctx.workspaceDir, ctx.sessionKey, ctx.trigger);
|
|
244
|
+
|
|
198
245
|
// We need actual assistant text to analyze
|
|
199
|
-
if (!event.assistantTexts || event.assistantTexts.length === 0)
|
|
200
|
-
|
|
246
|
+
if (!event.assistantTexts || event.assistantTexts.length === 0) return;
|
|
247
|
+
|
|
201
248
|
const text = event.assistantTexts.join('\n');
|
|
202
249
|
const signal = extractEmpathySignal(text);
|
|
203
250
|
const createdAt = new Date().toISOString();
|
|
204
|
-
let assistantTurnId = null;
|
|
251
|
+
let assistantTurnId: number | null = null;
|
|
205
252
|
try {
|
|
206
253
|
assistantTurnId = wctx.trajectory?.recordAssistantTurn?.({
|
|
207
254
|
sessionId: ctx.sessionId,
|
|
@@ -214,14 +261,15 @@ export function handleLlmOutput(event, ctx) {
|
|
|
214
261
|
empathySignalJson: signal,
|
|
215
262
|
createdAt,
|
|
216
263
|
});
|
|
217
|
-
}
|
|
218
|
-
catch (error) {
|
|
264
|
+
} catch (error) {
|
|
219
265
|
ctx.logger?.warn?.(`[PD:LLM] Failed to persist assistant turn to trajectory: ${String(error)}`);
|
|
220
266
|
}
|
|
267
|
+
|
|
221
268
|
// ── Track B: Semantic Pain Detection (V1.3.0 Funnel) ──
|
|
222
269
|
const detectionText = isEmpathyAuditPayload(text) ? '' : text;
|
|
223
270
|
const detectionService = DetectionService.get(wctx.stateDir);
|
|
224
271
|
const detection = detectionService.detect(detectionText);
|
|
272
|
+
|
|
225
273
|
if (detection.detected) {
|
|
226
274
|
eventLog.recordRuleMatch(ctx.sessionId, {
|
|
227
275
|
ruleId: detection.ruleId || detection.source,
|
|
@@ -230,6 +278,7 @@ export function handleLlmOutput(event, ctx) {
|
|
|
230
278
|
textPreview: detectionText.substring(0, 100)
|
|
231
279
|
});
|
|
232
280
|
}
|
|
281
|
+
|
|
233
282
|
let painScore = detection.detected ? (detection.severity || 0) : 0;
|
|
234
283
|
let source = detection.detected
|
|
235
284
|
? (detection.ruleId ? `llm_${detection.ruleId.toLowerCase()}` : `llm_${detection.source}`)
|
|
@@ -237,12 +286,18 @@ export function handleLlmOutput(event, ctx) {
|
|
|
237
286
|
let matchedReason = detection.detected
|
|
238
287
|
? `Agent triggered pain detection (Source: ${detection.source}${detection.ruleId ? `, Rule: ${detection.ruleId}` : ''})`
|
|
239
288
|
: '';
|
|
289
|
+
|
|
240
290
|
// ═══ Natural Language Rollback Detection ═══
|
|
241
291
|
const rollbackMatch = text.match(/^\s*\[EMPATHY_ROLLBACK_REQUEST\]\s*$/m);
|
|
242
292
|
if (rollbackMatch) {
|
|
243
293
|
const eventId = eventLog.getLastEmpathyEventId(ctx.sessionId);
|
|
244
294
|
if (eventId) {
|
|
245
|
-
const rolledBackScore = eventLog.rollbackEmpathyEvent(
|
|
295
|
+
const rolledBackScore = eventLog.rollbackEmpathyEvent(
|
|
296
|
+
eventId,
|
|
297
|
+
ctx.sessionId,
|
|
298
|
+
'Natural language rollback request detected',
|
|
299
|
+
'natural_language'
|
|
300
|
+
);
|
|
246
301
|
if (rolledBackScore > 0) {
|
|
247
302
|
// Reset GFI after successful rollback
|
|
248
303
|
resetFriction(ctx.sessionId, ctx.workspaceDir, {
|
|
@@ -252,28 +307,37 @@ export function handleLlmOutput(event, ctx) {
|
|
|
252
307
|
}
|
|
253
308
|
}
|
|
254
309
|
}
|
|
310
|
+
|
|
255
311
|
// 3. Paralysis Check (from session state tracker)
|
|
256
312
|
const stuckThreshold = config.get('thresholds.stuck_loops_trigger') || 3;
|
|
257
313
|
const inputThreshold = config.get('thresholds.cognitive_paralysis_input') || 4000;
|
|
258
314
|
const paralysisScore = config.get('scores.paralysis') || 40;
|
|
315
|
+
|
|
259
316
|
if (state.stuckLoops >= stuckThreshold && state.totalInputTokens > inputThreshold && painScore < paralysisScore) {
|
|
260
317
|
painScore = paralysisScore;
|
|
261
318
|
source = 'llm_paralysis';
|
|
262
319
|
matchedReason = `Agent is stuck in low-output loops (${state.stuckLoops} consecutive turns with tiny output but huge context), indicating cognitive paralysis.`;
|
|
263
320
|
}
|
|
321
|
+
|
|
264
322
|
// If a pain threshold is crossed, write the autonomous pain flag
|
|
265
323
|
const painTriggerThreshold = config.get('thresholds.pain_trigger') || 30;
|
|
266
324
|
if (painScore >= painTriggerThreshold) {
|
|
267
325
|
// Inject the actual text snippet that triggered this for the diagnostician to read later
|
|
268
326
|
const snippet = text.length > 200 ? text.substring(0, 100) + '...' + text.substring(text.length - 100) : text;
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
327
|
+
|
|
328
|
+
try {
|
|
329
|
+
writePainFlag(ctx.workspaceDir, {
|
|
330
|
+
source,
|
|
331
|
+
score: String(painScore),
|
|
332
|
+
time: new Date().toISOString(),
|
|
333
|
+
reason: matchedReason,
|
|
334
|
+
is_risky: 'false',
|
|
335
|
+
trigger_text_preview: snippet
|
|
336
|
+
});
|
|
337
|
+
} catch (e) {
|
|
338
|
+
ctx.logger?.warn?.(`[PD:LLM] Failed to write pain flag: ${String(e)}`);
|
|
339
|
+
}
|
|
340
|
+
|
|
277
341
|
eventLog.recordPainSignal(ctx.sessionId, {
|
|
278
342
|
score: painScore,
|
|
279
343
|
source: source,
|
|
@@ -281,6 +345,7 @@ export function handleLlmOutput(event, ctx) {
|
|
|
281
345
|
isRisky: false
|
|
282
346
|
});
|
|
283
347
|
}
|
|
348
|
+
|
|
284
349
|
// ═══ Thinking OS: Mental Model Usage Tracking ═══
|
|
285
350
|
trackThinkingModelUsage({
|
|
286
351
|
text,
|
|
@@ -292,41 +357,56 @@ export function handleLlmOutput(event, ctx) {
|
|
|
292
357
|
logger: ctx.logger,
|
|
293
358
|
});
|
|
294
359
|
}
|
|
295
|
-
|
|
360
|
+
|
|
361
|
+
function trackThinkingModelUsage(args: {
|
|
362
|
+
text: string;
|
|
363
|
+
wctx: WorkspaceContext;
|
|
364
|
+
sessionId?: string;
|
|
365
|
+
runId: string;
|
|
366
|
+
assistantTurnId: number | null;
|
|
367
|
+
createdAt: string;
|
|
368
|
+
logger?: PluginHookAgentContext['logger'];
|
|
369
|
+
}): void {
|
|
296
370
|
const { text, wctx, sessionId, runId, assistantTurnId, createdAt, logger } = args;
|
|
297
371
|
const logPath = wctx.resolve('THINKING_OS_USAGE');
|
|
298
372
|
const logDir = path.dirname(logPath);
|
|
299
|
-
if (!fs.existsSync(logDir))
|
|
300
|
-
|
|
301
|
-
let usageLog = {};
|
|
373
|
+
if (!fs.existsSync(logDir)) fs.mkdirSync(logDir, { recursive: true });
|
|
374
|
+
|
|
375
|
+
let usageLog: Record<string, number> = {};
|
|
376
|
+
|
|
302
377
|
if (fs.existsSync(logPath)) {
|
|
303
378
|
try {
|
|
304
379
|
usageLog = JSON.parse(fs.readFileSync(logPath, 'utf8'));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
console.error(`[PD:LLM] Failed to parse thinking OS usage log: ${String(e)}`);
|
|
380
|
+
} catch (e) {
|
|
381
|
+
logger?.error?.(`[PD:LLM] Failed to parse thinking OS usage log: ${String(e)}`);
|
|
308
382
|
}
|
|
309
383
|
}
|
|
384
|
+
|
|
310
385
|
const matches = detectThinkingModelMatches(text);
|
|
311
386
|
for (const match of matches) {
|
|
312
387
|
usageLog[match.modelId] = (usageLog[match.modelId] || 0) + 1;
|
|
313
388
|
}
|
|
389
|
+
|
|
314
390
|
usageLog['_total_turns'] = (usageLog['_total_turns'] || 0) + 1;
|
|
391
|
+
|
|
315
392
|
try {
|
|
316
393
|
fs.writeFileSync(logPath, JSON.stringify(usageLog, null, 2), 'utf8');
|
|
394
|
+
} catch (e) {
|
|
395
|
+
logger?.error?.(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
|
|
317
396
|
}
|
|
318
|
-
|
|
319
|
-
console.error(`[PD:LLM] Failed to write thinking OS usage log: ${String(e)}`);
|
|
320
|
-
}
|
|
397
|
+
|
|
321
398
|
if (matches.length === 0) {
|
|
322
399
|
return;
|
|
323
400
|
}
|
|
401
|
+
|
|
324
402
|
if (sessionId) {
|
|
325
403
|
recordThinkingCheckpoint(sessionId, wctx.workspaceDir);
|
|
326
404
|
}
|
|
405
|
+
|
|
327
406
|
if (!sessionId || !assistantTurnId) {
|
|
328
407
|
return;
|
|
329
408
|
}
|
|
409
|
+
|
|
330
410
|
const uiDb = new ControlUiDatabase({ workspaceDir: wctx.workspaceDir });
|
|
331
411
|
try {
|
|
332
412
|
const recentContext = uiDb.getRecentThinkingContext(sessionId, createdAt);
|
|
@@ -344,6 +424,7 @@ function trackThinkingModelUsage(args) {
|
|
|
344
424
|
eventType: event.eventType,
|
|
345
425
|
}));
|
|
346
426
|
const triggerExcerpt = text.length > 280 ? `${text.slice(0, 277)}...` : text;
|
|
427
|
+
|
|
347
428
|
for (const match of matches) {
|
|
348
429
|
const scenarios = deriveThinkingScenarios(match.modelId, {
|
|
349
430
|
recentToolCalls: toolContext,
|
|
@@ -357,6 +438,7 @@ function trackThinkingModelUsage(args) {
|
|
|
357
438
|
})),
|
|
358
439
|
recentPrincipleEvents: principleContext,
|
|
359
440
|
});
|
|
441
|
+
|
|
360
442
|
uiDb.recordThinkingModelEvent({
|
|
361
443
|
sessionId,
|
|
362
444
|
runId,
|
|
@@ -371,11 +453,9 @@ function trackThinkingModelUsage(args) {
|
|
|
371
453
|
createdAt,
|
|
372
454
|
});
|
|
373
455
|
}
|
|
374
|
-
}
|
|
375
|
-
catch (error) {
|
|
456
|
+
} catch (error) {
|
|
376
457
|
logger?.warn?.(`[PD:LLM] Failed to persist thinking model events: ${String(error)}`);
|
|
377
|
-
}
|
|
378
|
-
finally {
|
|
458
|
+
} finally {
|
|
379
459
|
uiDb.dispose();
|
|
380
460
|
}
|
|
381
461
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { PluginHookBeforeMessageWriteEvent, PluginHookBeforeMessageWriteResult } from '../openclaw-sdk.js';
|
|
2
|
+
|
|
3
|
+
const INTERNAL_TAG_PATTERNS = [
|
|
4
|
+
/\[EMOTIONAL_DAMAGE_DETECTED(?::(?:mild|moderate|severe))?\]/gi,
|
|
5
|
+
/\[EMPATHY_ROLLBACK_REQUEST\]/gi,
|
|
6
|
+
/<empathy\s+[^>]*\/?>(?:<\/empathy>)?/gi,
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
export function sanitizeAssistantText(text: string): string {
|
|
10
|
+
let result = text;
|
|
11
|
+
for (const pattern of INTERNAL_TAG_PATTERNS) {
|
|
12
|
+
result = result.replace(pattern, '');
|
|
13
|
+
}
|
|
14
|
+
return result
|
|
15
|
+
.replace(/[ \t]+\n/g, '\n')
|
|
16
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
17
|
+
.trim();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function handleBeforeMessageWrite(
|
|
21
|
+
event: PluginHookBeforeMessageWriteEvent,
|
|
22
|
+
): PluginHookBeforeMessageWriteResult | void {
|
|
23
|
+
const msg = event.message as { role?: string; content?: unknown } | undefined;
|
|
24
|
+
if (!msg || msg.role !== 'assistant') return;
|
|
25
|
+
|
|
26
|
+
if (typeof msg.content === 'string') {
|
|
27
|
+
const sanitized = sanitizeAssistantText(msg.content);
|
|
28
|
+
if (sanitized !== msg.content) {
|
|
29
|
+
return { message: { ...msg, content: sanitized } as any };
|
|
30
|
+
}
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(msg.content)) {
|
|
35
|
+
const next = msg.content.map((part: any) => {
|
|
36
|
+
if (part && typeof part === 'object' && part.type === 'text' && typeof part.text === 'string') {
|
|
37
|
+
return { ...part, text: sanitizeAssistantText(part.text) };
|
|
38
|
+
}
|
|
39
|
+
return part;
|
|
40
|
+
});
|
|
41
|
+
return { message: { ...msg, content: next } as any };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return;
|
|
45
|
+
}
|