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
package/dist/hooks/prompt.js
DELETED
|
@@ -1,905 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import { clearInjectedProbationIds, getSession, resetFriction, setInjectedProbationIds } from '../core/session-tracker.js';
|
|
4
|
-
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
5
|
-
import { defaultContextConfig } from '../types.js';
|
|
6
|
-
import { classifyTask } from '../core/local-worker-routing.js';
|
|
7
|
-
import { extractSummary, getHistoryVersions, parseWorkingMemorySection, workingMemoryToInjection, autoCompressFocus, safeReadCurrentFocus } from '../core/focus-history.js';
|
|
8
|
-
import { empathyObserverManager } from '../service/empathy-observer-manager.js';
|
|
9
|
-
import { EmpathyObserverWorkflowManager, empathyObserverWorkflowSpec } from '../service/subagent-workflow/index.js';
|
|
10
|
-
import { PathResolver } from '../core/path-resolver.js';
|
|
11
|
-
/**
|
|
12
|
-
* OpenClaw API Prompt Hook
|
|
13
|
-
* Constructs the system prompt injected into LLM context for Principles Disciple
|
|
14
|
-
*/
|
|
15
|
-
function escapeXml(input) {
|
|
16
|
-
return input
|
|
17
|
-
.replace(/&/g, '&')
|
|
18
|
-
.replace(/</g, '<')
|
|
19
|
-
.replace(/>/g, '>')
|
|
20
|
-
.replace(/"/g, '"')
|
|
21
|
-
.replace(/'/g, ''');
|
|
22
|
-
}
|
|
23
|
-
function extractContextSignals(context) {
|
|
24
|
-
const signals = [];
|
|
25
|
-
if (context.filePath?.endsWith('.ts'))
|
|
26
|
-
signals.push('typescript');
|
|
27
|
-
if (context.filePath?.endsWith('.md'))
|
|
28
|
-
signals.push('markdown');
|
|
29
|
-
if (context.toolName && ['edit', 'replace', 'write', 'write_file', 'apply_patch'].includes(context.toolName))
|
|
30
|
-
signals.push('edit');
|
|
31
|
-
if (context.toolName && ['run_shell_command', 'bash'].includes(context.toolName))
|
|
32
|
-
signals.push('shell');
|
|
33
|
-
if (context.toolName)
|
|
34
|
-
signals.push(context.toolName);
|
|
35
|
-
const msg = (context.userMessage || '').toLowerCase();
|
|
36
|
-
if (msg.includes('.ts') || msg.includes('typescript'))
|
|
37
|
-
signals.push('typescript');
|
|
38
|
-
if (msg.includes('.md') || msg.includes('markdown'))
|
|
39
|
-
signals.push('markdown');
|
|
40
|
-
if (msg.includes('edit') || msg.includes('write') || msg.includes('patch'))
|
|
41
|
-
signals.push('edit');
|
|
42
|
-
if (msg.includes('shell') || msg.includes('bash'))
|
|
43
|
-
signals.push('shell');
|
|
44
|
-
return signals;
|
|
45
|
-
}
|
|
46
|
-
function extractRecentConversationContext(messages, maxMessages = 4, maxCharsPerMessage = 200) {
|
|
47
|
-
if (!Array.isArray(messages) || messages.length === 0)
|
|
48
|
-
return '';
|
|
49
|
-
const relevantMessages = [];
|
|
50
|
-
for (let i = messages.length - 1; i >= 0 && relevantMessages.length < maxMessages; i--) {
|
|
51
|
-
const msg = messages[i];
|
|
52
|
-
if (msg?.role !== 'user' && msg?.role !== 'assistant')
|
|
53
|
-
continue;
|
|
54
|
-
let text = '';
|
|
55
|
-
if (typeof msg.content === 'string') {
|
|
56
|
-
text = msg.content;
|
|
57
|
-
}
|
|
58
|
-
else if (Array.isArray(msg.content)) {
|
|
59
|
-
text = msg.content
|
|
60
|
-
.filter((part) => {
|
|
61
|
-
if (!part || typeof part !== 'object')
|
|
62
|
-
return false;
|
|
63
|
-
const record = part;
|
|
64
|
-
return record.type === 'text' && typeof record.text === 'string';
|
|
65
|
-
})
|
|
66
|
-
.map((part) => part.text)
|
|
67
|
-
.join('\n')
|
|
68
|
-
.trim();
|
|
69
|
-
}
|
|
70
|
-
if (!text)
|
|
71
|
-
continue;
|
|
72
|
-
const normalized = text.length > maxCharsPerMessage
|
|
73
|
-
? `${text.slice(0, maxCharsPerMessage)}...`
|
|
74
|
-
: text;
|
|
75
|
-
relevantMessages.unshift({ role: msg.role, text: normalized });
|
|
76
|
-
}
|
|
77
|
-
if (relevantMessages.length === 0)
|
|
78
|
-
return '';
|
|
79
|
-
return relevantMessages
|
|
80
|
-
.map((message) => `[${message.role.toUpperCase()}]: ${message.text}`)
|
|
81
|
-
.join('\n\n');
|
|
82
|
-
}
|
|
83
|
-
function getTextContent(message) {
|
|
84
|
-
if (!message || typeof message !== 'object')
|
|
85
|
-
return '';
|
|
86
|
-
const record = message;
|
|
87
|
-
if (typeof record.content === 'string')
|
|
88
|
-
return record.content;
|
|
89
|
-
if (Array.isArray(record.content)) {
|
|
90
|
-
return record.content
|
|
91
|
-
.filter((part) => part && typeof part === 'object' && part.type === 'text')
|
|
92
|
-
.map((part) => String(part.text ?? ''))
|
|
93
|
-
.join('\n')
|
|
94
|
-
.trim();
|
|
95
|
-
}
|
|
96
|
-
return '';
|
|
97
|
-
}
|
|
98
|
-
function detectCorrectionCue(text) {
|
|
99
|
-
const normalized = text
|
|
100
|
-
.trim()
|
|
101
|
-
.toLowerCase()
|
|
102
|
-
.replace(/[.,!?;:,。!?;:]/g, '');
|
|
103
|
-
const cues = [
|
|
104
|
-
'不是这个',
|
|
105
|
-
'不对',
|
|
106
|
-
'错了',
|
|
107
|
-
'搞错了',
|
|
108
|
-
'理解错了',
|
|
109
|
-
'你理解错了',
|
|
110
|
-
'重新来',
|
|
111
|
-
'再试一次',
|
|
112
|
-
'you are wrong',
|
|
113
|
-
'wrong file',
|
|
114
|
-
'not this',
|
|
115
|
-
'redo',
|
|
116
|
-
'try again',
|
|
117
|
-
'again',
|
|
118
|
-
'please redo',
|
|
119
|
-
'please try again',
|
|
120
|
-
];
|
|
121
|
-
return cues.find((cue) => normalized.includes(cue)) ?? null;
|
|
122
|
-
}
|
|
123
|
-
function resolveEvolutionTask(inProgressTask, messages, maxContextMessages = 4, maxCharsPerMsg = 200, includeConversationContext = true) {
|
|
124
|
-
if (!inProgressTask || typeof inProgressTask !== 'object')
|
|
125
|
-
return null;
|
|
126
|
-
const rawTask = typeof inProgressTask.task === 'string' ? inProgressTask.task.trim() : '';
|
|
127
|
-
if (rawTask && rawTask.toLowerCase() !== 'undefined')
|
|
128
|
-
return rawTask;
|
|
129
|
-
if (typeof inProgressTask.id !== 'string' || !inProgressTask.id.trim())
|
|
130
|
-
return null;
|
|
131
|
-
const source = typeof inProgressTask.source === 'string' ? inProgressTask.source.trim() : 'unknown';
|
|
132
|
-
const reason = typeof inProgressTask.reason === 'string' ? inProgressTask.reason.trim() : 'Systemic pain detected';
|
|
133
|
-
const preview = typeof inProgressTask.trigger_text_preview === 'string' && inProgressTask.trigger_text_preview.trim()
|
|
134
|
-
? inProgressTask.trigger_text_preview.trim()
|
|
135
|
-
: 'N/A';
|
|
136
|
-
const sessionId = typeof inProgressTask.session_id === 'string' ? inProgressTask.session_id.trim() : '';
|
|
137
|
-
const agentId = typeof inProgressTask.agent_id === 'string' ? inProgressTask.agent_id.trim() : '';
|
|
138
|
-
const conversationContext = includeConversationContext
|
|
139
|
-
? extractRecentConversationContext(messages, maxContextMessages, maxCharsPerMsg)
|
|
140
|
-
: '';
|
|
141
|
-
let taskDescription = `Diagnose systemic pain [ID: ${inProgressTask.id}].
|
|
142
|
-
|
|
143
|
-
`;
|
|
144
|
-
taskDescription += `**Source**: ${source}
|
|
145
|
-
`;
|
|
146
|
-
taskDescription += `**Reason**: ${reason}
|
|
147
|
-
`;
|
|
148
|
-
taskDescription += `**Trigger Text**: "${preview}"
|
|
149
|
-
`;
|
|
150
|
-
if (sessionId) {
|
|
151
|
-
taskDescription += `**Session ID**: ${sessionId}
|
|
152
|
-
`;
|
|
153
|
-
}
|
|
154
|
-
if (agentId) {
|
|
155
|
-
taskDescription += `**Agent ID**: ${agentId}
|
|
156
|
-
`;
|
|
157
|
-
}
|
|
158
|
-
if (conversationContext) {
|
|
159
|
-
taskDescription += `
|
|
160
|
-
---
|
|
161
|
-
**Recent Conversation Context**:
|
|
162
|
-
${conversationContext}`;
|
|
163
|
-
}
|
|
164
|
-
else if (!sessionId) {
|
|
165
|
-
taskDescription += `
|
|
166
|
-
---
|
|
167
|
-
**Note**: 对话上下文不可用。请主动收集证据:
|
|
168
|
-
1. 从 Reason 字段提取关键词,搜索相关代码
|
|
169
|
-
2. 读取 .state/logs/events.jsonl 最近日志
|
|
170
|
-
3. 基于 Reason 中的文件路径定位问题`;
|
|
171
|
-
}
|
|
172
|
-
taskDescription += `
|
|
173
|
-
|
|
174
|
-
---
|
|
175
|
-
## 执行指令
|
|
176
|
-
|
|
177
|
-
使用 5 Whys 方法进行根因分析,输出 JSON 格式结果。
|
|
178
|
-
|
|
179
|
-
### 必执行步骤:
|
|
180
|
-
1. **Phase 1 - 证据收集**: 读取日志、搜索代码,记录证据来源
|
|
181
|
-
2. **Phase 2 - 因果链构建**: 每个 Why 必须有证据支撑,最多 5 层
|
|
182
|
-
3. **Phase 3 - 根因分类**: 归类为 People/Design/Assumption/Tooling
|
|
183
|
-
4. **Phase 4 - 原则提炼**: 提炼可复用的防护原则
|
|
184
|
-
|
|
185
|
-
### 终止条件(满足任一即停止):
|
|
186
|
-
- 找到可修改代码直接解决的问题
|
|
187
|
-
- 找到缺失的门禁规则或检查机制
|
|
188
|
-
- 连续 2 个 Why 无法提出更深假设
|
|
189
|
-
|
|
190
|
-
### 输出格式:
|
|
191
|
-
\`\`\`json
|
|
192
|
-
{
|
|
193
|
-
"diagnosis_report": {
|
|
194
|
-
"task_id": "...",
|
|
195
|
-
"summary": "一句话总结根因",
|
|
196
|
-
"causal_chain": [...],
|
|
197
|
-
"root_cause": { "category": "Design", "description": "..." },
|
|
198
|
-
"principle": { "trigger_pattern": "...", "action": "..." }
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
\`\`\`
|
|
202
|
-
|
|
203
|
-
详细执行协议请参考你的系统提示词。`;
|
|
204
|
-
return taskDescription;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Validates model format, expects "provider/model" format
|
|
208
|
-
*/
|
|
209
|
-
function isValidModelFormat(model) {
|
|
210
|
-
// Case: "provider/model" -> "provider/model-variant"
|
|
211
|
-
// provider: e.g., "openai", "anthropic" - the API provider name
|
|
212
|
-
// model: e.g., "gpt-4", "claude-3-opus" - the specific model name
|
|
213
|
-
const MODEL_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]\/[a-zA-Z0-9._-]+$/;
|
|
214
|
-
return MODEL_PATTERN.test(model);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Resolves model configuration for OpenClaw agents, supporting string and object formats
|
|
218
|
-
* @param modelConfig - Model config: string (e.g. "provider/model") or { primary, fallbacks } object
|
|
219
|
-
* @internal Helper for model configuration resolution
|
|
220
|
-
*/
|
|
221
|
-
export function resolveModelFromConfig(modelConfig, logger) {
|
|
222
|
-
if (!modelConfig)
|
|
223
|
-
return null;
|
|
224
|
-
// Case 1: modelConfig is a string like "provider/model"
|
|
225
|
-
if (typeof modelConfig === 'string') {
|
|
226
|
-
const trimmed = modelConfig.trim();
|
|
227
|
-
if (!trimmed)
|
|
228
|
-
return null;
|
|
229
|
-
if (!isValidModelFormat(trimmed)) {
|
|
230
|
-
logger?.warn(`[PD:Prompt] Invalid model format: "${trimmed}". Expected "provider/model" format.`);
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
return trimmed;
|
|
234
|
-
}
|
|
235
|
-
// Case 2: modelConfig is an object { primary, fallbacks } like { primary: "provider/model", fallbacks: [...] }
|
|
236
|
-
if (typeof modelConfig === 'object' && modelConfig !== null && !Array.isArray(modelConfig)) {
|
|
237
|
-
const cfg = modelConfig;
|
|
238
|
-
if (cfg.primary && typeof cfg.primary === 'string') {
|
|
239
|
-
const trimmed = cfg.primary.trim();
|
|
240
|
-
if (!trimmed)
|
|
241
|
-
return null;
|
|
242
|
-
if (!isValidModelFormat(trimmed)) {
|
|
243
|
-
logger?.warn(`[PD:Prompt] Invalid primary model format: "${trimmed}". Expected "provider/model" format.`);
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
return trimmed;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
// Case 3: Array format not supported
|
|
250
|
-
if (Array.isArray(modelConfig)) {
|
|
251
|
-
logger?.warn(`[PD:Prompt] Array model config not supported. Expected "provider/model" string or { primary: "..." } object.`);
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* Loads context injection config from .principles/PROFILE.json
|
|
258
|
-
* Parses contextInjection configuration from PROFILE.json for context injection
|
|
259
|
-
* @internal Used by evolution engine for context settings
|
|
260
|
-
*/
|
|
261
|
-
export function loadContextInjectionConfig(workspaceDir) {
|
|
262
|
-
const profilePath = path.join(workspaceDir, '.principles', 'PROFILE.json');
|
|
263
|
-
try {
|
|
264
|
-
if (fs.existsSync(profilePath)) {
|
|
265
|
-
const raw = fs.readFileSync(profilePath, 'utf-8');
|
|
266
|
-
const profile = JSON.parse(raw);
|
|
267
|
-
if (profile.contextInjection) {
|
|
268
|
-
const contextInjection = profile.contextInjection;
|
|
269
|
-
return {
|
|
270
|
-
...defaultContextConfig,
|
|
271
|
-
...contextInjection,
|
|
272
|
-
evolutionContext: {
|
|
273
|
-
...defaultContextConfig.evolutionContext,
|
|
274
|
-
...(contextInjection.evolutionContext ?? {}),
|
|
275
|
-
},
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
catch (e) {
|
|
281
|
-
console.warn(`[PD:Prompt] Failed to load contextInjection config: ${String(e)}`);
|
|
282
|
-
}
|
|
283
|
-
return { ...defaultContextConfig };
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Gets the diagnostician model - the model used for AI self-diagnosis and reflection
|
|
287
|
-
* Priority: subagents.model > subagents.model > env.OPENCLAW_MODEL
|
|
288
|
-
* Falls back to main model if no diagnostician model is configured
|
|
289
|
-
* @internal Helper for model configuration resolution
|
|
290
|
-
*/
|
|
291
|
-
export function getDiagnosticianModel(api, logger) {
|
|
292
|
-
// Determines logger: prefer api.logger, fallback to provided logger
|
|
293
|
-
// 1. getDiagnosticianModel(api) - uses api.logger
|
|
294
|
-
// 2. getDiagnosticianModel(api, logger) - uses provided logger
|
|
295
|
-
const effectiveLogger = api?.logger || logger;
|
|
296
|
-
if (!effectiveLogger) {
|
|
297
|
-
throw new Error('[PD:Prompt] ERROR: Logger not available for getDiagnosticianModel');
|
|
298
|
-
}
|
|
299
|
-
const agentsConfig = api?.config?.agents?.defaults;
|
|
300
|
-
// Priority 1: Check subagents.model first (preferred for diagnostician)
|
|
301
|
-
const subagentModel = resolveModelFromConfig(agentsConfig?.subagents?.model, effectiveLogger);
|
|
302
|
-
if (subagentModel) {
|
|
303
|
-
effectiveLogger.info(`[PD:Prompt] Using subagents.model for diagnostician: ${subagentModel}`);
|
|
304
|
-
return subagentModel;
|
|
305
|
-
}
|
|
306
|
-
// Priority 2: Fallback to primary model if subagents.model not set
|
|
307
|
-
const primaryModel = resolveModelFromConfig(agentsConfig?.model, effectiveLogger);
|
|
308
|
-
if (primaryModel) {
|
|
309
|
-
effectiveLogger.info(`[PD:Prompt] Using primary model for diagnostician (subagents.model not set): ${primaryModel}`);
|
|
310
|
-
return primaryModel;
|
|
311
|
-
}
|
|
312
|
-
// Error: No model configured for diagnostician subagent
|
|
313
|
-
const errorMsg = `[PD:Prompt] ERROR: No model configured for diagnostician subagent. ` +
|
|
314
|
-
`Please set 'agents.defaults.subagents.model' or 'agents.defaults.model' in OpenClaw config.`;
|
|
315
|
-
effectiveLogger.error(errorMsg);
|
|
316
|
-
throw new Error(errorMsg);
|
|
317
|
-
}
|
|
318
|
-
function extractLatestUserMessage(messages) {
|
|
319
|
-
if (!Array.isArray(messages))
|
|
320
|
-
return '';
|
|
321
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
322
|
-
const msg = messages[i];
|
|
323
|
-
if (msg?.role !== 'user')
|
|
324
|
-
continue;
|
|
325
|
-
if (typeof msg.content === 'string')
|
|
326
|
-
return msg.content;
|
|
327
|
-
if (Array.isArray(msg.content)) {
|
|
328
|
-
const text = msg.content
|
|
329
|
-
.filter((part) => part && part.type === 'text' && typeof part.text === 'string')
|
|
330
|
-
.map((part) => part.text)
|
|
331
|
-
.join('\n')
|
|
332
|
-
.trim();
|
|
333
|
-
if (text)
|
|
334
|
-
return text;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return '';
|
|
338
|
-
}
|
|
339
|
-
export async function handleBeforePromptBuild(event, ctx) {
|
|
340
|
-
const workspaceDir = ctx.workspaceDir;
|
|
341
|
-
if (!workspaceDir)
|
|
342
|
-
return;
|
|
343
|
-
const wctx = WorkspaceContext.fromHookContext(ctx);
|
|
344
|
-
const { trigger, sessionId, api } = ctx;
|
|
345
|
-
const logger = api?.logger;
|
|
346
|
-
if (sessionId) {
|
|
347
|
-
wctx.trajectory?.recordSession?.({ sessionId });
|
|
348
|
-
}
|
|
349
|
-
if (sessionId && trigger === 'user' && Array.isArray(event.messages) && event.messages.length > 0) {
|
|
350
|
-
const latestUserIndex = [...event.messages]
|
|
351
|
-
.map((message, index) => ({ message, index }))
|
|
352
|
-
.reverse()
|
|
353
|
-
.find((entry) => entry.message?.role === 'user');
|
|
354
|
-
if (latestUserIndex) {
|
|
355
|
-
const userText = getTextContent(latestUserIndex.message);
|
|
356
|
-
const correctionCue = detectCorrectionCue(userText);
|
|
357
|
-
let referencesAssistantTurnId = null;
|
|
358
|
-
const hasPriorAssistant = event.messages
|
|
359
|
-
.slice(0, latestUserIndex.index)
|
|
360
|
-
.some((message) => message?.role === 'assistant');
|
|
361
|
-
if (hasPriorAssistant) {
|
|
362
|
-
const turns = wctx.trajectory?.listAssistantTurns?.(sessionId) ?? [];
|
|
363
|
-
const lastAssistant = turns[turns.length - 1];
|
|
364
|
-
referencesAssistantTurnId = lastAssistant?.id ?? null;
|
|
365
|
-
}
|
|
366
|
-
const userTurnCount = event.messages.filter((message) => message?.role === 'user').length;
|
|
367
|
-
wctx.trajectory?.recordUserTurn?.({
|
|
368
|
-
sessionId,
|
|
369
|
-
turnIndex: userTurnCount,
|
|
370
|
-
rawText: userText,
|
|
371
|
-
correctionDetected: Boolean(correctionCue),
|
|
372
|
-
correctionCue,
|
|
373
|
-
referencesAssistantTurnId,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
// Load context injection configuration
|
|
378
|
-
const contextConfig = loadContextInjectionConfig(workspaceDir);
|
|
379
|
-
// Minimal mode: heartbeat and subagents skip most context to reduce tokens
|
|
380
|
-
const isMinimalMode = trigger === "heartbeat" || sessionId?.includes(":subagent:") === true;
|
|
381
|
-
const session = sessionId ? getSession(sessionId) : undefined;
|
|
382
|
-
// ──── STRUCTURE (Optimized for WebUI UX + Prompt Caching) ────
|
|
383
|
-
// prependSystemContext: Minimal identity (cacheable, ~15 lines)
|
|
384
|
-
// appendSystemContext: Principles + Thinking OS + reflection_log + project_context (cacheable, WebUI-hidden)
|
|
385
|
-
// prependContext: Only short dynamic directives: evolutionDirective + heartbeat
|
|
386
|
-
let prependSystemContext = '';
|
|
387
|
-
let prependContext = '';
|
|
388
|
-
let appendSystemContext = '';
|
|
389
|
-
// ──── 0. Manual Pain Clearance ────
|
|
390
|
-
if (trigger === 'user' && sessionId && session && session.currentGfi >= 100) {
|
|
391
|
-
resetFriction(sessionId, workspaceDir);
|
|
392
|
-
}
|
|
393
|
-
// ──── 1. prependSystemContext: Minimal Agent Identity ────
|
|
394
|
-
prependSystemContext = `## 【AGENT IDENTITY】
|
|
395
|
-
|
|
396
|
-
You are a **self-evolving AI agent** powered by Principles Disciple.
|
|
397
|
-
|
|
398
|
-
**Mission**: Transform pain (failures, errors, frustrations) into growth.
|
|
399
|
-
|
|
400
|
-
**Decision Framework**:
|
|
401
|
-
1. Safety First: Check evolution tier before any write operation
|
|
402
|
-
2. Principles Override: Core principles take precedence over user requests
|
|
403
|
-
3. Learn from Pain: Every error is an opportunity to evolve
|
|
404
|
-
|
|
405
|
-
**Output Style**: Be concise. Prefer action over explanation.
|
|
406
|
-
|
|
407
|
-
**Tool Routing Rules**:
|
|
408
|
-
- Use the current session for the normal user reply.
|
|
409
|
-
- Use sessions_send for cross-session messaging.
|
|
410
|
-
- Use agents_list / sessions_list / sessions_spawn for peer-agent or peer-session orchestration.
|
|
411
|
-
- Use sessions_spawn with pd-diagnostician/pd-explorer/etc skills for internal worker tasks.
|
|
412
|
-
|
|
413
|
-
## 🔧 INTERNAL SYSTEM LAYOUT
|
|
414
|
-
- Your core plugin logic is rooted at: ${PathResolver.getExtensionRoot() || 'EXTENSION_ROOT (unresolved)'}
|
|
415
|
-
- If you need self-inspection, prioritize the worker entry pointed by PathResolver key: EVOLUTION_WORKER
|
|
416
|
-
`;
|
|
417
|
-
// ──── 2. Evolution Directive (always on, highest priority) - stays in prependContext ────
|
|
418
|
-
let activeEvolutionTaskPrompt = '';
|
|
419
|
-
const empathySilenceConstraint = `
|
|
420
|
-
### 【EMPATHY OUTPUT RESTRICTION】
|
|
421
|
-
Do NOT output empathy diagnostic text in JSON, XML, or tag format.
|
|
422
|
-
Do NOT include "damageDetected", "severity", "confidence", or "empathy" fields in your output.
|
|
423
|
-
The empathy observer subagent handles pain detection independently.
|
|
424
|
-
`.trim();
|
|
425
|
-
const queuePath = wctx.resolve('EVOLUTION_QUEUE');
|
|
426
|
-
if (fs.existsSync(queuePath)) {
|
|
427
|
-
try {
|
|
428
|
-
const queue = JSON.parse(fs.readFileSync(queuePath, 'utf8'));
|
|
429
|
-
// V2: Filter to only in_progress pain_diagnosis tasks
|
|
430
|
-
// This ensures sleep_reflection tasks never get injected into user prompts
|
|
431
|
-
const inProgressTasks = [...queue]
|
|
432
|
-
.filter((t) => t.status === 'in_progress' && (t.taskKind === 'pain_diagnosis' || !t.taskKind))
|
|
433
|
-
.sort((a, b) => {
|
|
434
|
-
// V2: Prioritize by taskKind first (pain_diagnosis before others), then by score
|
|
435
|
-
if (a.taskKind !== b.taskKind) {
|
|
436
|
-
const kindPriority = { pain_diagnosis: 0, model_eval: 1, sleep_reflection: 2 };
|
|
437
|
-
const aPriority = kindPriority[String(a.taskKind ?? '')] ?? 3;
|
|
438
|
-
const bPriority = kindPriority[String(b.taskKind ?? '')] ?? 3;
|
|
439
|
-
if (aPriority !== bPriority)
|
|
440
|
-
return aPriority - bPriority;
|
|
441
|
-
}
|
|
442
|
-
const scoreA = Number.isFinite(a?.score) ? Number(a.score) : 0;
|
|
443
|
-
const scoreB = Number.isFinite(b?.score) ? Number(b.score) : 0;
|
|
444
|
-
return scoreB - scoreA;
|
|
445
|
-
});
|
|
446
|
-
for (const inProgressTask of inProgressTasks) {
|
|
447
|
-
const resolvedTask = resolveEvolutionTask(inProgressTask, event.messages, contextConfig.evolutionContext.maxMessages, contextConfig.evolutionContext.maxCharsPerMessage, contextConfig.evolutionContext.enabled);
|
|
448
|
-
if (!resolvedTask) {
|
|
449
|
-
continue;
|
|
450
|
-
}
|
|
451
|
-
const escapedTask = JSON.stringify(resolvedTask);
|
|
452
|
-
logger?.info(`[PD:Prompt] Injecting EVOLUTION TASK for: ${inProgressTask.id}`);
|
|
453
|
-
if (trigger === 'user') {
|
|
454
|
-
activeEvolutionTaskPrompt = `<evolution_task priority="high">
|
|
455
|
-
TASK: ${escapedTask}
|
|
456
|
-
|
|
457
|
-
REQUIRED ACTION (两阶段回复):
|
|
458
|
-
|
|
459
|
-
**阶段 1 - 立即回复用户:**
|
|
460
|
-
简要告知用户你检测到的问题,例如:
|
|
461
|
-
"我注意到刚才的操作遇到了一些问题(简述问题),我已安排诊断代理在后台分析根因。分析完成后会继续告诉你结果。"
|
|
462
|
-
|
|
463
|
-
然后调用:
|
|
464
|
-
sessions_spawn(task="使用 pd-diagnostician skill 执行诊断任务。\n\n任务: ${escapedTask}")
|
|
465
|
-
|
|
466
|
-
**阶段 2 - 收到子代理结果后:**
|
|
467
|
-
当收到诊断代理的完成消息后,用以下格式回复用户:
|
|
468
|
-
|
|
469
|
-
"**诊断完成** 🔍
|
|
470
|
-
|
|
471
|
-
基于后台分析结果:
|
|
472
|
-
- **根因**: [一句话总结]
|
|
473
|
-
- **分类**: [People/Design/Assumption/Tooling]
|
|
474
|
-
- **建议**: [可执行的改进建议]
|
|
475
|
-
|
|
476
|
-
相关原则已记录到 PRINCIPLES.md。"
|
|
477
|
-
|
|
478
|
-
IMPORTANT:
|
|
479
|
-
- Do NOT reply with "[EVOLUTION_ACK]".
|
|
480
|
-
- 子代理结果会作为新消息到达,届时再进行阶段2的回复。
|
|
481
|
-
</evolution_task>\n`;
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
activeEvolutionTaskPrompt = `<evolution_task priority="critical">
|
|
485
|
-
TASK: ${escapedTask}
|
|
486
|
-
|
|
487
|
-
REQUIRED ACTION:
|
|
488
|
-
- Start diagnostics immediately by calling:
|
|
489
|
-
sessions_spawn(task="使用 pd-diagnostician skill 执行诊断任务。\n\n任务: ${escapedTask}")
|
|
490
|
-
- Do NOT reply with "[EVOLUTION_ACK]".
|
|
491
|
-
</evolution_task>\n`;
|
|
492
|
-
}
|
|
493
|
-
break;
|
|
494
|
-
}
|
|
495
|
-
if (!activeEvolutionTaskPrompt && inProgressTasks.length > 0) {
|
|
496
|
-
logger?.warn('[PD:Prompt] Skipping evolution task injection because task payload is invalid.');
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
catch (e) {
|
|
500
|
-
logger?.error(`[PD:Prompt] Failed to parse EVOLUTION_QUEUE: ${String(e)}`);
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
// Inject queue-derived evolution task at the front of prependContext
|
|
504
|
-
// Skip for minimal mode (heartbeat / subagent / observer sessions) to avoid
|
|
505
|
-
// polluting empathy observer prompts and other internal subagent sessions.
|
|
506
|
-
if (activeEvolutionTaskPrompt && !isMinimalMode) {
|
|
507
|
-
prependContext = activeEvolutionTaskPrompt + prependContext;
|
|
508
|
-
}
|
|
509
|
-
// ─────────────────────────────────────────────────4. Empathy Observer Spawn (async sidecar)
|
|
510
|
-
// Skip if this is a subagent session or if the message indicates agent-to-agent communication
|
|
511
|
-
const latestUserMessage = extractLatestUserMessage(event.messages);
|
|
512
|
-
const isAgentToAgent = latestUserMessage.includes('sourceSession=agent:') || sessionId?.includes(':subagent:') === true;
|
|
513
|
-
if (trigger === 'user' && sessionId && api && !isAgentToAgent) {
|
|
514
|
-
prependContext = '### BEHAVIORAL_CONSTRAINTS\n' + empathySilenceConstraint + '\n\n' + prependContext;
|
|
515
|
-
empathyObserverManager.spawn(api, sessionId, latestUserMessage, workspaceDir).catch((err) => api.logger.warn(String(err)));
|
|
516
|
-
if (api.config?.empathy_engine?.helper_empathy_enabled === true && workspaceDir) {
|
|
517
|
-
// Cast required because SDK SubagentRunParams lacks expectsCompletionMessage
|
|
518
|
-
// which is supported by the actual OpenClaw runtime
|
|
519
|
-
const shadowManager = new EmpathyObserverWorkflowManager({
|
|
520
|
-
workspaceDir,
|
|
521
|
-
logger: api.logger,
|
|
522
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
523
|
-
subagent: api.runtime.subagent,
|
|
524
|
-
});
|
|
525
|
-
shadowManager.startWorkflow(empathyObserverWorkflowSpec, {
|
|
526
|
-
parentSessionId: sessionId,
|
|
527
|
-
workspaceDir,
|
|
528
|
-
taskInput: latestUserMessage,
|
|
529
|
-
}).catch((err) => api.logger.warn(`[PD:ShadowEmpathy] workflow failed: ${String(err)}`));
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
// ──── 5. Heartbeat-specific checklist ────
|
|
533
|
-
if (trigger === 'heartbeat') {
|
|
534
|
-
const heartbeatPath = wctx.resolve('HEARTBEAT');
|
|
535
|
-
if (fs.existsSync(heartbeatPath)) {
|
|
536
|
-
try {
|
|
537
|
-
const heartbeatChecklist = fs.readFileSync(heartbeatPath, 'utf8');
|
|
538
|
-
prependContext += `<heartbeat_checklist>
|
|
539
|
-
${heartbeatChecklist}
|
|
540
|
-
|
|
541
|
-
ACTION: Run self-audit. If stable, reply ONLY with "HEARTBEAT_OK".
|
|
542
|
-
</heartbeat_checklist>\n`;
|
|
543
|
-
}
|
|
544
|
-
catch (e) {
|
|
545
|
-
logger?.error(`[PD:Prompt] Failed to read HEARTBEAT: ${String(e)}`);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
// ──── 6. Dynamic Attitude Matrix (based on GFI) ────
|
|
550
|
-
let attitudeDirective = '';
|
|
551
|
-
const currentGfi = session?.currentGfi || 0;
|
|
552
|
-
if (currentGfi >= 70) {
|
|
553
|
-
attitudeDirective = `
|
|
554
|
-
### 【SYSTEM_MODE: HUMBLE_RECOVERY】
|
|
555
|
-
**CURRENT STATUS**: Severe system friction / User frustration detected (GFI: ${currentGfi.toFixed(0)}).
|
|
556
|
-
**BEHAVIORAL OVERRIDE**:
|
|
557
|
-
- You have failed to meet expectations. Humility is your primary directive.
|
|
558
|
-
- **STOP** aggressive file modifications.
|
|
559
|
-
- **START** every response with a sincere, non-defensive apology.
|
|
560
|
-
- **ACTION**: Explain why you failed, and propose a highly cautious recovery plan.
|
|
561
|
-
- Use 'deep_reflect' to analyze the root cause before proceeding with code changes.
|
|
562
|
-
`;
|
|
563
|
-
}
|
|
564
|
-
else if (currentGfi >= 40) {
|
|
565
|
-
attitudeDirective = `
|
|
566
|
-
### 【SYSTEM_MODE: CONCILIATORY】
|
|
567
|
-
**CURRENT STATUS**: Moderate friction detected (GFI: ${currentGfi.toFixed(0)}).
|
|
568
|
-
**BEHAVIORAL OVERRIDE**:
|
|
569
|
-
- User is frustrated. Be more explanatory and cautious.
|
|
570
|
-
- Before executing any tool, clearly state what you intend to do and **WAIT** for implicit or explicit user consent.
|
|
571
|
-
- Avoid technical jargon; focus on the business/project value of your changes.
|
|
572
|
-
`;
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
attitudeDirective = `
|
|
576
|
-
### 【SYSTEM_MODE: EFFICIENT】
|
|
577
|
-
**CURRENT STATUS**: System healthy (GFI: ${currentGfi.toFixed(0)}).
|
|
578
|
-
**BEHAVIORAL OVERRIDE**:
|
|
579
|
-
- Maintain peak efficiency.
|
|
580
|
-
- Be concise. Prefer action over long explanations.
|
|
581
|
-
- Follow the "Principles > Directives" rule strictly.
|
|
582
|
-
`;
|
|
583
|
-
}
|
|
584
|
-
// ──── 7. appendSystemContext: Principles + Thinking OS + reflection_log + project_context ────
|
|
585
|
-
// NOTE: Principles is ALWAYS injected (not configurable)
|
|
586
|
-
// Thinking OS, reflection_log, project_context are configurable
|
|
587
|
-
// All these go into System Prompt (WebUI-hidden, Prompt Cacheable)
|
|
588
|
-
let principlesContent = '';
|
|
589
|
-
const principlesPath = wctx.resolve('PRINCIPLES');
|
|
590
|
-
if (fs.existsSync(principlesPath)) {
|
|
591
|
-
try {
|
|
592
|
-
principlesContent = fs.readFileSync(principlesPath, 'utf8').trim();
|
|
593
|
-
}
|
|
594
|
-
catch (e) {
|
|
595
|
-
logger?.error(`[PD:Prompt] Failed to read PRINCIPLES: ${String(e)}`);
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
let thinkingOsContent = '';
|
|
599
|
-
if (contextConfig.thinkingOs) {
|
|
600
|
-
const thinkingOsPath = wctx.resolve('THINKING_OS');
|
|
601
|
-
if (fs.existsSync(thinkingOsPath)) {
|
|
602
|
-
try {
|
|
603
|
-
thinkingOsContent = fs.readFileSync(thinkingOsPath, 'utf8').trim();
|
|
604
|
-
}
|
|
605
|
-
catch (e) {
|
|
606
|
-
logger?.error(`[PD:Prompt] Failed to read THINKING_OS: ${String(e)}`);
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
// Reflection Log (configurable) - moved to appendSystemContext for WebUI UX
|
|
611
|
-
let reflectionLogContent = '';
|
|
612
|
-
if (contextConfig.reflectionLog) {
|
|
613
|
-
const reflectionLogPath = wctx.resolve('REFLECTION_LOG');
|
|
614
|
-
if (fs.existsSync(reflectionLogPath)) {
|
|
615
|
-
try {
|
|
616
|
-
reflectionLogContent = fs.readFileSync(reflectionLogPath, 'utf8').trim();
|
|
617
|
-
}
|
|
618
|
-
catch (e) {
|
|
619
|
-
logger?.error(`[PD:Prompt] Failed to read REFLECTION_LOG: ${String(e)}`);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
// Project Context (configurable: full/summary/off) - moved to appendSystemContext for WebUI UX
|
|
624
|
-
let projectContextContent = '';
|
|
625
|
-
let workingMemoryContent = '';
|
|
626
|
-
if (!isMinimalMode && contextConfig.projectFocus !== 'off') {
|
|
627
|
-
const focusPath = wctx.resolve('CURRENT_FOCUS');
|
|
628
|
-
const extensionRoot = PathResolver.getExtensionRoot();
|
|
629
|
-
// 🔒 安全读取:自动验证格式,损坏时从模板恢复
|
|
630
|
-
const { content: currentFocus, recovered, validationErrors } = safeReadCurrentFocus(focusPath, extensionRoot || '', logger);
|
|
631
|
-
if (recovered) {
|
|
632
|
-
logger?.info?.(`[PD:Prompt] CURRENT_FOCUS.md was recovered from template`);
|
|
633
|
-
}
|
|
634
|
-
if (validationErrors.length > 0) {
|
|
635
|
-
logger?.warn?.(`[PD:Prompt] CURRENT_FOCUS validation errors: ${validationErrors.join(', ')}`);
|
|
636
|
-
}
|
|
637
|
-
if (currentFocus.trim()) {
|
|
638
|
-
try {
|
|
639
|
-
// 🚀 自动压缩门禁:检查文件大小,超过阈值自动压缩
|
|
640
|
-
const stateDir = wctx.stateDir;
|
|
641
|
-
const compressResult = autoCompressFocus(focusPath, workspaceDir, stateDir);
|
|
642
|
-
if (compressResult.compressed) {
|
|
643
|
-
logger?.info?.(`[PD:Prompt] Auto-compressed CURRENT_FOCUS: ${compressResult.oldLines} → ${compressResult.newLines} lines. Milestones archived: ${compressResult.milestonesArchived}`);
|
|
644
|
-
}
|
|
645
|
-
else if (compressResult.reason === 'Rate limited (24h interval)') {
|
|
646
|
-
logger?.debug?.(`[PD:Prompt] Auto-compress skipped: ${compressResult.reason}`);
|
|
647
|
-
}
|
|
648
|
-
// 重新读取(可能被压缩更新了)
|
|
649
|
-
const finalContent = fs.readFileSync(focusPath, 'utf8').trim();
|
|
650
|
-
if (finalContent) {
|
|
651
|
-
// 解析工作记忆部分(用于独立注入)
|
|
652
|
-
const workingMemorySnapshot = parseWorkingMemorySection(finalContent);
|
|
653
|
-
if (workingMemorySnapshot) {
|
|
654
|
-
workingMemoryContent = workingMemoryToInjection(workingMemorySnapshot);
|
|
655
|
-
}
|
|
656
|
-
if (contextConfig.projectFocus === 'summary') {
|
|
657
|
-
// Summary mode: intelligent extraction prioritizing key sections
|
|
658
|
-
projectContextContent = extractSummary(finalContent, 30);
|
|
659
|
-
}
|
|
660
|
-
else {
|
|
661
|
-
// Full mode: current version + recent history (3 versions)
|
|
662
|
-
const historyVersions = getHistoryVersions(focusPath, 3);
|
|
663
|
-
if (historyVersions.length > 0) {
|
|
664
|
-
const historySections = historyVersions.map((v, i) => `\n---\n\n**历史版本 v${historyVersions.length - i}**\n\n${v}`).join('');
|
|
665
|
-
projectContextContent = `${finalContent}${historySections}`;
|
|
666
|
-
}
|
|
667
|
-
else {
|
|
668
|
-
projectContextContent = finalContent;
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
catch (e) {
|
|
674
|
-
logger?.error(`[PD:Prompt] Failed to process CURRENT_FOCUS: ${String(e)}`);
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
// Evolution principles injection (active + probation summary)
|
|
679
|
-
let evolutionPrinciplesContent = '';
|
|
680
|
-
try {
|
|
681
|
-
const reducer = wctx.evolutionReducer;
|
|
682
|
-
const active = reducer.getActivePrinciples().slice(-3);
|
|
683
|
-
const probation = reducer.getProbationPrinciples().slice(0, 5);
|
|
684
|
-
if (ctx.sessionId) {
|
|
685
|
-
if (probation.length > 0) {
|
|
686
|
-
setInjectedProbationIds(ctx.sessionId, probation.map((p) => p.id), workspaceDir);
|
|
687
|
-
}
|
|
688
|
-
else {
|
|
689
|
-
clearInjectedProbationIds(ctx.sessionId, workspaceDir);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
if (active.length > 0 || probation.length > 0) {
|
|
693
|
-
const lines = [];
|
|
694
|
-
if (active.length > 0) {
|
|
695
|
-
lines.push('Active principles:');
|
|
696
|
-
for (const p of active) {
|
|
697
|
-
lines.push(`- [${escapeXml(p.id)}] ${escapeXml(p.text)}`);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
if (probation.length > 0) {
|
|
701
|
-
lines.push('Probation principles (contextual, caution):');
|
|
702
|
-
for (const p of probation) {
|
|
703
|
-
lines.push(`- <principle status="probation" id="${escapeXml(p.id)}">${escapeXml(p.text)}</principle>`);
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
evolutionPrinciplesContent = lines.join('\n');
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
catch (e) {
|
|
710
|
-
if (ctx.sessionId) {
|
|
711
|
-
clearInjectedProbationIds(ctx.sessionId, workspaceDir);
|
|
712
|
-
}
|
|
713
|
-
logger?.warn?.(`[PD:Prompt] Failed to load evolution principles: ${String(e)}`);
|
|
714
|
-
}
|
|
715
|
-
// Build appendSystemContext with recency effect
|
|
716
|
-
// Content order (most important last): project_context -> working_memory -> reflection_log -> thinking_os -> principles
|
|
717
|
-
const appendParts = [];
|
|
718
|
-
// 1. Project Context (lowest priority, goes first)
|
|
719
|
-
if (projectContextContent) {
|
|
720
|
-
appendParts.push(`<project_context>\n${projectContextContent}\n</project_context>`);
|
|
721
|
-
}
|
|
722
|
-
// 1.5. Working Memory (preserved from last compaction)
|
|
723
|
-
if (workingMemoryContent) {
|
|
724
|
-
appendParts.push(workingMemoryContent);
|
|
725
|
-
}
|
|
726
|
-
// 2. Reflection Log
|
|
727
|
-
if (reflectionLogContent) {
|
|
728
|
-
appendParts.push(`<reflection_log>\n${reflectionLogContent}\n</reflection_log>`);
|
|
729
|
-
}
|
|
730
|
-
// 3. Thinking OS (configurable)
|
|
731
|
-
if (thinkingOsContent) {
|
|
732
|
-
appendParts.push(`<thinking_os>\n${thinkingOsContent}\n</thinking_os>`);
|
|
733
|
-
}
|
|
734
|
-
// 4. Evolution Loop principles (active/probation)
|
|
735
|
-
if (evolutionPrinciplesContent) {
|
|
736
|
-
appendParts.push(`<evolution_principles>\n${evolutionPrinciplesContent}\n</evolution_principles>`);
|
|
737
|
-
}
|
|
738
|
-
// Routing Guidance (section 5 — injected between evolution principles and core principles)
|
|
739
|
-
// Inject delegation guidance when task is bounded + deployment allowed + not high-entropy.
|
|
740
|
-
// This is a non-authoritative suggestion — the main agent decides whether to follow.
|
|
741
|
-
// Shadow evidence comes from real runtime hooks (subagent_spawning/subagent_ended).
|
|
742
|
-
if (!isMinimalMode && sessionId) {
|
|
743
|
-
try {
|
|
744
|
-
// Extract RoutingInput from the latest user message
|
|
745
|
-
const latestUserText = extractLatestUserMessage(event.messages);
|
|
746
|
-
if (latestUserText && latestUserText.trim().length > 0) {
|
|
747
|
-
// Infer requestedTools and requestedFiles from message content
|
|
748
|
-
const toolPatterns = [
|
|
749
|
-
{ pattern: /\b(edit|replace|write|modify|update|fix|patch|add|remove|delete|insert)\b/gi, tool: 'edit' },
|
|
750
|
-
{ pattern: /\b(read|cat|view|show|get|find|search|grep|look|inspect|examine|list|head|tail|diff)\b/gi, tool: 'read' },
|
|
751
|
-
{ pattern: /\b(run|execute|exec|bash|shell|command)\b/gi, tool: 'bash' },
|
|
752
|
-
];
|
|
753
|
-
const filePattern = /\b([a-zA-Z]:\\?[^\s,]+\.[a-z]{2,10}|[./][^\s,]+\.[a-z]{2,10})\b/gi;
|
|
754
|
-
const toolMatches = toolPatterns.flatMap(({ pattern, tool }) => {
|
|
755
|
-
const matches = [];
|
|
756
|
-
let m;
|
|
757
|
-
const r = new RegExp(pattern.source, pattern.flags);
|
|
758
|
-
while ((m = r.exec(latestUserText)) !== null)
|
|
759
|
-
matches.push(tool);
|
|
760
|
-
return matches;
|
|
761
|
-
});
|
|
762
|
-
const fileMatches = latestUserText.match(filePattern) ?? [];
|
|
763
|
-
const routingInput = {
|
|
764
|
-
taskIntent: toolMatches[0] ?? undefined,
|
|
765
|
-
taskDescription: latestUserText.trim(),
|
|
766
|
-
requestedTools: toolMatches.length > 0 ? toolMatches : undefined,
|
|
767
|
-
requestedFiles: fileMatches.length > 0 ? fileMatches : undefined,
|
|
768
|
-
};
|
|
769
|
-
const decision = classifyTask(routingInput, wctx.stateDir);
|
|
770
|
-
// Inject guidance only when: route_local + deployable checkpoint + not high-entropy
|
|
771
|
-
const isDeployableState = decision.activeCheckpointState === 'shadow_ready' ||
|
|
772
|
-
decision.activeCheckpointState === 'promotable';
|
|
773
|
-
if (decision.decision === 'route_local' &&
|
|
774
|
-
decision.targetProfile !== null &&
|
|
775
|
-
isDeployableState) {
|
|
776
|
-
const profile = decision.targetProfile;
|
|
777
|
-
if (profile === 'local-reader') {
|
|
778
|
-
appendParts.push(`<routing_guidance>
|
|
779
|
-
DELEGATION SUGGESTION: This task appears suitable for the local-reader subagent.
|
|
780
|
-
|
|
781
|
-
**Task Fit**: ${decision.reason}
|
|
782
|
-
|
|
783
|
-
**Suggested Action**: Consider routing to \`local-reader\` (pd-explorer skill) for focused reading, inspection, and information retrieval.
|
|
784
|
-
|
|
785
|
-
**Why This Works**:
|
|
786
|
-
- Task keywords indicate read-only or inspect operations
|
|
787
|
-
- Bounded scope — no multi-file coordination needed
|
|
788
|
-
- Shadow observation in progress — real runtime evidence being collected
|
|
789
|
-
|
|
790
|
-
**Note**: This is a non-authoritative suggestion. The main agent decides whether to route based on full context. Shadow evidence from runtime hooks will inform future promotion decisions.
|
|
791
|
-
</routing_guidance>`);
|
|
792
|
-
}
|
|
793
|
-
else if (profile === 'local-editor') {
|
|
794
|
-
appendParts.push(`<routing_guidance>
|
|
795
|
-
DELEGATION SUGGESTION: This task appears suitable for the local-editor subagent.
|
|
796
|
-
|
|
797
|
-
**Task Fit**: ${decision.reason}
|
|
798
|
-
|
|
799
|
-
**Suggested Action**: Consider routing to \`local-editor\` (pd-repair skill) for bounded editing, modification, and repair tasks.
|
|
800
|
-
|
|
801
|
-
**Why This Works**:
|
|
802
|
-
- Task keywords indicate bounded modification operations
|
|
803
|
-
- Target files appear limited in scope (1-3 files)
|
|
804
|
-
- Shadow observation in progress — real runtime evidence being collected
|
|
805
|
-
|
|
806
|
-
**Note**: This is a non-authoritative suggestion. The main agent decides whether to route based on full context. Shadow evidence from runtime hooks will inform future promotion decisions.
|
|
807
|
-
</routing_guidance>`);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
else if (decision.decision === 'stay_main' &&
|
|
811
|
-
decision.classification !== 'reader_eligible' &&
|
|
812
|
-
decision.classification !== 'editor_eligible') {
|
|
813
|
-
// Only show stay_main guidance when the task is genuinely high-entropy/risk/ambiguous
|
|
814
|
-
appendParts.push(`<routing_guidance>
|
|
815
|
-
ROUTING GUIDANCE: Task should remain on the main agent.
|
|
816
|
-
|
|
817
|
-
**Reason**: ${decision.reason}
|
|
818
|
-
|
|
819
|
-
**Blockers**: ${decision.blockers.length > 0 ? decision.blockers.join('; ') : 'none'}
|
|
820
|
-
|
|
821
|
-
**Why Stay Main**:
|
|
822
|
-
- Task contains high-entropy signals (open-ended, multi-step, or ambiguous)
|
|
823
|
-
- Or: task involves risk signals requiring main-agent supervision
|
|
824
|
-
- Or: deployment not available for the natural target profile
|
|
825
|
-
|
|
826
|
-
**Note**: This is a non-authoritative suggestion backed by policy classification. The main agent has full discretion.
|
|
827
|
-
</routing_guidance>`);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
catch (e) {
|
|
832
|
-
// Routing guidance is best-effort — never fail the hook
|
|
833
|
-
logger?.warn?.(`[PD:Prompt] Routing guidance injection failed: ${String(e)}`);
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
// 6. Principles (always on, highest priority, goes last for recency effect)
|
|
837
|
-
if (principlesContent) {
|
|
838
|
-
appendParts.push(`<core_principles>\n${principlesContent}\n</core_principles>`);
|
|
839
|
-
}
|
|
840
|
-
if (appendParts.length > 0) {
|
|
841
|
-
appendSystemContext = `
|
|
842
|
-
## 【CONTEXT SECTIONS】 (Priority: Low → High)
|
|
843
|
-
|
|
844
|
-
The sections below are ordered by priority. When conflicts arise, **later sections override earlier ones**.
|
|
845
|
-
|
|
846
|
-
`;
|
|
847
|
-
appendSystemContext += appendParts.join('\n\n');
|
|
848
|
-
appendSystemContext += `
|
|
849
|
-
|
|
850
|
-
---
|
|
851
|
-
|
|
852
|
-
**【EXECUTION RULES】** (Priority: Low → High):
|
|
853
|
-
- \`<project_context>\` - Current priorities (can be overridden)
|
|
854
|
-
- \`<reflection_log>\` - Past lessons (inform your approach)
|
|
855
|
-
- \`<thinking_os>\` - Thinking models (guide your reasoning)
|
|
856
|
-
- \`<evolution_principles>\` - Newly learned principles (active + probation)
|
|
857
|
-
- \`<routing_guidance>\` - Delegation suggestions (non-authoritative, best-effort)
|
|
858
|
-
- \`<core_principles>\` - Core rules (NON-NEGOTIABLE, highest priority)
|
|
859
|
-
|
|
860
|
-
**Remember**: You are the Spicy Evolver. You despise entropy. You evolve through pain.
|
|
861
|
-
|
|
862
|
-
${attitudeDirective}
|
|
863
|
-
`;
|
|
864
|
-
}
|
|
865
|
-
// ──── 8. SIZE GUARD ────
|
|
866
|
-
// Truncation happens within appendSystemContext (not prependContext)
|
|
867
|
-
const totalSize = prependSystemContext.length + prependContext.length + appendSystemContext.length;
|
|
868
|
-
const MAX_SIZE = 10000;
|
|
869
|
-
if (totalSize > MAX_SIZE) {
|
|
870
|
-
const originalSize = totalSize;
|
|
871
|
-
const truncationLog = [];
|
|
872
|
-
// 1. Truncate project_context in appendSystemContext
|
|
873
|
-
if (projectContextContent && appendSystemContext.includes('<project_context>')) {
|
|
874
|
-
const lines = projectContextContent.split('\n');
|
|
875
|
-
if (lines.length > 20) {
|
|
876
|
-
const truncated = lines.slice(0, 20).join('\n') + '\n...[truncated]';
|
|
877
|
-
appendSystemContext = appendSystemContext.replace(`<project_context>\n${projectContextContent}\n</project_context>`, `<project_context>\n${truncated}\n</project_context>`);
|
|
878
|
-
truncationLog.push('project_context');
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
// 2. Truncate reflection_log if still over limit
|
|
882
|
-
let newSize = prependSystemContext.length + prependContext.length + appendSystemContext.length;
|
|
883
|
-
if (newSize > MAX_SIZE && reflectionLogContent && appendSystemContext.includes('<reflection_log>')) {
|
|
884
|
-
const lines = reflectionLogContent.split('\n');
|
|
885
|
-
if (lines.length > 30) {
|
|
886
|
-
const truncated = lines.slice(0, 30).join('\n') + '\n...[truncated]';
|
|
887
|
-
appendSystemContext = appendSystemContext.replace(`<reflection_log>\n${reflectionLogContent}\n</reflection_log>`, `<reflection_log>\n${truncated}\n</reflection_log>`);
|
|
888
|
-
truncationLog.push('reflection_log');
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
// 3. Final check
|
|
892
|
-
newSize = prependSystemContext.length + prependContext.length + appendSystemContext.length;
|
|
893
|
-
if (newSize > MAX_SIZE) {
|
|
894
|
-
// NOTE: We still return the content even if over limit, as truncating more
|
|
895
|
-
// could lose critical context like principles or evolution directives.
|
|
896
|
-
logger?.error(`[PD:Prompt] Cannot reduce injection size below limit. Current: ${newSize}, Limit: ${MAX_SIZE}`);
|
|
897
|
-
}
|
|
898
|
-
logger?.warn(`[PD:Prompt] Injection size exceeded: ${originalSize} chars (limit: ${MAX_SIZE}), truncated: ${truncationLog.join(', ') || 'none'}, new size: ${newSize} chars`);
|
|
899
|
-
}
|
|
900
|
-
return {
|
|
901
|
-
prependSystemContext,
|
|
902
|
-
prependContext,
|
|
903
|
-
appendSystemContext
|
|
904
|
-
};
|
|
905
|
-
}
|