principles-disciple 1.8.0 → 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 +6 -1
- package/package.json +13 -15
- 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} +185 -63
- 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} +166 -139
- 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} +263 -36
- 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/src/service/subagent-workflow/empathy-observer-workflow-manager.ts +603 -0
- 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/src/service/subagent-workflow/types.ts +378 -0
- 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 -127
- 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 -99
- 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 -12
- 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 -51
- package/dist/hooks/progressive-trust-gate.js +0 -89
- package/dist/hooks/prompt.d.ts +0 -47
- package/dist/hooks/prompt.js +0 -884
- 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 -567
- 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 -52
- package/dist/service/empathy-observer-manager.js +0 -229
- 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 -974
- 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/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
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import type { PluginHookSubagentEndedEvent, PluginHookSubagentContext, PluginLogger, OpenClawPluginApi } from '../openclaw-sdk.js';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import { writePainFlag } from '../core/pain.js';
|
|
4
|
+
import { WorkspaceContext } from '../core/workspace-context.js';
|
|
5
|
+
// No longer needed — diagnostician runs via HEARTBEAT, not subagent
|
|
6
|
+
import { recordEvolutionSuccess } from '../core/evolution-engine.js';
|
|
7
|
+
import { WorkflowStore } from '../service/subagent-workflow/workflow-store.js';
|
|
8
|
+
import { EmpathyObserverWorkflowManager } from '../service/subagent-workflow/empathy-observer-workflow-manager.js';
|
|
9
|
+
import { DeepReflectWorkflowManager } from '../service/subagent-workflow/deep-reflect-workflow-manager.js';
|
|
10
|
+
import type { WorkflowManager } from '../service/subagent-workflow/types.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Factory to create the appropriate WorkflowManager by workflow_type string.
|
|
14
|
+
* Used by the subagent_ended hook to dispatch lifecycle recovery to the right manager.
|
|
15
|
+
*/
|
|
16
|
+
function createWorkflowManagerForType(
|
|
17
|
+
workflowType: string,
|
|
18
|
+
workspaceDir: string,
|
|
19
|
+
logger: HookLogger,
|
|
20
|
+
subagent: NonNullable<OpenClawPluginApi['runtime']>['subagent'],
|
|
21
|
+
): WorkflowManager | null {
|
|
22
|
+
const loggerAdapter: PluginLogger = {
|
|
23
|
+
info: (m: string) => logger.info(String(m)),
|
|
24
|
+
warn: (m: string) => logger.warn(String(m)),
|
|
25
|
+
error: (m: string) => logger.error(String(m)),
|
|
26
|
+
debug: () => {},
|
|
27
|
+
} as unknown as PluginLogger;
|
|
28
|
+
|
|
29
|
+
switch (workflowType) {
|
|
30
|
+
case 'empathy-observer':
|
|
31
|
+
return new EmpathyObserverWorkflowManager({
|
|
32
|
+
workspaceDir,
|
|
33
|
+
logger: loggerAdapter,
|
|
34
|
+
subagent,
|
|
35
|
+
});
|
|
36
|
+
case 'deep-reflect':
|
|
37
|
+
return new DeepReflectWorkflowManager({
|
|
38
|
+
workspaceDir,
|
|
39
|
+
logger: loggerAdapter,
|
|
40
|
+
subagent,
|
|
41
|
+
});
|
|
42
|
+
default:
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const HELPER_WORKFLOW_SESSION_PREFIX = 'agent:main:subagent:workflow-';
|
|
48
|
+
|
|
49
|
+
type HookLogger = Pick<PluginLogger, 'info' | 'warn' | 'error'>;
|
|
50
|
+
|
|
51
|
+
// Cleanup expired retry entries periodically
|
|
52
|
+
|
|
53
|
+
function emitSubagentPainEvent(
|
|
54
|
+
wctx: WorkspaceContext,
|
|
55
|
+
payload: {
|
|
56
|
+
source: string;
|
|
57
|
+
reason: string;
|
|
58
|
+
score: number;
|
|
59
|
+
sessionId?: string;
|
|
60
|
+
agentId?: string;
|
|
61
|
+
},
|
|
62
|
+
logger: HookLogger
|
|
63
|
+
): void {
|
|
64
|
+
try {
|
|
65
|
+
wctx.evolutionReducer.emitSync({
|
|
66
|
+
ts: new Date().toISOString(),
|
|
67
|
+
type: 'pain_detected',
|
|
68
|
+
data: {
|
|
69
|
+
painId: `pain_${Date.now()}_${Math.random().toString(36).slice(2, 10)}`,
|
|
70
|
+
painType: 'subagent_error',
|
|
71
|
+
source: payload.source,
|
|
72
|
+
reason: payload.reason,
|
|
73
|
+
score: payload.score,
|
|
74
|
+
sessionId: payload.sessionId,
|
|
75
|
+
agentId: payload.agentId,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
} catch (e) {
|
|
79
|
+
logger.warn(`[PD:Subagent] failed to emit evolution event: ${String(e)}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
function extractAgentIdFromSessionKey(sessionKey: string | undefined): string | undefined {
|
|
85
|
+
// sessionKey format: "agent:{agentId}:{type}:{uuid}" or "agent:{agentId}:{uuid}"
|
|
86
|
+
if (!sessionKey) return undefined;
|
|
87
|
+
const match = sessionKey.match(/^agent:([^:]+):/);
|
|
88
|
+
return match ? match[1] : undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
type SubagentEndedHookContext = PluginHookSubagentContext & {
|
|
96
|
+
api?: OpenClawPluginApi;
|
|
97
|
+
workspaceDir?: string;
|
|
98
|
+
sessionId?: string;
|
|
99
|
+
agentId?: string;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export async function handleSubagentEnded(
|
|
103
|
+
event: PluginHookSubagentEndedEvent,
|
|
104
|
+
ctx: SubagentEndedHookContext
|
|
105
|
+
): Promise<void> {
|
|
106
|
+
const { outcome, targetSessionKey } = event;
|
|
107
|
+
const workspaceDir = ctx.workspaceDir;
|
|
108
|
+
|
|
109
|
+
if (!workspaceDir) return;
|
|
110
|
+
|
|
111
|
+
const wctx = WorkspaceContext.fromHookContext(ctx);
|
|
112
|
+
const logger: HookLogger = ctx.api?.logger ?? console;
|
|
113
|
+
// ── Helper Workflow Lifecycle Notification ──
|
|
114
|
+
// When a helper workflow's subagent ends, notify the workflow manager
|
|
115
|
+
// so that it can trigger fallback recovery (notifyWaitResult → finalizeOnce)
|
|
116
|
+
if (targetSessionKey?.startsWith(HELPER_WORKFLOW_SESSION_PREFIX)) {
|
|
117
|
+
try {
|
|
118
|
+
const store = new WorkflowStore({ workspaceDir });
|
|
119
|
+
const workflow = store.getWorkflowByChildSession(targetSessionKey);
|
|
120
|
+
if (workflow && workflow.state !== 'completed' && workflow.state !== 'terminal_error' && workflow.state !== 'expired') {
|
|
121
|
+
logger.info(`[PD:Subagent] Helper workflow lifecycle event: workflowId=${workflow.workflow_id}, workflowType=${workflow.workflow_type}, outcome=${outcome}`);
|
|
122
|
+
|
|
123
|
+
const mappedOutcome = outcome === 'deleted' ? 'deleted' :
|
|
124
|
+
outcome === 'killed' ? 'killed' :
|
|
125
|
+
outcome === 'reset' ? 'reset' :
|
|
126
|
+
outcome === 'error' ? 'error' :
|
|
127
|
+
outcome === 'timeout' ? 'timeout' : 'ok';
|
|
128
|
+
|
|
129
|
+
// Call notifyLifecycleEvent on the appropriate manager so it
|
|
130
|
+
// triggers notifyWaitResult → finalizeOnce / terminal transition.
|
|
131
|
+
const subagentRuntime = ctx.api?.runtime?.subagent;
|
|
132
|
+
if (subagentRuntime) {
|
|
133
|
+
const mgr = createWorkflowManagerForType(workflow.workflow_type, workspaceDir, logger, subagentRuntime);
|
|
134
|
+
if (mgr) {
|
|
135
|
+
await mgr.notifyLifecycleEvent(workflow.workflow_id, 'subagent_ended', { outcome: mappedOutcome });
|
|
136
|
+
mgr.dispose();
|
|
137
|
+
} else {
|
|
138
|
+
logger.warn(`[PD:Subagent] Unknown workflow type ${workflow.workflow_type} — falling back to store-only event`);
|
|
139
|
+
store.recordEvent(workflow.workflow_id, 'subagent_ended', workflow.state, workflow.state, `subagent ended with outcome: ${outcome}`, { outcome: mappedOutcome });
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
logger.warn(`[PD:Subagent] Subagent runtime not available — cannot notify manager, falling back to store event`);
|
|
143
|
+
store.recordEvent(workflow.workflow_id, 'subagent_ended', workflow.state, workflow.state, `subagent ended with outcome: ${outcome}`, { outcome: mappedOutcome });
|
|
144
|
+
}
|
|
145
|
+
store.dispose();
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
store.dispose();
|
|
149
|
+
} catch (e) {
|
|
150
|
+
logger.warn(`[PD:Subagent] Failed to notify helper workflow lifecycle: ${String(e)}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const config = wctx.config;
|
|
155
|
+
|
|
156
|
+
// ── Outcome-based EP and Pain Signal handling ──
|
|
157
|
+
// OpenClaw v2026.3.23 fixes: timeout may be false positive (fast-finishing workers)
|
|
158
|
+
// Only penalize actual errors, not timeout/killed/reset
|
|
159
|
+
|
|
160
|
+
if (outcome === 'error') {
|
|
161
|
+
// Only actual errors trigger penalty
|
|
162
|
+
const scoreSettings = config.get('scores');
|
|
163
|
+
const score = scoreSettings.subagent_error_penalty;
|
|
164
|
+
const reason = `Subagent session ${targetSessionKey} ended with error`;
|
|
165
|
+
|
|
166
|
+
writePainFlag(workspaceDir, {
|
|
167
|
+
source: `subagent_error`,
|
|
168
|
+
score: String(score),
|
|
169
|
+
time: new Date().toISOString(),
|
|
170
|
+
reason,
|
|
171
|
+
is_risky: 'true',
|
|
172
|
+
session_id: ctx.sessionId || '',
|
|
173
|
+
agent_id: ctx.agentId || extractAgentIdFromSessionKey(targetSessionKey) || '',
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
emitSubagentPainEvent(wctx, {
|
|
177
|
+
source: `subagent_error`,
|
|
178
|
+
reason,
|
|
179
|
+
score,
|
|
180
|
+
sessionId: ctx.sessionId,
|
|
181
|
+
agentId: ctx.agentId || extractAgentIdFromSessionKey(targetSessionKey),
|
|
182
|
+
}, logger);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (outcome === 'timeout') {
|
|
186
|
+
// OpenClaw v2026.3.23 fix: timeout may be false positive
|
|
187
|
+
// Fast-finishing workers are no longer incorrectly reported as timed out
|
|
188
|
+
// Do not penalize - the task may have actually succeeded
|
|
189
|
+
logger.warn(`[PD:Subagent] Session ${targetSessionKey} timed out - not penalizing (OpenClaw fix applied)`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (outcome === 'killed' || outcome === 'reset') {
|
|
193
|
+
// User-initiated termination or system reset - not an agent failure
|
|
194
|
+
logger.info(`[PD:Subagent] Session ${targetSessionKey} ended with ${outcome} - no penalty (user/system action)`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
if (outcome === 'ok' || outcome === 'deleted') {
|
|
198
|
+
recordEvolutionSuccess(workspaceDir, 'subagent', {
|
|
199
|
+
sessionId: ctx.sessionId,
|
|
200
|
+
reason: 'subagent_success',
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// ── End of subagent_ended handling ──
|
|
205
|
+
// Note: Diagnostician runs via HEARTBEAT (main session LLM), not as a subagent.
|
|
206
|
+
// Principle creation happens in evolution-worker.ts marker detection path.
|
|
207
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thinking Checkpoint Module
|
|
3
|
+
*
|
|
4
|
+
* Enforces P-10 deep reflection requirement for high-risk tool operations.
|
|
5
|
+
*
|
|
6
|
+
* **Responsibilities:**
|
|
7
|
+
* - Check if high-risk tools have recent deep thinking (T-01 through T-10)
|
|
8
|
+
* - Block high-risk operations without preceding deep reflection
|
|
9
|
+
* - Configurable time window for thinking validity (default 5 minutes)
|
|
10
|
+
* - Provide clear guidance on required action (deep_reflect tool usage)
|
|
11
|
+
*
|
|
12
|
+
* **Configuration:**
|
|
13
|
+
* - Thinking checkpoint settings from profile.thinking_checkpoint
|
|
14
|
+
* - Window duration for thinking validity
|
|
15
|
+
* - High-risk tool list
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { hasRecentThinking } from '../core/session-tracker.js';
|
|
19
|
+
import type { PluginHookBeforeToolCallEvent, PluginHookBeforeToolCallResult } from '../openclaw-sdk.js';
|
|
20
|
+
import {
|
|
21
|
+
THINKING_CHECKPOINT_WINDOW_MS,
|
|
22
|
+
THINKING_CHECKPOINT_DEFAULT_HIGH_RISK_TOOLS
|
|
23
|
+
} from '../config/index.js';
|
|
24
|
+
|
|
25
|
+
export interface ThinkingCheckpointConfig {
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
window_ms?: number;
|
|
28
|
+
high_risk_tools?: string[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Checks if a tool call requires a recent deep thinking checkpoint.
|
|
33
|
+
*
|
|
34
|
+
* This enforces P-10 (Thinking OS Checkpoint) - high-risk operations must
|
|
35
|
+
* be preceded by deep reflection within the configured time window.
|
|
36
|
+
*
|
|
37
|
+
* @param event - The before_tool_call event
|
|
38
|
+
* @param config - Thinking checkpoint configuration from profile
|
|
39
|
+
* @param sessionId - Current session ID
|
|
40
|
+
* @param logger - Optional logger for info messages
|
|
41
|
+
* @returns Block result if thinking required, undefined otherwise
|
|
42
|
+
*/
|
|
43
|
+
export function checkThinkingCheckpoint(
|
|
44
|
+
event: PluginHookBeforeToolCallEvent,
|
|
45
|
+
config: ThinkingCheckpointConfig,
|
|
46
|
+
sessionId: string | undefined,
|
|
47
|
+
logger?: { info?: (message: string) => void }
|
|
48
|
+
): PluginHookBeforeToolCallResult | undefined {
|
|
49
|
+
const enabled = config.enabled ?? false;
|
|
50
|
+
const windowMs = config.window_ms ?? THINKING_CHECKPOINT_WINDOW_MS;
|
|
51
|
+
const highRiskTools = config.high_risk_tools ?? [...THINKING_CHECKPOINT_DEFAULT_HIGH_RISK_TOOLS];
|
|
52
|
+
|
|
53
|
+
if (!enabled || !sessionId) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const isHighRisk = highRiskTools.includes(event.toolName);
|
|
58
|
+
if (!isHighRisk) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const hasThinking = hasRecentThinking(sessionId, windowMs);
|
|
63
|
+
if (!hasThinking) {
|
|
64
|
+
logger?.info?.(`[PD:THINKING_GATE] High-risk tool "${event.toolName}" called without recent deep thinking`);
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
block: true,
|
|
68
|
+
blockReason: `[Thinking OS Checkpoint] 高风险操作 "${event.toolName}" 需要先进行深度思考。\n\n请先使用 deep_reflect 工具分析当前情况,然后再尝试此操作。\n\n这是强制性检查点,目的是确保决策质量。\n\n提示:调用 deep_reflect 后,${Math.round(windowMs/60000)}分钟内的操作将自动放行。\n\n可在PROFILE.json中设置 thinking_checkpoint.enabled: false 来禁用此检查。`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trajectory Collector - 行为进化引擎 Phase 0 数据收集
|
|
3
|
+
*
|
|
4
|
+
* 收集工具调用和 LLM 输出到 memory/trajectories/ 目录
|
|
5
|
+
* 用于分析工具使用模式、识别原则应用案例、评估行为质量
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import type {
|
|
11
|
+
PluginHookAfterToolCallEvent,
|
|
12
|
+
PluginHookToolContext,
|
|
13
|
+
PluginHookLlmOutputEvent,
|
|
14
|
+
PluginHookAgentContext,
|
|
15
|
+
PluginHookBeforeMessageWriteEvent
|
|
16
|
+
} from '../openclaw-sdk.js';
|
|
17
|
+
|
|
18
|
+
const TRAJECTORY_DIR = 'memory/trajectories/';
|
|
19
|
+
|
|
20
|
+
// 敏感字段匹配正则
|
|
21
|
+
const SENSITIVE_KEY_PATTERN = /password|token|authorization|secret|api[_-]?key|credential|cookie|session/i;
|
|
22
|
+
|
|
23
|
+
// 最大字符串长度
|
|
24
|
+
const MAX_STRING_LENGTH = 1000;
|
|
25
|
+
const MAX_RESULT_LENGTH = 500;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 递归脱敏处理:遍历对象/数组,移除敏感字段值
|
|
29
|
+
*/
|
|
30
|
+
function scrubSensitive(obj: unknown, depth = 0): unknown {
|
|
31
|
+
// 防止无限递归
|
|
32
|
+
if (depth > 10) return '[MAX_DEPTH]';
|
|
33
|
+
|
|
34
|
+
// 处理 null/undefined
|
|
35
|
+
if (obj == null) return obj;
|
|
36
|
+
|
|
37
|
+
// 处理基本类型
|
|
38
|
+
if (typeof obj !== 'object') {
|
|
39
|
+
if (typeof obj === 'string' && obj.length > MAX_STRING_LENGTH) {
|
|
40
|
+
return obj.slice(0, MAX_STRING_LENGTH) + '...[truncated]';
|
|
41
|
+
}
|
|
42
|
+
return obj;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// 处理数组
|
|
46
|
+
if (Array.isArray(obj)) {
|
|
47
|
+
return obj.map(item => scrubSensitive(item, depth + 1));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 处理对象
|
|
51
|
+
const result: Record<string, unknown> = {};
|
|
52
|
+
for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {
|
|
53
|
+
if (SENSITIVE_KEY_PATTERN.test(key)) {
|
|
54
|
+
result[key] = '[REDACTED]';
|
|
55
|
+
} else {
|
|
56
|
+
result[key] = scrubSensitive(value, depth + 1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 异步写入队列 - 确保有序、非阻塞写入
|
|
64
|
+
*/
|
|
65
|
+
class AsyncWriteQueue {
|
|
66
|
+
private queue: Array<() => Promise<void>> = [];
|
|
67
|
+
private processing = false;
|
|
68
|
+
|
|
69
|
+
async enqueue(task: () => Promise<void>): Promise<void> {
|
|
70
|
+
this.queue.push(task);
|
|
71
|
+
if (!this.processing) {
|
|
72
|
+
this.processNext();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private async processNext(): Promise<void> {
|
|
77
|
+
if (this.queue.length === 0) {
|
|
78
|
+
this.processing = false;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
this.processing = true;
|
|
83
|
+
const task = this.queue.shift();
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
await task!();
|
|
87
|
+
} catch {
|
|
88
|
+
// Silently fail - trajectory collection should not block main functionality
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 处理下一个任务
|
|
92
|
+
this.processNext();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 全局写入队列实例
|
|
97
|
+
const writeQueue = new AsyncWriteQueue();
|
|
98
|
+
|
|
99
|
+
// 目录缓存(避免重复检查)
|
|
100
|
+
const dirCache = new Map<string, boolean>();
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* 确保轨迹目录存在(异步)
|
|
104
|
+
*/
|
|
105
|
+
async function ensureTrajectoryDirAsync(workspaceDir: string): Promise<string> {
|
|
106
|
+
const dir = path.join(workspaceDir, TRAJECTORY_DIR);
|
|
107
|
+
|
|
108
|
+
if (dirCache.get(dir)) {
|
|
109
|
+
return dir;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
await fs.promises.mkdir(dir, { recursive: true });
|
|
114
|
+
dirCache.set(dir, true);
|
|
115
|
+
} catch {
|
|
116
|
+
// 目录可能已存在,忽略错误
|
|
117
|
+
dirCache.set(dir, true);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return dir;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 获取今日轨迹文件名
|
|
125
|
+
*/
|
|
126
|
+
function getTodayFilename(): string {
|
|
127
|
+
const now = new Date();
|
|
128
|
+
const year = now.getUTCFullYear();
|
|
129
|
+
const month = String(now.getUTCMonth() + 1).padStart(2, '0');
|
|
130
|
+
return `${year}-${month}-${String(now.getUTCDate()).padStart(2, '0')}.jsonl`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* 写入轨迹记录(JSON Lines 格式)- 异步版本
|
|
135
|
+
*/
|
|
136
|
+
function writeTrajectoryRecord(workspaceDir: string, record: object): void {
|
|
137
|
+
const line = JSON.stringify(record) + '\n';
|
|
138
|
+
|
|
139
|
+
writeQueue.enqueue(async () => {
|
|
140
|
+
const dir = await ensureTrajectoryDirAsync(workspaceDir);
|
|
141
|
+
const filepath = path.join(dir, getTodayFilename());
|
|
142
|
+
await fs.promises.appendFile(filepath, line, 'utf8');
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* 工具调用完成后的处理
|
|
148
|
+
* 记录:工具名、参数、结果、错误、执行时间
|
|
149
|
+
*/
|
|
150
|
+
export function handleAfterToolCall(
|
|
151
|
+
event: PluginHookAfterToolCallEvent,
|
|
152
|
+
ctx: PluginHookToolContext & { workspaceDir?: string }
|
|
153
|
+
): void {
|
|
154
|
+
const workspaceDir = ctx.workspaceDir;
|
|
155
|
+
if (!workspaceDir) return;
|
|
156
|
+
|
|
157
|
+
// 递归脱敏处理所有字段
|
|
158
|
+
const sanitizedParams = scrubSensitive(event.params);
|
|
159
|
+
const sanitizedResult = event.result == null
|
|
160
|
+
? null
|
|
161
|
+
: String(scrubSensitive(event.result)).slice(0, MAX_RESULT_LENGTH);
|
|
162
|
+
const sanitizedError = event.error == null
|
|
163
|
+
? null
|
|
164
|
+
: String(scrubSensitive(event.error));
|
|
165
|
+
|
|
166
|
+
writeTrajectoryRecord(workspaceDir, {
|
|
167
|
+
type: 'tool_call',
|
|
168
|
+
timestamp: new Date().toISOString(),
|
|
169
|
+
sessionId: ctx.sessionId || 'unknown',
|
|
170
|
+
toolName: event.toolName,
|
|
171
|
+
params: sanitizedParams,
|
|
172
|
+
result: sanitizedResult,
|
|
173
|
+
error: sanitizedError,
|
|
174
|
+
durationMs: event.durationMs,
|
|
175
|
+
success: !event.error,
|
|
176
|
+
runId: event.runId || null,
|
|
177
|
+
toolCallId: event.toolCallId || null
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* LLM 输出处理
|
|
183
|
+
* 记录:provider、model、输出长度、token 使用量
|
|
184
|
+
*/
|
|
185
|
+
export function handleLlmOutput(
|
|
186
|
+
event: PluginHookLlmOutputEvent,
|
|
187
|
+
ctx: PluginHookAgentContext & { workspaceDir?: string }
|
|
188
|
+
): void {
|
|
189
|
+
const workspaceDir = ctx.workspaceDir;
|
|
190
|
+
if (!workspaceDir) return;
|
|
191
|
+
|
|
192
|
+
const totalTextLength = event.assistantTexts?.reduce((sum, text) => sum + (text?.length || 0), 0) || 0;
|
|
193
|
+
|
|
194
|
+
writeTrajectoryRecord(workspaceDir, {
|
|
195
|
+
type: 'llm_output',
|
|
196
|
+
timestamp: new Date().toISOString(),
|
|
197
|
+
sessionId: ctx.sessionId || 'unknown',
|
|
198
|
+
provider: event.provider,
|
|
199
|
+
model: event.model,
|
|
200
|
+
textLength: totalTextLength,
|
|
201
|
+
outputCount: event.assistantTexts?.length || 0,
|
|
202
|
+
usage: event.usage ? scrubSensitive(event.usage) : null
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* 消息写入前的处理
|
|
208
|
+
* 记录:用户/助手消息内容
|
|
209
|
+
*/
|
|
210
|
+
export function handleBeforeMessageWrite(
|
|
211
|
+
event: PluginHookBeforeMessageWriteEvent,
|
|
212
|
+
ctx: PluginHookAgentContext & { workspaceDir?: string }
|
|
213
|
+
): void {
|
|
214
|
+
const workspaceDir = ctx.workspaceDir;
|
|
215
|
+
if (!workspaceDir) return;
|
|
216
|
+
|
|
217
|
+
const msg = event.message;
|
|
218
|
+
if (!msg || !msg.role) return;
|
|
219
|
+
|
|
220
|
+
// 只记录 user 和 assistant 消息
|
|
221
|
+
if (msg.role !== 'user' && msg.role !== 'assistant') return;
|
|
222
|
+
|
|
223
|
+
// 提取文本内容
|
|
224
|
+
let content = '';
|
|
225
|
+
if (typeof msg.content === 'string') {
|
|
226
|
+
content = msg.content;
|
|
227
|
+
} else if (Array.isArray(msg.content)) {
|
|
228
|
+
content = msg.content
|
|
229
|
+
.filter((part: any) => part?.type === 'text')
|
|
230
|
+
.map((part: any) => part.text)
|
|
231
|
+
.join('\n');
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 脱敏处理内容预览
|
|
235
|
+
const sanitizedPreview = scrubSensitive(content.slice(0, 200));
|
|
236
|
+
|
|
237
|
+
writeTrajectoryRecord(workspaceDir, {
|
|
238
|
+
type: 'message',
|
|
239
|
+
timestamp: new Date().toISOString(),
|
|
240
|
+
sessionId: event.sessionKey || 'unknown',
|
|
241
|
+
role: msg.role,
|
|
242
|
+
contentLength: content.length,
|
|
243
|
+
contentPreview: typeof sanitizedPreview === 'string' ? sanitizedPreview : '[sanitized]',
|
|
244
|
+
agentId: event.agentId || null
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 脱敏处理:移除敏感参数(保留旧函数签名以兼容)
|
|
250
|
+
* @deprecated 使用 scrubSensitive 替代
|
|
251
|
+
*/
|
|
252
|
+
function sanitizeParams(params: Record<string, any>): Record<string, any> {
|
|
253
|
+
return scrubSensitive(params) as Record<string, any>;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 轨迹汇总统计(供 cron 任务调用)
|
|
258
|
+
*/
|
|
259
|
+
export function computeTrajectoryStats(workspaceDir: string): object {
|
|
260
|
+
const dir = path.join(workspaceDir, TRAJECTORY_DIR);
|
|
261
|
+
const todayFile = path.join(dir, getTodayFilename());
|
|
262
|
+
|
|
263
|
+
if (!fs.existsSync(todayFile)) {
|
|
264
|
+
return { date: getTodayFilename(), totalRecords: 0, toolCalls: 0, llmOutputs: 0, messages: 0 };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const content = fs.readFileSync(todayFile, 'utf8');
|
|
268
|
+
const lines = content.split('\n').filter(line => line.trim());
|
|
269
|
+
|
|
270
|
+
const toolCalls = lines.filter(line => {
|
|
271
|
+
try { return JSON.parse(line).type === 'tool_call'; } catch { return false; }
|
|
272
|
+
}).length;
|
|
273
|
+
|
|
274
|
+
const llmOutputs = lines.filter(line => {
|
|
275
|
+
try { return JSON.parse(line).type === 'llm_output'; } catch { return false; }
|
|
276
|
+
}).length;
|
|
277
|
+
|
|
278
|
+
const messages = lines.filter(line => {
|
|
279
|
+
try { return JSON.parse(line).type === 'message'; } catch { return false; }
|
|
280
|
+
}).length;
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
date: getTodayFilename(),
|
|
284
|
+
totalRecords: lines.length,
|
|
285
|
+
toolCalls,
|
|
286
|
+
llmOutputs,
|
|
287
|
+
messages,
|
|
288
|
+
generatedAt: new Date().toISOString()
|
|
289
|
+
};
|
|
290
|
+
}
|