@moreih29/nexus-core 0.16.2 → 0.18.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/README.md +101 -67
- package/dist/cli/sync.d.ts +3 -0
- package/dist/cli/sync.d.ts.map +1 -0
- package/dist/cli/sync.js +59 -0
- package/dist/cli/sync.js.map +1 -0
- package/dist/generate/index.d.ts +3 -0
- package/dist/generate/index.d.ts.map +1 -0
- package/dist/generate/index.js +2 -0
- package/dist/generate/index.js.map +1 -0
- package/dist/generate/load-data.d.ts +8 -0
- package/dist/generate/load-data.d.ts.map +1 -0
- package/dist/generate/load-data.js +45 -0
- package/dist/generate/load-data.js.map +1 -0
- package/dist/generate/load-spec.d.ts +3 -0
- package/dist/generate/load-spec.d.ts.map +1 -0
- package/dist/generate/load-spec.js +48 -0
- package/dist/generate/load-spec.js.map +1 -0
- package/dist/generate/macros/expand.d.ts +3 -0
- package/dist/generate/macros/expand.d.ts.map +1 -0
- package/dist/generate/macros/expand.js +48 -0
- package/dist/generate/macros/expand.js.map +1 -0
- package/dist/generate/macros/parse.d.ts +4 -0
- package/dist/generate/macros/parse.d.ts.map +1 -0
- package/dist/generate/macros/parse.js +142 -0
- package/dist/generate/macros/parse.js.map +1 -0
- package/dist/generate/macros/validate.d.ts +3 -0
- package/dist/generate/macros/validate.d.ts.map +1 -0
- package/dist/generate/macros/validate.js +23 -0
- package/dist/generate/macros/validate.js.map +1 -0
- package/dist/generate/renderers/claude.d.ts +3 -0
- package/dist/generate/renderers/claude.d.ts.map +1 -0
- package/dist/generate/renderers/claude.js +48 -0
- package/dist/generate/renderers/claude.js.map +1 -0
- package/dist/generate/renderers/codex.d.ts +3 -0
- package/dist/generate/renderers/codex.d.ts.map +1 -0
- package/dist/generate/renderers/codex.js +79 -0
- package/dist/generate/renderers/codex.js.map +1 -0
- package/dist/generate/renderers/markdown.d.ts +2 -0
- package/dist/generate/renderers/markdown.d.ts.map +1 -0
- package/dist/generate/renderers/markdown.js +6 -0
- package/dist/generate/renderers/markdown.js.map +1 -0
- package/dist/generate/renderers/opencode.d.ts +3 -0
- package/dist/generate/renderers/opencode.d.ts.map +1 -0
- package/dist/generate/renderers/opencode.js +69 -0
- package/dist/generate/renderers/opencode.js.map +1 -0
- package/dist/generate/sync.d.ts +4 -0
- package/dist/generate/sync.d.ts.map +1 -0
- package/dist/generate/sync.js +60 -0
- package/dist/generate/sync.js.map +1 -0
- package/dist/generate/types.d.ts +74 -0
- package/dist/generate/types.d.ts.map +1 -0
- package/dist/generate/types.js +2 -0
- package/dist/generate/types.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/definitions/artifact.d.ts +20 -0
- package/dist/mcp/definitions/artifact.d.ts.map +1 -0
- package/dist/mcp/definitions/artifact.js +14 -0
- package/dist/mcp/definitions/artifact.js.map +1 -0
- package/dist/mcp/definitions/history.d.ts +20 -0
- package/dist/mcp/definitions/history.d.ts.map +1 -0
- package/dist/mcp/definitions/history.js +18 -0
- package/dist/mcp/definitions/history.js.map +1 -0
- package/dist/mcp/definitions/index.d.ts +276 -0
- package/dist/mcp/definitions/index.d.ts.map +1 -0
- package/dist/mcp/definitions/index.js +16 -0
- package/dist/mcp/definitions/index.js.map +1 -0
- package/dist/mcp/definitions/plan.d.ts +111 -0
- package/dist/mcp/definitions/plan.d.ts.map +1 -0
- package/dist/mcp/definitions/plan.js +89 -0
- package/dist/mcp/definitions/plan.js.map +1 -0
- package/dist/mcp/definitions/task.d.ts +138 -0
- package/dist/mcp/definitions/task.d.ts.map +1 -0
- package/dist/mcp/definitions/task.js +78 -0
- package/dist/mcp/definitions/task.js.map +1 -0
- package/dist/mcp/handlers/artifact.d.ts.map +1 -0
- package/dist/mcp/handlers/artifact.js +42 -0
- package/dist/mcp/handlers/artifact.js.map +1 -0
- package/dist/mcp/handlers/history.d.ts.map +1 -0
- package/dist/mcp/handlers/history.js +35 -0
- package/dist/mcp/handlers/history.js.map +1 -0
- package/dist/mcp/handlers/plan.d.ts.map +1 -0
- package/dist/mcp/handlers/plan.js +324 -0
- package/dist/mcp/handlers/plan.js.map +1 -0
- package/dist/mcp/handlers/task.d.ts.map +1 -0
- package/dist/mcp/handlers/task.js +216 -0
- package/dist/mcp/handlers/task.js.map +1 -0
- package/dist/{src/mcp → mcp}/server.d.ts +1 -1
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +58 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/shared/json-store.d.ts.map +1 -0
- package/dist/{src/shared → shared}/json-store.js +5 -4
- package/dist/shared/json-store.js.map +1 -0
- package/dist/shared/mcp-utils.d.ts.map +1 -0
- package/dist/shared/mcp-utils.js.map +1 -0
- package/dist/{src/shared → shared}/paths.d.ts +0 -4
- package/dist/shared/paths.d.ts.map +1 -0
- package/dist/shared/paths.js +62 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/shared/register-tool.d.ts +20 -0
- package/dist/shared/register-tool.d.ts.map +1 -0
- package/dist/shared/register-tool.js +15 -0
- package/dist/shared/register-tool.js.map +1 -0
- package/dist/{src/types → types}/state.d.ts +65 -65
- package/dist/types/state.d.ts.map +1 -0
- package/dist/{src/types → types}/state.js +1 -1
- package/dist/types/state.js.map +1 -0
- package/harness/claude/agent-rules.yml +21 -0
- package/harness/claude/invocations.yml +11 -0
- package/harness/claude/layout.yml +3 -0
- package/harness/codex/agent-rules.yml +28 -0
- package/harness/codex/invocations.yml +13 -0
- package/harness/codex/layout.yml +3 -0
- package/harness/opencode/agent-rules.yml +18 -0
- package/harness/opencode/invocations.yml +12 -0
- package/harness/opencode/layout.yml +3 -0
- package/package.json +38 -43
- package/{assets → spec}/agents/architect/body.ko.md +92 -84
- package/spec/agents/architect/body.md +185 -0
- package/spec/agents/designer/body.ko.md +330 -0
- package/spec/agents/designer/body.md +330 -0
- package/spec/agents/engineer/body.ko.md +166 -0
- package/spec/agents/engineer/body.md +166 -0
- package/spec/agents/lead/body.ko.md +276 -0
- package/spec/agents/lead/body.md +276 -0
- package/{assets → spec}/agents/postdoc/body.ko.md +116 -46
- package/spec/agents/postdoc/body.md +192 -0
- package/{assets → spec}/agents/researcher/body.ko.md +131 -45
- package/spec/agents/researcher/body.md +223 -0
- package/spec/agents/reviewer/body.ko.md +219 -0
- package/spec/agents/reviewer/body.md +219 -0
- package/{assets → spec}/agents/strategist/body.ko.md +108 -35
- package/spec/agents/strategist/body.md +187 -0
- package/spec/agents/tester/body.ko.md +272 -0
- package/spec/agents/tester/body.md +272 -0
- package/{assets → spec}/agents/writer/body.ko.md +109 -33
- package/spec/agents/writer/body.md +198 -0
- package/spec/skills/nx-auto-plan/body.ko.md +150 -0
- package/spec/skills/nx-auto-plan/body.md +150 -0
- package/spec/skills/nx-plan/body.ko.md +159 -0
- package/spec/skills/nx-plan/body.md +159 -0
- package/spec/skills/nx-run/body.ko.md +132 -0
- package/spec/skills/nx-run/body.md +132 -0
- package/vocabulary/enums/task-register-state.yml +4 -0
- package/vocabulary/invocations.yml +43 -0
- package/assets/agents/architect/body.md +0 -177
- package/assets/agents/designer/body.ko.md +0 -125
- package/assets/agents/designer/body.md +0 -125
- package/assets/agents/engineer/body.ko.md +0 -106
- package/assets/agents/engineer/body.md +0 -106
- package/assets/agents/lead/body.ko.md +0 -70
- package/assets/agents/lead/body.md +0 -70
- package/assets/agents/postdoc/body.md +0 -122
- package/assets/agents/researcher/body.md +0 -137
- package/assets/agents/reviewer/body.ko.md +0 -138
- package/assets/agents/reviewer/body.md +0 -138
- package/assets/agents/strategist/body.md +0 -116
- package/assets/agents/tester/body.ko.md +0 -195
- package/assets/agents/tester/body.md +0 -195
- package/assets/agents/writer/body.md +0 -122
- package/assets/capability-matrix.yml +0 -198
- package/assets/hooks/agent-bootstrap/handler.test.ts +0 -368
- package/assets/hooks/agent-bootstrap/handler.ts +0 -119
- package/assets/hooks/agent-bootstrap/meta.yml +0 -10
- package/assets/hooks/agent-finalize/handler.test.ts +0 -368
- package/assets/hooks/agent-finalize/handler.ts +0 -76
- package/assets/hooks/agent-finalize/meta.yml +0 -10
- package/assets/hooks/capability-matrix.yml +0 -313
- package/assets/hooks/post-tool-telemetry/handler.test.ts +0 -302
- package/assets/hooks/post-tool-telemetry/handler.ts +0 -49
- package/assets/hooks/post-tool-telemetry/meta.yml +0 -11
- package/assets/hooks/prompt-router/handler.test.ts +0 -801
- package/assets/hooks/prompt-router/handler.ts +0 -272
- package/assets/hooks/prompt-router/meta.yml +0 -11
- package/assets/hooks/session-init/handler.test.ts +0 -274
- package/assets/hooks/session-init/handler.ts +0 -30
- package/assets/hooks/session-init/meta.yml +0 -9
- package/assets/lsp-servers.json +0 -55
- package/assets/schema/lsp-servers.schema.json +0 -67
- package/assets/skills/nx-init/body.ko.md +0 -197
- package/assets/skills/nx-init/body.md +0 -197
- package/assets/skills/nx-plan/body.ko.md +0 -361
- package/assets/skills/nx-plan/body.md +0 -361
- package/assets/skills/nx-run/body.ko.md +0 -161
- package/assets/skills/nx-run/body.md +0 -160
- package/assets/skills/nx-sync/body.ko.md +0 -92
- package/assets/skills/nx-sync/body.md +0 -92
- package/assets/tools/tool-name-map.yml +0 -353
- package/dist/assets/hooks/agent-bootstrap/handler.d.ts +0 -4
- package/dist/assets/hooks/agent-bootstrap/handler.d.ts.map +0 -1
- package/dist/assets/hooks/agent-bootstrap/handler.js +0 -100
- package/dist/assets/hooks/agent-bootstrap/handler.js.map +0 -1
- package/dist/assets/hooks/agent-finalize/handler.d.ts +0 -4
- package/dist/assets/hooks/agent-finalize/handler.d.ts.map +0 -1
- package/dist/assets/hooks/agent-finalize/handler.js +0 -63
- package/dist/assets/hooks/agent-finalize/handler.js.map +0 -1
- package/dist/assets/hooks/post-tool-telemetry/handler.d.ts +0 -4
- package/dist/assets/hooks/post-tool-telemetry/handler.d.ts.map +0 -1
- package/dist/assets/hooks/post-tool-telemetry/handler.js +0 -40
- package/dist/assets/hooks/post-tool-telemetry/handler.js.map +0 -1
- package/dist/assets/hooks/prompt-router/handler.d.ts +0 -4
- package/dist/assets/hooks/prompt-router/handler.d.ts.map +0 -1
- package/dist/assets/hooks/prompt-router/handler.js +0 -214
- package/dist/assets/hooks/prompt-router/handler.js.map +0 -1
- package/dist/assets/hooks/session-init/handler.d.ts +0 -4
- package/dist/assets/hooks/session-init/handler.d.ts.map +0 -1
- package/dist/assets/hooks/session-init/handler.js +0 -23
- package/dist/assets/hooks/session-init/handler.js.map +0 -1
- package/dist/claude/.claude-plugin/marketplace.json +0 -75
- package/dist/claude/.claude-plugin/plugin.json +0 -67
- package/dist/claude/agents/architect.md +0 -172
- package/dist/claude/agents/designer.md +0 -120
- package/dist/claude/agents/engineer.md +0 -98
- package/dist/claude/agents/lead.md +0 -59
- package/dist/claude/agents/postdoc.md +0 -117
- package/dist/claude/agents/researcher.md +0 -132
- package/dist/claude/agents/reviewer.md +0 -133
- package/dist/claude/agents/strategist.md +0 -111
- package/dist/claude/agents/tester.md +0 -190
- package/dist/claude/agents/writer.md +0 -114
- package/dist/claude/dist/hooks/agent-bootstrap.js +0 -121
- package/dist/claude/dist/hooks/agent-finalize.js +0 -180
- package/dist/claude/dist/hooks/prompt-router.js +0 -7336
- package/dist/claude/dist/hooks/session-init.js +0 -37
- package/dist/claude/hooks/hooks.json +0 -52
- package/dist/claude/settings.json +0 -3
- package/dist/claude/skills/nx-init/SKILL.md +0 -189
- package/dist/claude/skills/nx-plan/SKILL.md +0 -353
- package/dist/claude/skills/nx-run/SKILL.md +0 -154
- package/dist/claude/skills/nx-sync/SKILL.md +0 -87
- package/dist/codex/agents/architect.toml +0 -175
- package/dist/codex/agents/designer.toml +0 -123
- package/dist/codex/agents/engineer.toml +0 -105
- package/dist/codex/agents/lead.toml +0 -64
- package/dist/codex/agents/postdoc.toml +0 -120
- package/dist/codex/agents/researcher.toml +0 -136
- package/dist/codex/agents/reviewer.toml +0 -137
- package/dist/codex/agents/strategist.toml +0 -114
- package/dist/codex/agents/tester.toml +0 -194
- package/dist/codex/agents/writer.toml +0 -121
- package/dist/codex/dist/hooks/agent-bootstrap.js +0 -121
- package/dist/codex/dist/hooks/agent-finalize.js +0 -180
- package/dist/codex/dist/hooks/prompt-router.js +0 -7336
- package/dist/codex/dist/hooks/session-init.js +0 -37
- package/dist/codex/hooks/hooks.json +0 -28
- package/dist/codex/install/AGENTS.fragment.md +0 -60
- package/dist/codex/install/config.fragment.toml +0 -5
- package/dist/codex/install/install.sh +0 -60
- package/dist/codex/package.json +0 -20
- package/dist/codex/plugin/.codex-plugin/plugin.json +0 -57
- package/dist/codex/plugin/skills/nx-init/SKILL.md +0 -189
- package/dist/codex/plugin/skills/nx-plan/SKILL.md +0 -353
- package/dist/codex/plugin/skills/nx-run/SKILL.md +0 -154
- package/dist/codex/plugin/skills/nx-sync/SKILL.md +0 -87
- package/dist/codex/prompts/architect.md +0 -166
- package/dist/codex/prompts/designer.md +0 -114
- package/dist/codex/prompts/engineer.md +0 -97
- package/dist/codex/prompts/lead.md +0 -60
- package/dist/codex/prompts/postdoc.md +0 -111
- package/dist/codex/prompts/researcher.md +0 -127
- package/dist/codex/prompts/reviewer.md +0 -128
- package/dist/codex/prompts/strategist.md +0 -105
- package/dist/codex/prompts/tester.md +0 -185
- package/dist/codex/prompts/writer.md +0 -113
- package/dist/hooks/agent-bootstrap.js +0 -121
- package/dist/hooks/agent-finalize.js +0 -180
- package/dist/hooks/prompt-router.js +0 -7336
- package/dist/hooks/session-init.js +0 -37
- package/dist/manifests/claude-hooks.json +0 -52
- package/dist/manifests/codex-hooks.json +0 -28
- package/dist/manifests/opencode-manifest.json +0 -44
- package/dist/manifests/portability-report.json +0 -87
- package/dist/opencode/.opencode/skills/nx-init/SKILL.md +0 -189
- package/dist/opencode/.opencode/skills/nx-plan/SKILL.md +0 -353
- package/dist/opencode/.opencode/skills/nx-run/SKILL.md +0 -154
- package/dist/opencode/.opencode/skills/nx-sync/SKILL.md +0 -87
- package/dist/opencode/package.json +0 -23
- package/dist/opencode/src/agents/architect.ts +0 -176
- package/dist/opencode/src/agents/designer.ts +0 -124
- package/dist/opencode/src/agents/engineer.ts +0 -105
- package/dist/opencode/src/agents/lead.ts +0 -66
- package/dist/opencode/src/agents/postdoc.ts +0 -121
- package/dist/opencode/src/agents/researcher.ts +0 -136
- package/dist/opencode/src/agents/reviewer.ts +0 -137
- package/dist/opencode/src/agents/strategist.ts +0 -115
- package/dist/opencode/src/agents/tester.ts +0 -194
- package/dist/opencode/src/agents/writer.ts +0 -121
- package/dist/opencode/src/index.ts +0 -25
- package/dist/opencode/src/plugin.ts +0 -6
- package/dist/scripts/build-agents.d.ts +0 -164
- package/dist/scripts/build-agents.d.ts.map +0 -1
- package/dist/scripts/build-agents.js +0 -890
- package/dist/scripts/build-agents.js.map +0 -1
- package/dist/scripts/build-hooks.d.ts +0 -57
- package/dist/scripts/build-hooks.d.ts.map +0 -1
- package/dist/scripts/build-hooks.js +0 -555
- package/dist/scripts/build-hooks.js.map +0 -1
- package/dist/scripts/cli.d.ts +0 -54
- package/dist/scripts/cli.d.ts.map +0 -1
- package/dist/scripts/cli.js +0 -504
- package/dist/scripts/cli.js.map +0 -1
- package/dist/scripts/smoke/smoke-claude.d.ts +0 -2
- package/dist/scripts/smoke/smoke-claude.d.ts.map +0 -1
- package/dist/scripts/smoke/smoke-claude.js +0 -58
- package/dist/scripts/smoke/smoke-claude.js.map +0 -1
- package/dist/scripts/smoke/smoke-codex.d.ts +0 -2
- package/dist/scripts/smoke/smoke-codex.d.ts.map +0 -1
- package/dist/scripts/smoke/smoke-codex.js +0 -50
- package/dist/scripts/smoke/smoke-codex.js.map +0 -1
- package/dist/scripts/smoke/smoke-consumer.d.ts +0 -2
- package/dist/scripts/smoke/smoke-consumer.d.ts.map +0 -1
- package/dist/scripts/smoke/smoke-consumer.js +0 -80
- package/dist/scripts/smoke/smoke-consumer.js.map +0 -1
- package/dist/scripts/smoke/smoke-opencode.d.ts +0 -2
- package/dist/scripts/smoke/smoke-opencode.d.ts.map +0 -1
- package/dist/scripts/smoke/smoke-opencode.js +0 -99
- package/dist/scripts/smoke/smoke-opencode.js.map +0 -1
- package/dist/src/hooks/opencode-mount.d.ts +0 -35
- package/dist/src/hooks/opencode-mount.d.ts.map +0 -1
- package/dist/src/hooks/opencode-mount.js +0 -352
- package/dist/src/hooks/opencode-mount.js.map +0 -1
- package/dist/src/hooks/runtime.d.ts +0 -37
- package/dist/src/hooks/runtime.d.ts.map +0 -1
- package/dist/src/hooks/runtime.js +0 -274
- package/dist/src/hooks/runtime.js.map +0 -1
- package/dist/src/hooks/types.d.ts +0 -196
- package/dist/src/hooks/types.d.ts.map +0 -1
- package/dist/src/hooks/types.js +0 -85
- package/dist/src/hooks/types.js.map +0 -1
- package/dist/src/lsp/cache.d.ts +0 -9
- package/dist/src/lsp/cache.d.ts.map +0 -1
- package/dist/src/lsp/cache.js +0 -216
- package/dist/src/lsp/cache.js.map +0 -1
- package/dist/src/lsp/client.d.ts +0 -24
- package/dist/src/lsp/client.d.ts.map +0 -1
- package/dist/src/lsp/client.js +0 -166
- package/dist/src/lsp/client.js.map +0 -1
- package/dist/src/lsp/detect.d.ts +0 -77
- package/dist/src/lsp/detect.d.ts.map +0 -1
- package/dist/src/lsp/detect.js +0 -116
- package/dist/src/lsp/detect.js.map +0 -1
- package/dist/src/mcp/server.d.ts.map +0 -1
- package/dist/src/mcp/server.js +0 -34
- package/dist/src/mcp/server.js.map +0 -1
- package/dist/src/mcp/tools/artifact.d.ts.map +0 -1
- package/dist/src/mcp/tools/artifact.js +0 -36
- package/dist/src/mcp/tools/artifact.js.map +0 -1
- package/dist/src/mcp/tools/history.d.ts.map +0 -1
- package/dist/src/mcp/tools/history.js +0 -29
- package/dist/src/mcp/tools/history.js.map +0 -1
- package/dist/src/mcp/tools/lsp.d.ts +0 -13
- package/dist/src/mcp/tools/lsp.d.ts.map +0 -1
- package/dist/src/mcp/tools/lsp.js +0 -225
- package/dist/src/mcp/tools/lsp.js.map +0 -1
- package/dist/src/mcp/tools/plan.d.ts.map +0 -1
- package/dist/src/mcp/tools/plan.js +0 -317
- package/dist/src/mcp/tools/plan.js.map +0 -1
- package/dist/src/mcp/tools/task.d.ts.map +0 -1
- package/dist/src/mcp/tools/task.js +0 -252
- package/dist/src/mcp/tools/task.js.map +0 -1
- package/dist/src/shared/invocations.d.ts +0 -74
- package/dist/src/shared/invocations.d.ts.map +0 -1
- package/dist/src/shared/invocations.js +0 -247
- package/dist/src/shared/invocations.js.map +0 -1
- package/dist/src/shared/json-store.d.ts.map +0 -1
- package/dist/src/shared/json-store.js.map +0 -1
- package/dist/src/shared/mcp-utils.d.ts.map +0 -1
- package/dist/src/shared/mcp-utils.js.map +0 -1
- package/dist/src/shared/package-root.d.ts +0 -6
- package/dist/src/shared/package-root.d.ts.map +0 -1
- package/dist/src/shared/package-root.js +0 -19
- package/dist/src/shared/package-root.js.map +0 -1
- package/dist/src/shared/paths.d.ts.map +0 -1
- package/dist/src/shared/paths.js +0 -81
- package/dist/src/shared/paths.js.map +0 -1
- package/dist/src/shared/tool-log.d.ts +0 -8
- package/dist/src/shared/tool-log.d.ts.map +0 -1
- package/dist/src/shared/tool-log.js +0 -22
- package/dist/src/shared/tool-log.js.map +0 -1
- package/dist/src/types/agent-config.d.ts +0 -22
- package/dist/src/types/agent-config.d.ts.map +0 -1
- package/dist/src/types/agent-config.js +0 -2
- package/dist/src/types/agent-config.js.map +0 -1
- package/dist/src/types/index.d.ts +0 -2
- package/dist/src/types/index.d.ts.map +0 -1
- package/dist/src/types/index.js +0 -2
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/types/state.d.ts.map +0 -1
- package/dist/src/types/state.js.map +0 -1
- package/docs/consuming/codex-lead-merge.md +0 -106
- package/docs/contract/harness-io.md +0 -333
- package/docs/plugin-guide.md +0 -355
- package/docs/plugin-template/claude/.github/workflows/build.yml +0 -60
- package/docs/plugin-template/claude/README.md +0 -110
- package/docs/plugin-template/claude/package.json +0 -16
- package/docs/plugin-template/codex/.github/workflows/build.yml +0 -51
- package/docs/plugin-template/codex/README.md +0 -147
- package/docs/plugin-template/codex/install/install.sh +0 -60
- package/docs/plugin-template/codex/package.json +0 -17
- package/docs/plugin-template/opencode/.github/workflows/build.yml +0 -61
- package/docs/plugin-template/opencode/README.md +0 -121
- package/docs/plugin-template/opencode/package.json +0 -25
- package/docs/plugin-template/opencode/src/plugin.ts +0 -6
- /package/dist/{src/mcp/tools → mcp/handlers}/artifact.d.ts +0 -0
- /package/dist/{src/mcp/tools → mcp/handlers}/history.d.ts +0 -0
- /package/dist/{src/mcp/tools → mcp/handlers}/plan.d.ts +0 -0
- /package/dist/{src/mcp/tools → mcp/handlers}/task.d.ts +0 -0
- /package/dist/{src/shared → shared}/json-store.d.ts +0 -0
- /package/dist/{src/shared → shared}/mcp-utils.d.ts +0 -0
- /package/dist/{src/shared → shared}/mcp-utils.js +0 -0
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* agent-bootstrap handler tests
|
|
3
|
-
*
|
|
4
|
-
* Scenarios:
|
|
5
|
-
* (1) fresh + registered role (assets/agents/architect exists) → additional_context contains core index + rules
|
|
6
|
-
* (2) fresh + unregistered role ("general") → silent skip (no additional_context)
|
|
7
|
-
* (3) resume_count > 0 → skip (not fresh)
|
|
8
|
-
* (4) .nexus/rules/<role>.md absent → core index only
|
|
9
|
-
* (5) core index > 2KB → truncated to recent-modified N entries
|
|
10
|
-
* (6) tracker write side-effect absent (agent-tracker.json unchanged before/after)
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
14
|
-
import { mkdtempSync, mkdirSync, writeFileSync, existsSync, readFileSync, rmSync, utimesSync } from "node:fs";
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
import { tmpdir } from "node:os";
|
|
17
|
-
|
|
18
|
-
import handler from "./handler.ts";
|
|
19
|
-
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// Fixture helpers
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
|
|
24
|
-
/** Create a temp directory tree suitable for agent-bootstrap tests.
|
|
25
|
-
* Returns the cwd (root of the fixture).
|
|
26
|
-
*
|
|
27
|
-
* Layout:
|
|
28
|
-
* <root>/
|
|
29
|
-
* assets/agents/architect/ ← registered role
|
|
30
|
-
* .nexus/memory/ ← memory .md files
|
|
31
|
-
* .nexus/context/ ← context .md files
|
|
32
|
-
* .nexus/rules/architect.md ← role rule
|
|
33
|
-
* .nexus/state/sessions/<sid>/ ← session dir (no tracker by default)
|
|
34
|
-
*/
|
|
35
|
-
function makeFixture(opts: {
|
|
36
|
-
withRule?: boolean;
|
|
37
|
-
memoryFiles?: number;
|
|
38
|
-
contextFiles?: number;
|
|
39
|
-
withTracker?: { agentId: string; resumeCount: number };
|
|
40
|
-
sessionId?: string;
|
|
41
|
-
} = {}): { cwd: string; sessionId: string; cleanup: () => void } {
|
|
42
|
-
const {
|
|
43
|
-
withRule = true,
|
|
44
|
-
memoryFiles = 1,
|
|
45
|
-
contextFiles = 1,
|
|
46
|
-
withTracker,
|
|
47
|
-
sessionId = "sess-test",
|
|
48
|
-
} = opts;
|
|
49
|
-
|
|
50
|
-
const cwd = mkdtempSync(join(tmpdir(), "nexus-bootstrap-"));
|
|
51
|
-
|
|
52
|
-
// Registered role directory
|
|
53
|
-
mkdirSync(join(cwd, "assets/agents/architect"), { recursive: true });
|
|
54
|
-
|
|
55
|
-
// Memory files
|
|
56
|
-
const memDir = join(cwd, ".nexus/memory");
|
|
57
|
-
mkdirSync(memDir, { recursive: true });
|
|
58
|
-
for (let i = 0; i < memoryFiles; i++) {
|
|
59
|
-
writeFileSync(join(memDir, `mem-${i}.md`), `# Memory file ${i}\nsome content`);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Context files
|
|
63
|
-
const ctxDir = join(cwd, ".nexus/context");
|
|
64
|
-
mkdirSync(ctxDir, { recursive: true });
|
|
65
|
-
for (let i = 0; i < contextFiles; i++) {
|
|
66
|
-
writeFileSync(join(ctxDir, `ctx-${i}.md`), `# Context file ${i}\nsome content`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Rules
|
|
70
|
-
const rulesDir = join(cwd, ".nexus/rules");
|
|
71
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
72
|
-
if (withRule) {
|
|
73
|
-
writeFileSync(join(rulesDir, "architect.md"), "Always think in systems.");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Session dir
|
|
77
|
-
const sessionDir = join(cwd, ".nexus/state", sessionId);
|
|
78
|
-
mkdirSync(sessionDir, { recursive: true });
|
|
79
|
-
|
|
80
|
-
// Optional tracker
|
|
81
|
-
if (withTracker) {
|
|
82
|
-
writeFileSync(
|
|
83
|
-
join(sessionDir, "agent-tracker.json"),
|
|
84
|
-
JSON.stringify([
|
|
85
|
-
{ agent_id: withTracker.agentId, resume_count: withTracker.resumeCount },
|
|
86
|
-
])
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
cwd,
|
|
92
|
-
sessionId,
|
|
93
|
-
cleanup: () => rmSync(cwd, { recursive: true, force: true }),
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/** Build a SubagentStart input */
|
|
98
|
-
function makeInput(
|
|
99
|
-
cwd: string,
|
|
100
|
-
sessionId: string,
|
|
101
|
-
agentType: string,
|
|
102
|
-
agentId = "agent-001"
|
|
103
|
-
) {
|
|
104
|
-
return {
|
|
105
|
-
hook_event_name: "SubagentStart" as const,
|
|
106
|
-
session_id: sessionId,
|
|
107
|
-
cwd,
|
|
108
|
-
agent_type: agentType,
|
|
109
|
-
agent_id: agentId,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ---------------------------------------------------------------------------
|
|
114
|
-
// Scenario (1): fresh + registered role → additional_context with core index + rules
|
|
115
|
-
// ---------------------------------------------------------------------------
|
|
116
|
-
|
|
117
|
-
describe("scenario 1: fresh + registered role", () => {
|
|
118
|
-
let cleanup: () => void;
|
|
119
|
-
|
|
120
|
-
afterAll(() => cleanup?.());
|
|
121
|
-
|
|
122
|
-
test("additional_context contains core index and role rule", async () => {
|
|
123
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({ withRule: true });
|
|
124
|
-
cleanup = c;
|
|
125
|
-
|
|
126
|
-
const result = await handler(makeInput(cwd, sessionId, "architect"));
|
|
127
|
-
|
|
128
|
-
expect(result).toBeDefined();
|
|
129
|
-
expect(result!.additional_context).toBeDefined();
|
|
130
|
-
const ctx = result!.additional_context!;
|
|
131
|
-
|
|
132
|
-
// Core index header
|
|
133
|
-
expect(ctx).toContain("Available memory/context:");
|
|
134
|
-
// At least one .md entry
|
|
135
|
-
expect(ctx).toMatch(/\.nexus\/(memory|context)\/.*\.md/);
|
|
136
|
-
// Role rule injection
|
|
137
|
-
expect(ctx).toContain("Custom rule for architect:");
|
|
138
|
-
expect(ctx).toContain("Always think in systems.");
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// ---------------------------------------------------------------------------
|
|
143
|
-
// Scenario (2): fresh + unregistered role → silent skip
|
|
144
|
-
// ---------------------------------------------------------------------------
|
|
145
|
-
|
|
146
|
-
describe("scenario 2: fresh + unregistered role", () => {
|
|
147
|
-
let cleanup: () => void;
|
|
148
|
-
|
|
149
|
-
afterAll(() => cleanup?.());
|
|
150
|
-
|
|
151
|
-
test("returns undefined (no additional_context) for unknown role", async () => {
|
|
152
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({ withRule: false });
|
|
153
|
-
cleanup = c;
|
|
154
|
-
|
|
155
|
-
const result = await handler(makeInput(cwd, sessionId, "general"));
|
|
156
|
-
|
|
157
|
-
// Silent skip: handler returns void / undefined
|
|
158
|
-
expect(result == null).toBe(true);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// ---------------------------------------------------------------------------
|
|
163
|
-
// Scenario (3): resume_count > 0 → skip entirely
|
|
164
|
-
// ---------------------------------------------------------------------------
|
|
165
|
-
|
|
166
|
-
describe("scenario 3: resume — skip on resume_count > 0", () => {
|
|
167
|
-
let cleanup: () => void;
|
|
168
|
-
|
|
169
|
-
afterAll(() => cleanup?.());
|
|
170
|
-
|
|
171
|
-
test("returns undefined when agent has been resumed", async () => {
|
|
172
|
-
const agentId = "agent-resume";
|
|
173
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({
|
|
174
|
-
withTracker: { agentId, resumeCount: 1 },
|
|
175
|
-
});
|
|
176
|
-
cleanup = c;
|
|
177
|
-
|
|
178
|
-
const result = await handler(makeInput(cwd, sessionId, "architect", agentId));
|
|
179
|
-
|
|
180
|
-
expect(result == null).toBe(true);
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// ---------------------------------------------------------------------------
|
|
185
|
-
// Scenario (4): no .nexus/rules/<role>.md → core index only (no rule block)
|
|
186
|
-
// ---------------------------------------------------------------------------
|
|
187
|
-
|
|
188
|
-
describe("scenario 4: no role rule file → core index only", () => {
|
|
189
|
-
let cleanup: () => void;
|
|
190
|
-
|
|
191
|
-
afterAll(() => cleanup?.());
|
|
192
|
-
|
|
193
|
-
test("additional_context has core index but no rule block", async () => {
|
|
194
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({ withRule: false });
|
|
195
|
-
cleanup = c;
|
|
196
|
-
|
|
197
|
-
const result = await handler(makeInput(cwd, sessionId, "architect"));
|
|
198
|
-
|
|
199
|
-
expect(result).toBeDefined();
|
|
200
|
-
const ctx = result!.additional_context!;
|
|
201
|
-
|
|
202
|
-
expect(ctx).toContain("Available memory/context:");
|
|
203
|
-
expect(ctx).not.toContain("Custom rule for architect:");
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
// ---------------------------------------------------------------------------
|
|
208
|
-
// Scenario (5): core index > 2KB → truncated to recent N entries
|
|
209
|
-
// ---------------------------------------------------------------------------
|
|
210
|
-
|
|
211
|
-
describe("scenario 5: 2KB truncation of core index", () => {
|
|
212
|
-
let cleanup: () => void;
|
|
213
|
-
|
|
214
|
-
afterAll(() => cleanup?.());
|
|
215
|
-
|
|
216
|
-
test("core index is truncated when total size exceeds 2KB", async () => {
|
|
217
|
-
// Create enough files to exceed 2KB.
|
|
218
|
-
// Each entry line looks like:
|
|
219
|
-
// "- .nexus/memory/mem-XX.md: Memory file XX" (~45 chars + newline)
|
|
220
|
-
// 2048 / 46 ≈ 44 entries needed; create 60 to be safe.
|
|
221
|
-
const LOTS = 60;
|
|
222
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({
|
|
223
|
-
withRule: false,
|
|
224
|
-
memoryFiles: LOTS,
|
|
225
|
-
contextFiles: 0,
|
|
226
|
-
});
|
|
227
|
-
cleanup = c;
|
|
228
|
-
|
|
229
|
-
// Spread mtimes so "recent" ordering is deterministic:
|
|
230
|
-
// give each file a distinct mtime (oldest → newest = index 0 → LOTS-1)
|
|
231
|
-
for (let i = 0; i < LOTS; i++) {
|
|
232
|
-
const filePath = join(cwd, ".nexus/memory", `mem-${i}.md`);
|
|
233
|
-
const t = new Date(Date.now() - (LOTS - i) * 10_000); // older files have smaller index
|
|
234
|
-
utimesSync(filePath, t, t);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
const result = await handler(makeInput(cwd, sessionId, "architect"));
|
|
238
|
-
|
|
239
|
-
expect(result).toBeDefined();
|
|
240
|
-
const ctx = result!.additional_context!;
|
|
241
|
-
expect(ctx).toContain("Available memory/context:");
|
|
242
|
-
|
|
243
|
-
// The raw section between <system-notice> tags for the core index
|
|
244
|
-
const indexSection = ctx.split("</system-notice>")[0];
|
|
245
|
-
|
|
246
|
-
// Should NOT contain all 60 files — truncation must have kicked in
|
|
247
|
-
const entryCount = (indexSection.match(/- \.nexus\/memory\/mem-/g) ?? []).length;
|
|
248
|
-
expect(entryCount).toBeGreaterThan(0);
|
|
249
|
-
expect(entryCount).toBeLessThan(LOTS);
|
|
250
|
-
|
|
251
|
-
// The index section must not exceed 2KB (plus small wrapper overhead)
|
|
252
|
-
const indexBytes = new TextEncoder().encode(indexSection).length;
|
|
253
|
-
// Allow a generous margin for the header line and wrapping
|
|
254
|
-
expect(indexBytes).toBeLessThan(2048 + 200);
|
|
255
|
-
});
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
// ---------------------------------------------------------------------------
|
|
259
|
-
// Scenario (6): no tracker write side-effects
|
|
260
|
-
// ---------------------------------------------------------------------------
|
|
261
|
-
|
|
262
|
-
describe("scenario 6: handler produces no file write side-effects", () => {
|
|
263
|
-
let cleanup: () => void;
|
|
264
|
-
|
|
265
|
-
afterAll(() => cleanup?.());
|
|
266
|
-
|
|
267
|
-
test("agent-tracker.json is not created or modified by handler", async () => {
|
|
268
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({ withTracker: undefined });
|
|
269
|
-
cleanup = c;
|
|
270
|
-
|
|
271
|
-
const trackerPath = join(cwd, ".nexus/state", sessionId, "agent-tracker.json");
|
|
272
|
-
|
|
273
|
-
// Tracker must not exist before the call
|
|
274
|
-
expect(existsSync(trackerPath)).toBe(false);
|
|
275
|
-
|
|
276
|
-
await handler(makeInput(cwd, sessionId, "architect"));
|
|
277
|
-
|
|
278
|
-
// Tracker must still not exist after the call
|
|
279
|
-
expect(existsSync(trackerPath)).toBe(false);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
test("pre-existing agent-tracker.json is not modified by handler", async () => {
|
|
283
|
-
const agentId = "agent-side-effect";
|
|
284
|
-
const { cwd, sessionId, cleanup: c } = makeFixture({
|
|
285
|
-
withTracker: { agentId, resumeCount: 0 },
|
|
286
|
-
});
|
|
287
|
-
cleanup = c;
|
|
288
|
-
|
|
289
|
-
const trackerPath = join(cwd, ".nexus/state", sessionId, "agent-tracker.json");
|
|
290
|
-
const before = readFileSync(trackerPath, "utf-8");
|
|
291
|
-
|
|
292
|
-
await handler(makeInput(cwd, sessionId, "architect", agentId));
|
|
293
|
-
|
|
294
|
-
const after = readFileSync(trackerPath, "utf-8");
|
|
295
|
-
expect(after).toBe(before);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// ---------------------------------------------------------------------------
|
|
300
|
-
// 모듈 전역 상태 격리
|
|
301
|
-
// ---------------------------------------------------------------------------
|
|
302
|
-
|
|
303
|
-
describe("모듈 전역 상태 격리", () => {
|
|
304
|
-
// Test A: two different cwds with different agent sets produce independent results
|
|
305
|
-
test("Test A: different cwds return only their own roles", async () => {
|
|
306
|
-
const tmpDir1 = mkdtempSync(join(tmpdir(), "nexus-isolation-a1-"));
|
|
307
|
-
const tmpDir2 = mkdtempSync(join(tmpdir(), "nexus-isolation-a2-"));
|
|
308
|
-
|
|
309
|
-
try {
|
|
310
|
-
// tmpDir1: only "architect"
|
|
311
|
-
mkdirSync(join(tmpDir1, "assets/agents/architect"), { recursive: true });
|
|
312
|
-
mkdirSync(join(tmpDir1, ".nexus/memory"), { recursive: true });
|
|
313
|
-
writeFileSync(join(tmpDir1, ".nexus/memory/mem.md"), "# mem\ncontent");
|
|
314
|
-
mkdirSync(join(tmpDir1, ".nexus/state/sess1"), { recursive: true });
|
|
315
|
-
|
|
316
|
-
// tmpDir2: only "engineer"
|
|
317
|
-
mkdirSync(join(tmpDir2, "assets/agents/engineer"), { recursive: true });
|
|
318
|
-
mkdirSync(join(tmpDir2, ".nexus/memory"), { recursive: true });
|
|
319
|
-
writeFileSync(join(tmpDir2, ".nexus/memory/mem.md"), "# mem\ncontent");
|
|
320
|
-
mkdirSync(join(tmpDir2, ".nexus/state/sess2"), { recursive: true });
|
|
321
|
-
|
|
322
|
-
// Call with tmpDir1 as architect → should return context
|
|
323
|
-
const r1a = await handler(makeInput(tmpDir1, "sess1", "architect"));
|
|
324
|
-
expect(r1a).toBeDefined();
|
|
325
|
-
|
|
326
|
-
// Call with tmpDir1 as engineer → should be skipped (engineer not in tmpDir1)
|
|
327
|
-
const r1b = await handler(makeInput(tmpDir1, "sess1", "engineer"));
|
|
328
|
-
expect(r1b == null).toBe(true);
|
|
329
|
-
|
|
330
|
-
// Call with tmpDir2 as engineer → should return context
|
|
331
|
-
const r2a = await handler(makeInput(tmpDir2, "sess2", "engineer"));
|
|
332
|
-
expect(r2a).toBeDefined();
|
|
333
|
-
|
|
334
|
-
// Call with tmpDir2 as architect → should be skipped (architect not in tmpDir2)
|
|
335
|
-
const r2b = await handler(makeInput(tmpDir2, "sess2", "architect"));
|
|
336
|
-
expect(r2b == null).toBe(true);
|
|
337
|
-
} finally {
|
|
338
|
-
rmSync(tmpDir1, { recursive: true, force: true });
|
|
339
|
-
rmSync(tmpDir2, { recursive: true, force: true });
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
// Test B: adding a new role directory is picked up on the next call
|
|
344
|
-
test("Test B: newly added role is reflected in subsequent call", async () => {
|
|
345
|
-
const tmpDir = mkdtempSync(join(tmpdir(), "nexus-isolation-b-"));
|
|
346
|
-
|
|
347
|
-
try {
|
|
348
|
-
// Start with only "architect"
|
|
349
|
-
mkdirSync(join(tmpDir, "assets/agents/architect"), { recursive: true });
|
|
350
|
-
mkdirSync(join(tmpDir, ".nexus/memory"), { recursive: true });
|
|
351
|
-
writeFileSync(join(tmpDir, ".nexus/memory/mem.md"), "# mem\ncontent");
|
|
352
|
-
mkdirSync(join(tmpDir, ".nexus/state/sess"), { recursive: true });
|
|
353
|
-
|
|
354
|
-
// "foo" does not exist yet → should be skipped
|
|
355
|
-
const r1 = await handler(makeInput(tmpDir, "sess", "foo"));
|
|
356
|
-
expect(r1 == null).toBe(true);
|
|
357
|
-
|
|
358
|
-
// Add "foo" role directory
|
|
359
|
-
mkdirSync(join(tmpDir, "assets/agents/foo"), { recursive: true });
|
|
360
|
-
|
|
361
|
-
// Now "foo" should be recognized on the next call
|
|
362
|
-
const r2 = await handler(makeInput(tmpDir, "sess", "foo"));
|
|
363
|
-
expect(r2).toBeDefined();
|
|
364
|
-
} finally {
|
|
365
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
});
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import type { HookHandler } from "../../../src/hooks/types.js";
|
|
2
|
-
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
const CORE_INDEX_SIZE_LIMIT = 2 * 1024; // 2KB
|
|
6
|
-
|
|
7
|
-
function loadValidRoles(cwd: string): string[] {
|
|
8
|
-
const agentsDir = join(cwd, "assets/agents");
|
|
9
|
-
const roles: string[] = [];
|
|
10
|
-
if (existsSync(agentsDir)) {
|
|
11
|
-
for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
12
|
-
if (entry.isDirectory()) roles.push(entry.name);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
return roles;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function readFirstLine(path: string): string {
|
|
19
|
-
try {
|
|
20
|
-
const content = readFileSync(path, "utf-8");
|
|
21
|
-
const firstNonEmpty =
|
|
22
|
-
content.split("\n").find((l) => l.trim().length > 0) ?? "";
|
|
23
|
-
return firstNonEmpty.replace(/^#+\s*/, "").slice(0, 80);
|
|
24
|
-
} catch {
|
|
25
|
-
return "";
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function buildCoreIndex(cwd: string): string {
|
|
30
|
-
const entries: Array<{ path: string; mtime: number; line: string }> = [];
|
|
31
|
-
|
|
32
|
-
for (const sub of [".nexus/memory", ".nexus/context"]) {
|
|
33
|
-
const absDir = join(cwd, sub);
|
|
34
|
-
if (!existsSync(absDir)) continue;
|
|
35
|
-
for (const f of readdirSync(absDir, { withFileTypes: true })) {
|
|
36
|
-
if (!f.isFile() || !f.name.endsWith(".md")) continue;
|
|
37
|
-
const full = join(absDir, f.name);
|
|
38
|
-
entries.push({
|
|
39
|
-
path: `${sub}/${f.name}`,
|
|
40
|
-
mtime: statSync(full).mtimeMs,
|
|
41
|
-
line: readFirstLine(full),
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
entries.sort((a, b) => b.mtime - a.mtime);
|
|
47
|
-
|
|
48
|
-
const lines: string[] = [];
|
|
49
|
-
let bytes = 0;
|
|
50
|
-
for (const e of entries) {
|
|
51
|
-
const formatted = `- ${e.path}: ${e.line}`;
|
|
52
|
-
if (bytes + formatted.length + 1 > CORE_INDEX_SIZE_LIMIT) break;
|
|
53
|
-
lines.push(formatted);
|
|
54
|
-
bytes += formatted.length + 1;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return lines.length > 0
|
|
58
|
-
? "Available memory/context:\n" + lines.join("\n")
|
|
59
|
-
: "";
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getResumeCount(
|
|
63
|
-
cwd: string,
|
|
64
|
-
sessionId: string,
|
|
65
|
-
agentId: string
|
|
66
|
-
): number {
|
|
67
|
-
const trackerPath = join(
|
|
68
|
-
cwd,
|
|
69
|
-
".nexus/state",
|
|
70
|
-
sessionId,
|
|
71
|
-
"agent-tracker.json"
|
|
72
|
-
);
|
|
73
|
-
if (!existsSync(trackerPath)) return 0;
|
|
74
|
-
try {
|
|
75
|
-
const tracker = JSON.parse(readFileSync(trackerPath, "utf-8"));
|
|
76
|
-
const entry = Array.isArray(tracker)
|
|
77
|
-
? tracker.find((e: { agent_id?: string }) => e.agent_id === agentId)
|
|
78
|
-
: null;
|
|
79
|
-
return (entry as { resume_count?: number } | null)?.resume_count ?? 0;
|
|
80
|
-
} catch {
|
|
81
|
-
return 0;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const handler: HookHandler = async (input) => {
|
|
86
|
-
if (input.hook_event_name !== "SubagentStart") return;
|
|
87
|
-
|
|
88
|
-
const { cwd, session_id, agent_type, agent_id } = input;
|
|
89
|
-
|
|
90
|
-
// fresh only — skip on resume
|
|
91
|
-
const resumeCount = getResumeCount(cwd, session_id, agent_id);
|
|
92
|
-
if (resumeCount > 0) return;
|
|
93
|
-
|
|
94
|
-
// unregistered role: silent skip
|
|
95
|
-
const validRoles = loadValidRoles(cwd);
|
|
96
|
-
if (!validRoles.includes(agent_type)) return;
|
|
97
|
-
|
|
98
|
-
const parts: string[] = [];
|
|
99
|
-
|
|
100
|
-
const coreIndex = buildCoreIndex(cwd);
|
|
101
|
-
if (coreIndex) {
|
|
102
|
-
parts.push(`<system-notice>\n${coreIndex}\n</system-notice>`);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const rulePath = join(cwd, ".nexus/rules", `${agent_type}.md`);
|
|
106
|
-
if (existsSync(rulePath)) {
|
|
107
|
-
const ruleContent = readFileSync(rulePath, "utf-8").trim();
|
|
108
|
-
if (ruleContent) {
|
|
109
|
-
parts.push(
|
|
110
|
-
`<system-notice>\nCustom rule for ${agent_type}:\n${ruleContent}\n</system-notice>`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (parts.length === 0) return;
|
|
116
|
-
return { additional_context: parts.join("\n\n") };
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
export default handler;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
name: agent-bootstrap
|
|
2
|
-
description: Inject core memory index and role-specific rules on fresh subagent spawn
|
|
3
|
-
events: [SubagentStart]
|
|
4
|
-
matcher: "*"
|
|
5
|
-
timeout: 10
|
|
6
|
-
fallback: warn
|
|
7
|
-
priority: 0
|
|
8
|
-
requires_capabilities:
|
|
9
|
-
- event.subagent_start
|
|
10
|
-
- output.additional_context.session_start
|