opencode-repos 0.3.0 → 0.3.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/index.ts +25 -11
- package/package.json +27 -27
- package/src/__tests__/git.test.ts +33 -2
- package/src/git.ts +32 -5
- package/.sisyphus/boulder.json +0 -8
- package/.sisyphus/notepads/opencode-repos/decisions.md +0 -15
- package/.sisyphus/notepads/opencode-repos/learnings.md +0 -384
- package/.sisyphus/plans/opencode-repos.md +0 -987
- package/.tmux-sessionizer +0 -8
- package/TODO.md +0 -3
- package/oh-my-opencode/.github/FUNDING.yml +0 -15
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/bug_report.yml +0 -129
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/feature_request.yml +0 -100
- package/oh-my-opencode/.github/ISSUE_TEMPLATE/general.yml +0 -83
- package/oh-my-opencode/.github/assets/google.jpg +0 -0
- package/oh-my-opencode/.github/assets/hero.jpg +0 -0
- package/oh-my-opencode/.github/assets/indent.jpg +0 -0
- package/oh-my-opencode/.github/assets/microsoft.jpg +0 -0
- package/oh-my-opencode/.github/assets/omo.png +0 -0
- package/oh-my-opencode/.github/assets/orchestrator-atlas.png +0 -0
- package/oh-my-opencode/.github/assets/sisyphus.png +0 -0
- package/oh-my-opencode/.github/assets/sisyphuslabs.png +0 -0
- package/oh-my-opencode/.github/pull_request_template.md +0 -34
- package/oh-my-opencode/.github/workflows/ci.yml +0 -138
- package/oh-my-opencode/.github/workflows/cla.yml +0 -41
- package/oh-my-opencode/.github/workflows/lint-workflows.yml +0 -22
- package/oh-my-opencode/.github/workflows/publish.yml +0 -165
- package/oh-my-opencode/.github/workflows/sisyphus-agent.yml +0 -500
- package/oh-my-opencode/.opencode/background-tasks.json +0 -27
- package/oh-my-opencode/.opencode/command/get-unpublished-changes.md +0 -84
- package/oh-my-opencode/.opencode/command/omomomo.md +0 -37
- package/oh-my-opencode/.opencode/command/publish.md +0 -257
- package/oh-my-opencode/AGENTS.md +0 -179
- package/oh-my-opencode/CLA.md +0 -58
- package/oh-my-opencode/CONTRIBUTING.md +0 -268
- package/oh-my-opencode/LICENSE.md +0 -82
- package/oh-my-opencode/README.ja.md +0 -370
- package/oh-my-opencode/README.md +0 -376
- package/oh-my-opencode/README.zh-cn.md +0 -380
- package/oh-my-opencode/assets/oh-my-opencode.schema.json +0 -2171
- package/oh-my-opencode/bin/oh-my-opencode.js +0 -80
- package/oh-my-opencode/bin/platform.js +0 -38
- package/oh-my-opencode/bin/platform.test.ts +0 -148
- package/oh-my-opencode/bun.lock +0 -314
- package/oh-my-opencode/bunfig.toml +0 -2
- package/oh-my-opencode/docs/category-skill-guide.md +0 -200
- package/oh-my-opencode/docs/cli-guide.md +0 -272
- package/oh-my-opencode/docs/configurations.md +0 -654
- package/oh-my-opencode/docs/features.md +0 -550
- package/oh-my-opencode/docs/guide/installation.md +0 -288
- package/oh-my-opencode/docs/guide/overview.md +0 -97
- package/oh-my-opencode/docs/guide/understanding-orchestration-system.md +0 -445
- package/oh-my-opencode/docs/orchestration-guide.md +0 -152
- package/oh-my-opencode/docs/ultrawork-manifesto.md +0 -197
- package/oh-my-opencode/package.json +0 -89
- package/oh-my-opencode/packages/darwin-arm64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/darwin-arm64/package.json +0 -22
- package/oh-my-opencode/packages/darwin-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/darwin-x64/package.json +0 -22
- package/oh-my-opencode/packages/linux-arm64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-arm64/package.json +0 -25
- package/oh-my-opencode/packages/linux-arm64-musl/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-arm64-musl/package.json +0 -25
- package/oh-my-opencode/packages/linux-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-x64/package.json +0 -25
- package/oh-my-opencode/packages/linux-x64-musl/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/linux-x64-musl/package.json +0 -25
- package/oh-my-opencode/packages/windows-x64/bin/.gitkeep +0 -0
- package/oh-my-opencode/packages/windows-x64/package.json +0 -22
- package/oh-my-opencode/postinstall.mjs +0 -43
- package/oh-my-opencode/script/build-binaries.ts +0 -103
- package/oh-my-opencode/script/build-schema.ts +0 -28
- package/oh-my-opencode/script/generate-changelog.ts +0 -92
- package/oh-my-opencode/script/publish.ts +0 -344
- package/oh-my-opencode/signatures/cla.json +0 -676
- package/oh-my-opencode/src/agents/AGENTS.md +0 -67
- package/oh-my-opencode/src/agents/atlas.ts +0 -1383
- package/oh-my-opencode/src/agents/dynamic-agent-prompt-builder.ts +0 -400
- package/oh-my-opencode/src/agents/explore.ts +0 -122
- package/oh-my-opencode/src/agents/index.ts +0 -13
- package/oh-my-opencode/src/agents/librarian.ts +0 -326
- package/oh-my-opencode/src/agents/metis.ts +0 -315
- package/oh-my-opencode/src/agents/momus.test.ts +0 -57
- package/oh-my-opencode/src/agents/momus.ts +0 -444
- package/oh-my-opencode/src/agents/multimodal-looker.ts +0 -56
- package/oh-my-opencode/src/agents/oracle.ts +0 -122
- package/oh-my-opencode/src/agents/prometheus-prompt.test.ts +0 -22
- package/oh-my-opencode/src/agents/prometheus-prompt.ts +0 -1196
- package/oh-my-opencode/src/agents/sisyphus-junior.test.ts +0 -232
- package/oh-my-opencode/src/agents/sisyphus-junior.ts +0 -134
- package/oh-my-opencode/src/agents/sisyphus.ts +0 -633
- package/oh-my-opencode/src/agents/types.ts +0 -80
- package/oh-my-opencode/src/agents/utils.test.ts +0 -311
- package/oh-my-opencode/src/agents/utils.ts +0 -240
- package/oh-my-opencode/src/cli/AGENTS.md +0 -91
- package/oh-my-opencode/src/cli/config-manager.test.ts +0 -364
- package/oh-my-opencode/src/cli/config-manager.ts +0 -641
- package/oh-my-opencode/src/cli/doctor/checks/auth.test.ts +0 -114
- package/oh-my-opencode/src/cli/doctor/checks/auth.ts +0 -115
- package/oh-my-opencode/src/cli/doctor/checks/config.test.ts +0 -103
- package/oh-my-opencode/src/cli/doctor/checks/config.ts +0 -123
- package/oh-my-opencode/src/cli/doctor/checks/dependencies.test.ts +0 -152
- package/oh-my-opencode/src/cli/doctor/checks/dependencies.ts +0 -163
- package/oh-my-opencode/src/cli/doctor/checks/gh.test.ts +0 -151
- package/oh-my-opencode/src/cli/doctor/checks/gh.ts +0 -171
- package/oh-my-opencode/src/cli/doctor/checks/index.ts +0 -34
- package/oh-my-opencode/src/cli/doctor/checks/lsp.test.ts +0 -134
- package/oh-my-opencode/src/cli/doctor/checks/lsp.ts +0 -77
- package/oh-my-opencode/src/cli/doctor/checks/mcp.test.ts +0 -115
- package/oh-my-opencode/src/cli/doctor/checks/mcp.ts +0 -128
- package/oh-my-opencode/src/cli/doctor/checks/opencode.test.ts +0 -227
- package/oh-my-opencode/src/cli/doctor/checks/opencode.ts +0 -178
- package/oh-my-opencode/src/cli/doctor/checks/plugin.test.ts +0 -109
- package/oh-my-opencode/src/cli/doctor/checks/plugin.ts +0 -124
- package/oh-my-opencode/src/cli/doctor/checks/version.test.ts +0 -148
- package/oh-my-opencode/src/cli/doctor/checks/version.ts +0 -135
- package/oh-my-opencode/src/cli/doctor/constants.ts +0 -72
- package/oh-my-opencode/src/cli/doctor/formatter.test.ts +0 -218
- package/oh-my-opencode/src/cli/doctor/formatter.ts +0 -140
- package/oh-my-opencode/src/cli/doctor/index.ts +0 -11
- package/oh-my-opencode/src/cli/doctor/runner.test.ts +0 -153
- package/oh-my-opencode/src/cli/doctor/runner.ts +0 -132
- package/oh-my-opencode/src/cli/doctor/types.ts +0 -113
- package/oh-my-opencode/src/cli/get-local-version/formatter.ts +0 -66
- package/oh-my-opencode/src/cli/get-local-version/index.ts +0 -106
- package/oh-my-opencode/src/cli/get-local-version/types.ts +0 -14
- package/oh-my-opencode/src/cli/index.ts +0 -153
- package/oh-my-opencode/src/cli/install.ts +0 -523
- package/oh-my-opencode/src/cli/model-fallback.ts +0 -246
- package/oh-my-opencode/src/cli/run/completion.test.ts +0 -170
- package/oh-my-opencode/src/cli/run/completion.ts +0 -79
- package/oh-my-opencode/src/cli/run/events.test.ts +0 -155
- package/oh-my-opencode/src/cli/run/events.ts +0 -325
- package/oh-my-opencode/src/cli/run/index.ts +0 -2
- package/oh-my-opencode/src/cli/run/runner.ts +0 -159
- package/oh-my-opencode/src/cli/run/types.ts +0 -76
- package/oh-my-opencode/src/cli/types.ts +0 -40
- package/oh-my-opencode/src/config/index.ts +0 -26
- package/oh-my-opencode/src/config/schema.test.ts +0 -444
- package/oh-my-opencode/src/config/schema.ts +0 -339
- package/oh-my-opencode/src/features/AGENTS.md +0 -77
- package/oh-my-opencode/src/features/background-agent/concurrency.test.ts +0 -418
- package/oh-my-opencode/src/features/background-agent/concurrency.ts +0 -137
- package/oh-my-opencode/src/features/background-agent/index.ts +0 -3
- package/oh-my-opencode/src/features/background-agent/manager.test.ts +0 -1928
- package/oh-my-opencode/src/features/background-agent/manager.ts +0 -1335
- package/oh-my-opencode/src/features/background-agent/types.ts +0 -66
- package/oh-my-opencode/src/features/boulder-state/constants.ts +0 -13
- package/oh-my-opencode/src/features/boulder-state/index.ts +0 -3
- package/oh-my-opencode/src/features/boulder-state/storage.test.ts +0 -250
- package/oh-my-opencode/src/features/boulder-state/storage.ts +0 -150
- package/oh-my-opencode/src/features/boulder-state/types.ts +0 -26
- package/oh-my-opencode/src/features/builtin-commands/commands.ts +0 -89
- package/oh-my-opencode/src/features/builtin-commands/index.ts +0 -2
- package/oh-my-opencode/src/features/builtin-commands/templates/init-deep.ts +0 -300
- package/oh-my-opencode/src/features/builtin-commands/templates/ralph-loop.ts +0 -38
- package/oh-my-opencode/src/features/builtin-commands/templates/refactor.ts +0 -619
- package/oh-my-opencode/src/features/builtin-commands/templates/start-work.ts +0 -72
- package/oh-my-opencode/src/features/builtin-commands/types.ts +0 -9
- package/oh-my-opencode/src/features/builtin-skills/frontend-ui-ux/SKILL.md +0 -78
- package/oh-my-opencode/src/features/builtin-skills/git-master/SKILL.md +0 -1105
- package/oh-my-opencode/src/features/builtin-skills/index.ts +0 -2
- package/oh-my-opencode/src/features/builtin-skills/skills.ts +0 -1203
- package/oh-my-opencode/src/features/builtin-skills/types.ts +0 -16
- package/oh-my-opencode/src/features/claude-code-agent-loader/index.ts +0 -2
- package/oh-my-opencode/src/features/claude-code-agent-loader/loader.ts +0 -90
- package/oh-my-opencode/src/features/claude-code-agent-loader/types.ts +0 -17
- package/oh-my-opencode/src/features/claude-code-command-loader/index.ts +0 -2
- package/oh-my-opencode/src/features/claude-code-command-loader/loader.ts +0 -144
- package/oh-my-opencode/src/features/claude-code-command-loader/types.ts +0 -46
- package/oh-my-opencode/src/features/claude-code-mcp-loader/env-expander.ts +0 -27
- package/oh-my-opencode/src/features/claude-code-mcp-loader/index.ts +0 -11
- package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.test.ts +0 -162
- package/oh-my-opencode/src/features/claude-code-mcp-loader/loader.ts +0 -113
- package/oh-my-opencode/src/features/claude-code-mcp-loader/transformer.ts +0 -53
- package/oh-my-opencode/src/features/claude-code-mcp-loader/types.ts +0 -42
- package/oh-my-opencode/src/features/claude-code-plugin-loader/index.ts +0 -3
- package/oh-my-opencode/src/features/claude-code-plugin-loader/loader.ts +0 -486
- package/oh-my-opencode/src/features/claude-code-plugin-loader/types.ts +0 -210
- package/oh-my-opencode/src/features/claude-code-session-state/index.ts +0 -1
- package/oh-my-opencode/src/features/claude-code-session-state/state.test.ts +0 -126
- package/oh-my-opencode/src/features/claude-code-session-state/state.ts +0 -37
- package/oh-my-opencode/src/features/context-injector/collector.test.ts +0 -330
- package/oh-my-opencode/src/features/context-injector/collector.ts +0 -85
- package/oh-my-opencode/src/features/context-injector/index.ts +0 -14
- package/oh-my-opencode/src/features/context-injector/injector.test.ts +0 -122
- package/oh-my-opencode/src/features/context-injector/injector.ts +0 -167
- package/oh-my-opencode/src/features/context-injector/types.ts +0 -91
- package/oh-my-opencode/src/features/hook-message-injector/constants.ts +0 -6
- package/oh-my-opencode/src/features/hook-message-injector/index.ts +0 -4
- package/oh-my-opencode/src/features/hook-message-injector/injector.ts +0 -195
- package/oh-my-opencode/src/features/hook-message-injector/types.ts +0 -47
- package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.test.ts +0 -448
- package/oh-my-opencode/src/features/opencode-skill-loader/async-loader.ts +0 -180
- package/oh-my-opencode/src/features/opencode-skill-loader/blocking.test.ts +0 -210
- package/oh-my-opencode/src/features/opencode-skill-loader/blocking.ts +0 -62
- package/oh-my-opencode/src/features/opencode-skill-loader/discover-worker.ts +0 -59
- package/oh-my-opencode/src/features/opencode-skill-loader/index.ts +0 -4
- package/oh-my-opencode/src/features/opencode-skill-loader/loader.test.ts +0 -273
- package/oh-my-opencode/src/features/opencode-skill-loader/loader.ts +0 -259
- package/oh-my-opencode/src/features/opencode-skill-loader/merger.ts +0 -267
- package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.test.ts +0 -267
- package/oh-my-opencode/src/features/opencode-skill-loader/skill-content.ts +0 -206
- package/oh-my-opencode/src/features/opencode-skill-loader/types.ts +0 -38
- package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.test.ts +0 -201
- package/oh-my-opencode/src/features/skill-mcp-manager/env-cleaner.ts +0 -27
- package/oh-my-opencode/src/features/skill-mcp-manager/index.ts +0 -2
- package/oh-my-opencode/src/features/skill-mcp-manager/manager.test.ts +0 -611
- package/oh-my-opencode/src/features/skill-mcp-manager/manager.ts +0 -520
- package/oh-my-opencode/src/features/skill-mcp-manager/types.ts +0 -14
- package/oh-my-opencode/src/features/task-toast-manager/index.ts +0 -2
- package/oh-my-opencode/src/features/task-toast-manager/manager.test.ts +0 -249
- package/oh-my-opencode/src/features/task-toast-manager/manager.ts +0 -215
- package/oh-my-opencode/src/features/task-toast-manager/types.ts +0 -24
- package/oh-my-opencode/src/hooks/AGENTS.md +0 -73
- package/oh-my-opencode/src/hooks/agent-usage-reminder/constants.ts +0 -54
- package/oh-my-opencode/src/hooks/agent-usage-reminder/index.ts +0 -109
- package/oh-my-opencode/src/hooks/agent-usage-reminder/storage.ts +0 -42
- package/oh-my-opencode/src/hooks/agent-usage-reminder/types.ts +0 -6
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.test.ts +0 -307
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/executor.ts +0 -485
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/index.ts +0 -151
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/parser.ts +0 -201
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.test.ts +0 -33
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-deduplication.ts +0 -184
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/pruning-types.ts +0 -44
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.test.ts +0 -77
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/storage.ts +0 -250
- package/oh-my-opencode/src/hooks/anthropic-context-window-limit-recovery/types.ts +0 -42
- package/oh-my-opencode/src/hooks/atlas/index.test.ts +0 -953
- package/oh-my-opencode/src/hooks/atlas/index.ts +0 -771
- package/oh-my-opencode/src/hooks/auto-slash-command/constants.ts +0 -12
- package/oh-my-opencode/src/hooks/auto-slash-command/detector.test.ts +0 -296
- package/oh-my-opencode/src/hooks/auto-slash-command/detector.ts +0 -65
- package/oh-my-opencode/src/hooks/auto-slash-command/executor.ts +0 -205
- package/oh-my-opencode/src/hooks/auto-slash-command/index.test.ts +0 -254
- package/oh-my-opencode/src/hooks/auto-slash-command/index.ts +0 -89
- package/oh-my-opencode/src/hooks/auto-slash-command/types.ts +0 -23
- package/oh-my-opencode/src/hooks/auto-update-checker/cache.ts +0 -93
- package/oh-my-opencode/src/hooks/auto-update-checker/checker.test.ts +0 -24
- package/oh-my-opencode/src/hooks/auto-update-checker/checker.ts +0 -284
- package/oh-my-opencode/src/hooks/auto-update-checker/constants.ts +0 -64
- package/oh-my-opencode/src/hooks/auto-update-checker/index.test.ts +0 -254
- package/oh-my-opencode/src/hooks/auto-update-checker/index.ts +0 -260
- package/oh-my-opencode/src/hooks/auto-update-checker/types.ts +0 -29
- package/oh-my-opencode/src/hooks/background-compaction/index.ts +0 -87
- package/oh-my-opencode/src/hooks/background-notification/index.ts +0 -28
- package/oh-my-opencode/src/hooks/background-notification/types.ts +0 -5
- package/oh-my-opencode/src/hooks/claude-code-hooks/AGENTS.md +0 -70
- package/oh-my-opencode/src/hooks/claude-code-hooks/config-loader.ts +0 -107
- package/oh-my-opencode/src/hooks/claude-code-hooks/config.ts +0 -103
- package/oh-my-opencode/src/hooks/claude-code-hooks/index.ts +0 -401
- package/oh-my-opencode/src/hooks/claude-code-hooks/plugin-config.ts +0 -12
- package/oh-my-opencode/src/hooks/claude-code-hooks/post-tool-use.ts +0 -199
- package/oh-my-opencode/src/hooks/claude-code-hooks/pre-compact.ts +0 -109
- package/oh-my-opencode/src/hooks/claude-code-hooks/pre-tool-use.ts +0 -172
- package/oh-my-opencode/src/hooks/claude-code-hooks/stop.ts +0 -118
- package/oh-my-opencode/src/hooks/claude-code-hooks/todo.ts +0 -76
- package/oh-my-opencode/src/hooks/claude-code-hooks/tool-input-cache.ts +0 -47
- package/oh-my-opencode/src/hooks/claude-code-hooks/transcript.ts +0 -252
- package/oh-my-opencode/src/hooks/claude-code-hooks/types.ts +0 -204
- package/oh-my-opencode/src/hooks/claude-code-hooks/user-prompt-submit.ts +0 -117
- package/oh-my-opencode/src/hooks/comment-checker/cli.test.ts +0 -68
- package/oh-my-opencode/src/hooks/comment-checker/cli.ts +0 -221
- package/oh-my-opencode/src/hooks/comment-checker/downloader.ts +0 -196
- package/oh-my-opencode/src/hooks/comment-checker/index.ts +0 -171
- package/oh-my-opencode/src/hooks/comment-checker/types.ts +0 -33
- package/oh-my-opencode/src/hooks/compaction-context-injector/index.ts +0 -61
- package/oh-my-opencode/src/hooks/context-window-monitor.ts +0 -99
- package/oh-my-opencode/src/hooks/delegate-task-retry/index.test.ts +0 -119
- package/oh-my-opencode/src/hooks/delegate-task-retry/index.ts +0 -136
- package/oh-my-opencode/src/hooks/directory-agents-injector/constants.ts +0 -9
- package/oh-my-opencode/src/hooks/directory-agents-injector/index.ts +0 -182
- package/oh-my-opencode/src/hooks/directory-agents-injector/storage.ts +0 -48
- package/oh-my-opencode/src/hooks/directory-agents-injector/types.ts +0 -5
- package/oh-my-opencode/src/hooks/directory-readme-injector/constants.ts +0 -9
- package/oh-my-opencode/src/hooks/directory-readme-injector/index.ts +0 -177
- package/oh-my-opencode/src/hooks/directory-readme-injector/storage.ts +0 -48
- package/oh-my-opencode/src/hooks/directory-readme-injector/types.ts +0 -5
- package/oh-my-opencode/src/hooks/edit-error-recovery/index.test.ts +0 -126
- package/oh-my-opencode/src/hooks/edit-error-recovery/index.ts +0 -57
- package/oh-my-opencode/src/hooks/empty-task-response-detector.ts +0 -27
- package/oh-my-opencode/src/hooks/index.ts +0 -32
- package/oh-my-opencode/src/hooks/interactive-bash-session/constants.ts +0 -15
- package/oh-my-opencode/src/hooks/interactive-bash-session/index.ts +0 -262
- package/oh-my-opencode/src/hooks/interactive-bash-session/storage.ts +0 -59
- package/oh-my-opencode/src/hooks/interactive-bash-session/types.ts +0 -11
- package/oh-my-opencode/src/hooks/keyword-detector/constants.ts +0 -300
- package/oh-my-opencode/src/hooks/keyword-detector/detector.ts +0 -52
- package/oh-my-opencode/src/hooks/keyword-detector/index.test.ts +0 -529
- package/oh-my-opencode/src/hooks/keyword-detector/index.ts +0 -100
- package/oh-my-opencode/src/hooks/keyword-detector/types.ts +0 -4
- package/oh-my-opencode/src/hooks/non-interactive-env/constants.ts +0 -70
- package/oh-my-opencode/src/hooks/non-interactive-env/detector.ts +0 -19
- package/oh-my-opencode/src/hooks/non-interactive-env/index.test.ts +0 -323
- package/oh-my-opencode/src/hooks/non-interactive-env/index.ts +0 -63
- package/oh-my-opencode/src/hooks/non-interactive-env/types.ts +0 -3
- package/oh-my-opencode/src/hooks/prometheus-md-only/constants.ts +0 -32
- package/oh-my-opencode/src/hooks/prometheus-md-only/index.test.ts +0 -488
- package/oh-my-opencode/src/hooks/prometheus-md-only/index.ts +0 -136
- package/oh-my-opencode/src/hooks/ralph-loop/constants.ts +0 -5
- package/oh-my-opencode/src/hooks/ralph-loop/index.test.ts +0 -835
- package/oh-my-opencode/src/hooks/ralph-loop/index.ts +0 -417
- package/oh-my-opencode/src/hooks/ralph-loop/storage.ts +0 -115
- package/oh-my-opencode/src/hooks/ralph-loop/types.ts +0 -19
- package/oh-my-opencode/src/hooks/rules-injector/constants.ts +0 -30
- package/oh-my-opencode/src/hooks/rules-injector/finder.test.ts +0 -381
- package/oh-my-opencode/src/hooks/rules-injector/finder.ts +0 -263
- package/oh-my-opencode/src/hooks/rules-injector/index.ts +0 -223
- package/oh-my-opencode/src/hooks/rules-injector/matcher.ts +0 -63
- package/oh-my-opencode/src/hooks/rules-injector/parser.test.ts +0 -226
- package/oh-my-opencode/src/hooks/rules-injector/parser.ts +0 -211
- package/oh-my-opencode/src/hooks/rules-injector/storage.ts +0 -59
- package/oh-my-opencode/src/hooks/rules-injector/types.ts +0 -57
- package/oh-my-opencode/src/hooks/session-notification-utils.ts +0 -140
- package/oh-my-opencode/src/hooks/session-notification.test.ts +0 -361
- package/oh-my-opencode/src/hooks/session-notification.ts +0 -330
- package/oh-my-opencode/src/hooks/session-recovery/constants.ts +0 -10
- package/oh-my-opencode/src/hooks/session-recovery/index.test.ts +0 -223
- package/oh-my-opencode/src/hooks/session-recovery/index.ts +0 -435
- package/oh-my-opencode/src/hooks/session-recovery/storage.ts +0 -390
- package/oh-my-opencode/src/hooks/session-recovery/types.ts +0 -98
- package/oh-my-opencode/src/hooks/start-work/index.test.ts +0 -402
- package/oh-my-opencode/src/hooks/start-work/index.ts +0 -242
- package/oh-my-opencode/src/hooks/task-resume-info/index.ts +0 -36
- package/oh-my-opencode/src/hooks/think-mode/detector.ts +0 -57
- package/oh-my-opencode/src/hooks/think-mode/index.test.ts +0 -353
- package/oh-my-opencode/src/hooks/think-mode/index.ts +0 -89
- package/oh-my-opencode/src/hooks/think-mode/switcher.test.ts +0 -461
- package/oh-my-opencode/src/hooks/think-mode/switcher.ts +0 -222
- package/oh-my-opencode/src/hooks/think-mode/types.ts +0 -21
- package/oh-my-opencode/src/hooks/thinking-block-validator/index.ts +0 -171
- package/oh-my-opencode/src/hooks/todo-continuation-enforcer.test.ts +0 -876
- package/oh-my-opencode/src/hooks/todo-continuation-enforcer.ts +0 -480
- package/oh-my-opencode/src/hooks/tool-output-truncator.test.ts +0 -168
- package/oh-my-opencode/src/hooks/tool-output-truncator.ts +0 -61
- package/oh-my-opencode/src/index.ts +0 -589
- package/oh-my-opencode/src/mcp/AGENTS.md +0 -70
- package/oh-my-opencode/src/mcp/context7.ts +0 -6
- package/oh-my-opencode/src/mcp/grep-app.ts +0 -6
- package/oh-my-opencode/src/mcp/index.test.ts +0 -86
- package/oh-my-opencode/src/mcp/index.ts +0 -32
- package/oh-my-opencode/src/mcp/types.ts +0 -9
- package/oh-my-opencode/src/mcp/websearch.ts +0 -10
- package/oh-my-opencode/src/plugin-config.test.ts +0 -119
- package/oh-my-opencode/src/plugin-config.ts +0 -135
- package/oh-my-opencode/src/plugin-handlers/config-handler.test.ts +0 -103
- package/oh-my-opencode/src/plugin-handlers/config-handler.ts +0 -399
- package/oh-my-opencode/src/plugin-handlers/index.ts +0 -1
- package/oh-my-opencode/src/plugin-state.ts +0 -30
- package/oh-my-opencode/src/shared/AGENTS.md +0 -63
- package/oh-my-opencode/src/shared/agent-tool-restrictions.ts +0 -44
- package/oh-my-opencode/src/shared/agent-variant.test.ts +0 -83
- package/oh-my-opencode/src/shared/agent-variant.ts +0 -40
- package/oh-my-opencode/src/shared/claude-config-dir.test.ts +0 -60
- package/oh-my-opencode/src/shared/claude-config-dir.ts +0 -11
- package/oh-my-opencode/src/shared/command-executor.ts +0 -225
- package/oh-my-opencode/src/shared/config-errors.ts +0 -18
- package/oh-my-opencode/src/shared/config-path.ts +0 -47
- package/oh-my-opencode/src/shared/data-path.ts +0 -22
- package/oh-my-opencode/src/shared/deep-merge.test.ts +0 -336
- package/oh-my-opencode/src/shared/deep-merge.ts +0 -53
- package/oh-my-opencode/src/shared/dynamic-truncator.ts +0 -193
- package/oh-my-opencode/src/shared/external-plugin-detector.test.ts +0 -133
- package/oh-my-opencode/src/shared/external-plugin-detector.ts +0 -132
- package/oh-my-opencode/src/shared/file-reference-resolver.ts +0 -85
- package/oh-my-opencode/src/shared/file-utils.ts +0 -40
- package/oh-my-opencode/src/shared/first-message-variant.test.ts +0 -32
- package/oh-my-opencode/src/shared/first-message-variant.ts +0 -28
- package/oh-my-opencode/src/shared/frontmatter.test.ts +0 -262
- package/oh-my-opencode/src/shared/frontmatter.ts +0 -31
- package/oh-my-opencode/src/shared/hook-disabled.ts +0 -22
- package/oh-my-opencode/src/shared/index.ts +0 -29
- package/oh-my-opencode/src/shared/jsonc-parser.test.ts +0 -266
- package/oh-my-opencode/src/shared/jsonc-parser.ts +0 -66
- package/oh-my-opencode/src/shared/logger.ts +0 -20
- package/oh-my-opencode/src/shared/migration.test.ts +0 -602
- package/oh-my-opencode/src/shared/migration.ts +0 -191
- package/oh-my-opencode/src/shared/model-resolver.test.ts +0 -101
- package/oh-my-opencode/src/shared/model-resolver.ts +0 -35
- package/oh-my-opencode/src/shared/model-sanitizer.ts +0 -12
- package/oh-my-opencode/src/shared/opencode-config-dir.test.ts +0 -318
- package/oh-my-opencode/src/shared/opencode-config-dir.ts +0 -142
- package/oh-my-opencode/src/shared/opencode-version.test.ts +0 -223
- package/oh-my-opencode/src/shared/opencode-version.ts +0 -72
- package/oh-my-opencode/src/shared/pattern-matcher.ts +0 -29
- package/oh-my-opencode/src/shared/permission-compat.test.ts +0 -134
- package/oh-my-opencode/src/shared/permission-compat.ts +0 -77
- package/oh-my-opencode/src/shared/session-cursor.test.ts +0 -66
- package/oh-my-opencode/src/shared/session-cursor.ts +0 -85
- package/oh-my-opencode/src/shared/shell-env.test.ts +0 -278
- package/oh-my-opencode/src/shared/shell-env.ts +0 -111
- package/oh-my-opencode/src/shared/snake-case.ts +0 -49
- package/oh-my-opencode/src/shared/system-directive.ts +0 -40
- package/oh-my-opencode/src/shared/tool-name.ts +0 -26
- package/oh-my-opencode/src/shared/zip-extractor.ts +0 -83
- package/oh-my-opencode/src/tools/AGENTS.md +0 -74
- package/oh-my-opencode/src/tools/ast-grep/cli.ts +0 -230
- package/oh-my-opencode/src/tools/ast-grep/constants.ts +0 -261
- package/oh-my-opencode/src/tools/ast-grep/downloader.ts +0 -128
- package/oh-my-opencode/src/tools/ast-grep/index.ts +0 -13
- package/oh-my-opencode/src/tools/ast-grep/tools.ts +0 -112
- package/oh-my-opencode/src/tools/ast-grep/types.ts +0 -61
- package/oh-my-opencode/src/tools/ast-grep/utils.ts +0 -102
- package/oh-my-opencode/src/tools/background-task/constants.ts +0 -7
- package/oh-my-opencode/src/tools/background-task/index.ts +0 -7
- package/oh-my-opencode/src/tools/background-task/tools.ts +0 -479
- package/oh-my-opencode/src/tools/background-task/types.ts +0 -16
- package/oh-my-opencode/src/tools/call-omo-agent/constants.ts +0 -7
- package/oh-my-opencode/src/tools/call-omo-agent/index.ts +0 -3
- package/oh-my-opencode/src/tools/call-omo-agent/tools.ts +0 -338
- package/oh-my-opencode/src/tools/call-omo-agent/types.ts +0 -27
- package/oh-my-opencode/src/tools/delegate-task/constants.ts +0 -205
- package/oh-my-opencode/src/tools/delegate-task/index.ts +0 -3
- package/oh-my-opencode/src/tools/delegate-task/tools.test.ts +0 -1575
- package/oh-my-opencode/src/tools/delegate-task/tools.ts +0 -885
- package/oh-my-opencode/src/tools/delegate-task/types.ts +0 -9
- package/oh-my-opencode/src/tools/glob/cli.test.ts +0 -158
- package/oh-my-opencode/src/tools/glob/cli.ts +0 -191
- package/oh-my-opencode/src/tools/glob/constants.ts +0 -12
- package/oh-my-opencode/src/tools/glob/index.ts +0 -3
- package/oh-my-opencode/src/tools/glob/tools.ts +0 -41
- package/oh-my-opencode/src/tools/glob/types.ts +0 -22
- package/oh-my-opencode/src/tools/glob/utils.ts +0 -26
- package/oh-my-opencode/src/tools/grep/cli.ts +0 -229
- package/oh-my-opencode/src/tools/grep/constants.ts +0 -127
- package/oh-my-opencode/src/tools/grep/downloader.test.ts +0 -103
- package/oh-my-opencode/src/tools/grep/downloader.ts +0 -145
- package/oh-my-opencode/src/tools/grep/index.ts +0 -3
- package/oh-my-opencode/src/tools/grep/tools.ts +0 -40
- package/oh-my-opencode/src/tools/grep/types.ts +0 -39
- package/oh-my-opencode/src/tools/grep/utils.ts +0 -53
- package/oh-my-opencode/src/tools/index.ts +0 -72
- package/oh-my-opencode/src/tools/interactive-bash/constants.ts +0 -18
- package/oh-my-opencode/src/tools/interactive-bash/index.ts +0 -4
- package/oh-my-opencode/src/tools/interactive-bash/tools.ts +0 -126
- package/oh-my-opencode/src/tools/interactive-bash/utils.ts +0 -71
- package/oh-my-opencode/src/tools/look-at/constants.ts +0 -3
- package/oh-my-opencode/src/tools/look-at/index.ts +0 -3
- package/oh-my-opencode/src/tools/look-at/tools.test.ts +0 -73
- package/oh-my-opencode/src/tools/look-at/tools.ts +0 -173
- package/oh-my-opencode/src/tools/look-at/types.ts +0 -4
- package/oh-my-opencode/src/tools/lsp/client.ts +0 -596
- package/oh-my-opencode/src/tools/lsp/config.test.ts +0 -130
- package/oh-my-opencode/src/tools/lsp/config.ts +0 -285
- package/oh-my-opencode/src/tools/lsp/constants.ts +0 -390
- package/oh-my-opencode/src/tools/lsp/index.ts +0 -7
- package/oh-my-opencode/src/tools/lsp/tools.ts +0 -261
- package/oh-my-opencode/src/tools/lsp/types.ts +0 -124
- package/oh-my-opencode/src/tools/lsp/utils.ts +0 -406
- package/oh-my-opencode/src/tools/session-manager/constants.ts +0 -97
- package/oh-my-opencode/src/tools/session-manager/index.ts +0 -3
- package/oh-my-opencode/src/tools/session-manager/storage.test.ts +0 -315
- package/oh-my-opencode/src/tools/session-manager/storage.ts +0 -238
- package/oh-my-opencode/src/tools/session-manager/tools.test.ts +0 -124
- package/oh-my-opencode/src/tools/session-manager/tools.ts +0 -146
- package/oh-my-opencode/src/tools/session-manager/types.ts +0 -99
- package/oh-my-opencode/src/tools/session-manager/utils.test.ts +0 -160
- package/oh-my-opencode/src/tools/session-manager/utils.ts +0 -199
- package/oh-my-opencode/src/tools/skill/constants.ts +0 -8
- package/oh-my-opencode/src/tools/skill/index.ts +0 -3
- package/oh-my-opencode/src/tools/skill/tools.test.ts +0 -239
- package/oh-my-opencode/src/tools/skill/tools.ts +0 -200
- package/oh-my-opencode/src/tools/skill/types.ts +0 -31
- package/oh-my-opencode/src/tools/skill-mcp/constants.ts +0 -3
- package/oh-my-opencode/src/tools/skill-mcp/index.ts +0 -3
- package/oh-my-opencode/src/tools/skill-mcp/tools.test.ts +0 -215
- package/oh-my-opencode/src/tools/skill-mcp/tools.ts +0 -172
- package/oh-my-opencode/src/tools/skill-mcp/types.ts +0 -8
- package/oh-my-opencode/src/tools/slashcommand/index.ts +0 -2
- package/oh-my-opencode/src/tools/slashcommand/tools.ts +0 -252
- package/oh-my-opencode/src/tools/slashcommand/types.ts +0 -28
- package/oh-my-opencode/test-setup.ts +0 -6
- package/oh-my-opencode/tsconfig.json +0 -20
|
@@ -1,529 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, beforeEach, afterEach, spyOn } from "bun:test"
|
|
2
|
-
import { createKeywordDetectorHook } from "./index"
|
|
3
|
-
import { setMainSession, updateSessionAgent, clearSessionAgent, _resetForTesting } from "../../features/claude-code-session-state"
|
|
4
|
-
import { ContextCollector } from "../../features/context-injector"
|
|
5
|
-
import * as sharedModule from "../../shared"
|
|
6
|
-
import * as sessionState from "../../features/claude-code-session-state"
|
|
7
|
-
|
|
8
|
-
describe("keyword-detector registers to ContextCollector", () => {
|
|
9
|
-
let logCalls: Array<{ msg: string; data?: unknown }>
|
|
10
|
-
let logSpy: ReturnType<typeof spyOn>
|
|
11
|
-
let getMainSessionSpy: ReturnType<typeof spyOn>
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
_resetForTesting()
|
|
15
|
-
logCalls = []
|
|
16
|
-
logSpy = spyOn(sharedModule, "log").mockImplementation((msg: string, data?: unknown) => {
|
|
17
|
-
logCalls.push({ msg, data })
|
|
18
|
-
})
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
afterEach(() => {
|
|
22
|
-
logSpy?.mockRestore()
|
|
23
|
-
getMainSessionSpy?.mockRestore()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
function createMockPluginInput() {
|
|
27
|
-
return {
|
|
28
|
-
client: {
|
|
29
|
-
tui: {
|
|
30
|
-
showToast: async () => {},
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
} as any
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
test("should register ultrawork keyword to ContextCollector", async () => {
|
|
37
|
-
// #given - a fresh ContextCollector and keyword-detector hook
|
|
38
|
-
const collector = new ContextCollector()
|
|
39
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
40
|
-
const sessionID = "test-session-123"
|
|
41
|
-
const output = {
|
|
42
|
-
message: {} as Record<string, unknown>,
|
|
43
|
-
parts: [{ type: "text", text: "ultrawork do something" }],
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// #when - keyword detection runs
|
|
47
|
-
await hook["chat.message"]({ sessionID }, output)
|
|
48
|
-
|
|
49
|
-
// #then - ultrawork context should be registered in collector
|
|
50
|
-
expect(collector.hasPending(sessionID)).toBe(true)
|
|
51
|
-
const pending = collector.getPending(sessionID)
|
|
52
|
-
expect(pending.entries.length).toBeGreaterThan(0)
|
|
53
|
-
expect(pending.entries[0].source).toBe("keyword-detector")
|
|
54
|
-
expect(pending.entries[0].id).toBe("keyword-ultrawork")
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
test("should register search keyword to ContextCollector", async () => {
|
|
58
|
-
// #given - mock getMainSessionID to return our session (isolate from global state)
|
|
59
|
-
const collector = new ContextCollector()
|
|
60
|
-
const sessionID = "search-test-session"
|
|
61
|
-
getMainSessionSpy = spyOn(sessionState, "getMainSessionID").mockReturnValue(sessionID)
|
|
62
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
63
|
-
const output = {
|
|
64
|
-
message: {} as Record<string, unknown>,
|
|
65
|
-
parts: [{ type: "text", text: "search for the bug" }],
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// #when - keyword detection runs
|
|
69
|
-
await hook["chat.message"]({ sessionID }, output)
|
|
70
|
-
|
|
71
|
-
// #then - search context should be registered in collector
|
|
72
|
-
expect(collector.hasPending(sessionID)).toBe(true)
|
|
73
|
-
const pending = collector.getPending(sessionID)
|
|
74
|
-
expect(pending.entries.some((e) => e.id === "keyword-search")).toBe(true)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
test("should NOT register to collector when no keywords detected", async () => {
|
|
78
|
-
// #given - no keywords in message
|
|
79
|
-
const collector = new ContextCollector()
|
|
80
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
81
|
-
const sessionID = "test-session"
|
|
82
|
-
const output = {
|
|
83
|
-
message: {} as Record<string, unknown>,
|
|
84
|
-
parts: [{ type: "text", text: "just a normal message" }],
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// #when - keyword detection runs
|
|
88
|
-
await hook["chat.message"]({ sessionID }, output)
|
|
89
|
-
|
|
90
|
-
// #then - nothing should be registered
|
|
91
|
-
expect(collector.hasPending(sessionID)).toBe(false)
|
|
92
|
-
})
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
describe("keyword-detector session filtering", () => {
|
|
96
|
-
let logCalls: Array<{ msg: string; data?: unknown }>
|
|
97
|
-
let logSpy: ReturnType<typeof spyOn>
|
|
98
|
-
|
|
99
|
-
beforeEach(() => {
|
|
100
|
-
setMainSession(undefined)
|
|
101
|
-
logCalls = []
|
|
102
|
-
logSpy = spyOn(sharedModule, "log").mockImplementation((msg: string, data?: unknown) => {
|
|
103
|
-
logCalls.push({ msg, data })
|
|
104
|
-
})
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
afterEach(() => {
|
|
108
|
-
logSpy?.mockRestore()
|
|
109
|
-
setMainSession(undefined)
|
|
110
|
-
})
|
|
111
|
-
|
|
112
|
-
function createMockPluginInput(options: { toastCalls?: string[] } = {}) {
|
|
113
|
-
const toastCalls = options.toastCalls ?? []
|
|
114
|
-
return {
|
|
115
|
-
client: {
|
|
116
|
-
tui: {
|
|
117
|
-
showToast: async (opts: any) => {
|
|
118
|
-
toastCalls.push(opts.body.title)
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
} as any
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
test("should skip non-ultrawork keywords in non-main session (using mainSessionID check)", async () => {
|
|
126
|
-
// #given - main session is set, different session submits search keyword
|
|
127
|
-
const mainSessionID = "main-123"
|
|
128
|
-
const subagentSessionID = "subagent-456"
|
|
129
|
-
setMainSession(mainSessionID)
|
|
130
|
-
|
|
131
|
-
const hook = createKeywordDetectorHook(createMockPluginInput())
|
|
132
|
-
const output = {
|
|
133
|
-
message: {} as Record<string, unknown>,
|
|
134
|
-
parts: [{ type: "text", text: "search mode 찾아줘" }],
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// #when - non-main session triggers keyword detection
|
|
138
|
-
await hook["chat.message"](
|
|
139
|
-
{ sessionID: subagentSessionID },
|
|
140
|
-
output
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
// #then - search keyword should be filtered out based on mainSessionID comparison
|
|
144
|
-
const skipLog = logCalls.find(c => c.msg.includes("Skipping non-ultrawork keywords in non-main session"))
|
|
145
|
-
expect(skipLog).toBeDefined()
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
test("should allow ultrawork keywords in non-main session", async () => {
|
|
149
|
-
// #given - main session is set, different session submits ultrawork keyword
|
|
150
|
-
const mainSessionID = "main-123"
|
|
151
|
-
const subagentSessionID = "subagent-456"
|
|
152
|
-
setMainSession(mainSessionID)
|
|
153
|
-
|
|
154
|
-
const toastCalls: string[] = []
|
|
155
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
156
|
-
const output = {
|
|
157
|
-
message: {} as Record<string, unknown>,
|
|
158
|
-
parts: [{ type: "text", text: "ultrawork mode" }],
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// #when - non-main session triggers ultrawork keyword
|
|
162
|
-
await hook["chat.message"](
|
|
163
|
-
{ sessionID: subagentSessionID },
|
|
164
|
-
output
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
// #then - ultrawork should still work (variant set to max)
|
|
168
|
-
expect(output.message.variant).toBe("max")
|
|
169
|
-
expect(toastCalls).toContain("Ultrawork Mode Activated")
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
test("should allow all keywords in main session", async () => {
|
|
173
|
-
// #given - main session submits search keyword
|
|
174
|
-
const mainSessionID = "main-123"
|
|
175
|
-
setMainSession(mainSessionID)
|
|
176
|
-
|
|
177
|
-
const hook = createKeywordDetectorHook(createMockPluginInput())
|
|
178
|
-
const output = {
|
|
179
|
-
message: {} as Record<string, unknown>,
|
|
180
|
-
parts: [{ type: "text", text: "search mode 찾아줘" }],
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// #when - main session triggers keyword detection
|
|
184
|
-
await hook["chat.message"](
|
|
185
|
-
{ sessionID: mainSessionID },
|
|
186
|
-
output
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
// #then - search keyword should be detected (output unchanged but detection happens)
|
|
190
|
-
// Note: search keywords don't set variant, they inject messages via context-injector
|
|
191
|
-
// This test verifies the detection logic runs without filtering
|
|
192
|
-
expect(output.message.variant).toBeUndefined() // search doesn't set variant
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
test("should allow all keywords when mainSessionID is not set", async () => {
|
|
196
|
-
// #given - no main session set (early startup or standalone mode)
|
|
197
|
-
setMainSession(undefined)
|
|
198
|
-
|
|
199
|
-
const toastCalls: string[] = []
|
|
200
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
201
|
-
const output = {
|
|
202
|
-
message: {} as Record<string, unknown>,
|
|
203
|
-
parts: [{ type: "text", text: "ultrawork search" }],
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
// #when - any session triggers keyword detection
|
|
207
|
-
await hook["chat.message"](
|
|
208
|
-
{ sessionID: "any-session" },
|
|
209
|
-
output
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
// #then - all keywords should work
|
|
213
|
-
expect(output.message.variant).toBe("max")
|
|
214
|
-
expect(toastCalls).toContain("Ultrawork Mode Activated")
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
test("should not override existing variant", async () => {
|
|
218
|
-
// #given - main session set with pre-existing variant
|
|
219
|
-
setMainSession("main-123")
|
|
220
|
-
|
|
221
|
-
const toastCalls: string[] = []
|
|
222
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
223
|
-
const output = {
|
|
224
|
-
message: { variant: "low" } as Record<string, unknown>,
|
|
225
|
-
parts: [{ type: "text", text: "ultrawork mode" }],
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// #when - ultrawork keyword triggers
|
|
229
|
-
await hook["chat.message"](
|
|
230
|
-
{ sessionID: "main-123" },
|
|
231
|
-
output
|
|
232
|
-
)
|
|
233
|
-
|
|
234
|
-
// #then - existing variant should remain
|
|
235
|
-
expect(output.message.variant).toBe("low")
|
|
236
|
-
expect(toastCalls).toContain("Ultrawork Mode Activated")
|
|
237
|
-
})
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
describe("keyword-detector word boundary", () => {
|
|
241
|
-
let logCalls: Array<{ msg: string; data?: unknown }>
|
|
242
|
-
let logSpy: ReturnType<typeof spyOn>
|
|
243
|
-
|
|
244
|
-
beforeEach(() => {
|
|
245
|
-
setMainSession(undefined)
|
|
246
|
-
logCalls = []
|
|
247
|
-
logSpy = spyOn(sharedModule, "log").mockImplementation((msg: string, data?: unknown) => {
|
|
248
|
-
logCalls.push({ msg, data })
|
|
249
|
-
})
|
|
250
|
-
})
|
|
251
|
-
|
|
252
|
-
afterEach(() => {
|
|
253
|
-
logSpy?.mockRestore()
|
|
254
|
-
setMainSession(undefined)
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
function createMockPluginInput(options: { toastCalls?: string[] } = {}) {
|
|
258
|
-
const toastCalls = options.toastCalls ?? []
|
|
259
|
-
return {
|
|
260
|
-
client: {
|
|
261
|
-
tui: {
|
|
262
|
-
showToast: async (opts: any) => {
|
|
263
|
-
toastCalls.push(opts.body.title)
|
|
264
|
-
},
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
} as any
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
test("should NOT trigger ultrawork on partial matches like 'StatefulWidget' containing 'ulw'", async () => {
|
|
271
|
-
// #given - text contains 'ulw' as part of another word (StatefulWidget)
|
|
272
|
-
setMainSession(undefined)
|
|
273
|
-
|
|
274
|
-
const toastCalls: string[] = []
|
|
275
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
276
|
-
const output = {
|
|
277
|
-
message: {} as Record<string, unknown>,
|
|
278
|
-
parts: [{ type: "text", text: "refactor the StatefulWidget component" }],
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
// #when - message with partial 'ulw' match is processed
|
|
282
|
-
await hook["chat.message"](
|
|
283
|
-
{ sessionID: "any-session" },
|
|
284
|
-
output
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
// #then - ultrawork should NOT be triggered
|
|
288
|
-
expect(output.message.variant).toBeUndefined()
|
|
289
|
-
expect(toastCalls).not.toContain("Ultrawork Mode Activated")
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
test("should trigger ultrawork on standalone 'ulw' keyword", async () => {
|
|
293
|
-
// #given - text contains standalone 'ulw'
|
|
294
|
-
setMainSession(undefined)
|
|
295
|
-
|
|
296
|
-
const toastCalls: string[] = []
|
|
297
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
298
|
-
const output = {
|
|
299
|
-
message: {} as Record<string, unknown>,
|
|
300
|
-
parts: [{ type: "text", text: "ulw do this task" }],
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// #when - message with standalone 'ulw' is processed
|
|
304
|
-
await hook["chat.message"](
|
|
305
|
-
{ sessionID: "any-session" },
|
|
306
|
-
output
|
|
307
|
-
)
|
|
308
|
-
|
|
309
|
-
// #then - ultrawork should be triggered
|
|
310
|
-
expect(output.message.variant).toBe("max")
|
|
311
|
-
expect(toastCalls).toContain("Ultrawork Mode Activated")
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
test("should NOT trigger ultrawork on file references containing 'ulw' substring", async () => {
|
|
315
|
-
// #given - file reference contains 'ulw' as substring
|
|
316
|
-
setMainSession(undefined)
|
|
317
|
-
|
|
318
|
-
const toastCalls: string[] = []
|
|
319
|
-
const hook = createKeywordDetectorHook(createMockPluginInput({ toastCalls }))
|
|
320
|
-
const output = {
|
|
321
|
-
message: {} as Record<string, unknown>,
|
|
322
|
-
parts: [{ type: "text", text: "@StatefulWidget.tsx please review this file" }],
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// #when - message referencing file with 'ulw' substring is processed
|
|
326
|
-
await hook["chat.message"](
|
|
327
|
-
{ sessionID: "any-session" },
|
|
328
|
-
output
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
// #then - ultrawork should NOT be triggered
|
|
332
|
-
expect(output.message.variant).toBeUndefined()
|
|
333
|
-
expect(toastCalls).not.toContain("Ultrawork Mode Activated")
|
|
334
|
-
})
|
|
335
|
-
})
|
|
336
|
-
|
|
337
|
-
describe("keyword-detector agent-specific ultrawork messages", () => {
|
|
338
|
-
let logCalls: Array<{ msg: string; data?: unknown }>
|
|
339
|
-
let logSpy: ReturnType<typeof spyOn>
|
|
340
|
-
|
|
341
|
-
beforeEach(() => {
|
|
342
|
-
setMainSession(undefined)
|
|
343
|
-
logCalls = []
|
|
344
|
-
logSpy = spyOn(sharedModule, "log").mockImplementation((msg: string, data?: unknown) => {
|
|
345
|
-
logCalls.push({ msg, data })
|
|
346
|
-
})
|
|
347
|
-
})
|
|
348
|
-
|
|
349
|
-
afterEach(() => {
|
|
350
|
-
logSpy?.mockRestore()
|
|
351
|
-
setMainSession(undefined)
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
function createMockPluginInput() {
|
|
355
|
-
return {
|
|
356
|
-
client: {
|
|
357
|
-
tui: {
|
|
358
|
-
showToast: async () => {},
|
|
359
|
-
},
|
|
360
|
-
},
|
|
361
|
-
} as any
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
test("should use planner-specific ultrawork message when agent is prometheus", async () => {
|
|
365
|
-
// #given - collector and prometheus agent
|
|
366
|
-
const collector = new ContextCollector()
|
|
367
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
368
|
-
const sessionID = "prometheus-session"
|
|
369
|
-
const output = {
|
|
370
|
-
message: {} as Record<string, unknown>,
|
|
371
|
-
parts: [{ type: "text", text: "ultrawork plan this feature" }],
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// #when - ultrawork keyword detected with prometheus agent
|
|
375
|
-
await hook["chat.message"]({ sessionID, agent: "prometheus" }, output)
|
|
376
|
-
|
|
377
|
-
// #then - should use planner-specific message with "YOU ARE A PLANNER" content
|
|
378
|
-
const pending = collector.getPending(sessionID)
|
|
379
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
380
|
-
expect(ultraworkEntry).toBeDefined()
|
|
381
|
-
expect(ultraworkEntry!.content).toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
382
|
-
expect(ultraworkEntry!.content).not.toContain("YOU MUST LEVERAGE ALL AVAILABLE AGENTS")
|
|
383
|
-
})
|
|
384
|
-
|
|
385
|
-
test("should use planner-specific ultrawork message when agent name contains 'planner'", async () => {
|
|
386
|
-
// #given - collector and agent with 'planner' in name
|
|
387
|
-
const collector = new ContextCollector()
|
|
388
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
389
|
-
const sessionID = "planner-session"
|
|
390
|
-
const output = {
|
|
391
|
-
message: {} as Record<string, unknown>,
|
|
392
|
-
parts: [{ type: "text", text: "ulw create a work plan" }],
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// #when - ultrawork keyword detected with planner agent
|
|
396
|
-
await hook["chat.message"]({ sessionID, agent: "Prometheus (Planner)" }, output)
|
|
397
|
-
|
|
398
|
-
// #then - should use planner-specific message
|
|
399
|
-
const pending = collector.getPending(sessionID)
|
|
400
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
401
|
-
expect(ultraworkEntry).toBeDefined()
|
|
402
|
-
expect(ultraworkEntry!.content).toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
test("should use normal ultrawork message when agent is Sisyphus", async () => {
|
|
406
|
-
// #given - collector and Sisyphus agent
|
|
407
|
-
const collector = new ContextCollector()
|
|
408
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
409
|
-
const sessionID = "sisyphus-session"
|
|
410
|
-
const output = {
|
|
411
|
-
message: {} as Record<string, unknown>,
|
|
412
|
-
parts: [{ type: "text", text: "ultrawork implement this feature" }],
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
// #when - ultrawork keyword detected with Sisyphus agent
|
|
416
|
-
await hook["chat.message"]({ sessionID, agent: "Sisyphus" }, output)
|
|
417
|
-
|
|
418
|
-
// #then - should use normal ultrawork message with agent utilization instructions
|
|
419
|
-
const pending = collector.getPending(sessionID)
|
|
420
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
421
|
-
expect(ultraworkEntry).toBeDefined()
|
|
422
|
-
expect(ultraworkEntry!.content).toContain("YOU MUST LEVERAGE ALL AVAILABLE AGENTS")
|
|
423
|
-
expect(ultraworkEntry!.content).not.toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
424
|
-
})
|
|
425
|
-
|
|
426
|
-
test("should use normal ultrawork message when agent is undefined", async () => {
|
|
427
|
-
// #given - collector with no agent specified
|
|
428
|
-
const collector = new ContextCollector()
|
|
429
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
430
|
-
const sessionID = "no-agent-session"
|
|
431
|
-
const output = {
|
|
432
|
-
message: {} as Record<string, unknown>,
|
|
433
|
-
parts: [{ type: "text", text: "ultrawork do something" }],
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// #when - ultrawork keyword detected without agent
|
|
437
|
-
await hook["chat.message"]({ sessionID }, output)
|
|
438
|
-
|
|
439
|
-
// #then - should use normal ultrawork message (default behavior)
|
|
440
|
-
const pending = collector.getPending(sessionID)
|
|
441
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
442
|
-
expect(ultraworkEntry).toBeDefined()
|
|
443
|
-
expect(ultraworkEntry!.content).toContain("YOU MUST LEVERAGE ALL AVAILABLE AGENTS")
|
|
444
|
-
expect(ultraworkEntry!.content).not.toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
test("should switch from planner to normal message when agent changes", async () => {
|
|
448
|
-
// #given - two sessions, one with prometheus, one with sisyphus
|
|
449
|
-
const collector = new ContextCollector()
|
|
450
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
451
|
-
|
|
452
|
-
// First session with prometheus
|
|
453
|
-
const prometheusSessionID = "prometheus-first"
|
|
454
|
-
const prometheusOutput = {
|
|
455
|
-
message: {} as Record<string, unknown>,
|
|
456
|
-
parts: [{ type: "text", text: "ultrawork plan" }],
|
|
457
|
-
}
|
|
458
|
-
await hook["chat.message"]({ sessionID: prometheusSessionID, agent: "prometheus" }, prometheusOutput)
|
|
459
|
-
|
|
460
|
-
// Second session with sisyphus
|
|
461
|
-
const sisyphusSessionID = "sisyphus-second"
|
|
462
|
-
const sisyphusOutput = {
|
|
463
|
-
message: {} as Record<string, unknown>,
|
|
464
|
-
parts: [{ type: "text", text: "ultrawork implement" }],
|
|
465
|
-
}
|
|
466
|
-
await hook["chat.message"]({ sessionID: sisyphusSessionID, agent: "Sisyphus" }, sisyphusOutput)
|
|
467
|
-
|
|
468
|
-
// #then - each session should have the correct message type
|
|
469
|
-
const prometheusPending = collector.getPending(prometheusSessionID)
|
|
470
|
-
const prometheusEntry = prometheusPending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
471
|
-
expect(prometheusEntry!.content).toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
472
|
-
|
|
473
|
-
const sisyphusPending = collector.getPending(sisyphusSessionID)
|
|
474
|
-
const sisyphusEntry = sisyphusPending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
475
|
-
expect(sisyphusEntry!.content).toContain("YOU MUST LEVERAGE ALL AVAILABLE AGENTS")
|
|
476
|
-
})
|
|
477
|
-
|
|
478
|
-
test("should use session state agent over stale input.agent (bug fix)", async () => {
|
|
479
|
-
// #given - same session, agent switched from prometheus to sisyphus in session state
|
|
480
|
-
const collector = new ContextCollector()
|
|
481
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
482
|
-
const sessionID = "same-session-agent-switch"
|
|
483
|
-
|
|
484
|
-
// Simulate: session state was updated to sisyphus (by index.ts updateSessionAgent)
|
|
485
|
-
updateSessionAgent(sessionID, "Sisyphus")
|
|
486
|
-
|
|
487
|
-
const output = {
|
|
488
|
-
message: {} as Record<string, unknown>,
|
|
489
|
-
parts: [{ type: "text", text: "ultrawork implement this" }],
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// #when - hook receives stale input.agent="prometheus" but session state says "Sisyphus"
|
|
493
|
-
await hook["chat.message"]({ sessionID, agent: "prometheus" }, output)
|
|
494
|
-
|
|
495
|
-
// #then - should use Sisyphus from session state, NOT prometheus from stale input
|
|
496
|
-
const pending = collector.getPending(sessionID)
|
|
497
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
498
|
-
expect(ultraworkEntry).toBeDefined()
|
|
499
|
-
expect(ultraworkEntry!.content).toContain("YOU MUST LEVERAGE ALL AVAILABLE AGENTS")
|
|
500
|
-
expect(ultraworkEntry!.content).not.toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
501
|
-
|
|
502
|
-
// cleanup
|
|
503
|
-
clearSessionAgent(sessionID)
|
|
504
|
-
})
|
|
505
|
-
|
|
506
|
-
test("should fall back to input.agent when session state is empty", async () => {
|
|
507
|
-
// #given - no session state, only input.agent available
|
|
508
|
-
const collector = new ContextCollector()
|
|
509
|
-
const hook = createKeywordDetectorHook(createMockPluginInput(), collector)
|
|
510
|
-
const sessionID = "no-session-state"
|
|
511
|
-
|
|
512
|
-
// Ensure no session state
|
|
513
|
-
clearSessionAgent(sessionID)
|
|
514
|
-
|
|
515
|
-
const output = {
|
|
516
|
-
message: {} as Record<string, unknown>,
|
|
517
|
-
parts: [{ type: "text", text: "ultrawork plan this" }],
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
// #when - hook receives input.agent="prometheus" with no session state
|
|
521
|
-
await hook["chat.message"]({ sessionID, agent: "prometheus" }, output)
|
|
522
|
-
|
|
523
|
-
// #then - should use prometheus from input.agent as fallback
|
|
524
|
-
const pending = collector.getPending(sessionID)
|
|
525
|
-
const ultraworkEntry = pending.entries.find((e) => e.id === "keyword-ultrawork")
|
|
526
|
-
expect(ultraworkEntry).toBeDefined()
|
|
527
|
-
expect(ultraworkEntry!.content).toContain("YOU ARE A PLANNER, NOT AN IMPLEMENTER")
|
|
528
|
-
})
|
|
529
|
-
})
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type { PluginInput } from "@opencode-ai/plugin"
|
|
2
|
-
import { detectKeywordsWithType, extractPromptText, removeCodeBlocks } from "./detector"
|
|
3
|
-
import { log } from "../../shared"
|
|
4
|
-
import { isSystemDirective } from "../../shared/system-directive"
|
|
5
|
-
import { getMainSessionID, getSessionAgent, subagentSessions } from "../../features/claude-code-session-state"
|
|
6
|
-
import type { ContextCollector } from "../../features/context-injector"
|
|
7
|
-
|
|
8
|
-
export * from "./detector"
|
|
9
|
-
export * from "./constants"
|
|
10
|
-
export * from "./types"
|
|
11
|
-
|
|
12
|
-
export function createKeywordDetectorHook(ctx: PluginInput, collector?: ContextCollector) {
|
|
13
|
-
return {
|
|
14
|
-
"chat.message": async (
|
|
15
|
-
input: {
|
|
16
|
-
sessionID: string
|
|
17
|
-
agent?: string
|
|
18
|
-
model?: { providerID: string; modelID: string }
|
|
19
|
-
messageID?: string
|
|
20
|
-
},
|
|
21
|
-
output: {
|
|
22
|
-
message: Record<string, unknown>
|
|
23
|
-
parts: Array<{ type: string; text?: string; [key: string]: unknown }>
|
|
24
|
-
}
|
|
25
|
-
): Promise<void> => {
|
|
26
|
-
const promptText = extractPromptText(output.parts)
|
|
27
|
-
|
|
28
|
-
if (isSystemDirective(promptText)) {
|
|
29
|
-
log(`[keyword-detector] Skipping system directive message`, { sessionID: input.sessionID })
|
|
30
|
-
return
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const currentAgent = getSessionAgent(input.sessionID) ?? input.agent
|
|
34
|
-
let detectedKeywords = detectKeywordsWithType(removeCodeBlocks(promptText), currentAgent)
|
|
35
|
-
|
|
36
|
-
if (detectedKeywords.length === 0) {
|
|
37
|
-
return
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Skip keyword detection for background task sessions to prevent mode injection
|
|
41
|
-
// (e.g., [analyze-mode]) which incorrectly triggers Prometheus restrictions
|
|
42
|
-
const isBackgroundTaskSession = subagentSessions.has(input.sessionID)
|
|
43
|
-
if (isBackgroundTaskSession) {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const mainSessionID = getMainSessionID()
|
|
48
|
-
const isNonMainSession = mainSessionID && input.sessionID !== mainSessionID
|
|
49
|
-
|
|
50
|
-
if (isNonMainSession) {
|
|
51
|
-
detectedKeywords = detectedKeywords.filter((k) => k.type === "ultrawork")
|
|
52
|
-
if (detectedKeywords.length === 0) {
|
|
53
|
-
log(`[keyword-detector] Skipping non-ultrawork keywords in non-main session`, {
|
|
54
|
-
sessionID: input.sessionID,
|
|
55
|
-
mainSessionID,
|
|
56
|
-
})
|
|
57
|
-
return
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork")
|
|
62
|
-
if (hasUltrawork) {
|
|
63
|
-
log(`[keyword-detector] Ultrawork mode activated`, { sessionID: input.sessionID })
|
|
64
|
-
|
|
65
|
-
if (output.message.variant === undefined) {
|
|
66
|
-
output.message.variant = "max"
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
ctx.client.tui
|
|
70
|
-
.showToast({
|
|
71
|
-
body: {
|
|
72
|
-
title: "Ultrawork Mode Activated",
|
|
73
|
-
message: "Maximum precision engaged. All agents at your disposal.",
|
|
74
|
-
variant: "success" as const,
|
|
75
|
-
duration: 3000,
|
|
76
|
-
},
|
|
77
|
-
})
|
|
78
|
-
.catch((err) =>
|
|
79
|
-
log(`[keyword-detector] Failed to show toast`, { error: err, sessionID: input.sessionID })
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (collector) {
|
|
84
|
-
for (const keyword of detectedKeywords) {
|
|
85
|
-
collector.register(input.sessionID, {
|
|
86
|
-
id: `keyword-${keyword.type}`,
|
|
87
|
-
source: "keyword-detector",
|
|
88
|
-
content: keyword.message,
|
|
89
|
-
priority: keyword.type === "ultrawork" ? "critical" : "high",
|
|
90
|
-
})
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
log(`[keyword-detector] Detected ${detectedKeywords.length} keywords`, {
|
|
95
|
-
sessionID: input.sessionID,
|
|
96
|
-
types: detectedKeywords.map((k) => k.type),
|
|
97
|
-
})
|
|
98
|
-
},
|
|
99
|
-
}
|
|
100
|
-
}
|