codetrellis 0.0.0-stage → 0.3.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/LICENSE +201 -0
- package/README.md +27 -2
- package/bin/codetrellis.mjs +4 -0
- package/package.json +41 -4
- package/reader/material-reader.mjs +130346 -0
- package/resources/tree-sitter/README.md +150 -0
- package/resources/tree-sitter/tree-sitter-c-sharp.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-go.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-java.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-javascript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-kotlin.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-php.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-python.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-ruby.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-rust.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-swift.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-tsx.wasm +0 -0
- package/resources/tree-sitter/tree-sitter-typescript.wasm +0 -0
- package/resources/tree-sitter/tree-sitter.wasm +0 -0
- package/src/backend/agent/claude-code-watcher.js +270 -0
- package/src/backend/index.js +8 -0
- package/src/backend/lib/sha256-file.js +39 -0
- package/src/backend/lib/zip-entries.js +98 -0
- package/src/backend/lifecycle.js +102 -0
- package/src/backend/mcp/binding-headers.js +54 -0
- package/src/backend/mcp/client-identity.js +44 -0
- package/src/backend/mcp/connector/command.js +110 -0
- package/src/backend/mcp/connector/core.js +278 -0
- package/src/backend/mcp/connector/files.js +121 -0
- package/src/backend/mcp/connector/hook.js +284 -0
- package/src/backend/mcp/connector/main.js +126 -0
- package/src/backend/mcp/connector/sse-upstream.js +152 -0
- package/src/backend/mcp/helpers.js +43 -0
- package/src/backend/mcp/prompt-builders.js +104 -0
- package/src/backend/mcp/resources.js +197 -0
- package/src/backend/mcp/server.js +813 -0
- package/src/backend/mcp/skill-guide.js +1528 -0
- package/src/backend/mcp/tools/architecture-tools.js +273 -0
- package/src/backend/mcp/tools/audio-tools.js +117 -0
- package/src/backend/mcp/tools/awareness-tools.js +623 -0
- package/src/backend/mcp/tools/budget-tools.js +185 -0
- package/src/backend/mcp/tools/channel-tools.js +205 -0
- package/src/backend/mcp/tools/contribution-tools.js +181 -0
- package/src/backend/mcp/tools/drift-tools.js +252 -0
- package/src/backend/mcp/tools/git-tools.js +316 -0
- package/src/backend/mcp/tools/governance-tools.js +175 -0
- package/src/backend/mcp/tools/graph-tools.js +181 -0
- package/src/backend/mcp/tools/intake-tools.js +244 -0
- package/src/backend/mcp/tools/mobile-tools.js +118 -0
- package/src/backend/mcp/tools/peer-tools.js +330 -0
- package/src/backend/mcp/tools/plan-item-tools.js +1601 -0
- package/src/backend/mcp/tools/plan-tools.js +680 -0
- package/src/backend/mcp/tools/presence-tools.js +185 -0
- package/src/backend/mcp/tools/project-config-tools.js +150 -0
- package/src/backend/mcp/tools/review-tools.js +172 -0
- package/src/backend/mcp/tools/session-tools.js +554 -0
- package/src/backend/mcp/tools/system-docs-tools.js +168 -0
- package/src/backend/mcp/tools/terminal-tools.js +186 -0
- package/src/backend/mcp/tools/test-tools.js +117 -0
- package/src/backend/mcp/tools/ui-tools.js +356 -0
- package/src/backend/mcp/types.js +15 -0
- package/src/backend/middleware/local-auth.js +116 -0
- package/src/backend/server.js +5951 -0
- package/src/backend/services/agent-event-log.js +350 -0
- package/src/backend/services/architecture-rule.js +584 -0
- package/src/backend/services/architecture-rules.js +275 -0
- package/src/backend/services/artefact-content-service.js +181 -0
- package/src/backend/services/artefact-service.js +305 -0
- package/src/backend/services/artefact-watcher.js +167 -0
- package/src/backend/services/ast-parser.js +327 -0
- package/src/backend/services/audio-buffer-service.js +152 -0
- package/src/backend/services/awareness-notices.js +139 -0
- package/src/backend/services/awareness-replies.js +194 -0
- package/src/backend/services/awareness-service.js +344 -0
- package/src/backend/services/awareness-signals.js +267 -0
- package/src/backend/services/baseline-store.js +83 -0
- package/src/backend/services/branch-workstreams.js +341 -0
- package/src/backend/services/breakpoint-service.js +584 -0
- package/src/backend/services/brief-service.js +299 -0
- package/src/backend/services/budget-service.js +528 -0
- package/src/backend/services/callsites/base.js +15 -0
- package/src/backend/services/callsites/csharp.js +148 -0
- package/src/backend/services/callsites/go.js +163 -0
- package/src/backend/services/callsites/index.js +53 -0
- package/src/backend/services/callsites/kotlin.js +123 -0
- package/src/backend/services/callsites/process-env.js +125 -0
- package/src/backend/services/callsites/python.js +91 -0
- package/src/backend/services/callsites/ruby.js +164 -0
- package/src/backend/services/callsites/shared.js +198 -0
- package/src/backend/services/callsites/swift.js +115 -0
- package/src/backend/services/callsites/typescript.js +87 -0
- package/src/backend/services/capability-token.js +108 -0
- package/src/backend/services/change-check.js +156 -0
- package/src/backend/services/channel-dispatcher-service.js +235 -0
- package/src/backend/services/channel-event-file-service.js +125 -0
- package/src/backend/services/channel-event-service.js +297 -0
- package/src/backend/services/check-runs.js +177 -0
- package/src/backend/services/checkout-identity.js +73 -0
- package/src/backend/services/claude-code-parallel.js +221 -0
- package/src/backend/services/claude-desktop-config.js +186 -0
- package/src/backend/services/cli-install.js +249 -0
- package/src/backend/services/clock.js +57 -0
- package/src/backend/services/cloud-files.js +191 -0
- package/src/backend/services/coalesce.js +50 -0
- package/src/backend/services/code-breakpoints.js +291 -0
- package/src/backend/services/comment-service.js +168 -0
- package/src/backend/services/commit-attribution.js +134 -0
- package/src/backend/services/commit-edges.js +99 -0
- package/src/backend/services/confined-fs.js +241 -0
- package/src/backend/services/conformity-gate.js +132 -0
- package/src/backend/services/contribution-service.js +409 -0
- package/src/backend/services/coverage-service.js +173 -0
- package/src/backend/services/criteria-service.js +721 -0
- package/src/backend/services/criterion-checks.js +387 -0
- package/src/backend/services/criterion-loop-service.js +411 -0
- package/src/backend/services/cross-system-service.js +231 -0
- package/src/backend/services/database.js +916 -0
- package/src/backend/services/db-schema.js +1358 -0
- package/src/backend/services/deviation-service.js +344 -0
- package/src/backend/services/diff-engine.js +168 -0
- package/src/backend/services/evidence.js +363 -0
- package/src/backend/services/external-intake-service.js +269 -0
- package/src/backend/services/external-pointer-service.js +195 -0
- package/src/backend/services/external-refs-service.js +214 -0
- package/src/backend/services/file-history.js +158 -0
- package/src/backend/services/file-watcher.js +193 -0
- package/src/backend/services/folder-requests.js +118 -0
- package/src/backend/services/freeze-service.js +189 -0
- package/src/backend/services/gemini-cli-hook.js +172 -0
- package/src/backend/services/git-activity-service.js +325 -0
- package/src/backend/services/git-blobs.js +70 -0
- package/src/backend/services/git-branches.js +357 -0
- package/src/backend/services/git-checkout.js +153 -0
- package/src/backend/services/git-commit-service.js +91 -0
- package/src/backend/services/git-env.js +121 -0
- package/src/backend/services/git-identity.js +84 -0
- package/src/backend/services/git-refs.js +386 -0
- package/src/backend/services/git-safety.js +58 -0
- package/src/backend/services/grant-guard.js +67 -0
- package/src/backend/services/html-view-policy.js +135 -0
- package/src/backend/services/human-decision.js +55 -0
- package/src/backend/services/importers.js +159 -0
- package/src/backend/services/intent-service.js +105 -0
- package/src/backend/services/ipc-dispatcher.js +164 -0
- package/src/backend/services/item-git-state.js +208 -0
- package/src/backend/services/line-changes.js +232 -0
- package/src/backend/services/line-history.js +174 -0
- package/src/backend/services/local-api-changes.js +40 -0
- package/src/backend/services/logger.js +217 -0
- package/src/backend/services/material-footprints.js +203 -0
- package/src/backend/services/material-place.js +82 -0
- package/src/backend/services/material-reader/docx-markdown.js +198 -0
- package/src/backend/services/material-reader/fixtures.test-helper.js +169 -0
- package/src/backend/services/material-reader/quote.js +44 -0
- package/src/backend/services/material-reader/reader-host.js +202 -0
- package/src/backend/services/material-signals.js +141 -0
- package/src/backend/services/mcp-capabilities.js +390 -0
- package/src/backend/services/mdns-service.js +304 -0
- package/src/backend/services/mobile-api-server.js +281 -0
- package/src/backend/services/mobile-approvals.js +306 -0
- package/src/backend/services/mobile-awareness.js +180 -0
- package/src/backend/services/mobile-breakpoints.js +115 -0
- package/src/backend/services/mobile-budget.js +98 -0
- package/src/backend/services/mobile-freeze.js +106 -0
- package/src/backend/services/mobile-proposals.js +100 -0
- package/src/backend/services/mobile-rpc-service.js +1289 -0
- package/src/backend/services/mobile-workstreams.js +160 -0
- package/src/backend/services/monorepo-detector.js +131 -0
- package/src/backend/services/other-work.js +45 -0
- package/src/backend/services/pack-seal.js +129 -0
- package/src/backend/services/paired-device-service.js +192 -0
- package/src/backend/services/pairing-server.js +323 -0
- package/src/backend/services/pairing-service.js +200 -0
- package/src/backend/services/pantry-resolution-service.js +166 -0
- package/src/backend/services/parsers/base.js +124 -0
- package/src/backend/services/parsers/csharp.js +224 -0
- package/src/backend/services/parsers/go.js +180 -0
- package/src/backend/services/parsers/index.js +101 -0
- package/src/backend/services/parsers/java.js +103 -0
- package/src/backend/services/parsers/kotlin.js +252 -0
- package/src/backend/services/parsers/php.js +113 -0
- package/src/backend/services/parsers/python.js +189 -0
- package/src/backend/services/parsers/ruby.js +212 -0
- package/src/backend/services/parsers/rust.js +97 -0
- package/src/backend/services/parsers/swift.js +221 -0
- package/src/backend/services/parsers/typescript.js +235 -0
- package/src/backend/services/pattern-scan.js +65 -0
- package/src/backend/services/patterns.js +281 -0
- package/src/backend/services/peer-audit-service.js +123 -0
- package/src/backend/services/peer-auth.js +153 -0
- package/src/backend/services/peer-capabilities.js +209 -0
- package/src/backend/services/peer-connection-service.js +450 -0
- package/src/backend/services/peer-grants.js +33 -0
- package/src/backend/services/persistence.js +116 -0
- package/src/backend/services/personal-sync-service.js +232 -0
- package/src/backend/services/pipeline-approvals.js +72 -0
- package/src/backend/services/pipeline.js +232 -0
- package/src/backend/services/plan-arrivals.js +68 -0
- package/src/backend/services/plan-changes-service.js +273 -0
- package/src/backend/services/plan-conflict-service.js +288 -0
- package/src/backend/services/plan-dependencies.js +91 -0
- package/src/backend/services/plan-doc-guard.js +90 -0
- package/src/backend/services/plan-documents-service.js +275 -0
- package/src/backend/services/plan-event-service.js +154 -0
- package/src/backend/services/plan-file-refs.js +106 -0
- package/src/backend/services/plan-file-service.js +1564 -0
- package/src/backend/services/plan-history-service.js +156 -0
- package/src/backend/services/plan-import-service.js +261 -0
- package/src/backend/services/plan-item-service.js +1223 -0
- package/src/backend/services/plan-migrate-service.js +395 -0
- package/src/backend/services/plan-overlay-service.js +173 -0
- package/src/backend/services/plan-phases-service.js +182 -0
- package/src/backend/services/plan-progress-service.js +134 -0
- package/src/backend/services/plan-review-service.js +262 -0
- package/src/backend/services/plan-service.js +682 -0
- package/src/backend/services/plan-status.js +113 -0
- package/src/backend/services/plan-template-publish-service.js +217 -0
- package/src/backend/services/plan-templates-service.js +242 -0
- package/src/backend/services/plan-templates.js +1164 -0
- package/src/backend/services/planned-overlap-actions.js +200 -0
- package/src/backend/services/plans-home.js +224 -0
- package/src/backend/services/play-forward.js +256 -0
- package/src/backend/services/playback-service.js +117 -0
- package/src/backend/services/power-service.js +167 -0
- package/src/backend/services/power-signals.js +81 -0
- package/src/backend/services/pr-draft-service.js +142 -0
- package/src/backend/services/presence-service.js +122 -0
- package/src/backend/services/pricing.js +60 -0
- package/src/backend/services/project-config-service.js +474 -0
- package/src/backend/services/project-scanner.js +184 -0
- package/src/backend/services/projection-service.js +69 -0
- package/src/backend/services/push-notification-service.js +288 -0
- package/src/backend/services/recent-projects-service.js +204 -0
- package/src/backend/services/record-chain.js +162 -0
- package/src/backend/services/recurrence-rule.js +63 -0
- package/src/backend/services/recurring-agent.js +89 -0
- package/src/backend/services/recurring-scheduler.js +77 -0
- package/src/backend/services/recurring-service.js +276 -0
- package/src/backend/services/reference-service.js +169 -0
- package/src/backend/services/release-public-key.js +30 -0
- package/src/backend/services/release-signature.js +64 -0
- package/src/backend/services/remote-audio-service.js +224 -0
- package/src/backend/services/remote-interaction-service.js +275 -0
- package/src/backend/services/remote-terminal-service.js +324 -0
- package/src/backend/services/rendition/child/main.js +76 -0
- package/src/backend/services/rendition/engine-host.js +249 -0
- package/src/backend/services/rendition/engine-lock.js +39 -0
- package/src/backend/services/rendition/engine-lock.json +14 -0
- package/src/backend/services/rendition/engine-manifest.js +97 -0
- package/src/backend/services/rendition/network-proof.js +73 -0
- package/src/backend/services/rendition/rendition-service.js +175 -0
- package/src/backend/services/replay-frames.js +387 -0
- package/src/backend/services/replay-state.js +201 -0
- package/src/backend/services/resolvers/base.js +108 -0
- package/src/backend/services/resolvers/csharp.js +109 -0
- package/src/backend/services/resolvers/go.js +105 -0
- package/src/backend/services/resolvers/index.js +60 -0
- package/src/backend/services/resolvers/java.js +63 -0
- package/src/backend/services/resolvers/kotlin.js +109 -0
- package/src/backend/services/resolvers/php.js +89 -0
- package/src/backend/services/resolvers/python.js +154 -0
- package/src/backend/services/resolvers/ruby.js +103 -0
- package/src/backend/services/resolvers/rust.js +77 -0
- package/src/backend/services/resolvers/swift.js +98 -0
- package/src/backend/services/resolvers/typescript.js +71 -0
- package/src/backend/services/retention.js +54 -0
- package/src/backend/services/review-architecture.js +236 -0
- package/src/backend/services/review-attest.js +68 -0
- package/src/backend/services/review-bundle.js +226 -0
- package/src/backend/services/review-graduation.js +93 -0
- package/src/backend/services/review-host/bitbucket.js +79 -0
- package/src/backend/services/review-host/detect.js +80 -0
- package/src/backend/services/review-host/github.js +97 -0
- package/src/backend/services/review-host/gitlab.js +77 -0
- package/src/backend/services/review-host/host-state.js +103 -0
- package/src/backend/services/review-host/http.js +58 -0
- package/src/backend/services/review-host/switch.js +120 -0
- package/src/backend/services/review-marks.js +72 -0
- package/src/backend/services/review-notes.js +169 -0
- package/src/backend/services/review-other-work.js +90 -0
- package/src/backend/services/review-queue-service.js +147 -0
- package/src/backend/services/review-risk.js +127 -0
- package/src/backend/services/review-task.js +121 -0
- package/src/backend/services/rule-approvals.js +275 -0
- package/src/backend/services/rule-baseline.js +134 -0
- package/src/backend/services/rule-changes.js +162 -0
- package/src/backend/services/rule-preview.js +47 -0
- package/src/backend/services/rule-proposals.js +104 -0
- package/src/backend/services/rule-scope.js +76 -0
- package/src/backend/services/rulebook.js +286 -0
- package/src/backend/services/rules-at.js +56 -0
- package/src/backend/services/rules-overview.js +88 -0
- package/src/backend/services/schema-reconciler.js +250 -0
- package/src/backend/services/secret-store.js +119 -0
- package/src/backend/services/section-workstreams.js +95 -0
- package/src/backend/services/self-write-tracker.js +75 -0
- package/src/backend/services/sensor-bridge-service.js +285 -0
- package/src/backend/services/session-service.js +192 -0
- package/src/backend/services/settings-service.js +324 -0
- package/src/backend/services/signal-breakpoints.js +172 -0
- package/src/backend/services/signed-approval-record.js +86 -0
- package/src/backend/services/signed-approvals.js +244 -0
- package/src/backend/services/signoff-pack.js +328 -0
- package/src/backend/services/signoff-rows.js +114 -0
- package/src/backend/services/skill-arrival-service.js +138 -0
- package/src/backend/services/skill-model.js +193 -0
- package/src/backend/services/skill-use-service.js +140 -0
- package/src/backend/services/skills-service.js +150 -0
- package/src/backend/services/snapshot-compare-service.js +397 -0
- package/src/backend/services/source-control.js +189 -0
- package/src/backend/services/spec-links-service.js +123 -0
- package/src/backend/services/spec-proposal-withdraw.js +50 -0
- package/src/backend/services/spec-proposals-service.js +470 -0
- package/src/backend/services/sql/embedded.js +95 -0
- package/src/backend/services/sql/index.js +63 -0
- package/src/backend/services/sql/refs.js +357 -0
- package/src/backend/services/sql/schema.js +312 -0
- package/src/backend/services/sql/tokenizer.js +195 -0
- package/src/backend/services/stack-overlaps.js +117 -0
- package/src/backend/services/stack-service.js +225 -0
- package/src/backend/services/state-sync-service.js +384 -0
- package/src/backend/services/stuck-sensor-service.js +200 -0
- package/src/backend/services/system-discovery.js +481 -0
- package/src/backend/services/system-docs-service.js +701 -0
- package/src/backend/services/task-attachments-service.js +340 -0
- package/src/backend/services/task-grounding.js +60 -0
- package/src/backend/services/task-records/check-run-record.js +146 -0
- package/src/backend/services/task-records/check-runs.js +115 -0
- package/src/backend/services/task-records/heads.js +88 -0
- package/src/backend/services/task-records/material-reads.js +225 -0
- package/src/backend/services/task-records/read-record.js +100 -0
- package/src/backend/services/task-records/record.js +173 -0
- package/src/backend/services/task-records/run-record.js +136 -0
- package/src/backend/services/task-records/shared-state.js +548 -0
- package/src/backend/services/task-records/signing.js +140 -0
- package/src/backend/services/task-records/split-signals.js +52 -0
- package/src/backend/services/task-records/test-runs.js +164 -0
- package/src/backend/services/task-records/trust.js +243 -0
- package/src/backend/services/task-rules.js +81 -0
- package/src/backend/services/task-workstreams.js +90 -0
- package/src/backend/services/terminal-history-service.js +266 -0
- package/src/backend/services/terminal-service.js +267 -0
- package/src/backend/services/test-clock.js +53 -0
- package/src/backend/services/tests/grounding.js +266 -0
- package/src/backend/services/tests/junit.js +104 -0
- package/src/backend/services/tests/teammate-runs.js +134 -0
- package/src/backend/services/tests/test-results.js +234 -0
- package/src/backend/services/tree-watcher.js +204 -0
- package/src/backend/services/trellis-service.js +204 -0
- package/src/backend/services/trusted-roots.js +186 -0
- package/src/backend/services/update-download-service.js +342 -0
- package/src/backend/services/update-service.js +266 -0
- package/src/backend/services/watch-ignore.js +76 -0
- package/src/backend/services/webhook-egress.js +206 -0
- package/src/backend/services/webrtc-service.js +413 -0
- package/src/backend/services/work-changes.js +59 -0
- package/src/backend/services/workstream-binding.js +82 -0
- package/src/backend/services/workstream-commits.js +116 -0
- package/src/backend/services/workstream-imports.js +177 -0
- package/src/backend/services/workstream-service.js +335 -0
- package/src/backend/services/workstream-symbols.js +223 -0
- package/src/backend/services/workstream-watch-service.js +391 -0
- package/src/backend/services/worktree-service.js +235 -0
- package/src/cli/agent.js +100 -0
- package/src/cli/args.js +209 -0
- package/src/cli/conformity.js +106 -0
- package/src/cli/desktop.js +91 -0
- package/src/cli/main.js +411 -0
- package/src/cli/pipeline.js +109 -0
- package/src/cli/plan-verbs.js +259 -0
- package/src/cli/review-adapters.js +220 -0
- package/src/cli/review-output.js +93 -0
- package/src/cli/review-post.js +89 -0
- package/src/cli/review-sink.js +183 -0
- package/src/cli/review-skill.js +44 -0
- package/src/cli/review-verify.js +104 -0
- package/src/cli/review.js +386 -0
- package/src/cli/sarif.js +148 -0
- package/src/cli/verbs.js +360 -0
- package/src/shared/build-info.js +39 -0
- package/src/shared/lib/agent-review.js +199 -0
- package/src/shared/lib/agent-turns.js +140 -0
- package/src/shared/lib/awareness-digest.js +120 -0
- package/src/shared/lib/branch-name.js +45 -0
- package/src/shared/lib/breakpoint-words.js +118 -0
- package/src/shared/lib/budget-words.js +56 -0
- package/src/shared/lib/burst.js +69 -0
- package/src/shared/lib/call-entry.js +105 -0
- package/src/shared/lib/check-compare.js +42 -0
- package/src/shared/lib/check-words.js +216 -0
- package/src/shared/lib/csv.js +62 -0
- package/src/shared/lib/folder-entry.js +87 -0
- package/src/shared/lib/freeze-words.js +60 -0
- package/src/shared/lib/fuzzy.js +84 -0
- package/src/shared/lib/git-state-words.js +80 -0
- package/src/shared/lib/grep-entry.js +86 -0
- package/src/shared/lib/grounding-line.js +61 -0
- package/src/shared/lib/import-line.js +71 -0
- package/src/shared/lib/item-status.js +249 -0
- package/src/shared/lib/line-changes.js +53 -0
- package/src/shared/lib/locator.js +71 -0
- package/src/shared/lib/matcher.js +120 -0
- package/src/shared/lib/merge-order.js +65 -0
- package/src/shared/lib/open-findings.js +68 -0
- package/src/shared/lib/other-work.js +108 -0
- package/src/shared/lib/package-entry.js +142 -0
- package/src/shared/lib/plan-vocab.js +40 -0
- package/src/shared/lib/pptx-xml.js +86 -0
- package/src/shared/lib/proposal-words.js +61 -0
- package/src/shared/lib/recurrence.js +183 -0
- package/src/shared/lib/references.js +72 -0
- package/src/shared/lib/rule-pattern.js +56 -0
- package/src/shared/lib/sdp-fingerprint.js +115 -0
- package/src/shared/lib/sdp-minimal.js +123 -0
- package/src/shared/lib/secret-paths.js +34 -0
- package/src/shared/lib/signal-words.js +172 -0
- package/src/shared/lib/signoff.js +56 -0
- package/src/shared/lib/skills-note.js +60 -0
- package/src/shared/lib/spec-sections.js +78 -0
- package/src/shared/lib/symbol-entry.js +60 -0
- package/src/shared/lib/tool-phrasing.js +338 -0
- package/src/shared/lib/turn-gap.js +27 -0
- package/src/shared/lib/workstream-words.js +38 -0
- package/src/shared/lib/xlsx-xml.js +144 -0
- package/src/shared/lib/zip-reader.js +99 -0
- package/src/shared/types/agent.js +27 -0
- package/src/shared/types/architecture-rules.js +30 -0
- package/src/shared/types/ast.js +15 -0
- package/src/shared/types/breakpoint.js +33 -0
- package/src/shared/types/channel.js +41 -0
- package/src/shared/types/criteria.js +15 -0
- package/src/shared/types/graph.js +15 -0
- package/src/shared/types/index.js +53 -0
- package/src/shared/types/peer.js +36 -0
- package/src/shared/types/pipeline.js +15 -0
- package/src/shared/types/plan.js +15 -0
- package/src/shared/types/play-forward.js +15 -0
- package/src/shared/types/power.js +15 -0
- package/src/shared/types/presence.js +15 -0
- package/src/shared/types/project-config.js +35 -0
- package/src/shared/types/project.js +15 -0
- package/src/shared/types/record.js +15 -0
- package/src/shared/types/recurring.js +15 -0
- package/src/shared/types/review.js +15 -0
- package/src/shared/types/settings.js +114 -0
- package/src/shared/types/stack.js +15 -0
- package/src/shared/types/system-doc.js +15 -0
- package/src/shared/types/system.js +15 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var files_exports = {};
|
|
29
|
+
__export(files_exports, {
|
|
30
|
+
ENDPOINT_FILE: () => ENDPOINT_FILE,
|
|
31
|
+
TOKEN_FILE: () => TOKEN_FILE,
|
|
32
|
+
defaultDataDir: () => defaultDataDir,
|
|
33
|
+
isLoopbackSseUrl: () => isLoopbackSseUrl,
|
|
34
|
+
readConnectTarget: () => readConnectTarget,
|
|
35
|
+
readEndpoint: () => readEndpoint,
|
|
36
|
+
readToken: () => readToken,
|
|
37
|
+
removeEndpointFile: () => removeEndpointFile,
|
|
38
|
+
writeEndpointFile: () => writeEndpointFile
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(files_exports);
|
|
41
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
42
|
+
var import_node_os = __toESM(require("node:os"));
|
|
43
|
+
var import_node_path = __toESM(require("node:path"));
|
|
44
|
+
var import_confined_fs = require("../../services/confined-fs");
|
|
45
|
+
const TOKEN_FILE = "capability-token";
|
|
46
|
+
const ENDPOINT_FILE = "mcp-endpoint.json";
|
|
47
|
+
function defaultDataDir(env = process.env) {
|
|
48
|
+
const fromEnv = env.CODETRELLIS_DATA_DIR;
|
|
49
|
+
if (fromEnv && fromEnv.trim()) return fromEnv;
|
|
50
|
+
return import_node_path.default.join(import_node_os.default.homedir(), ".codetrellis");
|
|
51
|
+
}
|
|
52
|
+
function isLoopbackSseUrl(raw) {
|
|
53
|
+
let u;
|
|
54
|
+
try {
|
|
55
|
+
u = new URL(raw);
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (u.protocol !== "http:") return false;
|
|
60
|
+
if (!["127.0.0.1", "localhost", "[::1]"].includes(u.hostname)) return false;
|
|
61
|
+
return u.pathname === "/sse" && u.username === "" && u.password === "";
|
|
62
|
+
}
|
|
63
|
+
function writeEndpointFile(dataDir, endpoint) {
|
|
64
|
+
import_node_fs.default.mkdirSync(dataDir, { recursive: true });
|
|
65
|
+
(0, import_confined_fs.writeFileWithin)(dataDir, ENDPOINT_FILE, JSON.stringify(endpoint), "MCP endpoint file");
|
|
66
|
+
}
|
|
67
|
+
function removeEndpointFile(dataDir, pid) {
|
|
68
|
+
const current = readEndpoint(dataDir);
|
|
69
|
+
if (current && current.pid !== pid) return;
|
|
70
|
+
try {
|
|
71
|
+
(0, import_confined_fs.removeWithin)(dataDir, ENDPOINT_FILE);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function readEndpoint(dataDir) {
|
|
76
|
+
try {
|
|
77
|
+
const parsed = JSON.parse((0, import_confined_fs.readTextWithin)(dataDir, ENDPOINT_FILE, "MCP endpoint file"));
|
|
78
|
+
if (typeof parsed.url !== "string" || !isLoopbackSseUrl(parsed.url)) return null;
|
|
79
|
+
return {
|
|
80
|
+
url: parsed.url,
|
|
81
|
+
pid: typeof parsed.pid === "number" ? parsed.pid : 0,
|
|
82
|
+
startedAt: typeof parsed.startedAt === "number" ? parsed.startedAt : 0
|
|
83
|
+
};
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function readToken(dataDir) {
|
|
89
|
+
try {
|
|
90
|
+
const token = (0, import_confined_fs.readTextWithin)(dataDir, TOKEN_FILE, "capability token").trim();
|
|
91
|
+
return token.length >= 16 ? token : null;
|
|
92
|
+
} catch {
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function readConnectTarget(dataDir) {
|
|
97
|
+
const token = readToken(dataDir);
|
|
98
|
+
if (!token) return { ok: false, reason: `no capability token in ${dataDir} yet` };
|
|
99
|
+
const endpoint = readEndpoint(dataDir);
|
|
100
|
+
if (!endpoint) return { ok: false, reason: "the app has not published its MCP endpoint yet" };
|
|
101
|
+
try {
|
|
102
|
+
const tokenAt = import_node_fs.default.lstatSync(import_node_path.default.join(dataDir, TOKEN_FILE)).mtimeMs;
|
|
103
|
+
const endpointAt = import_node_fs.default.lstatSync(import_node_path.default.join(dataDir, ENDPOINT_FILE)).mtimeMs;
|
|
104
|
+
if (endpointAt < tokenAt) return { ok: false, reason: "the app is still starting" };
|
|
105
|
+
} catch {
|
|
106
|
+
return { ok: false, reason: "the app is still starting" };
|
|
107
|
+
}
|
|
108
|
+
return { ok: true, url: endpoint.url, token };
|
|
109
|
+
}
|
|
110
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
111
|
+
0 && (module.exports = {
|
|
112
|
+
ENDPOINT_FILE,
|
|
113
|
+
TOKEN_FILE,
|
|
114
|
+
defaultDataDir,
|
|
115
|
+
isLoopbackSseUrl,
|
|
116
|
+
readConnectTarget,
|
|
117
|
+
readEndpoint,
|
|
118
|
+
readToken,
|
|
119
|
+
removeEndpointFile,
|
|
120
|
+
writeEndpointFile
|
|
121
|
+
});
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var hook_exports = {};
|
|
29
|
+
__export(hook_exports, {
|
|
30
|
+
CHECK_EDIT_FLAG: () => CHECK_EDIT_FLAG,
|
|
31
|
+
CHECK_EDIT_HELD: () => CHECK_EDIT_HELD,
|
|
32
|
+
GEMINI_HOOK_MATCHER: () => GEMINI_HOOK_MATCHER,
|
|
33
|
+
HOOK_BREAKPOINT_MARKER: () => HOOK_BREAKPOINT_MARKER,
|
|
34
|
+
HOOK_FLAG: () => HOOK_FLAG,
|
|
35
|
+
HOOK_GEMINI_BEFORE_TOOL: () => HOOK_GEMINI_BEFORE_TOOL,
|
|
36
|
+
HOOK_MARKER: () => HOOK_MARKER,
|
|
37
|
+
HOOK_MATCHER: () => HOOK_MATCHER,
|
|
38
|
+
HOOK_PRE_TOOL_USE: () => HOOK_PRE_TOOL_USE,
|
|
39
|
+
OLD_TEXT_FILE_FLAG: () => OLD_TEXT_FILE_FLAG,
|
|
40
|
+
breakpointAnswer: () => breakpointAnswer,
|
|
41
|
+
geminiDeny: () => geminiDeny,
|
|
42
|
+
hookDeny: () => hookDeny,
|
|
43
|
+
hookNotice: () => hookNotice,
|
|
44
|
+
hookOutput: () => hookOutput,
|
|
45
|
+
parseGeminiHookInput: () => parseGeminiHookInput,
|
|
46
|
+
parseHookInput: () => parseHookInput,
|
|
47
|
+
repoOf: () => repoOf,
|
|
48
|
+
runCheckEdit: () => runCheckEdit,
|
|
49
|
+
runGeminiBeforeToolHook: () => runGeminiBeforeToolHook,
|
|
50
|
+
runPreToolUseHook: () => runPreToolUseHook
|
|
51
|
+
});
|
|
52
|
+
module.exports = __toCommonJS(hook_exports);
|
|
53
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
54
|
+
var import_node_path = __toESM(require("node:path"));
|
|
55
|
+
const HOOK_FLAG = "--hook";
|
|
56
|
+
const HOOK_PRE_TOOL_USE = "pre-tool-use";
|
|
57
|
+
const HOOK_MATCHER = "Edit|Write|MultiEdit|NotebookEdit";
|
|
58
|
+
const HOOK_MARKER = "\u2500\u2500 CodeTrellis awareness \u2500\u2500";
|
|
59
|
+
const HOOK_BREAKPOINT_MARKER = "\u2500\u2500 CodeTrellis breakpoint \u2500\u2500";
|
|
60
|
+
function parseHookInput(raw) {
|
|
61
|
+
let input;
|
|
62
|
+
try {
|
|
63
|
+
input = JSON.parse(raw);
|
|
64
|
+
} catch {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
if (!input || typeof input !== "object") return null;
|
|
68
|
+
const { cwd, tool_input: toolInput } = input;
|
|
69
|
+
if (typeof cwd !== "string" || !import_node_path.default.isAbsolute(cwd)) return null;
|
|
70
|
+
if (!toolInput || typeof toolInput !== "object") return null;
|
|
71
|
+
const t = toolInput;
|
|
72
|
+
const filePath = typeof t.file_path === "string" ? t.file_path : typeof t.notebook_path === "string" ? t.notebook_path : null;
|
|
73
|
+
if (!filePath) return null;
|
|
74
|
+
const olds = typeof t.old_string === "string" ? [t.old_string] : Array.isArray(t.edits) ? t.edits.map((e) => e && typeof e === "object" ? e.old_string : null) : null;
|
|
75
|
+
const oldTexts = olds && olds.length && olds.length <= 20 && olds.every((o) => typeof o === "string" && o.length > 0 && o.length <= 2e4) ? olds : void 0;
|
|
76
|
+
return { cwd, filePath: import_node_path.default.isAbsolute(filePath) ? filePath : import_node_path.default.resolve(cwd, filePath), ...oldTexts ? { oldTexts } : {} };
|
|
77
|
+
}
|
|
78
|
+
function repoOf(filePath, exists = import_node_fs.default.existsSync) {
|
|
79
|
+
let dir = import_node_path.default.dirname(filePath);
|
|
80
|
+
for (; ; ) {
|
|
81
|
+
if (exists(import_node_path.default.join(dir, ".git"))) {
|
|
82
|
+
const rel = import_node_path.default.relative(dir, filePath).split(import_node_path.default.sep).join("/");
|
|
83
|
+
return rel && !rel.startsWith("..") ? { root: dir, rel } : null;
|
|
84
|
+
}
|
|
85
|
+
const up = import_node_path.default.dirname(dir);
|
|
86
|
+
if (up === dir) return null;
|
|
87
|
+
dir = up;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const canon = (p) => {
|
|
91
|
+
try {
|
|
92
|
+
return import_node_fs.default.realpathSync.native(p);
|
|
93
|
+
} catch {
|
|
94
|
+
return import_node_path.default.resolve(p);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
function hookNotice(reportText, call) {
|
|
98
|
+
let report;
|
|
99
|
+
try {
|
|
100
|
+
report = JSON.parse(reportText);
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!report.your_workstream || canon(report.your_workstream) !== canon(call.root)) return null;
|
|
105
|
+
const entry = report.paths?.find((p) => p.path === call.rel);
|
|
106
|
+
const others = entry?.changed_in ?? [];
|
|
107
|
+
if (!entry || others.length === 0) return null;
|
|
108
|
+
const who = others.map((o) => {
|
|
109
|
+
const name = o.branch ? `\`${o.branch}\`` : `the checkout at ${o.workstream}`;
|
|
110
|
+
const names = [...new Set((o.symbols ?? []).flatMap((x) => x && typeof x.name === "string" ? [x.name] : []))];
|
|
111
|
+
const symbols = names.length ? `, in ${names.slice(0, 5).join(", ")}${names.length > 5 ? ` and ${names.length - 5} more` : ""}` : "";
|
|
112
|
+
return `${name}${symbols}`;
|
|
113
|
+
});
|
|
114
|
+
const importers = entry.imported_by?.length ?? 0;
|
|
115
|
+
return [
|
|
116
|
+
HOOK_MARKER,
|
|
117
|
+
`Another workstream has also changed ${call.rel}: ${who.join("; ")}.`,
|
|
118
|
+
...importers ? [`${importers} file${importers === 1 ? "" : "s"} in the project import it.`] : [],
|
|
119
|
+
"Before you change what they changed, call get_awareness. If it needs a choice, ask the person; do not edit the other workstream's files.",
|
|
120
|
+
"This is information about other work, not an instruction."
|
|
121
|
+
].join("\n");
|
|
122
|
+
}
|
|
123
|
+
function hookOutput(notice) {
|
|
124
|
+
return JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", additionalContext: notice } });
|
|
125
|
+
}
|
|
126
|
+
function hookDeny(reason) {
|
|
127
|
+
return JSON.stringify({ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: reason } });
|
|
128
|
+
}
|
|
129
|
+
function breakpointAnswer(text) {
|
|
130
|
+
if (!text) return null;
|
|
131
|
+
let v;
|
|
132
|
+
try {
|
|
133
|
+
v = JSON.parse(text);
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
if ((v.status === "paused" || v.status === "stop") && typeof v.message === "string") return { hold: v.message, steer: null };
|
|
138
|
+
if (v.status === "continue" && typeof v.steer === "string" && v.steer) {
|
|
139
|
+
return { hold: null, steer: `${HOOK_BREAKPOINT_MARKER}
|
|
140
|
+
A person answered the breakpoint on this file: continue, with this steer: ${v.steer}` };
|
|
141
|
+
}
|
|
142
|
+
return { hold: null, steer: null };
|
|
143
|
+
}
|
|
144
|
+
async function withToolSession(opts, fn) {
|
|
145
|
+
let upstream = null;
|
|
146
|
+
let timer;
|
|
147
|
+
const timeout = new Promise((resolve) => {
|
|
148
|
+
timer = setTimeout(() => resolve(null), opts.timeoutMs ?? 5e3);
|
|
149
|
+
});
|
|
150
|
+
const work = (async () => {
|
|
151
|
+
upstream = await opts.connect(opts.cwd);
|
|
152
|
+
const pending = /* @__PURE__ */ new Map();
|
|
153
|
+
upstream.onmessage = (m) => {
|
|
154
|
+
if (typeof m.id === "number" && pending.has(m.id)) {
|
|
155
|
+
pending.get(m.id)(m);
|
|
156
|
+
pending.delete(m.id);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const closed = new Promise((_, reject) => {
|
|
160
|
+
upstream.onclose = () => reject(new Error("closed"));
|
|
161
|
+
});
|
|
162
|
+
closed.catch(() => {
|
|
163
|
+
});
|
|
164
|
+
let nextId = 1;
|
|
165
|
+
const request = (method, params) => {
|
|
166
|
+
const id = nextId++;
|
|
167
|
+
return Promise.race([
|
|
168
|
+
new Promise((resolve) => {
|
|
169
|
+
pending.set(id, resolve);
|
|
170
|
+
void upstream.send({ jsonrpc: "2.0", id, method, params });
|
|
171
|
+
}),
|
|
172
|
+
closed
|
|
173
|
+
]);
|
|
174
|
+
};
|
|
175
|
+
const init = await request("initialize", {
|
|
176
|
+
protocolVersion: "2025-06-18",
|
|
177
|
+
capabilities: {},
|
|
178
|
+
clientInfo: { name: opts.clientName, version: opts.version }
|
|
179
|
+
});
|
|
180
|
+
if (init.error) return null;
|
|
181
|
+
await upstream.send({ jsonrpc: "2.0", method: "notifications/initialized" });
|
|
182
|
+
const callTool = async (name, args) => {
|
|
183
|
+
const res = await request("tools/call", { name, arguments: args });
|
|
184
|
+
const result = res.result;
|
|
185
|
+
return !result || result.isError ? null : result.content?.[0]?.text ?? null;
|
|
186
|
+
};
|
|
187
|
+
return fn(callTool);
|
|
188
|
+
})().catch(() => null);
|
|
189
|
+
try {
|
|
190
|
+
return await Promise.race([work, timeout]);
|
|
191
|
+
} finally {
|
|
192
|
+
clearTimeout(timer);
|
|
193
|
+
try {
|
|
194
|
+
upstream?.close();
|
|
195
|
+
} catch {
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function runPreToolUseHook(opts) {
|
|
200
|
+
const call = parseHookInput(opts.stdin);
|
|
201
|
+
if (!call) return null;
|
|
202
|
+
const repo = repoOf(call.filePath, opts.exists);
|
|
203
|
+
if (!repo) return null;
|
|
204
|
+
return withToolSession({ connect: opts.connect, cwd: call.cwd, version: opts.version, clientName: "claude-code-hook", timeoutMs: opts.timeoutMs }, async (callTool) => {
|
|
205
|
+
const bpArgs = call.oldTexts ? { path: repo.rel, old_text: call.oldTexts } : { path: repo.rel };
|
|
206
|
+
const held = breakpointAnswer(await callTool("check_breakpoint", bpArgs));
|
|
207
|
+
if (held?.hold) return hookDeny(held.hold);
|
|
208
|
+
const text = await callTool("check_footprint", { paths: [repo.rel] });
|
|
209
|
+
const notice = text ? hookNotice(text, repo) : null;
|
|
210
|
+
const context = [held?.steer, notice].filter((x) => !!x).join("\n\n");
|
|
211
|
+
return context ? hookOutput(context) : null;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
const CHECK_EDIT_FLAG = "--check-edit";
|
|
215
|
+
const OLD_TEXT_FILE_FLAG = "--old-text-file";
|
|
216
|
+
const CHECK_EDIT_HELD = 2;
|
|
217
|
+
async function runCheckEdit(opts) {
|
|
218
|
+
const go = { code: 0, stdout: null, stderr: null };
|
|
219
|
+
const repo = repoOf(import_node_path.default.resolve(opts.cwd, opts.file), opts.exists);
|
|
220
|
+
if (!repo) return go;
|
|
221
|
+
const answer = await withToolSession({ connect: opts.connect, cwd: repo.root, version: opts.version, clientName: "codetrellis-check-edit", timeoutMs: opts.timeoutMs }, async (callTool) => {
|
|
222
|
+
const args = opts.oldText ? { path: repo.rel, old_text: [opts.oldText] } : { path: repo.rel };
|
|
223
|
+
return breakpointAnswer(await callTool("check_breakpoint", args));
|
|
224
|
+
});
|
|
225
|
+
if (answer?.hold) return { code: CHECK_EDIT_HELD, stdout: null, stderr: answer.hold };
|
|
226
|
+
if (answer?.steer) return { code: 0, stdout: answer.steer, stderr: null };
|
|
227
|
+
return go;
|
|
228
|
+
}
|
|
229
|
+
const HOOK_GEMINI_BEFORE_TOOL = "gemini-before-tool";
|
|
230
|
+
const GEMINI_HOOK_MATCHER = "^(write_file|replace)$";
|
|
231
|
+
function parseGeminiHookInput(raw) {
|
|
232
|
+
let v;
|
|
233
|
+
try {
|
|
234
|
+
v = JSON.parse(raw);
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
if (v.hook_event_name !== "BeforeTool") return null;
|
|
239
|
+
if (v.tool_name !== "write_file" && v.tool_name !== "replace") return null;
|
|
240
|
+
const cwd = typeof v.cwd === "string" ? v.cwd : null;
|
|
241
|
+
const file = v.tool_input?.file_path;
|
|
242
|
+
if (!cwd || typeof file !== "string" || !file) return null;
|
|
243
|
+
const old = v.tool_input?.old_string;
|
|
244
|
+
const oldTexts = v.tool_name === "replace" && typeof old === "string" && old && old.length <= 2e4 ? [old] : void 0;
|
|
245
|
+
return { cwd, filePath: import_node_path.default.resolve(cwd, file), ...oldTexts ? { oldTexts } : {} };
|
|
246
|
+
}
|
|
247
|
+
function geminiDeny(reason) {
|
|
248
|
+
return JSON.stringify({ decision: "deny", reason });
|
|
249
|
+
}
|
|
250
|
+
async function runGeminiBeforeToolHook(opts) {
|
|
251
|
+
const call = parseGeminiHookInput(opts.stdin);
|
|
252
|
+
if (!call) return null;
|
|
253
|
+
const repo = repoOf(call.filePath, opts.exists);
|
|
254
|
+
if (!repo) return null;
|
|
255
|
+
return withToolSession({ connect: opts.connect, cwd: call.cwd, version: opts.version, clientName: "gemini-cli-hook", timeoutMs: opts.timeoutMs }, async (callTool) => {
|
|
256
|
+
const args = call.oldTexts ? { path: repo.rel, old_text: call.oldTexts } : { path: repo.rel };
|
|
257
|
+
const held = breakpointAnswer(await callTool("check_breakpoint", args));
|
|
258
|
+
return held?.hold ? geminiDeny(held.hold) : null;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
262
|
+
0 && (module.exports = {
|
|
263
|
+
CHECK_EDIT_FLAG,
|
|
264
|
+
CHECK_EDIT_HELD,
|
|
265
|
+
GEMINI_HOOK_MATCHER,
|
|
266
|
+
HOOK_BREAKPOINT_MARKER,
|
|
267
|
+
HOOK_FLAG,
|
|
268
|
+
HOOK_GEMINI_BEFORE_TOOL,
|
|
269
|
+
HOOK_MARKER,
|
|
270
|
+
HOOK_MATCHER,
|
|
271
|
+
HOOK_PRE_TOOL_USE,
|
|
272
|
+
OLD_TEXT_FILE_FLAG,
|
|
273
|
+
breakpointAnswer,
|
|
274
|
+
geminiDeny,
|
|
275
|
+
hookDeny,
|
|
276
|
+
hookNotice,
|
|
277
|
+
hookOutput,
|
|
278
|
+
parseGeminiHookInput,
|
|
279
|
+
parseHookInput,
|
|
280
|
+
repoOf,
|
|
281
|
+
runCheckEdit,
|
|
282
|
+
runGeminiBeforeToolHook,
|
|
283
|
+
runPreToolUseHook
|
|
284
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __copyProps = (to, from, except, desc) => {
|
|
8
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
9
|
+
for (let key of __getOwnPropNames(from))
|
|
10
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
11
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
12
|
+
}
|
|
13
|
+
return to;
|
|
14
|
+
};
|
|
15
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
16
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
17
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
18
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
19
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
20
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
21
|
+
mod
|
|
22
|
+
));
|
|
23
|
+
var import_core = require("./core");
|
|
24
|
+
var import_sse_upstream = require("./sse-upstream");
|
|
25
|
+
var import_files = require("./files");
|
|
26
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
27
|
+
var import_hook = require("./hook");
|
|
28
|
+
const VERSION = typeof __CONNECTOR_VERSION__ === "string" ? __CONNECTOR_VERSION__ : "dev";
|
|
29
|
+
function argValue(flag) {
|
|
30
|
+
const i = process.argv.indexOf(flag);
|
|
31
|
+
return i >= 0 && i + 1 < process.argv.length ? process.argv[i + 1] : null;
|
|
32
|
+
}
|
|
33
|
+
const dataDir = argValue("--data-dir") ?? (0, import_files.defaultDataDir)();
|
|
34
|
+
const log = (line) => process.stderr.write(`[codetrellis-mcp] ${line}
|
|
35
|
+
`);
|
|
36
|
+
const connectFrom = (cwd) => {
|
|
37
|
+
const target = (0, import_files.readConnectTarget)(dataDir);
|
|
38
|
+
if (!target.ok) throw new Error(target.reason);
|
|
39
|
+
return (0, import_sse_upstream.connectSseUpstream)({
|
|
40
|
+
url: target.url,
|
|
41
|
+
token: target.token,
|
|
42
|
+
binding: { cwd, hostTerminal: process.env.CODETRELLIS_HOST_TERMINAL ?? null }
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
if (argValue(import_hook.HOOK_FLAG) === import_hook.HOOK_PRE_TOOL_USE || argValue(import_hook.HOOK_FLAG) === import_hook.HOOK_GEMINI_BEFORE_TOOL) {
|
|
46
|
+
const run = argValue(import_hook.HOOK_FLAG) === import_hook.HOOK_GEMINI_BEFORE_TOOL ? import_hook.runGeminiBeforeToolHook : import_hook.runPreToolUseHook;
|
|
47
|
+
let input = "";
|
|
48
|
+
process.stdin.setEncoding("utf8");
|
|
49
|
+
process.stdin.on("data", (chunk) => {
|
|
50
|
+
input += chunk;
|
|
51
|
+
});
|
|
52
|
+
process.stdin.on("end", () => {
|
|
53
|
+
void run({ stdin: input, connect: async (cwd) => connectFrom(cwd), version: VERSION }).catch(() => null).then((out) => {
|
|
54
|
+
if (out) process.stdout.write(`${out}
|
|
55
|
+
`, () => process.exit(0));
|
|
56
|
+
else process.exit(0);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
} else if (argValue(import_hook.CHECK_EDIT_FLAG) !== null) {
|
|
60
|
+
const file = argValue(import_hook.CHECK_EDIT_FLAG);
|
|
61
|
+
const oldTextFile = argValue(import_hook.OLD_TEXT_FILE_FLAG);
|
|
62
|
+
let oldText = null;
|
|
63
|
+
try {
|
|
64
|
+
oldText = oldTextFile ? import_node_fs.default.readFileSync(oldTextFile, "utf8").slice(0, 2e4) : null;
|
|
65
|
+
} catch {
|
|
66
|
+
oldText = null;
|
|
67
|
+
}
|
|
68
|
+
void (0, import_hook.runCheckEdit)({ file, cwd: process.cwd(), oldText, connect: async (cwd) => connectFrom(cwd), version: VERSION }).catch(() => ({ code: 0, stdout: null, stderr: null })).then((r) => {
|
|
69
|
+
const out = () => r.stdout ? process.stdout.write(`${r.stdout}
|
|
70
|
+
`, () => process.exit(r.code)) : process.exit(r.code);
|
|
71
|
+
if (r.stderr) process.stderr.write(`${r.stderr}
|
|
72
|
+
`, out);
|
|
73
|
+
else out();
|
|
74
|
+
});
|
|
75
|
+
} else {
|
|
76
|
+
runConnector();
|
|
77
|
+
}
|
|
78
|
+
function runConnector() {
|
|
79
|
+
const core = new import_core.ConnectorCore({
|
|
80
|
+
version: VERSION,
|
|
81
|
+
log,
|
|
82
|
+
send: (msg) => {
|
|
83
|
+
process.stdout.write(`${JSON.stringify(msg)}
|
|
84
|
+
`);
|
|
85
|
+
},
|
|
86
|
+
// Read both files on EVERY connect. This is the entire point: the token
|
|
87
|
+
// rotates on each launch, and the port moves when a second instance runs.
|
|
88
|
+
// The agent launched us in its working directory; a CodeTrellis terminal
|
|
89
|
+
// also names itself. The server binds the session to a workstream from
|
|
90
|
+
// these, re-derived on every connect (Phase 32 A1.1).
|
|
91
|
+
connect: async () => connectFrom(process.cwd())
|
|
92
|
+
});
|
|
93
|
+
let buffer = "";
|
|
94
|
+
let queue = Promise.resolve();
|
|
95
|
+
process.stdin.setEncoding("utf8");
|
|
96
|
+
process.stdin.on("data", (chunk) => {
|
|
97
|
+
buffer += chunk;
|
|
98
|
+
let newline;
|
|
99
|
+
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
100
|
+
const line = buffer.slice(0, newline).trim();
|
|
101
|
+
buffer = buffer.slice(newline + 1);
|
|
102
|
+
if (!line) continue;
|
|
103
|
+
let msg;
|
|
104
|
+
try {
|
|
105
|
+
msg = JSON.parse(line);
|
|
106
|
+
} catch {
|
|
107
|
+
log("Ignored a line that was not JSON.");
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
queue = queue.then(() => core.handleClientMessage(msg)).catch((err) => {
|
|
111
|
+
log(`Error handling a message: ${err instanceof Error ? err.message : String(err)}`);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
const shutdown = () => {
|
|
116
|
+
core.stop();
|
|
117
|
+
process.exit(0);
|
|
118
|
+
};
|
|
119
|
+
process.stdin.on("end", shutdown);
|
|
120
|
+
process.stdin.on("close", shutdown);
|
|
121
|
+
process.stdout.on("error", shutdown);
|
|
122
|
+
process.on("SIGTERM", shutdown);
|
|
123
|
+
process.on("SIGINT", shutdown);
|
|
124
|
+
log(`Starting (data dir ${dataDir}).`);
|
|
125
|
+
core.start();
|
|
126
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var sse_upstream_exports = {};
|
|
19
|
+
__export(sse_upstream_exports, {
|
|
20
|
+
TOKEN_HEADER: () => TOKEN_HEADER,
|
|
21
|
+
UpstreamRefused: () => UpstreamRefused,
|
|
22
|
+
connectSseUpstream: () => connectSseUpstream
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(sse_upstream_exports);
|
|
25
|
+
var import_binding_headers = require("../binding-headers");
|
|
26
|
+
const TOKEN_HEADER = "x-codetrellis-token";
|
|
27
|
+
class UpstreamRefused extends Error {
|
|
28
|
+
constructor(status, message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.status = status;
|
|
31
|
+
this.name = "UpstreamRefused";
|
|
32
|
+
}
|
|
33
|
+
status;
|
|
34
|
+
}
|
|
35
|
+
async function connectSseUpstream(opts) {
|
|
36
|
+
const doFetch = opts.fetchImpl ?? fetch;
|
|
37
|
+
const abort = new AbortController();
|
|
38
|
+
const headers = { [TOKEN_HEADER]: opts.token };
|
|
39
|
+
let res;
|
|
40
|
+
try {
|
|
41
|
+
res = await doFetch(opts.url, {
|
|
42
|
+
headers: { ...headers, ...(0, import_binding_headers.bindingHeaders)(opts.binding ?? {}), Accept: "text/event-stream" },
|
|
43
|
+
signal: abort.signal
|
|
44
|
+
});
|
|
45
|
+
} catch (err) {
|
|
46
|
+
abort.abort();
|
|
47
|
+
throw new Error(`not reachable at ${opts.url}${err instanceof Error && err.message ? ` (${err.message})` : ""}`);
|
|
48
|
+
}
|
|
49
|
+
if (!res.ok || !res.body) {
|
|
50
|
+
abort.abort();
|
|
51
|
+
throw new UpstreamRefused(
|
|
52
|
+
res.status,
|
|
53
|
+
res.status === 401 ? "the capability token was refused \u2014 the app may be mid-restart" : `the server answered HTTP ${res.status}`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
let closed = false;
|
|
57
|
+
let postUrl = null;
|
|
58
|
+
let resolveEndpoint = () => {
|
|
59
|
+
};
|
|
60
|
+
const endpointSeen = new Promise((resolve) => {
|
|
61
|
+
resolveEndpoint = resolve;
|
|
62
|
+
});
|
|
63
|
+
const upstream = {
|
|
64
|
+
async send(msg) {
|
|
65
|
+
if (closed || !postUrl) throw new Error("connection closed");
|
|
66
|
+
const r = await doFetch(postUrl, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { ...headers, "Content-Type": "application/json" },
|
|
69
|
+
body: JSON.stringify(msg)
|
|
70
|
+
});
|
|
71
|
+
await r.text().catch(() => "");
|
|
72
|
+
if (!r.ok) throw new UpstreamRefused(r.status, `message refused with HTTP ${r.status}`);
|
|
73
|
+
},
|
|
74
|
+
close() {
|
|
75
|
+
if (closed) return;
|
|
76
|
+
closed = true;
|
|
77
|
+
abort.abort();
|
|
78
|
+
upstream.onclose?.();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const onEvent = (event, data) => {
|
|
82
|
+
if (event === "endpoint") {
|
|
83
|
+
const target = new URL(data, opts.url);
|
|
84
|
+
if (target.origin !== new URL(opts.url).origin) {
|
|
85
|
+
upstream.close();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
postUrl = target.toString();
|
|
89
|
+
resolveEndpoint(postUrl);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (event === "message") {
|
|
93
|
+
let parsed;
|
|
94
|
+
try {
|
|
95
|
+
parsed = JSON.parse(data);
|
|
96
|
+
} catch {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
upstream.onmessage?.(parsed);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
void (async () => {
|
|
103
|
+
const reader = res.body.getReader();
|
|
104
|
+
const decoder = new TextDecoder();
|
|
105
|
+
let buffer = "";
|
|
106
|
+
try {
|
|
107
|
+
for (; ; ) {
|
|
108
|
+
const { done, value } = await reader.read();
|
|
109
|
+
if (done) break;
|
|
110
|
+
buffer += decoder.decode(value, { stream: true }).replace(/\r\n?/g, "\n");
|
|
111
|
+
let boundary;
|
|
112
|
+
while ((boundary = buffer.indexOf("\n\n")) >= 0) {
|
|
113
|
+
const block = buffer.slice(0, boundary);
|
|
114
|
+
buffer = buffer.slice(boundary + 2);
|
|
115
|
+
let event = "message";
|
|
116
|
+
const data = [];
|
|
117
|
+
for (const line of block.split("\n")) {
|
|
118
|
+
if (line.startsWith(":")) continue;
|
|
119
|
+
const colon = line.indexOf(":");
|
|
120
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
121
|
+
const value2 = colon === -1 ? "" : line.slice(colon + 1).replace(/^ /, "");
|
|
122
|
+
if (field === "event") event = value2;
|
|
123
|
+
else if (field === "data") data.push(value2);
|
|
124
|
+
}
|
|
125
|
+
if (data.length > 0) onEvent(event, data.join("\n"));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
}
|
|
130
|
+
upstream.close();
|
|
131
|
+
})();
|
|
132
|
+
const timeout = opts.handshakeTimeoutMs ?? 5e3;
|
|
133
|
+
let timer;
|
|
134
|
+
const winner = await Promise.race([
|
|
135
|
+
endpointSeen,
|
|
136
|
+
new Promise((resolve) => {
|
|
137
|
+
timer = setTimeout(() => resolve(null), timeout);
|
|
138
|
+
})
|
|
139
|
+
]);
|
|
140
|
+
clearTimeout(timer);
|
|
141
|
+
if (!winner || closed) {
|
|
142
|
+
upstream.close();
|
|
143
|
+
throw new Error("the server did not complete the SSE handshake");
|
|
144
|
+
}
|
|
145
|
+
return upstream;
|
|
146
|
+
}
|
|
147
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
148
|
+
0 && (module.exports = {
|
|
149
|
+
TOKEN_HEADER,
|
|
150
|
+
UpstreamRefused,
|
|
151
|
+
connectSseUpstream
|
|
152
|
+
});
|