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,221 @@
|
|
|
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 claude_code_parallel_exports = {};
|
|
29
|
+
__export(claude_code_parallel_exports, {
|
|
30
|
+
HOOK_TIMEOUT: () => HOOK_TIMEOUT,
|
|
31
|
+
SETTINGS_FILE: () => SETTINGS_FILE,
|
|
32
|
+
SKILL_FILE: () => SKILL_FILE,
|
|
33
|
+
SKILL_NAME: () => SKILL_NAME,
|
|
34
|
+
applyClaudeCode: () => applyClaudeCode,
|
|
35
|
+
claudeCodeDir: () => claudeCodeDir,
|
|
36
|
+
hookCommand: () => hookCommand,
|
|
37
|
+
planHook: () => planHook,
|
|
38
|
+
planSkill: () => planSkill,
|
|
39
|
+
previewClaudeCode: () => previewClaudeCode,
|
|
40
|
+
skillText: () => skillText,
|
|
41
|
+
thisMachine: () => thisMachine
|
|
42
|
+
});
|
|
43
|
+
module.exports = __toCommonJS(claude_code_parallel_exports);
|
|
44
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
45
|
+
var import_node_os = __toESM(require("node:os"));
|
|
46
|
+
var import_node_path = __toESM(require("node:path"));
|
|
47
|
+
var import_skill_guide = require("../mcp/skill-guide");
|
|
48
|
+
var import_command = require("../mcp/connector/command");
|
|
49
|
+
var import_hook = require("../mcp/connector/hook");
|
|
50
|
+
var import_claude_desktop_config = require("./claude-desktop-config");
|
|
51
|
+
var import_confined_fs = require("./confined-fs");
|
|
52
|
+
const SKILL_NAME = "codetrellis-parallel";
|
|
53
|
+
const SKILL_FILE = `skills/${SKILL_NAME}/SKILL.md`;
|
|
54
|
+
const SETTINGS_FILE = "settings.json";
|
|
55
|
+
const HOOK_TIMEOUT = 10;
|
|
56
|
+
function claudeCodeDir(w) {
|
|
57
|
+
const dir = w.env.CLAUDE_CONFIG_DIR?.trim() || import_node_path.default.join(w.home, ".claude");
|
|
58
|
+
return w.exists(dir) ? dir : null;
|
|
59
|
+
}
|
|
60
|
+
function skillText() {
|
|
61
|
+
const guide = (0, import_skill_guide.buildSkillGuide)("parallel").replace(/^# .*\n+/, "");
|
|
62
|
+
return [
|
|
63
|
+
"---",
|
|
64
|
+
`name: ${SKILL_NAME}`,
|
|
65
|
+
"description: Working alongside other AI agents in the same repository (other git worktrees, clones or branches), with CodeTrellis running. Use when starting work in a repository where other agents may be working, when planning changes to shared or exported code, or when CodeTrellis reports an overlap with other work.",
|
|
66
|
+
"---",
|
|
67
|
+
"",
|
|
68
|
+
"# Working in parallel, with CodeTrellis",
|
|
69
|
+
"",
|
|
70
|
+
"The tools below are the CodeTrellis MCP server's. In Claude Code they are named",
|
|
71
|
+
"`mcp__codetrellis__<tool>` (for example `mcp__codetrellis__get_awareness`). If they",
|
|
72
|
+
"are not available, CodeTrellis is not connected: say so rather than guessing.",
|
|
73
|
+
"",
|
|
74
|
+
"This skill is written by the CodeTrellis app (Settings \u2192 Connect an agent). The same",
|
|
75
|
+
"guide is served by the app as `codetrellis://skill/parallel`.",
|
|
76
|
+
"",
|
|
77
|
+
guide.trimEnd(),
|
|
78
|
+
""
|
|
79
|
+
].join("\n");
|
|
80
|
+
}
|
|
81
|
+
function hookCommand(connector) {
|
|
82
|
+
const env = Object.entries(connector.env).map(([k, v]) => `${k}=${(0, import_command.shellQuote)(v, "linux")}`);
|
|
83
|
+
return [...env, (0, import_command.shellQuote)(connector.command, "linux"), ...connector.args.map((a) => (0, import_command.shellQuote)(a, "linux")), import_hook.HOOK_FLAG, import_hook.HOOK_PRE_TOOL_USE].join(" ");
|
|
84
|
+
}
|
|
85
|
+
const isOurHook = (h) => !!h && typeof h === "object" && typeof h.command === "string" && /mcp-connector\.cjs/.test(h.command) && h.command.includes(`${import_hook.HOOK_FLAG} ${import_hook.HOOK_PRE_TOOL_USE}`);
|
|
86
|
+
const planned = (before, after, existed) => {
|
|
87
|
+
const status = before === after ? "unchanged" : existed ? "update" : "add";
|
|
88
|
+
return { ok: true, status, before, after, diff: status === "unchanged" ? [] : (0, import_claude_desktop_config.lineDiff)(before, after) };
|
|
89
|
+
};
|
|
90
|
+
function planSkill(current) {
|
|
91
|
+
return planned(current ?? "", skillText(), current !== null);
|
|
92
|
+
}
|
|
93
|
+
function planHook(current, command) {
|
|
94
|
+
let doc = {};
|
|
95
|
+
if (current !== null && current.trim() !== "") {
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = JSON.parse(current);
|
|
99
|
+
} catch {
|
|
100
|
+
return { ok: false, reason: "Claude Code's settings.json is not valid JSON, so it was left alone. Fix it, then try again." };
|
|
101
|
+
}
|
|
102
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
103
|
+
return { ok: false, reason: "Claude Code's settings.json is not a JSON object, so it was left alone." };
|
|
104
|
+
}
|
|
105
|
+
doc = parsed;
|
|
106
|
+
}
|
|
107
|
+
const hooks = doc.hooks ?? {};
|
|
108
|
+
if (!hooks || typeof hooks !== "object" || Array.isArray(hooks)) {
|
|
109
|
+
return { ok: false, reason: `Claude Code's settings have a "hooks" that is not an object, so they were left alone.` };
|
|
110
|
+
}
|
|
111
|
+
const pre = hooks.PreToolUse ?? [];
|
|
112
|
+
if (!Array.isArray(pre)) {
|
|
113
|
+
return { ok: false, reason: `Claude Code's settings have a "PreToolUse" that is not a list, so they were left alone.` };
|
|
114
|
+
}
|
|
115
|
+
const ours = { type: "command", command, timeout: HOOK_TIMEOUT };
|
|
116
|
+
let placed = false;
|
|
117
|
+
const kept = pre.flatMap((group) => {
|
|
118
|
+
const g = group;
|
|
119
|
+
if (!g || typeof g !== "object" || !Array.isArray(g.hooks) || !g.hooks.some(isOurHook)) return [group];
|
|
120
|
+
const others = g.hooks.filter((h) => !isOurHook(h));
|
|
121
|
+
const mine = placed ? [] : [{ matcher: import_hook.HOOK_MATCHER, hooks: [ours] }];
|
|
122
|
+
placed = true;
|
|
123
|
+
return [...mine, ...others.length ? [{ ...g, hooks: others }] : []];
|
|
124
|
+
});
|
|
125
|
+
const next = placed ? kept : [...kept, { matcher: import_hook.HOOK_MATCHER, hooks: [ours] }];
|
|
126
|
+
const merged = { ...doc, hooks: { ...hooks, PreToolUse: next } };
|
|
127
|
+
const before = current ?? "";
|
|
128
|
+
const unchanged = current !== null && JSON.stringify(JSON.parse(current || "{}")) === JSON.stringify(merged);
|
|
129
|
+
return planned(before, unchanged ? before : `${JSON.stringify(merged, null, 2)}
|
|
130
|
+
`, current !== null);
|
|
131
|
+
}
|
|
132
|
+
function readCurrent(dir, rel, label) {
|
|
133
|
+
if (!import_node_fs.default.existsSync(import_node_path.default.join(dir, rel))) return { text: null };
|
|
134
|
+
try {
|
|
135
|
+
return { text: (0, import_confined_fs.readTextWithin)(dir, rel, label) };
|
|
136
|
+
} catch {
|
|
137
|
+
return { error: `Claude Code's ${label} could not be read (it may be a link, which is not followed), so it was left alone.` };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const NO_DIR = "Claude Code's settings folder (~/.claude) was not found on this computer. Install Claude Code and run it once, then try again.";
|
|
141
|
+
const NO_CONNECTOR = "The connector is not built in this checkout, so there is no hook to add yet (npm run build:connector).";
|
|
142
|
+
function previewItem(dir, rel, label, plan) {
|
|
143
|
+
const current = readCurrent(dir, rel, label);
|
|
144
|
+
if ("error" in current) return current;
|
|
145
|
+
const p = plan(current.text);
|
|
146
|
+
if (!p.ok) return { error: p.reason };
|
|
147
|
+
return { path: import_node_path.default.join(dir, rel), status: p.status, diff: p.diff, beforeHash: (0, import_claude_desktop_config.hashOf)(current.text), exists: current.text !== null };
|
|
148
|
+
}
|
|
149
|
+
function previewClaudeCode(where, connector) {
|
|
150
|
+
const dir = claudeCodeDir(where);
|
|
151
|
+
if (!dir) return { ok: false, reason: NO_DIR };
|
|
152
|
+
const skill = previewItem(dir, SKILL_FILE, "skill file", planSkill);
|
|
153
|
+
if ("error" in skill) return { ok: false, reason: skill.error };
|
|
154
|
+
let hook;
|
|
155
|
+
if (!connector) hook = { unavailable: NO_CONNECTOR };
|
|
156
|
+
else {
|
|
157
|
+
const h = previewItem(dir, SETTINGS_FILE, "settings.json", (t) => planHook(t, hookCommand(connector)));
|
|
158
|
+
hook = "error" in h ? { unavailable: h.error } : { ...h, ...connector.caveat ? { caveat: connector.caveat } : {} };
|
|
159
|
+
}
|
|
160
|
+
return { ok: true, dir, skill, hook };
|
|
161
|
+
}
|
|
162
|
+
const stampOf = (now) => now.toISOString().replace(/[:.]/g, "-");
|
|
163
|
+
function applyClaudeCode(where, connector, choice, now = /* @__PURE__ */ new Date()) {
|
|
164
|
+
const dir = claudeCodeDir(where);
|
|
165
|
+
if (!dir) return { ok: false, reason: NO_DIR };
|
|
166
|
+
if (!choice.skill && !choice.hook) return { ok: false, reason: "Choose the skill, the hook, or both." };
|
|
167
|
+
if (choice.hook && !connector) return { ok: false, reason: NO_CONNECTOR };
|
|
168
|
+
const items = [];
|
|
169
|
+
if (choice.skill) items.push({ key: "skill", rel: SKILL_FILE, label: "skill file", shown: choice.skill, plan: planSkill });
|
|
170
|
+
if (choice.hook) items.push({ key: "hook", rel: SETTINGS_FILE, label: "settings.json", shown: choice.hook, plan: (t) => planHook(t, hookCommand(connector)) });
|
|
171
|
+
const ready = [];
|
|
172
|
+
for (const it of items) {
|
|
173
|
+
const current = readCurrent(dir, it.rel, it.label);
|
|
174
|
+
if ("error" in current) return { ok: false, reason: current.error };
|
|
175
|
+
if ((0, import_claude_desktop_config.hashOf)(current.text) !== it.shown) {
|
|
176
|
+
return { ok: false, changed: true, reason: `Claude Code's ${it.label} changed after you looked at it. Here is the change again, against the file as it is now.` };
|
|
177
|
+
}
|
|
178
|
+
const plan = it.plan(current.text);
|
|
179
|
+
if (!plan.ok) return plan;
|
|
180
|
+
ready.push({ key: it.key, rel: it.rel, label: it.label, current: current.text, plan });
|
|
181
|
+
}
|
|
182
|
+
const out = {};
|
|
183
|
+
try {
|
|
184
|
+
for (const r of ready) {
|
|
185
|
+
const target = import_node_path.default.join(dir, r.rel);
|
|
186
|
+
if (r.plan.status === "unchanged") {
|
|
187
|
+
out[r.key] = { path: target, backupPath: null, status: "unchanged" };
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
let backupPath = null;
|
|
191
|
+
if (r.current !== null) {
|
|
192
|
+
const ext = import_node_path.default.extname(r.rel);
|
|
193
|
+
const backupRel = `${r.rel.slice(0, -ext.length)}.before-codetrellis-${stampOf(now)}${ext}`;
|
|
194
|
+
backupPath = (0, import_confined_fs.writeFileWithin)(dir, backupRel, r.current, `Claude Code ${r.label} backup`);
|
|
195
|
+
}
|
|
196
|
+
(0, import_confined_fs.writeFileWithin)(dir, r.rel, r.plan.after, `Claude Code ${r.label}`);
|
|
197
|
+
out[r.key] = { path: target, backupPath, status: r.plan.status };
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
return { ok: false, reason: "Claude Code's files could not be written (a link at their place is not written through). Anything already written is listed by a fresh preview." };
|
|
201
|
+
}
|
|
202
|
+
return { ok: true, ...out };
|
|
203
|
+
}
|
|
204
|
+
function thisMachine() {
|
|
205
|
+
return { home: import_node_os.default.homedir(), env: process.env, exists: (p) => import_node_fs.default.existsSync(p) };
|
|
206
|
+
}
|
|
207
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
208
|
+
0 && (module.exports = {
|
|
209
|
+
HOOK_TIMEOUT,
|
|
210
|
+
SETTINGS_FILE,
|
|
211
|
+
SKILL_FILE,
|
|
212
|
+
SKILL_NAME,
|
|
213
|
+
applyClaudeCode,
|
|
214
|
+
claudeCodeDir,
|
|
215
|
+
hookCommand,
|
|
216
|
+
planHook,
|
|
217
|
+
planSkill,
|
|
218
|
+
previewClaudeCode,
|
|
219
|
+
skillText,
|
|
220
|
+
thisMachine
|
|
221
|
+
});
|
|
@@ -0,0 +1,186 @@
|
|
|
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 claude_desktop_config_exports = {};
|
|
29
|
+
__export(claude_desktop_config_exports, {
|
|
30
|
+
CONFIG_NAME: () => CONFIG_NAME,
|
|
31
|
+
applyClaudeDesktop: () => applyClaudeDesktop,
|
|
32
|
+
claudeDesktopConfigDir: () => claudeDesktopConfigDir,
|
|
33
|
+
hashOf: () => hashOf,
|
|
34
|
+
lineDiff: () => lineDiff,
|
|
35
|
+
planMerge: () => planMerge,
|
|
36
|
+
previewClaudeDesktop: () => previewClaudeDesktop,
|
|
37
|
+
thisMachine: () => thisMachine
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(claude_desktop_config_exports);
|
|
40
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
41
|
+
var import_node_os = __toESM(require("node:os"));
|
|
42
|
+
var import_node_path = __toESM(require("node:path"));
|
|
43
|
+
var import_node_crypto = require("node:crypto");
|
|
44
|
+
var import_confined_fs = require("./confined-fs");
|
|
45
|
+
const CONFIG_NAME = "claude_desktop_config.json";
|
|
46
|
+
function claudeDesktopConfigDir(w) {
|
|
47
|
+
const candidates = [];
|
|
48
|
+
if (w.platform === "darwin") {
|
|
49
|
+
candidates.push(import_node_path.default.join(w.home, "Library", "Application Support", "Claude"));
|
|
50
|
+
} else if (w.platform === "win32") {
|
|
51
|
+
const appData = w.env.APPDATA ?? import_node_path.default.join(w.home, "AppData", "Roaming");
|
|
52
|
+
candidates.push(import_node_path.default.join(appData, "Claude"));
|
|
53
|
+
const local = w.env.LOCALAPPDATA ?? import_node_path.default.join(w.home, "AppData", "Local");
|
|
54
|
+
const packages = import_node_path.default.join(local, "Packages");
|
|
55
|
+
if (w.exists(packages)) {
|
|
56
|
+
for (const name of w.list(packages).filter((n) => /^Claude_/i.test(n)).sort()) {
|
|
57
|
+
candidates.push(import_node_path.default.join(packages, name, "LocalCache", "Roaming", "Claude"));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} else {
|
|
61
|
+
candidates.push(import_node_path.default.join(w.env.XDG_CONFIG_HOME || import_node_path.default.join(w.home, ".config"), "Claude"));
|
|
62
|
+
}
|
|
63
|
+
return candidates.find((d) => w.exists(d)) ?? null;
|
|
64
|
+
}
|
|
65
|
+
function lineDiff(before, after) {
|
|
66
|
+
const a = before === "" ? [] : before.replace(/\n$/, "").split("\n");
|
|
67
|
+
const b = after.replace(/\n$/, "").split("\n");
|
|
68
|
+
const n = a.length;
|
|
69
|
+
const m = b.length;
|
|
70
|
+
const lcs = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
|
|
71
|
+
for (let i2 = n - 1; i2 >= 0; i2--) {
|
|
72
|
+
for (let j2 = m - 1; j2 >= 0; j2--) {
|
|
73
|
+
lcs[i2][j2] = a[i2] === b[j2] ? lcs[i2 + 1][j2 + 1] + 1 : Math.max(lcs[i2 + 1][j2], lcs[i2][j2 + 1]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const out = [];
|
|
77
|
+
let i = 0;
|
|
78
|
+
let j = 0;
|
|
79
|
+
while (i < n && j < m) {
|
|
80
|
+
if (a[i] === b[j]) {
|
|
81
|
+
out.push({ op: " ", text: a[i] });
|
|
82
|
+
i++;
|
|
83
|
+
j++;
|
|
84
|
+
} else if (lcs[i + 1][j] >= lcs[i][j + 1]) out.push({ op: "-", text: a[i++] });
|
|
85
|
+
else out.push({ op: "+", text: b[j++] });
|
|
86
|
+
}
|
|
87
|
+
while (i < n) out.push({ op: "-", text: a[i++] });
|
|
88
|
+
while (j < m) out.push({ op: "+", text: b[j++] });
|
|
89
|
+
return out;
|
|
90
|
+
}
|
|
91
|
+
function planMerge(current, entry) {
|
|
92
|
+
let doc = {};
|
|
93
|
+
if (current !== null && current.trim() !== "") {
|
|
94
|
+
let parsed;
|
|
95
|
+
try {
|
|
96
|
+
parsed = JSON.parse(current);
|
|
97
|
+
} catch {
|
|
98
|
+
return { ok: false, reason: "Claude Desktop's config file is not valid JSON, so it was left alone. Fix or remove it, then try again." };
|
|
99
|
+
}
|
|
100
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
101
|
+
return { ok: false, reason: "Claude Desktop's config file is not a JSON object, so it was left alone." };
|
|
102
|
+
}
|
|
103
|
+
doc = parsed;
|
|
104
|
+
}
|
|
105
|
+
const servers = doc.mcpServers ?? {};
|
|
106
|
+
if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
|
|
107
|
+
return { ok: false, reason: `Claude Desktop's config has an "mcpServers" that is not an object, so it was left alone.` };
|
|
108
|
+
}
|
|
109
|
+
const existing = servers.codetrellis;
|
|
110
|
+
const status = existing === void 0 ? "add" : JSON.stringify(existing) === JSON.stringify(entry) ? "unchanged" : "update";
|
|
111
|
+
const merged = { ...doc, mcpServers: { ...servers, codetrellis: entry } };
|
|
112
|
+
const before = current ?? "";
|
|
113
|
+
const after = status === "unchanged" ? before : `${JSON.stringify(merged, null, 2)}
|
|
114
|
+
`;
|
|
115
|
+
return { ok: true, status, before, after, diff: status === "unchanged" ? [] : lineDiff(before, after) };
|
|
116
|
+
}
|
|
117
|
+
const hashOf = (text) => (0, import_node_crypto.createHash)("sha256").update(text ?? "\0absent").digest("hex");
|
|
118
|
+
function readCurrent(dir) {
|
|
119
|
+
if (!import_node_fs.default.existsSync(import_node_path.default.join(dir, CONFIG_NAME))) return { text: null };
|
|
120
|
+
try {
|
|
121
|
+
return { text: (0, import_confined_fs.readTextWithin)(dir, CONFIG_NAME, "Claude Desktop config") };
|
|
122
|
+
} catch {
|
|
123
|
+
return { error: "Claude Desktop's config file could not be read (it may be a link, which is not followed), so it was left alone." };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function previewClaudeDesktop(where, entry) {
|
|
127
|
+
if (!entry) return { ok: false, reason: "The connector is not built in this checkout, so there is nothing to add yet (npm run build:connector)." };
|
|
128
|
+
const dir = claudeDesktopConfigDir(where);
|
|
129
|
+
if (!dir) return { ok: false, reason: "Claude Desktop's settings folder was not found on this computer. Install Claude Desktop and open it once, then try again." };
|
|
130
|
+
const current = readCurrent(dir);
|
|
131
|
+
if ("error" in current) return { ok: false, reason: current.error };
|
|
132
|
+
const plan = planMerge(current.text, entry);
|
|
133
|
+
if (!plan.ok) return plan;
|
|
134
|
+
return { ok: true, path: import_node_path.default.join(dir, CONFIG_NAME), status: plan.status, diff: plan.diff, beforeHash: hashOf(current.text), exists: current.text !== null };
|
|
135
|
+
}
|
|
136
|
+
function applyClaudeDesktop(where, entry, shownHash, now = /* @__PURE__ */ new Date()) {
|
|
137
|
+
if (!entry) return { ok: false, reason: "The connector is not built in this checkout." };
|
|
138
|
+
const dir = claudeDesktopConfigDir(where);
|
|
139
|
+
if (!dir) return { ok: false, reason: "Claude Desktop's settings folder was not found on this computer." };
|
|
140
|
+
const current = readCurrent(dir);
|
|
141
|
+
if ("error" in current) return { ok: false, reason: current.error };
|
|
142
|
+
if (hashOf(current.text) !== shownHash) {
|
|
143
|
+
return { ok: false, changed: true, reason: "Claude Desktop's config changed after you looked at it. Here is the change again, against the file as it is now." };
|
|
144
|
+
}
|
|
145
|
+
const plan = planMerge(current.text, entry);
|
|
146
|
+
if (!plan.ok) return plan;
|
|
147
|
+
const target = import_node_path.default.join(dir, CONFIG_NAME);
|
|
148
|
+
if (plan.status === "unchanged") return { ok: true, path: target, backupPath: null, status: "unchanged" };
|
|
149
|
+
try {
|
|
150
|
+
let backupPath = null;
|
|
151
|
+
if (current.text !== null) {
|
|
152
|
+
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
153
|
+
backupPath = (0, import_confined_fs.writeFileWithin)(dir, `claude_desktop_config.before-codetrellis-${stamp}.json`, current.text, "Claude Desktop config backup");
|
|
154
|
+
}
|
|
155
|
+
(0, import_confined_fs.writeFileWithin)(dir, CONFIG_NAME, plan.after, "Claude Desktop config");
|
|
156
|
+
return { ok: true, path: target, backupPath, status: plan.status };
|
|
157
|
+
} catch {
|
|
158
|
+
return { ok: false, reason: "Claude Desktop's config could not be written (a link at its place is not written through). Nothing was changed." };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function thisMachine() {
|
|
162
|
+
return {
|
|
163
|
+
platform: process.platform,
|
|
164
|
+
env: process.env,
|
|
165
|
+
home: import_node_os.default.homedir(),
|
|
166
|
+
exists: (p) => import_node_fs.default.existsSync(p),
|
|
167
|
+
list: (d) => {
|
|
168
|
+
try {
|
|
169
|
+
return import_node_fs.default.readdirSync(d);
|
|
170
|
+
} catch {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
177
|
+
0 && (module.exports = {
|
|
178
|
+
CONFIG_NAME,
|
|
179
|
+
applyClaudeDesktop,
|
|
180
|
+
claudeDesktopConfigDir,
|
|
181
|
+
hashOf,
|
|
182
|
+
lineDiff,
|
|
183
|
+
planMerge,
|
|
184
|
+
previewClaudeDesktop,
|
|
185
|
+
thisMachine
|
|
186
|
+
});
|
|
@@ -0,0 +1,249 @@
|
|
|
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 cli_install_exports = {};
|
|
29
|
+
__export(cli_install_exports, {
|
|
30
|
+
LAUNCHER_MARK: () => LAUNCHER_MARK,
|
|
31
|
+
appImageLauncher: () => appImageLauncher,
|
|
32
|
+
applyCliInstall: () => applyCliInstall,
|
|
33
|
+
planCliInstall: () => planCliInstall,
|
|
34
|
+
refreshCliInstall: () => refreshCliInstall,
|
|
35
|
+
removeCliInstall: () => removeCliInstall,
|
|
36
|
+
thisCliMachine: () => thisCliMachine
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(cli_install_exports);
|
|
39
|
+
var import_node_child_process = require("node:child_process");
|
|
40
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
41
|
+
var import_node_path = __toESM(require("node:path"));
|
|
42
|
+
var import_command = require("../mcp/connector/command");
|
|
43
|
+
const LAUNCHER_MARK = "Written by the CodeTrellis app";
|
|
44
|
+
const join = (m, ...p) => m.platform === "win32" ? import_node_path.default.win32.join(...p) : import_node_path.default.posix.join(...p);
|
|
45
|
+
function onPathOf(m, dir) {
|
|
46
|
+
const list = (m.env.PATH ?? "").split(m.platform === "win32" ? ";" : ":").map((d) => d.replace(/[\\/]+$/, ""));
|
|
47
|
+
return list.some((d) => m.platform === "win32" ? d.toLowerCase() === dir.toLowerCase() : d === dir);
|
|
48
|
+
}
|
|
49
|
+
function appImageLauncher(appImage) {
|
|
50
|
+
const q = `'${appImage.replace(/'/g, `'\\''`)}'`;
|
|
51
|
+
return [
|
|
52
|
+
"#!/bin/sh",
|
|
53
|
+
`# codetrellis: ${LAUNCHER_MARK} for the AppImage below; it rewrites this`,
|
|
54
|
+
"# file if the AppImage moves. Runs the CLI the app carries, in Node mode.",
|
|
55
|
+
// --no-sandbox last, after --: the AppImage's AppRun adds it as the first
|
|
56
|
+
// argument unless it is already there, and in Node mode that is a "bad
|
|
57
|
+
// option". As the connector's AppImage command does; app.cjs drops it.
|
|
58
|
+
`ELECTRON_RUN_AS_NODE=1 exec ${q} -e "require(require('path').join(process.resourcesPath, 'cli', 'bin', 'app.cjs'))" -- "$@" --no-sandbox`,
|
|
59
|
+
""
|
|
60
|
+
].join("\n");
|
|
61
|
+
}
|
|
62
|
+
function readLink(p) {
|
|
63
|
+
try {
|
|
64
|
+
return import_node_fs.default.readlinkSync(p);
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function readText(p) {
|
|
70
|
+
try {
|
|
71
|
+
return import_node_fs.default.readFileSync(p, "utf8");
|
|
72
|
+
} catch {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function present(p) {
|
|
77
|
+
try {
|
|
78
|
+
import_node_fs.default.lstatSync(p);
|
|
79
|
+
return true;
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function oursAt(p) {
|
|
85
|
+
const link = readLink(p);
|
|
86
|
+
if (link) return /[\\/]cli[\\/]bin[\\/]codetrellis$/.test(link);
|
|
87
|
+
return (readText(p) ?? "").includes(LAUNCHER_MARK);
|
|
88
|
+
}
|
|
89
|
+
function planCliInstall(m) {
|
|
90
|
+
if (!(0, import_command.isPackagedElectron)({ execPath: m.execPath, electronVersion: m.electronVersion }) || !m.resourcesPath) {
|
|
91
|
+
return { ok: false, reason: "Only the installed app can add the codetrellis command. From a checkout, run npm link; anywhere, npm install -g codetrellis." };
|
|
92
|
+
}
|
|
93
|
+
if (m.platform === "win32" && m.env.PORTABLE_EXECUTABLE_FILE) {
|
|
94
|
+
return { ok: false, reason: "The portable build unpacks to a temporary folder each time it starts, so a command on the PATH would stop working. Use the installer, or npm install -g codetrellis." };
|
|
95
|
+
}
|
|
96
|
+
const binDir = join(m, m.resourcesPath, "cli", "bin");
|
|
97
|
+
if (m.platform === "win32") {
|
|
98
|
+
const userPath = m.windowsUserPath?.() ?? "";
|
|
99
|
+
const has = userPath.split(";").some((d) => d.replace(/[\\/]+$/, "").toLowerCase() === binDir.toLowerCase());
|
|
100
|
+
return {
|
|
101
|
+
ok: true,
|
|
102
|
+
how: "path",
|
|
103
|
+
target: binDir,
|
|
104
|
+
source: join(m, binDir, "codetrellis.cmd"),
|
|
105
|
+
admin: false,
|
|
106
|
+
state: has ? "installed" : "missing",
|
|
107
|
+
onPath: onPathOf(m, binDir),
|
|
108
|
+
says: `Adds ${binDir} to your PATH. Open a new terminal afterwards.`
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const localBin = import_node_path.default.posix.join(m.home, ".local", "bin");
|
|
112
|
+
const appImage = m.platform === "linux" && m.env.APPIMAGE && m.env.APPDIR && import_node_path.default.isAbsolute(m.env.APPIMAGE) && m.resourcesPath.startsWith(m.env.APPDIR) ? m.env.APPIMAGE : null;
|
|
113
|
+
const source = appImage ?? import_node_path.default.posix.join(binDir, "codetrellis");
|
|
114
|
+
const how = appImage ? "launcher" : "link";
|
|
115
|
+
const target = m.platform === "darwin" ? import_node_path.default.posix.join(m.macBin ?? "/usr/local/bin", "codetrellis") : import_node_path.default.posix.join(localBin, "codetrellis");
|
|
116
|
+
const dir = import_node_path.default.posix.dirname(target);
|
|
117
|
+
const admin = m.platform === "darwin" && !writable(dir);
|
|
118
|
+
let state = "missing";
|
|
119
|
+
let existing;
|
|
120
|
+
if (present(target)) {
|
|
121
|
+
const link = readLink(target);
|
|
122
|
+
if (how === "link" && link === source) state = "installed";
|
|
123
|
+
else if (how === "launcher" && readText(target) === appImageLauncher(appImage)) state = "installed";
|
|
124
|
+
else if (oursAt(target)) state = "stale";
|
|
125
|
+
else {
|
|
126
|
+
state = "other";
|
|
127
|
+
existing = link ? `a link to ${link}` : "a file CodeTrellis did not write";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const says = how === "launcher" ? `Writes ${target}, which runs this AppImage as the codetrellis command.` : `Links ${target} to the codetrellis command inside the app${admin ? ". macOS asks for your password to write there" : ""}.`;
|
|
131
|
+
return { ok: true, how, target, source, admin, state, existing, onPath: onPathOf(m, dir), says };
|
|
132
|
+
}
|
|
133
|
+
function writable(dir) {
|
|
134
|
+
try {
|
|
135
|
+
import_node_fs.default.accessSync(dir, import_node_fs.default.constants.W_OK);
|
|
136
|
+
return true;
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const appleString = (s) => `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
142
|
+
const runProgram = (command, args, env) => new Promise((resolve, reject) => {
|
|
143
|
+
(0, import_node_child_process.execFile)(command, args, { env: env ? { ...process.env, ...env } : process.env }, (err) => err ? reject(err) : resolve());
|
|
144
|
+
});
|
|
145
|
+
async function applyCliInstall(m, opts = {}, run = runProgram) {
|
|
146
|
+
const plan = planCliInstall(m);
|
|
147
|
+
if (!plan.ok) return plan;
|
|
148
|
+
if (plan.state === "installed") return { ok: true, target: plan.target, onPath: plan.onPath };
|
|
149
|
+
if (plan.state === "other" && !opts.replace) {
|
|
150
|
+
return { ok: false, reason: `${plan.target} is already ${plan.existing}. Choose Replace to put the app's command there instead.` };
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
if (plan.how === "path") {
|
|
154
|
+
await run(
|
|
155
|
+
"powershell.exe",
|
|
156
|
+
[
|
|
157
|
+
"-NoProfile",
|
|
158
|
+
"-NonInteractive",
|
|
159
|
+
"-Command",
|
|
160
|
+
"$p=[Environment]::GetEnvironmentVariable('Path','User'); if (-not $p) { $p='' }; $parts=@($p -split ';' | Where-Object { $_ -and ($_.TrimEnd('\\') -ne $env:CT_DIR.TrimEnd('\\')) }); [Environment]::SetEnvironmentVariable('Path', (($parts + $env:CT_DIR) -join ';'), 'User')"
|
|
161
|
+
],
|
|
162
|
+
{ CT_DIR: plan.target }
|
|
163
|
+
);
|
|
164
|
+
} else if (plan.how === "launcher") {
|
|
165
|
+
import_node_fs.default.mkdirSync(import_node_path.default.posix.dirname(plan.target), { recursive: true });
|
|
166
|
+
if (present(plan.target)) import_node_fs.default.rmSync(plan.target, { force: true });
|
|
167
|
+
import_node_fs.default.writeFileSync(plan.target, appImageLauncher(plan.source), { mode: 493 });
|
|
168
|
+
} else if (plan.admin) {
|
|
169
|
+
const dir = import_node_path.default.posix.dirname(plan.target);
|
|
170
|
+
const script = `do shell script "mkdir -p " & quoted form of ${appleString(dir)} & " && ln -sf " & quoted form of ${appleString(plan.source)} & " " & quoted form of ${appleString(plan.target)} with administrator privileges`;
|
|
171
|
+
await run("osascript", ["-e", script]);
|
|
172
|
+
} else {
|
|
173
|
+
import_node_fs.default.mkdirSync(import_node_path.default.posix.dirname(plan.target), { recursive: true });
|
|
174
|
+
if (present(plan.target)) import_node_fs.default.rmSync(plan.target, { force: true });
|
|
175
|
+
import_node_fs.default.symlinkSync(plan.source, plan.target);
|
|
176
|
+
}
|
|
177
|
+
} catch (err) {
|
|
178
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
179
|
+
return { ok: false, reason: /User canceled|-128/.test(msg) ? "Cancelled: macOS did not get the password." : `Could not add the command: ${msg}` };
|
|
180
|
+
}
|
|
181
|
+
const after = planCliInstall(m);
|
|
182
|
+
if (!after.ok || after.state !== "installed") return { ok: false, reason: `The command was not added at ${plan.target}.` };
|
|
183
|
+
return { ok: true, target: after.target, onPath: after.onPath };
|
|
184
|
+
}
|
|
185
|
+
async function refreshCliInstall(m) {
|
|
186
|
+
const plan = planCliInstall(m);
|
|
187
|
+
if (!plan.ok || plan.state !== "stale" || plan.admin || plan.how === "path") return false;
|
|
188
|
+
return (await applyCliInstall(m)).ok;
|
|
189
|
+
}
|
|
190
|
+
async function removeCliInstall(m, run = runProgram) {
|
|
191
|
+
const plan = planCliInstall(m);
|
|
192
|
+
if (!plan.ok) return plan;
|
|
193
|
+
if (plan.state === "missing") return { ok: true, target: plan.target, onPath: plan.onPath };
|
|
194
|
+
if (plan.state === "other") return { ok: false, reason: `${plan.target} is not CodeTrellis's; it was left as it is.` };
|
|
195
|
+
try {
|
|
196
|
+
if (plan.how === "path") {
|
|
197
|
+
await run(
|
|
198
|
+
"powershell.exe",
|
|
199
|
+
[
|
|
200
|
+
"-NoProfile",
|
|
201
|
+
"-NonInteractive",
|
|
202
|
+
"-Command",
|
|
203
|
+
"$p=[Environment]::GetEnvironmentVariable('Path','User'); if (-not $p) { $p='' }; [Environment]::SetEnvironmentVariable('Path', ((@($p -split ';' | Where-Object { $_ -and ($_.TrimEnd('\\') -ne $env:CT_DIR.TrimEnd('\\')) })) -join ';'), 'User')"
|
|
204
|
+
],
|
|
205
|
+
{ CT_DIR: plan.target }
|
|
206
|
+
);
|
|
207
|
+
} else if (plan.admin) {
|
|
208
|
+
await run("osascript", ["-e", `do shell script "rm -f " & quoted form of ${appleString(plan.target)} with administrator privileges`]);
|
|
209
|
+
} else {
|
|
210
|
+
import_node_fs.default.rmSync(plan.target, { force: true });
|
|
211
|
+
}
|
|
212
|
+
} catch (err) {
|
|
213
|
+
return { ok: false, reason: `Could not remove the command: ${err instanceof Error ? err.message : String(err)}` };
|
|
214
|
+
}
|
|
215
|
+
return { ok: true, target: plan.target, onPath: plan.onPath };
|
|
216
|
+
}
|
|
217
|
+
function thisCliMachine() {
|
|
218
|
+
return {
|
|
219
|
+
platform: process.platform,
|
|
220
|
+
home: process.env.HOME || process.env.USERPROFILE || "",
|
|
221
|
+
execPath: process.execPath,
|
|
222
|
+
resourcesPath: process.resourcesPath,
|
|
223
|
+
electronVersion: process.versions.electron,
|
|
224
|
+
env: {
|
|
225
|
+
APPIMAGE: process.env.APPIMAGE,
|
|
226
|
+
APPDIR: process.env.APPDIR,
|
|
227
|
+
PORTABLE_EXECUTABLE_FILE: process.env.PORTABLE_EXECUTABLE_FILE,
|
|
228
|
+
PATH: process.env.PATH
|
|
229
|
+
},
|
|
230
|
+
windowsUserPath: () => {
|
|
231
|
+
try {
|
|
232
|
+
const out = (0, import_node_child_process.execFileSync)("reg", ["query", "HKCU\\Environment", "/v", "Path"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
233
|
+
return /Path\s+REG_(?:EXPAND_)?SZ\s+(.*)/i.exec(out)?.[1]?.trim() ?? null;
|
|
234
|
+
} catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
241
|
+
0 && (module.exports = {
|
|
242
|
+
LAUNCHER_MARK,
|
|
243
|
+
appImageLauncher,
|
|
244
|
+
applyCliInstall,
|
|
245
|
+
planCliInstall,
|
|
246
|
+
refreshCliInstall,
|
|
247
|
+
removeCliInstall,
|
|
248
|
+
thisCliMachine
|
|
249
|
+
});
|