aios-core 4.2.15 → 4.4.0
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/.aios-core/cli/commands/validate/index.js +1 -1
- package/.aios-core/core/code-intel/code-intel-client.js +19 -5
- package/.aios-core/core/code-intel/helpers/creation-helper.js +183 -0
- package/.aios-core/core/code-intel/helpers/devops-helper.js +166 -0
- package/.aios-core/core/code-intel/helpers/planning-helper.js +248 -0
- package/.aios-core/core/code-intel/helpers/qa-helper.js +187 -0
- package/.aios-core/core/code-intel/helpers/story-helper.js +146 -0
- package/.aios-core/core/code-intel/hook-runtime.js +186 -0
- package/.aios-core/core/code-intel/index.js +2 -0
- package/.aios-core/core/code-intel/providers/code-graph-provider.js +8 -0
- package/.aios-core/core/code-intel/providers/provider-interface.js +9 -0
- package/.aios-core/core/code-intel/providers/registry-provider.js +515 -0
- package/.aios-core/core/config/schemas/framework-config.schema.json +155 -7
- package/.aios-core/core/config/schemas/project-config.schema.json +329 -15
- package/.aios-core/core/config/template-overrides.js +84 -0
- package/.aios-core/core/docs/troubleshooting-guide.md +1 -1
- package/.aios-core/core/doctor/checks/agent-memory.js +63 -0
- package/.aios-core/core/doctor/checks/claude-md.js +56 -0
- package/.aios-core/core/doctor/checks/code-intel.js +131 -0
- package/.aios-core/core/doctor/checks/commands-count.js +81 -0
- package/.aios-core/core/doctor/checks/core-config.js +53 -0
- package/.aios-core/core/doctor/checks/entity-registry.js +53 -0
- package/.aios-core/core/doctor/checks/git-hooks.js +50 -0
- package/.aios-core/core/doctor/checks/graph-dashboard.js +48 -0
- package/.aios-core/core/doctor/checks/hooks-claude-count.js +118 -0
- package/.aios-core/core/doctor/checks/ide-sync.js +85 -0
- package/.aios-core/core/doctor/checks/index.js +46 -0
- package/.aios-core/core/doctor/checks/node-version.js +33 -0
- package/.aios-core/core/doctor/checks/npm-packages.js +35 -0
- package/.aios-core/core/doctor/checks/rules-files.js +61 -0
- package/.aios-core/core/doctor/checks/settings-json.js +121 -0
- package/.aios-core/core/doctor/checks/skills-count.js +72 -0
- package/.aios-core/core/doctor/fix-handler.js +165 -0
- package/.aios-core/core/doctor/formatters/json.js +14 -0
- package/.aios-core/core/doctor/formatters/text.js +59 -0
- package/.aios-core/core/doctor/index.js +94 -0
- package/.aios-core/core/graph-dashboard/cli.js +361 -0
- package/.aios-core/core/graph-dashboard/data-sources/code-intel-source.js +234 -0
- package/.aios-core/core/graph-dashboard/data-sources/metrics-source.js +95 -0
- package/.aios-core/core/graph-dashboard/data-sources/registry-source.js +106 -0
- package/.aios-core/core/graph-dashboard/formatters/dot-formatter.js +45 -0
- package/.aios-core/core/graph-dashboard/formatters/html-formatter.js +1437 -0
- package/.aios-core/core/graph-dashboard/formatters/json-formatter.js +13 -0
- package/.aios-core/core/graph-dashboard/formatters/mermaid-formatter.js +59 -0
- package/.aios-core/core/graph-dashboard/index.js +21 -0
- package/.aios-core/core/graph-dashboard/renderers/stats-renderer.js +217 -0
- package/.aios-core/core/graph-dashboard/renderers/status-renderer.js +125 -0
- package/.aios-core/core/graph-dashboard/renderers/tree-renderer.js +119 -0
- package/.aios-core/core/health-check/base-check.js +1 -1
- package/.aios-core/core/health-check/check-registry.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/build-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/ci-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/deployment-readiness.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/docker-config.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/env-file.js +1 -1
- package/.aios-core/core/health-check/checks/deployment/index.js +1 -1
- package/.aios-core/core/health-check/checks/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/disk-space.js +1 -1
- package/.aios-core/core/health-check/checks/local/environment-vars.js +1 -1
- package/.aios-core/core/health-check/checks/local/git-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/ide-detection.js +1 -1
- package/.aios-core/core/health-check/checks/local/index.js +1 -1
- package/.aios-core/core/health-check/checks/local/memory.js +1 -1
- package/.aios-core/core/health-check/checks/local/network.js +1 -1
- package/.aios-core/core/health-check/checks/local/npm-install.js +1 -1
- package/.aios-core/core/health-check/checks/local/shell-environment.js +1 -1
- package/.aios-core/core/health-check/checks/project/agent-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/aios-directory.js +1 -1
- package/.aios-core/core/health-check/checks/project/dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/project/framework-config.js +1 -1
- package/.aios-core/core/health-check/checks/project/index.js +1 -1
- package/.aios-core/core/health-check/checks/project/node-version.js +1 -1
- package/.aios-core/core/health-check/checks/project/package-json.js +1 -1
- package/.aios-core/core/health-check/checks/project/task-definitions.js +1 -1
- package/.aios-core/core/health-check/checks/project/workflow-dependencies.js +1 -1
- package/.aios-core/core/health-check/checks/repository/branch-protection.js +1 -1
- package/.aios-core/core/health-check/checks/repository/commit-history.js +1 -1
- package/.aios-core/core/health-check/checks/repository/conflicts.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-repo.js +1 -1
- package/.aios-core/core/health-check/checks/repository/git-status.js +1 -1
- package/.aios-core/core/health-check/checks/repository/gitignore.js +1 -1
- package/.aios-core/core/health-check/checks/repository/index.js +1 -1
- package/.aios-core/core/health-check/checks/repository/large-files.js +1 -1
- package/.aios-core/core/health-check/checks/repository/lockfile-integrity.js +1 -1
- package/.aios-core/core/health-check/checks/services/api-endpoints.js +1 -1
- package/.aios-core/core/health-check/checks/services/claude-code.js +1 -1
- package/.aios-core/core/health-check/checks/services/gemini-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/github-cli.js +1 -1
- package/.aios-core/core/health-check/checks/services/index.js +1 -1
- package/.aios-core/core/health-check/checks/services/mcp-integration.js +1 -1
- package/.aios-core/core/health-check/engine.js +1 -1
- package/.aios-core/core/health-check/healers/backup-manager.js +1 -1
- package/.aios-core/core/health-check/healers/index.js +1 -1
- package/.aios-core/core/health-check/index.js +9 -2
- package/.aios-core/core/health-check/reporters/console.js +1 -1
- package/.aios-core/core/health-check/reporters/index.js +1 -1
- package/.aios-core/core/health-check/reporters/json.js +1 -1
- package/.aios-core/core/health-check/reporters/markdown.js +1 -1
- package/.aios-core/core/ids/layer-classifier.js +65 -0
- package/.aios-core/core/ids/registry-updater.js +49 -0
- package/.aios-core/core/index.esm.js +1 -1
- package/.aios-core/core/index.js +1 -1
- package/.aios-core/core/session/context-detector.js +2 -7
- package/.aios-core/core/synapse/context/context-tracker.js +9 -1
- package/.aios-core/core/synapse/engine.js +33 -13
- package/.aios-core/core/synapse/memory/memory-bridge.js +17 -43
- package/.aios-core/core/synapse/memory/synapse-memory-provider.js +201 -0
- package/.aios-core/core/synapse/runtime/hook-runtime.js +40 -2
- package/.aios-core/core/synapse/session/session-manager.js +3 -2
- package/.aios-core/core/synapse/utils/atomic-write.js +79 -0
- package/.aios-core/core-config.yaml +34 -1
- package/.aios-core/data/aios-kb.md +2 -2
- package/.aios-core/data/capability-detection.js +290 -0
- package/.aios-core/data/entity-registry.yaml +10450 -2129
- package/.aios-core/data/mcp-discipline.js +166 -0
- package/.aios-core/data/mcp-tool-examples.yaml +215 -0
- package/.aios-core/data/tok2-validation.js +168 -0
- package/.aios-core/data/tok3-token-comparison.js +123 -0
- package/.aios-core/data/tool-registry.yaml +648 -0
- package/.aios-core/data/tool-search-validation.js +174 -0
- package/.aios-core/data/workflow-chains.yaml +156 -0
- package/.aios-core/development/agents/aios-master.md +17 -10
- package/.aios-core/development/agents/analyst/MEMORY.md +33 -0
- package/.aios-core/development/agents/analyst.md +17 -10
- package/.aios-core/development/agents/architect/MEMORY.md +39 -0
- package/.aios-core/development/agents/architect.md +17 -10
- package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
- package/.aios-core/development/agents/data-engineer.md +17 -10
- package/.aios-core/development/agents/dev/MEMORY.md +46 -0
- package/.aios-core/development/agents/dev.md +18 -11
- package/.aios-core/development/agents/devops/MEMORY.md +39 -0
- package/.aios-core/development/agents/devops.md +44 -10
- package/.aios-core/development/agents/pm/MEMORY.md +38 -0
- package/.aios-core/development/agents/pm.md +17 -10
- package/.aios-core/development/agents/po/MEMORY.md +45 -0
- package/.aios-core/development/agents/po.md +17 -10
- package/.aios-core/development/agents/qa/MEMORY.md +42 -0
- package/.aios-core/development/agents/qa.md +18 -11
- package/.aios-core/development/agents/sm/MEMORY.md +31 -0
- package/.aios-core/development/agents/sm.md +17 -10
- package/.aios-core/development/agents/squad-creator.md +18 -9
- package/.aios-core/development/agents/ux/MEMORY.md +31 -0
- package/.aios-core/development/agents/ux-design-expert.md +16 -9
- package/.aios-core/development/checklists/issue-triage-checklist.md +35 -0
- package/.aios-core/development/checklists/memory-audit-checklist.md +53 -0
- package/.aios-core/development/scripts/issue-triage.js +171 -0
- package/.aios-core/development/scripts/populate-entity-registry.js +412 -19
- package/.aios-core/development/scripts/unified-activation-pipeline.js +31 -10
- package/.aios-core/development/tasks/analyze-project-structure.md +48 -0
- package/.aios-core/development/tasks/apply-qa-fixes.md +7 -0
- package/.aios-core/development/tasks/architect-analyze-impact.md +8 -1
- package/.aios-core/development/tasks/brownfield-create-epic.md +41 -0
- package/.aios-core/development/tasks/brownfield-create-story.md +7 -0
- package/.aios-core/development/tasks/build-autonomous.md +7 -0
- package/.aios-core/development/tasks/create-deep-research-prompt.md +7 -0
- package/.aios-core/development/tasks/create-doc.md +44 -0
- package/.aios-core/development/tasks/create-next-story.md +17 -0
- package/.aios-core/development/tasks/create-suite.md +7 -0
- package/.aios-core/development/tasks/dev-develop-story.md +9 -1
- package/.aios-core/development/tasks/execute-checklist.md +7 -0
- package/.aios-core/development/tasks/github-devops-github-pr-automation.md +56 -0
- package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +70 -0
- package/.aios-core/development/tasks/github-issue-triage.md +118 -0
- package/.aios-core/development/tasks/health-check.yaml +206 -171
- package/.aios-core/development/tasks/kb-mode-interaction.md +3 -3
- package/.aios-core/development/tasks/plan-create-context.md +47 -1
- package/.aios-core/development/tasks/plan-create-implementation.md +55 -0
- package/.aios-core/development/tasks/po-close-story.md +7 -0
- package/.aios-core/development/tasks/pr-automation.md +5 -5
- package/.aios-core/development/tasks/qa-create-fix-request.md +7 -0
- package/.aios-core/development/tasks/qa-fix-issues.md +7 -0
- package/.aios-core/development/tasks/qa-gate.md +56 -0
- package/.aios-core/development/tasks/qa-review-story.md +32 -1
- package/.aios-core/development/tasks/release-management.md +7 -0
- package/.aios-core/development/tasks/resolve-github-issue.md +608 -0
- package/.aios-core/development/tasks/review-contributor-pr.md +152 -0
- package/.aios-core/development/tasks/setup-llm-routing.md +1 -1
- package/.aios-core/development/tasks/spec-critique.md +8 -0
- package/.aios-core/development/tasks/spec-gather-requirements.md +7 -0
- package/.aios-core/development/tasks/spec-research-dependencies.md +4 -0
- package/.aios-core/development/tasks/spec-write-spec.md +5 -0
- package/.aios-core/development/tasks/triage-github-issues.md +356 -0
- package/.aios-core/development/tasks/validate-agents.md +4 -0
- package/.aios-core/development/tasks/validate-next-story.md +17 -0
- package/.aios-core/development/templates/agent-handoff-tmpl.yaml +48 -0
- package/.aios-core/development/templates/code-intel-integration-pattern.md +199 -0
- package/.aios-core/development/templates/ptc-entity-validation.md +113 -0
- package/.aios-core/development/templates/ptc-qa-gate.md +100 -0
- package/.aios-core/development/templates/ptc-research-aggregation.md +94 -0
- package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
- package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
- package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
- package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
- package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
- package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
- package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
- package/.aios-core/development/templates/squad/agent-template.md +11 -0
- package/.aios-core/development/templates/squad/task-template.md +21 -0
- package/.aios-core/development/templates/squad-template/LICENSE +21 -21
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +1 -1
- package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1 -1
- package/.aios-core/framework-config.yaml +8 -0
- package/.aios-core/index.esm.js +1 -1
- package/.aios-core/index.js +1 -1
- package/.aios-core/infrastructure/integrations/ai-providers/index.js +1 -1
- package/.aios-core/infrastructure/schemas/task-v3-schema.json +6 -0
- package/.aios-core/infrastructure/scripts/collect-tool-usage.js +311 -0
- package/.aios-core/infrastructure/scripts/generate-optimization-report.js +497 -0
- package/.aios-core/infrastructure/scripts/generate-settings-json.js +300 -0
- package/.aios-core/infrastructure/scripts/git-config-detector.js +65 -9
- package/.aios-core/infrastructure/scripts/ide-sync/index.js +3 -1
- package/.aios-core/infrastructure/scripts/ide-sync/transformers/github-copilot.js +184 -0
- package/.aios-core/infrastructure/scripts/repository-detector.js +3 -3
- package/.aios-core/infrastructure/templates/aios-sync.yaml.template +182 -182
- package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
- package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
- package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
- package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
- package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
- package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
- package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
- package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
- package/.aios-core/install-manifest.yaml +613 -305
- package/.aios-core/lib/build.json +1 -0
- package/.aios-core/local-config.yaml.template +71 -71
- package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
- package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
- package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
- package/.aios-core/monitor/hooks/notification.py +29 -29
- package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
- package/.aios-core/monitor/hooks/pre_compact.py +29 -29
- package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
- package/.aios-core/monitor/hooks/stop.py +29 -29
- package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
- package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
- package/.aios-core/product/templates/adr.hbs +125 -125
- package/.aios-core/product/templates/dbdr.hbs +241 -241
- package/.aios-core/product/templates/epic.hbs +212 -212
- package/.aios-core/product/templates/ide-rules/claude-rules.md +125 -0
- package/.aios-core/product/templates/pmdr.hbs +186 -186
- package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
- package/.aios-core/product/templates/prd.hbs +201 -201
- package/.aios-core/product/templates/story.hbs +263 -263
- package/.aios-core/product/templates/task.hbs +170 -170
- package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
- package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
- package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
- package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
- package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
- package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
- package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
- package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
- package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
- package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
- package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
- package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
- package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
- package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
- package/.aios-core/product/templates/tmpl-view.sql +177 -177
- package/.aios-core/scripts/pm.sh +0 -0
- package/.aios-core/user-guide.md +15 -15
- package/.aios-core/utils/filters/constants.js +10 -0
- package/.aios-core/utils/filters/content-filter.js +223 -0
- package/.aios-core/utils/filters/field-filter.js +126 -0
- package/.aios-core/utils/filters/index.js +180 -0
- package/.aios-core/utils/filters/schema-filter.js +157 -0
- package/.claude/CLAUDE.md +62 -0
- package/.claude/hooks/enforce-architecture-first.py +196 -196
- package/.claude/hooks/enforce-git-push-authority.sh +33 -0
- package/.claude/hooks/mind-clone-governance.py +192 -192
- package/.claude/hooks/read-protection.py +151 -151
- package/.claude/hooks/slug-validation.py +176 -176
- package/.claude/hooks/sql-governance.py +182 -182
- package/.claude/hooks/synapse-engine.cjs +28 -5
- package/.claude/hooks/write-path-validation.py +194 -194
- package/.claude/rules/agent-authority.md +105 -0
- package/.claude/rules/agent-handoff.md +97 -0
- package/.claude/rules/agent-memory-imports.md +15 -0
- package/.claude/rules/coderabbit-integration.md +101 -0
- package/.claude/rules/ids-principles.md +119 -0
- package/.claude/rules/story-lifecycle.md +145 -0
- package/.claude/rules/tool-examples.md +64 -0
- package/.claude/rules/tool-response-filtering.md +57 -0
- package/.claude/rules/workflow-execution.md +150 -0
- package/LICENSE +33 -33
- package/bin/aios-graph.js +9 -0
- package/bin/aios-init.js +2 -2
- package/bin/aios-minimal.js +0 -0
- package/bin/aios.js +17 -221
- package/bin/utils/detect-fsmonitor.js +70 -0
- package/bin/utils/framework-guard.js +238 -0
- package/bin/utils/validate-publish.js +108 -0
- package/package.json +6 -3
- package/packages/aios-install/bin/aios-install.js +0 -0
- package/packages/aios-install/bin/edmcp.js +0 -0
- package/packages/aios-pro-cli/bin/aios-pro.js +2 -0
- package/packages/installer/src/config/templates/core-config-template.js +25 -0
- package/packages/installer/src/installer/brownfield-upgrader.js +68 -5
- package/packages/installer/src/merger/index.js +3 -0
- package/packages/installer/src/merger/strategies/index.js +6 -0
- package/packages/installer/src/merger/strategies/yaml-merger.js +181 -0
- package/packages/installer/src/updater/index.js +4 -4
- package/packages/installer/src/wizard/i18n.js +321 -3
- package/packages/installer/src/wizard/ide-config-generator.js +173 -25
- package/packages/installer/src/wizard/index.js +119 -1
- package/packages/installer/src/wizard/pro-setup.js +137 -121
- package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +271 -0
- package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +192 -0
- package/packages/installer/tests/unit/doctor/doctor-checks.test.js +610 -0
- package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +134 -0
- package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +186 -0
- package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +309 -0
- package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +230 -0
- package/packages/installer/tests/unit/merger/strategies.test.js +2 -2
- package/packages/installer/tests/unit/merger/yaml-merger.test.js +327 -0
- package/scripts/check-markdown-links.py +352 -352
- package/scripts/dashboard-parallel-dev.sh +0 -0
- package/scripts/dashboard-parallel-phase3.sh +0 -0
- package/scripts/dashboard-parallel-phase4.sh +0 -0
- package/scripts/install-monitor-hooks.sh +0 -0
- package/scripts/package-synapse.js +2 -1
- package/pro/README.md +0 -66
- package/pro/license/degradation.js +0 -220
- package/pro/license/errors.js +0 -450
- package/pro/license/feature-gate.js +0 -354
- package/pro/license/index.js +0 -181
- package/pro/license/license-api.js +0 -651
- package/pro/license/license-cache.js +0 -523
- package/pro/license/license-crypto.js +0 -303
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
|
|
9
|
+
const CORE_CONFIG_FILE = '.aios-core/core-config.yaml';
|
|
10
|
+
const SETTINGS_FILE = '.claude/settings.json';
|
|
11
|
+
const TOOLS = ['Edit', 'Write'];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Validate that a boundary path does not escape the project root via traversal.
|
|
15
|
+
* Rejects paths containing '..' segments or absolute paths.
|
|
16
|
+
*/
|
|
17
|
+
function validateBoundaryPath(p) {
|
|
18
|
+
const segments = p.replace(/\\/g, '/').split('/');
|
|
19
|
+
if (segments.some(function(s) { return s === '..'; })) {
|
|
20
|
+
throw new Error('Path traversal detected in boundary config: ' + p);
|
|
21
|
+
}
|
|
22
|
+
if (path.isAbsolute(p)) {
|
|
23
|
+
throw new Error('Absolute path not allowed in boundary config: ' + p);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Read boundary configuration from core-config.yaml.
|
|
29
|
+
*/
|
|
30
|
+
function readBoundaryConfig(projectRoot) {
|
|
31
|
+
const configPath = path.join(projectRoot, CORE_CONFIG_FILE);
|
|
32
|
+
|
|
33
|
+
if (!fs.existsSync(configPath)) {
|
|
34
|
+
throw new Error(`core-config.yaml not found at ${configPath}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
38
|
+
const config = yaml.load(content);
|
|
39
|
+
|
|
40
|
+
if (!config || !config.boundary) {
|
|
41
|
+
throw new Error('core-config.yaml missing "boundary" section');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const { boundary } = config;
|
|
45
|
+
|
|
46
|
+
const result = {
|
|
47
|
+
frameworkProtection: boundary.frameworkProtection !== false,
|
|
48
|
+
protected: Array.isArray(boundary.protected) ? boundary.protected : [],
|
|
49
|
+
exceptions: Array.isArray(boundary.exceptions) ? boundary.exceptions : [],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
for (const p of result.protected) { validateBoundaryPath(p); }
|
|
53
|
+
for (const p of result.exceptions) { validateBoundaryPath(p); }
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Check if an exception path falls within a given directory.
|
|
60
|
+
*/
|
|
61
|
+
function isChildOf(exceptionPath, parentDir) {
|
|
62
|
+
const clean = exceptionPath.replace(/\/\*\*$/, '');
|
|
63
|
+
const parts = clean.split('/');
|
|
64
|
+
const parentParts = parentDir.split('/');
|
|
65
|
+
|
|
66
|
+
if (parts.length <= parentParts.length) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < parentParts.length; i++) {
|
|
71
|
+
if (parts[i] !== parentParts[i]) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Expand a directory one level deep into subdirectory/** and file entries.
|
|
81
|
+
* Returns { dirs: [...], files: [...] } sorted separately.
|
|
82
|
+
*/
|
|
83
|
+
function expandOneLevel(dirRelative, projectRoot) {
|
|
84
|
+
const dirAbsolute = path.join(projectRoot, dirRelative);
|
|
85
|
+
|
|
86
|
+
if (!fs.existsSync(dirAbsolute)) {
|
|
87
|
+
return { dirs: [dirRelative + '/**'], files: [] };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const entries = fs.readdirSync(dirAbsolute, { withFileTypes: true });
|
|
91
|
+
const dirs = [];
|
|
92
|
+
const files = [];
|
|
93
|
+
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const entryRelative = dirRelative + '/' + entry.name;
|
|
96
|
+
if (entry.isDirectory()) {
|
|
97
|
+
dirs.push(entryRelative);
|
|
98
|
+
} else {
|
|
99
|
+
files.push(entryRelative);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
dirs.sort();
|
|
104
|
+
files.sort();
|
|
105
|
+
|
|
106
|
+
return { dirs, files };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* For a subdirectory that has exceptions inside it, expand to individual
|
|
111
|
+
* file-level deny rules excluding files/dirs covered by exceptions.
|
|
112
|
+
*/
|
|
113
|
+
function expandSubdirWithExceptions(subdirPath, exceptions, projectRoot) {
|
|
114
|
+
const dirAbsolute = path.join(projectRoot, subdirPath);
|
|
115
|
+
|
|
116
|
+
if (!fs.existsSync(dirAbsolute)) {
|
|
117
|
+
return [subdirPath + '/**'];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const entries = fs.readdirSync(dirAbsolute, { withFileTypes: true });
|
|
121
|
+
const result = [];
|
|
122
|
+
|
|
123
|
+
for (const entry of entries) {
|
|
124
|
+
const entryRelative = subdirPath + '/' + entry.name;
|
|
125
|
+
const entryGlob = entry.isDirectory() ? entryRelative + '/**' : entryRelative;
|
|
126
|
+
|
|
127
|
+
const isCoveredByException = exceptions.some(function(exc) {
|
|
128
|
+
return exc === entryGlob || exc === entryRelative;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
if (!isCoveredByException) {
|
|
132
|
+
result.push(entryGlob);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
result.sort();
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Expand protected paths according to the specific rules:
|
|
142
|
+
* - .aios-core/core/** gets expanded one level deep
|
|
143
|
+
* - Subdirs with exceptions inside get expanded further (file-level)
|
|
144
|
+
* - Order: regular subdirs first (sorted), then root files (sorted),
|
|
145
|
+
* then exception-expanded subdirs (sorted) at the end
|
|
146
|
+
* - All other paths stay as-is (no expansion)
|
|
147
|
+
*/
|
|
148
|
+
function expandProtectedPaths(protectedPaths, exceptions, projectRoot) {
|
|
149
|
+
const allPaths = [];
|
|
150
|
+
|
|
151
|
+
for (const globPath of protectedPaths) {
|
|
152
|
+
if (globPath === '.aios-core/core/**') {
|
|
153
|
+
const { dirs, files } = expandOneLevel('.aios-core/core', projectRoot);
|
|
154
|
+
|
|
155
|
+
// Separate dirs into regular (no exceptions inside) and special (has exceptions)
|
|
156
|
+
const regularDirs = [];
|
|
157
|
+
const specialDirEntries = [];
|
|
158
|
+
|
|
159
|
+
for (const dir of dirs) {
|
|
160
|
+
const relevantExceptions = exceptions.filter(function(exc) {
|
|
161
|
+
return isChildOf(exc, dir);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (relevantExceptions.length > 0) {
|
|
165
|
+
// Expand this dir further, excluding exceptions
|
|
166
|
+
const expanded = expandSubdirWithExceptions(dir, relevantExceptions, projectRoot);
|
|
167
|
+
specialDirEntries.push(...expanded);
|
|
168
|
+
} else {
|
|
169
|
+
regularDirs.push(dir + '/**');
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Order: regular subdirs, then root files, then special-expanded entries
|
|
174
|
+
allPaths.push(...regularDirs);
|
|
175
|
+
allPaths.push(...files);
|
|
176
|
+
allPaths.push(...specialDirEntries);
|
|
177
|
+
} else {
|
|
178
|
+
allPaths.push(globPath);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return allPaths;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Keep exception paths as-is (no expansion needed).
|
|
187
|
+
*/
|
|
188
|
+
function expandExceptionPaths(exceptionPaths) {
|
|
189
|
+
return [...exceptionPaths].sort();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Generate permissions object from boundary config.
|
|
194
|
+
*/
|
|
195
|
+
function generatePermissions(boundary, projectRoot) {
|
|
196
|
+
if (!boundary.frameworkProtection) {
|
|
197
|
+
return { deny: [], allow: [] };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const denyPaths = expandProtectedPaths(boundary.protected, boundary.exceptions, projectRoot);
|
|
201
|
+
|
|
202
|
+
const deny = [];
|
|
203
|
+
for (const denyPath of denyPaths) {
|
|
204
|
+
for (const tool of TOOLS) {
|
|
205
|
+
deny.push(tool + '(' + denyPath + ')');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const allowPaths = expandExceptionPaths(boundary.exceptions);
|
|
210
|
+
|
|
211
|
+
const allow = [];
|
|
212
|
+
for (const allowPath of allowPaths) {
|
|
213
|
+
for (const tool of TOOLS) {
|
|
214
|
+
allow.push(tool + '(' + allowPath + ')');
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
allow.push('Read(.aios-core/**)');
|
|
219
|
+
|
|
220
|
+
return { deny, allow };
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Write settings.json preserving user sections outside permissions.
|
|
225
|
+
*/
|
|
226
|
+
function writeSettingsJson(projectRoot, permissions) {
|
|
227
|
+
const claudeDir = path.join(projectRoot, '.claude');
|
|
228
|
+
const fullSettingsPath = path.join(projectRoot, SETTINGS_FILE);
|
|
229
|
+
|
|
230
|
+
if (!fs.existsSync(claudeDir)) {
|
|
231
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let existing = {};
|
|
235
|
+
if (fs.existsSync(fullSettingsPath)) {
|
|
236
|
+
try {
|
|
237
|
+
const content = fs.readFileSync(fullSettingsPath, 'utf8');
|
|
238
|
+
existing = JSON.parse(content);
|
|
239
|
+
} catch {
|
|
240
|
+
console.warn('WARNING: Existing settings.json is invalid JSON, starting fresh.');
|
|
241
|
+
existing = {};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const updated = { ...existing };
|
|
246
|
+
|
|
247
|
+
if (permissions.deny.length > 0 || permissions.allow.length > 0) {
|
|
248
|
+
updated.permissions = permissions;
|
|
249
|
+
} else {
|
|
250
|
+
delete updated.permissions;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const newContent = JSON.stringify(updated, null, 2) + '\n';
|
|
254
|
+
|
|
255
|
+
if (fs.existsSync(fullSettingsPath)) {
|
|
256
|
+
const currentContent = fs.readFileSync(fullSettingsPath, 'utf8');
|
|
257
|
+
if (currentContent === newContent) {
|
|
258
|
+
console.log('PASS: settings.json already up to date, no changes needed.');
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fs.writeFileSync(fullSettingsPath, newContent, 'utf8');
|
|
264
|
+
console.log('PASS: settings.json updated with ' + permissions.deny.length + ' deny rules and ' + permissions.allow.length + ' allow rules.');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Main generator entry point.
|
|
269
|
+
*/
|
|
270
|
+
function generate(projectRoot, configOverride) {
|
|
271
|
+
const root = projectRoot || process.cwd();
|
|
272
|
+
const resolvedRoot = path.resolve(root);
|
|
273
|
+
|
|
274
|
+
const boundary = configOverride || readBoundaryConfig(resolvedRoot);
|
|
275
|
+
const permissions = generatePermissions(boundary, resolvedRoot);
|
|
276
|
+
|
|
277
|
+
writeSettingsJson(resolvedRoot, permissions);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (require.main === module) {
|
|
281
|
+
const projectRoot = process.argv[2] || process.cwd();
|
|
282
|
+
try {
|
|
283
|
+
generate(projectRoot);
|
|
284
|
+
} catch (error) {
|
|
285
|
+
console.error('ERROR: ' + error.message);
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
module.exports = {
|
|
291
|
+
generate,
|
|
292
|
+
validateBoundaryPath,
|
|
293
|
+
readBoundaryConfig,
|
|
294
|
+
expandProtectedPaths,
|
|
295
|
+
expandExceptionPaths,
|
|
296
|
+
expandOneLevel,
|
|
297
|
+
expandSubdirWithExceptions,
|
|
298
|
+
generatePermissions,
|
|
299
|
+
writeSettingsJson,
|
|
300
|
+
};
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const { execSync } = require('child_process');
|
|
15
|
+
const fs = require('fs');
|
|
16
|
+
const path = require('path');
|
|
15
17
|
|
|
16
18
|
const DEFAULT_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
17
19
|
const GIT_TIMEOUT = 1000; // 1 second
|
|
@@ -113,25 +115,79 @@ class GitConfigDetector {
|
|
|
113
115
|
* @returns {boolean} True if git repository
|
|
114
116
|
*/
|
|
115
117
|
_isGitRepository() {
|
|
118
|
+
// NOG-18: Replace execSync (~34ms) with synchronous fs check (~0.05ms).
|
|
119
|
+
// .git/HEAD exists in normal repos AND worktrees (as file or via gitdir link).
|
|
116
120
|
try {
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}).trim();
|
|
122
|
-
|
|
123
|
-
return output === 'true';
|
|
124
|
-
} catch (error) {
|
|
121
|
+
const gitPath = path.join(process.cwd(), '.git');
|
|
122
|
+
// .git can be a directory (normal repo) or a file (worktree with "gitdir:" pointer)
|
|
123
|
+
return fs.existsSync(gitPath);
|
|
124
|
+
} catch {
|
|
125
125
|
return false;
|
|
126
126
|
}
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
* Get current git branch name
|
|
130
|
+
* Get current git branch name via direct .git/HEAD file read.
|
|
131
|
+
* Fallback chain: .git/HEAD read → worktree/gitfile resolution → execSync.
|
|
131
132
|
* @private
|
|
132
133
|
* @returns {string|null} Branch name or null
|
|
133
134
|
*/
|
|
134
135
|
_getCurrentBranch() {
|
|
136
|
+
const direct = this._detectBranchDirect();
|
|
137
|
+
if (direct !== undefined) return direct;
|
|
138
|
+
|
|
139
|
+
// Fallback: execSync (slow but reliable)
|
|
140
|
+
return this._getCurrentBranchExec();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Read branch directly from .git/HEAD file (~0.06ms vs ~52ms for execSync).
|
|
145
|
+
* Handles: normal branch, detached HEAD, worktree/gitfile.
|
|
146
|
+
* @private
|
|
147
|
+
* @returns {string|null|undefined} Branch name, null (detached/no-git), or undefined (needs fallback)
|
|
148
|
+
*/
|
|
149
|
+
_detectBranchDirect() {
|
|
150
|
+
try {
|
|
151
|
+
const gitPath = path.join(process.cwd(), '.git');
|
|
152
|
+
const stat = fs.statSync(gitPath);
|
|
153
|
+
|
|
154
|
+
let headPath;
|
|
155
|
+
if (stat.isFile()) {
|
|
156
|
+
// Worktree/gitfile: .git is a file with "gitdir: <path>"
|
|
157
|
+
const gitContent = fs.readFileSync(gitPath, 'utf8').trim();
|
|
158
|
+
const match = gitContent.match(/^gitdir:\s*(.+)$/);
|
|
159
|
+
if (!match) return undefined;
|
|
160
|
+
const gitDir = path.resolve(process.cwd(), match[1]);
|
|
161
|
+
headPath = path.join(gitDir, 'HEAD');
|
|
162
|
+
} else {
|
|
163
|
+
headPath = path.join(gitPath, 'HEAD');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const headContent = fs.readFileSync(headPath, 'utf8').trim();
|
|
167
|
+
|
|
168
|
+
// Normal branch: "ref: refs/heads/feat/my-branch"
|
|
169
|
+
const refMatch = headContent.match(/^ref:\s*refs\/heads\/(.+)$/);
|
|
170
|
+
if (refMatch) return refMatch[1];
|
|
171
|
+
|
|
172
|
+
// Detached HEAD: raw commit hash
|
|
173
|
+
if (/^[0-9a-f]{40}$/.test(headContent)) {
|
|
174
|
+
return headContent.substring(0, 7) + ' (detached)';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return undefined; // Unexpected format — fallback
|
|
178
|
+
} catch (_err) {
|
|
179
|
+
// File not found or permission error — could be no .git dir
|
|
180
|
+
if (_err.code === 'ENOENT') return null;
|
|
181
|
+
return undefined; // Other error — fallback
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Fallback: get branch via execSync (original method).
|
|
187
|
+
* @private
|
|
188
|
+
* @returns {string|null} Branch name or null
|
|
189
|
+
*/
|
|
190
|
+
_getCurrentBranchExec() {
|
|
135
191
|
try {
|
|
136
192
|
const branch = execSync('git branch --show-current', {
|
|
137
193
|
encoding: 'utf8',
|
|
@@ -30,6 +30,7 @@ const { syncGeminiCommands, buildGeminiCommandFiles } = require('./gemini-comman
|
|
|
30
30
|
const claudeCodeTransformer = require('./transformers/claude-code');
|
|
31
31
|
const cursorTransformer = require('./transformers/cursor');
|
|
32
32
|
const antigravityTransformer = require('./transformers/antigravity');
|
|
33
|
+
const githubCopilotTransformer = require('./transformers/github-copilot');
|
|
33
34
|
|
|
34
35
|
// ANSI colors for output
|
|
35
36
|
const colors = {
|
|
@@ -74,7 +75,7 @@ function loadConfig(projectRoot) {
|
|
|
74
75
|
'github-copilot': {
|
|
75
76
|
enabled: true,
|
|
76
77
|
path: '.github/agents',
|
|
77
|
-
format: '
|
|
78
|
+
format: 'github-copilot',
|
|
78
79
|
},
|
|
79
80
|
cursor: {
|
|
80
81
|
enabled: true,
|
|
@@ -126,6 +127,7 @@ function getTransformer(format) {
|
|
|
126
127
|
'full-markdown-yaml': claudeCodeTransformer,
|
|
127
128
|
'condensed-rules': cursorTransformer,
|
|
128
129
|
'cursor-style': antigravityTransformer,
|
|
130
|
+
'github-copilot': githubCopilotTransformer,
|
|
129
131
|
};
|
|
130
132
|
|
|
131
133
|
return transformers[format] || claudeCodeTransformer;
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Copilot Transformer - YAML frontmatter + condensed markdown
|
|
3
|
+
* @story 6.19 - IDE Command Auto-Sync System
|
|
4
|
+
* @issue #138 - Agent files not compatible with GitHub Copilot
|
|
5
|
+
*
|
|
6
|
+
* Format: .agent.md files with YAML frontmatter (--- delimiters)
|
|
7
|
+
* Target: .github/agents/*.agent.md
|
|
8
|
+
*
|
|
9
|
+
* GitHub Copilot custom agents require:
|
|
10
|
+
* - YAML frontmatter with `description` (required), `name`, `tools`
|
|
11
|
+
* - Markdown body under 30,000 characters
|
|
12
|
+
* - File extension: .agent.md
|
|
13
|
+
*
|
|
14
|
+
* @see https://docs.github.com/en/copilot/reference/custom-agents-configuration
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { normalizeCommands, getVisibleCommands } = require('../agent-parser');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Transform agent data to GitHub Copilot custom agent format
|
|
21
|
+
* @param {object} agentData - Parsed agent data from agent-parser
|
|
22
|
+
* @returns {string} - Transformed content with YAML frontmatter
|
|
23
|
+
*/
|
|
24
|
+
function transform(agentData) {
|
|
25
|
+
const agent = agentData.agent || {};
|
|
26
|
+
const persona = agentData.persona_profile || {};
|
|
27
|
+
const yamlData = agentData.yaml || {};
|
|
28
|
+
const personaBlock = yamlData.persona || {};
|
|
29
|
+
|
|
30
|
+
const id = agent.id || agentData.id;
|
|
31
|
+
const name = agent.name || id;
|
|
32
|
+
const title = agent.title || 'AIOS Agent';
|
|
33
|
+
const icon = agent.icon || '';
|
|
34
|
+
const description = escapeYamlString(agent.whenToUse || `${title} agent for development tasks`);
|
|
35
|
+
|
|
36
|
+
// Build YAML frontmatter
|
|
37
|
+
const frontmatter = [
|
|
38
|
+
'---',
|
|
39
|
+
`name: ${id}`,
|
|
40
|
+
`description: '${description}'`,
|
|
41
|
+
`tools: ['read', 'edit', 'search', 'execute']`,
|
|
42
|
+
'---',
|
|
43
|
+
].join('\n');
|
|
44
|
+
|
|
45
|
+
// Build markdown body
|
|
46
|
+
const body = buildMarkdownBody({
|
|
47
|
+
id,
|
|
48
|
+
name,
|
|
49
|
+
title,
|
|
50
|
+
icon,
|
|
51
|
+
personaBlock,
|
|
52
|
+
persona,
|
|
53
|
+
commands: agentData.commands || [],
|
|
54
|
+
sections: agentData.sections || {},
|
|
55
|
+
corePrinciples: yamlData.core_principles,
|
|
56
|
+
filename: agentData.filename,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const content = `${frontmatter}\n\n${body}`;
|
|
60
|
+
|
|
61
|
+
// Enforce 30K character limit
|
|
62
|
+
if (content.length > 30000) {
|
|
63
|
+
return truncateContent(content, 30000);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return content;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Build the markdown body for the Copilot agent prompt
|
|
71
|
+
* @param {object} params - Agent parameters
|
|
72
|
+
* @returns {string} - Markdown body
|
|
73
|
+
*/
|
|
74
|
+
function buildMarkdownBody(params) {
|
|
75
|
+
const { id, name, title, icon, personaBlock, persona, commands, sections, filename } = params;
|
|
76
|
+
|
|
77
|
+
const parts = [];
|
|
78
|
+
|
|
79
|
+
// Header
|
|
80
|
+
const headerIcon = icon ? `${icon} ` : '';
|
|
81
|
+
parts.push(`# ${headerIcon}${name} Agent (@${id})\n`);
|
|
82
|
+
|
|
83
|
+
// Role description
|
|
84
|
+
if (personaBlock.role) {
|
|
85
|
+
parts.push(`You are an expert ${personaBlock.role}.\n`);
|
|
86
|
+
} else {
|
|
87
|
+
parts.push(`You are an expert ${title}.\n`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Style
|
|
91
|
+
if (personaBlock.style) {
|
|
92
|
+
parts.push(`## Style\n\n${personaBlock.style}\n`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Core principles (may be in persona block or at root level of YAML)
|
|
96
|
+
const corePrinciples = personaBlock.core_principles || params.corePrinciples;
|
|
97
|
+
if (corePrinciples && Array.isArray(corePrinciples)) {
|
|
98
|
+
parts.push('## Core Principles\n');
|
|
99
|
+
for (const principle of corePrinciples) {
|
|
100
|
+
// Handle both string and object formats (YAML may parse "KEY: value" as {KEY: value})
|
|
101
|
+
if (typeof principle === 'string') {
|
|
102
|
+
parts.push(`- ${principle}`);
|
|
103
|
+
} else if (typeof principle === 'object' && principle !== null) {
|
|
104
|
+
const entries = Object.entries(principle);
|
|
105
|
+
for (const [key, value] of entries) {
|
|
106
|
+
parts.push(`- ${key}: ${value}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
parts.push('');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Commands reference
|
|
114
|
+
const allCommands = normalizeCommands(commands);
|
|
115
|
+
const keyCommands = getVisibleCommands(allCommands, 'key');
|
|
116
|
+
const quickCommands = getVisibleCommands(allCommands, 'quick');
|
|
117
|
+
const displayCommands = keyCommands.length > 0 ? keyCommands : quickCommands.slice(0, 10);
|
|
118
|
+
|
|
119
|
+
if (displayCommands.length > 0) {
|
|
120
|
+
parts.push('## Commands\n');
|
|
121
|
+
parts.push('Use `*` prefix for commands:\n');
|
|
122
|
+
for (const cmd of displayCommands) {
|
|
123
|
+
parts.push(`- \`*${cmd.name}\` - ${cmd.description || 'No description'}`);
|
|
124
|
+
}
|
|
125
|
+
parts.push('');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Collaboration section (condensed)
|
|
129
|
+
if (sections.collaboration) {
|
|
130
|
+
parts.push(`## Collaboration\n\n${sections.collaboration}\n`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Sync footer
|
|
134
|
+
parts.push('---');
|
|
135
|
+
parts.push(`*AIOS Agent - Synced from .aios-core/development/agents/${filename}*`);
|
|
136
|
+
parts.push('');
|
|
137
|
+
|
|
138
|
+
return parts.join('\n');
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Escape a string for use as a YAML single-quoted value
|
|
143
|
+
* Single quotes inside the string must be doubled
|
|
144
|
+
* @param {string} str - Input string
|
|
145
|
+
* @returns {string} - Escaped string
|
|
146
|
+
*/
|
|
147
|
+
function escapeYamlString(str) {
|
|
148
|
+
if (!str) return '';
|
|
149
|
+
// In YAML single-quoted strings, single quotes are escaped by doubling them
|
|
150
|
+
return str.replace(/'/g, "''");
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Truncate content to fit within character limit while keeping structure valid
|
|
155
|
+
* @param {string} content - Full content
|
|
156
|
+
* @param {number} maxChars - Maximum characters
|
|
157
|
+
* @returns {string} - Truncated content
|
|
158
|
+
*/
|
|
159
|
+
function truncateContent(content, maxChars) {
|
|
160
|
+
// Find the last complete section before the limit
|
|
161
|
+
const truncated = content.substring(0, maxChars - 100);
|
|
162
|
+
const lastNewline = truncated.lastIndexOf('\n\n');
|
|
163
|
+
|
|
164
|
+
if (lastNewline > 0) {
|
|
165
|
+
return truncated.substring(0, lastNewline) + '\n\n---\n*Content truncated to fit 30K limit*\n';
|
|
166
|
+
}
|
|
167
|
+
return truncated + '\n\n---\n*Content truncated to fit 30K limit*\n';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get the target filename for this agent (with .agent.md extension)
|
|
172
|
+
* @param {object} agentData - Parsed agent data
|
|
173
|
+
* @returns {string} - Target filename (e.g., "dev.agent.md")
|
|
174
|
+
*/
|
|
175
|
+
function getFilename(agentData) {
|
|
176
|
+
const id = (agentData.agent && agentData.agent.id) || agentData.id;
|
|
177
|
+
return `${id}.agent.md`;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = {
|
|
181
|
+
transform,
|
|
182
|
+
getFilename,
|
|
183
|
+
format: 'github-copilot',
|
|
184
|
+
};
|
|
@@ -36,11 +36,11 @@ function detectRepositoryContext() {
|
|
|
36
36
|
|
|
37
37
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
38
38
|
|
|
39
|
-
// Detect if we're in
|
|
39
|
+
// Detect if we're in aios-core repo itself
|
|
40
40
|
const isFrameworkRepo =
|
|
41
41
|
packageJson.name === '@aios/fullstack' ||
|
|
42
|
-
packageJson.name === '
|
|
43
|
-
remoteUrl.includes('
|
|
42
|
+
packageJson.name === 'aios-core' ||
|
|
43
|
+
remoteUrl.includes('aios-core');
|
|
44
44
|
|
|
45
45
|
// Load installation config if exists
|
|
46
46
|
let installConfig = null;
|