@unbrained/pm-cli 2026.9.6 → 2026.9.8
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/.agents/skills/pm-developer/SKILL.md +12 -4
- package/.agents/skills/pm-developer/references/MULTI_AGENT_MERGE.md +19 -10
- package/.agents/skills/pm-extensions/SKILL.md +6 -0
- package/.agents/skills/pm-sdk/SKILL.md +11 -2
- package/.agents/skills/pm-user/SKILL.md +5 -0
- package/.agents/skills/pm-user/references/ECOSYSTEM_PLANNING.md +95 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +218 -182
- package/dist/cli/after-command-context-usage.js +1 -48
- package/dist/cli/argv-utils.js +1 -40
- package/dist/cli/bootstrap-args.js +1 -9
- package/dist/cli/bundle-integrity.js +2 -110
- package/dist/cli/commander-usage.js +11 -771
- package/dist/cli/commands/activity.js +1 -9
- package/dist/cli/commands/aggregate.js +1 -5
- package/dist/cli/commands/append.js +1 -5
- package/dist/cli/commands/claim.js +1 -5
- package/dist/cli/commands/close-many.js +1 -5
- package/dist/cli/commands/close.js +1 -9
- package/dist/cli/commands/comments.js +1 -5
- package/dist/cli/commands/config.js +1 -9
- package/dist/cli/commands/context.js +1 -9
- package/dist/cli/commands/contracts.js +1 -5
- package/dist/cli/commands/copy.js +1 -9
- package/dist/cli/commands/create.js +1 -9
- package/dist/cli/commands/delete.js +1 -9
- package/dist/cli/commands/deps.js +1 -9
- package/dist/cli/commands/docs.js +1 -9
- package/dist/cli/commands/duplicates.js +1 -9
- package/dist/cli/commands/eval.js +1 -9
- package/dist/cli/commands/extension/describe.js +1 -5
- package/dist/cli/commands/extension/scaffold.js +1 -5
- package/dist/cli/commands/extension/shared.js +1 -5
- package/dist/cli/commands/extension.js +1 -9
- package/dist/cli/commands/files.js +1 -9
- package/dist/cli/commands/focus.js +1 -9
- package/dist/cli/commands/gc.js +1 -9
- package/dist/cli/commands/get.js +1 -9
- package/dist/cli/commands/graph.js +1 -10
- package/dist/cli/commands/health.js +1 -9
- package/dist/cli/commands/history-compact.js +1 -10
- package/dist/cli/commands/history-redact.js +1 -11
- package/dist/cli/commands/history-repair.js +1 -10
- package/dist/cli/commands/history.js +1 -5
- package/dist/cli/commands/index.js +1 -58
- package/dist/cli/commands/init-agent-guidance.js +1 -9
- package/dist/cli/commands/init.js +1 -9
- package/dist/cli/commands/learnings.js +1 -5
- package/dist/cli/commands/lifecycle-transitions.js +1 -5
- package/dist/cli/commands/list.js +1 -9
- package/dist/cli/commands/merge.js +1 -11
- package/dist/cli/commands/next.js +1 -9
- package/dist/cli/commands/notes.js +1 -5
- package/dist/cli/commands/plan.js +1 -9
- package/dist/cli/commands/profile.js +1 -9
- package/dist/cli/commands/restore.js +1 -9
- package/dist/cli/commands/scheduling-shortcuts.js +1 -9
- package/dist/cli/commands/schema.js +1 -10
- package/dist/cli/commands/search.js +1 -9
- package/dist/cli/commands/stats.js +1 -9
- package/dist/cli/commands/telemetry.js +1 -9
- package/dist/cli/commands/test-all.js +1 -9
- package/dist/cli/commands/test-runs.js +1 -9
- package/dist/cli/commands/test.js +1 -9
- package/dist/cli/commands/update-many.js +1 -5
- package/dist/cli/commands/update.js +1 -9
- package/dist/cli/commands/upgrade.js +1 -5
- package/dist/cli/commands/validate.js +1 -15
- package/dist/cli/context-intent-invocation.js +1 -20
- package/dist/cli/description-stdin.js +1 -17
- package/dist/cli/error-guidance.js +1 -1353
- package/dist/cli/extension-command-help.js +5 -636
- package/dist/cli/extension-command-options.js +1 -427
- package/dist/cli/extension-recovery.js +1 -126
- package/dist/cli/help-content.js +2 -1001
- package/dist/cli/help-json-payload.js +4 -570
- package/dist/cli/main.d.ts +4 -0
- package/dist/cli/main.js +5 -2573
- package/dist/cli/migration-gates.js +1 -289
- package/dist/cli/public.js +1 -20
- package/dist/cli/register-annotations.js +1 -270
- package/dist/cli/register-assurance.js +1 -62
- package/dist/cli/register-files-lookup.js +1 -56
- package/dist/cli/register-history-activity.d.ts +8 -0
- package/dist/cli/register-history-activity.js +2 -0
- package/dist/cli/register-history-author.js +1 -38
- package/dist/cli/register-history-maintenance.d.ts +9 -0
- package/dist/cli/register-history-maintenance.js +2 -0
- package/dist/cli/register-list-query.js +10 -943
- package/dist/cli/register-mutation-options.js +1 -9
- package/dist/cli/register-mutation.js +19 -1893
- package/dist/cli/register-operations.js +1 -920
- package/dist/cli/register-setup.js +1 -716
- package/dist/cli/register-structured-mutation.js +1 -196
- package/dist/cli/registration-helpers.js +1 -5
- package/dist/cli/runtime-compatibility-boundary.js +4 -42
- package/dist/cli/schema-registration-helpers.js +1 -73
- package/dist/cli/search-refresh.js +1 -13
- package/dist/cli/stats-analytics-json.js +1 -68
- package/dist/cli/telemetry-flush.js +1 -10
- package/dist/cli-bundle/bundle-manifest.json +164 -156
- package/dist/cli-bundle/chunks/chunk-3BZZA6A3.js +5 -0
- package/dist/cli-bundle/chunks/chunk-AMRDVX36.js +235 -0
- package/dist/cli-bundle/chunks/chunk-DAM4CBBR.js +2202 -0
- package/dist/cli-bundle/chunks/{chunk-WYRZZ5ZE.js → chunk-DEZPZOQ7.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-FLDWYEND.js +77 -0
- package/dist/cli-bundle/chunks/{chunk-NPN5I67J.js → chunk-G5ADGQ2D.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-JAAEYHUA.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-JX4DH4WC.js → chunk-KR3RP4FH.js} +3 -3
- package/dist/cli-bundle/chunks/chunk-LEZOUXG6.js +2 -0
- package/dist/cli-bundle/chunks/chunk-NSAPNEYH.js +2 -0
- package/dist/cli-bundle/chunks/chunk-QOEKOECV.js +29 -0
- package/dist/cli-bundle/chunks/chunk-RHSFOMHU.js +2 -0
- package/dist/cli-bundle/chunks/chunk-XOD2PCB6.js +20 -0
- package/dist/cli-bundle/chunks/{chunk-JT6XF6GE.js → chunk-YVEQ2AMO.js} +4 -4
- package/dist/cli-bundle/chunks/register-list-query-KSK3R63M.js +11 -0
- package/dist/cli-bundle/chunks/register-mutation-IQ5C7U6O.js +20 -0
- package/dist/cli-bundle/chunks/{register-operations-I5W3KMGB.js → register-operations-DWVHR2NC.js} +2 -2
- package/dist/cli-bundle/chunks/register-setup-BQ5SVD4B.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-3WRPWLA7.js +3 -0
- package/dist/cli-bundle/focused-chunks/chunk-7MBUII7U.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-COPBO5HW.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-DUN4IXYN.js +20 -0
- package/dist/cli-bundle/focused-chunks/{chunk-LIJIA4TY.js → chunk-EE5QSM4Z.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-HJVARYM3.js +6 -0
- package/dist/cli-bundle/focused-chunks/chunk-IAUOUGVR.js +177 -0
- package/dist/cli-bundle/focused-chunks/chunk-KOOMJ54F.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MZDXX7JY.js +56 -0
- package/dist/cli-bundle/focused-chunks/{chunk-M6PBRFSH.js → chunk-OPFHFGDD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QHNETP77.js +9 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3BZEOXLT.js → chunk-RMWES4M6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-RXT4P5QH.js +10 -0
- package/dist/cli-bundle/focused-chunks/chunk-SDOL6FM2.js +12 -0
- package/dist/cli-bundle/focused-chunks/chunk-SQV4AAUC.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PEFABF7E.js → chunk-WE3IUNIW.js} +3 -3
- package/dist/cli-bundle/focused-chunks/chunk-YALOUBWJ.js +2 -0
- package/dist/cli-bundle/main.js +20 -20
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +29 -29
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +42 -42
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +11 -11
- package/dist/cli.js +1 -104
- package/dist/core/checkpoint/checkpoint-gc.js +1 -169
- package/dist/core/checkpoint/mutation-checkpoint.js +2 -133
- package/dist/core/config/nested-settings.js +1 -534
- package/dist/core/config/positional-value.js +1 -109
- package/dist/core/diagnostics/remediation.js +1 -506
- package/dist/core/extensions/activation-summary-markdown.js +2 -145
- package/dist/core/extensions/activation-summary.js +1 -92
- package/dist/core/extensions/activation-transaction.js +1 -46
- package/dist/core/extensions/capability-usage.js +1 -173
- package/dist/core/extensions/command-hook-context.js +1 -13
- package/dist/core/extensions/command-metadata-contract.js +1 -22
- package/dist/core/extensions/command-visibility-tier.js +1 -29
- package/dist/core/extensions/contribution-inventory.js +1 -173
- package/dist/core/extensions/exporter-output-contract.js +1 -66
- package/dist/core/extensions/extension-candidate.js +1 -18
- package/dist/core/extensions/extension-capability-aliases.js +1 -158
- package/dist/core/extensions/extension-hook-runtime.js +1 -699
- package/dist/core/extensions/extension-policy.js +1 -599
- package/dist/core/extensions/extension-registries.js +1 -62
- package/dist/core/extensions/extension-runtime-helpers.js +1 -33
- package/dist/core/extensions/extension-types.js +1 -102
- package/dist/core/extensions/flag-definition-validation.js +1 -52
- package/dist/core/extensions/flag-value-types.js +1 -64
- package/dist/core/extensions/index.js +1 -526
- package/dist/core/extensions/item-field-types.js +1 -39
- package/dist/core/extensions/item-fields.js +1 -261
- package/dist/core/extensions/loader.js +1 -2223
- package/dist/core/extensions/manifest-schema.js +1 -69
- package/dist/core/extensions/module-graph-snapshot.js +1 -33
- package/dist/core/extensions/preflight-ownership.js +1 -41
- package/dist/core/extensions/registration-validation.js +1 -82
- package/dist/core/extensions/registration-values.js +1 -209
- package/dist/core/extensions/reserved-host-flags.js +1 -36
- package/dist/core/extensions/runtime-registrations.js +1 -67
- package/dist/core/extensions/service-ownership.js +1 -19
- package/dist/core/extensions/version-compat.js +1 -216
- package/dist/core/fs/fs-utils.js +2 -158
- package/dist/core/fs/host-environment-errors.js +1 -141
- package/dist/core/fs/index.js +1 -9
- package/dist/core/fs/path-utils.js +1 -17
- package/dist/core/governance/content-fields.js +1 -160
- package/dist/core/governance/issue-codes.js +1 -151
- package/dist/core/governance/metadata-coverage.js +1 -358
- package/dist/core/history/drift-cache.js +3 -72
- package/dist/core/history/drift-scan.js +1 -342
- package/dist/core/history/event-classification.js +1 -109
- package/dist/core/history/event-index.js +8 -784
- package/dist/core/history/history-compact-bulk.js +1 -104
- package/dist/core/history/history-diff.js +1 -158
- package/dist/core/history/history-rewrite.d.ts +6 -1
- package/dist/core/history/history-rewrite.js +1 -107
- package/dist/core/history/history-storage-stats.js +1 -102
- package/dist/core/history/history-stream-policy.js +1 -62
- package/dist/core/history/history.js +2 -617
- package/dist/core/history/identity.js +1 -30
- package/dist/core/history/index.js +1 -9
- package/dist/core/history/projection.js +1 -196
- package/dist/core/history/read.d.ts +9 -0
- package/dist/core/history/read.js +1 -57
- package/dist/core/history/replay.js +2 -439
- package/dist/core/history/version-address.js +1 -32
- package/dist/core/history/workspace-history.js +2 -433
- package/dist/core/io/body-file.js +1 -62
- package/dist/core/io/bulk-ids-input.js +1 -112
- package/dist/core/item/actionability.js +1 -327
- package/dist/core/item/dependency-reference.js +1 -20
- package/dist/core/item/id.js +1 -112
- package/dist/core/item/index.js +1 -12
- package/dist/core/item/item-format-version.js +1 -78
- package/dist/core/item/item-format.js +5 -1473
- package/dist/core/item/item-record.js +1 -23
- package/dist/core/item/item-type-definition.js +1 -133
- package/dist/core/item/parent-reference-policy.js +1 -57
- package/dist/core/item/parse.js +2 -603
- package/dist/core/item/plan-lifecycle.js +1 -19
- package/dist/core/item/priority.js +1 -61
- package/dist/core/item/sprint-release-format.js +1 -38
- package/dist/core/item/status-filter.js +1 -115
- package/dist/core/item/status.js +1 -43
- package/dist/core/item/toon-decode.js +1 -29
- package/dist/core/item/type-registry.js +1 -715
- package/dist/core/item/type-synonyms.js +1 -38
- package/dist/core/lock/index.js +1 -9
- package/dist/core/lock/lock-gc.js +1 -240
- package/dist/core/lock/lock.js +3 -590
- package/dist/core/output/mutation-projection.js +1 -217
- package/dist/core/output/output-control.js +1 -25
- package/dist/core/output/output.js +11 -494
- package/dist/core/output/query-summary.js +1 -58
- package/dist/core/output/tabular.js +1 -77
- package/dist/core/packages/manifest.js +1 -244
- package/dist/core/packages/root.js +1 -84
- package/dist/core/profile/profile-describe.js +1 -83
- package/dist/core/profile/profile-lint.js +1 -415
- package/dist/core/profile/profile-plan.js +0 -0
- package/dist/core/profile/profile-presets.js +1 -370
- package/dist/core/reproducibility/context.js +1 -82
- package/dist/core/schema/fields-file.js +2 -288
- package/dist/core/schema/item-types-file.js +2 -296
- package/dist/core/schema/runtime-field-filters.js +1 -49
- package/dist/core/schema/runtime-field-values.js +1 -313
- package/dist/core/schema/runtime-schema.js +2 -826
- package/dist/core/schema/status-defs-file.js +2 -227
- package/dist/core/schema/status-token.js +1 -31
- package/dist/core/schema/type-inference.js +1 -95
- package/dist/core/schema/type-presets.js +1 -87
- package/dist/core/schema/type-workflows.js +1 -104
- package/dist/core/search/background-refresh.js +2 -286
- package/dist/core/search/bm25.js +1 -146
- package/dist/core/search/cache.js +2 -534
- package/dist/core/search/corpus.js +1 -311
- package/dist/core/search/embedding-batches.js +1 -163
- package/dist/core/search/eval.js +1 -225
- package/dist/core/search/http-client.js +1 -75
- package/dist/core/search/providers.js +1 -242
- package/dist/core/search/relevance.js +1 -244
- package/dist/core/search/semantic-defaults.js +1 -199
- package/dist/core/search/staleness.js +1 -30
- package/dist/core/search/vector-stores.js +2 -664
- package/dist/core/search/vectorization-metadata.js +1 -81
- package/dist/core/sentry/helpers.js +1 -272
- package/dist/core/sentry/instrument.js +1 -387
- package/dist/core/session/session-state.js +1 -260
- package/dist/core/shared/agent-session-context.js +1 -133
- package/dist/core/shared/author.js +1 -1172
- package/dist/core/shared/command-types.js +1 -4
- package/dist/core/shared/conflict-markers.js +1 -31
- package/dist/core/shared/constants.js +1 -405
- package/dist/core/shared/errors.js +1 -20
- package/dist/core/shared/html-entity-decode.js +1 -131
- package/dist/core/shared/index.js +1 -12
- package/dist/core/shared/item-metadata-contract.js +1 -89
- package/dist/core/shared/lazy-module.js +1 -16
- package/dist/core/shared/levenshtein.js +1 -61
- package/dist/core/shared/memo.js +1 -19
- package/dist/core/shared/numeric-parsers.js +1 -20
- package/dist/core/shared/option-alias-visibility.js +1 -67
- package/dist/core/shared/primitives.js +1 -127
- package/dist/core/shared/serial-queue.js +1 -79
- package/dist/core/shared/serialization.js +1 -210
- package/dist/core/shared/split-comma-list.js +1 -30
- package/dist/core/shared/text-normalization.js +1 -38
- package/dist/core/shared/time.js +1 -306
- package/dist/core/store/index.js +1 -12
- package/dist/core/store/item-format-migration.js +1 -125
- package/dist/core/store/item-metadata-cache.js +1 -1116
- package/dist/core/store/item-metadata-query-index.js +9 -394
- package/dist/core/store/item-metadata-read-work.js +1 -43
- package/dist/core/store/item-store.js +1 -693
- package/dist/core/store/paths.d.ts +1 -1
- package/dist/core/store/paths.js +1 -214
- package/dist/core/store/settings-read-cache.js +1 -85
- package/dist/core/store/settings-validator.js +1 -421
- package/dist/core/store/settings.js +3 -1309
- package/dist/core/store/tracker-preflight.js +1 -141
- package/dist/core/telemetry/consent.js +5 -108
- package/dist/core/telemetry/observability.js +1 -246
- package/dist/core/telemetry/runtime.js +4 -1988
- package/dist/core/test/background-runs.js +4 -945
- package/dist/core/test/item-test-run-tracking.js +1 -63
- package/dist/core/test/run-selectors.js +1 -120
- package/dist/core/validate/estimate-defaults.js +1 -89
- package/dist/core/validate/fix-planning.js +1 -189
- package/dist/core/validate/linked-artifact-reference.js +1 -36
- package/dist/core/validate/missing-by-type.js +1 -34
- package/dist/core/validate/missing-link-owners.js +1 -95
- package/dist/core/validate/stale-file-classification.js +1 -82
- package/dist/mcp/http-server.js +5 -448
- package/dist/mcp/legacy-adapter.js +1 -77
- package/dist/mcp/runtime-capabilities.js +1 -200
- package/dist/mcp/server.js +4 -1233
- package/dist/mcp/tool-definitions.js +1 -804
- package/dist/sdk/actionability.js +1 -13
- package/dist/sdk/agent/closed-domain-contracts.js +1 -161
- package/dist/sdk/agent/command-recovery.js +1 -59
- package/dist/sdk/agent/command-suggestions.js +1 -66
- package/dist/sdk/agent/create-option-policy.js +1 -31
- package/dist/sdk/agent/identity-config.js +1 -106
- package/dist/sdk/agent/item-addressing.js +1 -207
- package/dist/sdk/agent/refusal-closure-census.js +1 -151
- package/dist/sdk/agent/refusal-closure.js +1 -133
- package/dist/sdk/agent/refusal-corpus-contracts.js +1 -193
- package/dist/sdk/agent/refusal-reachability.js +1 -593
- package/dist/sdk/agent/subcommand-recovery.js +1 -83
- package/dist/sdk/agent/task-transcript-contracts.js +1 -197
- package/dist/sdk/agent/tracker-preflight-contracts.js +1 -126
- package/dist/sdk/agent-capability-contracts.js +1 -428
- package/dist/sdk/agent-session-context.js +1 -9
- package/dist/sdk/annotations.js +1 -448
- package/dist/sdk/author-attribution.js +1 -468
- package/dist/sdk/authoring.js +1 -20
- package/dist/sdk/cli-bootstrap.js +1 -838
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/agent-output-contracts.js +4 -476
- package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +1 -79
- package/dist/sdk/cli-contracts/command-aliases.d.ts +4 -0
- package/dist/sdk/cli-contracts/command-aliases.js +1 -107
- package/dist/sdk/cli-contracts/command-exit-contracts.js +1 -151
- package/dist/sdk/cli-contracts/commander-mutation-options.js +1 -1081
- package/dist/sdk/cli-contracts/commander-types.js +1 -159
- package/dist/sdk/cli-contracts/completeness.js +1 -393
- package/dist/sdk/cli-contracts/enum-contracts.js +1 -222
- package/dist/sdk/cli-contracts/flag-contracts.js +1 -1947
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -347
- package/dist/sdk/cli-contracts/grammar-contracts.js +1 -986
- package/dist/sdk/cli-contracts/registration-helpers.js +7 -990
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +5 -0
- package/dist/sdk/cli-contracts/runtime-contracts.js +1 -2090
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +1 -324
- package/dist/sdk/cli-contracts/string-lists.js +1 -16
- package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -461
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +1 -2167
- package/dist/sdk/cli-contracts/tool-schema.d.ts +3 -1
- package/dist/sdk/cli-contracts/tool-schema.js +1 -1664
- package/dist/sdk/cli-contracts/typed-action-inputs.js +1 -4
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +1 -17
- package/dist/sdk/cli-program.js +1 -49
- package/dist/sdk/command-line.d.ts +2 -5
- package/dist/sdk/command-line.js +1 -78
- package/dist/sdk/comments.js +1 -133
- package/dist/sdk/compile-cache.js +1 -73
- package/dist/sdk/completion.js +157 -837
- package/dist/sdk/compose.js +1 -1090
- package/dist/sdk/config.js +1 -1204
- package/dist/sdk/context/recency.js +1 -33
- package/dist/sdk/context/semantic-session-attribution.js +1 -82
- package/dist/sdk/context/usage-egress.js +1 -29
- package/dist/sdk/context/usage-ledger.js +3 -185
- package/dist/sdk/context-intent-contracts.js +1 -709
- package/dist/sdk/context-intent-runtime.js +1 -115
- package/dist/sdk/context-packing.js +1 -218
- package/dist/sdk/context-relevance.js +1 -503
- package/dist/sdk/context-signal-store.js +2 -426
- package/dist/sdk/context-usage.js +1 -367
- package/dist/sdk/contracts.js +1 -23
- package/dist/sdk/core-governance.js +1 -14
- package/dist/sdk/core.js +1 -14
- package/dist/sdk/corpus-shape.js +1 -401
- package/dist/sdk/define.js +1 -220
- package/dist/sdk/dependencies.js +1 -718
- package/dist/sdk/dependency-flag-validation.js +1 -156
- package/dist/sdk/dependency-provenance.js +1 -135
- package/dist/sdk/docs.js +1 -14
- package/dist/sdk/duplicates.js +1 -40
- package/dist/sdk/environment/agent-environment.js +1 -466
- package/dist/sdk/environment/host-environment-errors.js +1 -8
- package/dist/sdk/environment/project-runtime-compatibility.js +1 -481
- package/dist/sdk/environment/source-context.js +1 -28
- package/dist/sdk/environment/tracker-preflight.js +1 -9
- package/dist/sdk/error-code-catalog.js +1 -153
- package/dist/sdk/error-runtime.js +1 -58
- package/dist/sdk/errors.js +1 -58
- package/dist/sdk/eval.js +1 -190
- package/dist/sdk/extension/author-manifest.js +1 -92
- package/dist/sdk/extension/bundled-catalog.js +1 -332
- package/dist/sdk/extension/concurrency.js +1 -25
- package/dist/sdk/extension/copy-scope.d.ts +2 -0
- package/dist/sdk/extension/copy-scope.js +2 -0
- package/dist/sdk/extension/custom-field-collisions.js +1 -30
- package/dist/sdk/extension/describe.js +3 -189
- package/dist/sdk/extension/doctor.js +1 -606
- package/dist/sdk/extension/install-plan.d.ts +69 -0
- package/dist/sdk/extension/install-plan.js +2 -0
- package/dist/sdk/extension/install-receipts.d.ts +7 -0
- package/dist/sdk/extension/install-receipts.js +2 -0
- package/dist/sdk/extension/install-runtime.js +3 -313
- package/dist/sdk/extension/install-snapshot.js +1 -66
- package/dist/sdk/extension/install-sources.js +5 -1057
- package/dist/sdk/extension/managed-state.js +2 -252
- package/dist/sdk/extension/migrations.js +2 -174
- package/dist/sdk/extension/output-ownership.js +1 -25
- package/dist/sdk/extension/runtime-summary.js +1 -18
- package/dist/sdk/extension/scaffold.js +4 -2308
- package/dist/sdk/extension/shared.js +1 -147
- package/dist/sdk/extension/source-resolution.js +1 -65
- package/dist/sdk/extension/update-check.js +1 -67
- package/dist/sdk/extension-command-context.js +1 -44
- package/dist/sdk/extension-contracts.js +1 -73
- package/dist/sdk/extension.d.ts +7 -2
- package/dist/sdk/extension.js +1 -2196
- package/dist/sdk/files.js +1 -535
- package/dist/sdk/flag-invocation-contracts.d.ts +0 -5
- package/dist/sdk/flag-invocation-contracts.js +1 -344
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -2224
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -2236
- package/dist/sdk/generated-error-code-catalog.js +1 -16
- package/dist/sdk/governance/assurance-action-contracts.js +1 -4
- package/dist/sdk/governance/assurance-action.js +1 -411
- package/dist/sdk/governance/assurance-limits.js +1 -10
- package/dist/sdk/governance/assurance-mutation-error.js +1 -81
- package/dist/sdk/governance/assurance-presets.js +1 -135
- package/dist/sdk/governance/assurance-runtime.js +1 -238
- package/dist/sdk/governance/assurance.js +4 -1182
- package/dist/sdk/governance/boundary-fixtures.js +1 -200
- package/dist/sdk/governance/coverage-assurance.js +1 -60
- package/dist/sdk/governance/defect-recurrence-coverage.js +1 -188
- package/dist/sdk/governance/defect-recurrence-graph.js +1 -120
- package/dist/sdk/governance/defect-recurrence-signals.js +1 -24
- package/dist/sdk/governance/defect-recurrence.js +1 -623
- package/dist/sdk/governance/extension-host-version.js +1 -115
- package/dist/sdk/governance/gc.js +1 -368
- package/dist/sdk/governance/health.js +1 -2367
- package/dist/sdk/governance/hierarchy-validation.js +1 -108
- package/dist/sdk/governance/linked-file-report.js +1 -71
- package/dist/sdk/governance/merge-receipt-history.js +1 -206
- package/dist/sdk/governance/provenance-health.js +1 -282
- package/dist/sdk/governance/reindex.js +4 -761
- package/dist/sdk/governance/stale-work.js +1 -82
- package/dist/sdk/governance/status-role-diagnostics.js +1 -35
- package/dist/sdk/governance/storage-integrity.js +1 -280
- package/dist/sdk/governance/tracked-runtime-cache.js +1 -106
- package/dist/sdk/governance/upgrade.js +2 -327
- package/dist/sdk/governance/validate-history-drift.js +1 -81
- package/dist/sdk/governance/validate-item-reader.js +1 -17
- package/dist/sdk/governance/validate-normalization.js +1 -36
- package/dist/sdk/governance/validate.js +1 -2261
- package/dist/sdk/governance/workspace-position.js +1 -163
- package/dist/sdk/governance.d.ts +1 -0
- package/dist/sdk/governance.js +1 -31
- package/dist/sdk/graph/adapter.js +1 -181
- package/dist/sdk/graph/analytics.js +1 -474
- package/dist/sdk/graph/assembly.js +1 -377
- package/dist/sdk/graph/cache.js +1 -160
- package/dist/sdk/graph/centrality.js +1 -258
- package/dist/sdk/graph/conformance.js +1 -130
- package/dist/sdk/graph/deadline-scheduling.d.ts +90 -0
- package/dist/sdk/graph/deadline-scheduling.js +2 -0
- package/dist/sdk/graph/durable-cache.d.ts +1 -1
- package/dist/sdk/graph/durable-cache.js +1 -361
- package/dist/sdk/graph/governance-contracts.js +1 -34
- package/dist/sdk/graph/governance.d.ts +13 -1
- package/dist/sdk/graph/governance.js +1 -735
- package/dist/sdk/graph/hierarchy-integrity.js +1 -310
- package/dist/sdk/graph/index.d.ts +3 -2
- package/dist/sdk/graph/index.js +1 -26
- package/dist/sdk/graph/lifecycle-coverage.d.ts +32 -0
- package/dist/sdk/graph/lifecycle-coverage.js +2 -0
- package/dist/sdk/graph/mutation-advisory.js +1 -176
- package/dist/sdk/graph/remediation.js +1 -197
- package/dist/sdk/graph/run.d.ts +15 -1
- package/dist/sdk/graph/run.js +1 -768
- package/dist/sdk/graph/scheduling.js +1 -124
- package/dist/sdk/graph/traversal.js +1 -284
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +1 -27
- package/dist/sdk/graph.js +1 -15
- package/dist/sdk/guide-topics.js +1 -707
- package/dist/sdk/guide.js +1 -279
- package/dist/sdk/history/maintenance.d.ts +71 -0
- package/dist/sdk/history/maintenance.js +2 -0
- package/dist/sdk/history/salvage.js +2 -247
- package/dist/sdk/history/subject.d.ts +19 -0
- package/dist/sdk/history/subject.js +2 -0
- package/dist/sdk/history-analytics.js +1 -282
- package/dist/sdk/history-compact.js +1 -527
- package/dist/sdk/history-mcp.js +1 -68
- package/dist/sdk/history-provenance.js +1 -182
- package/dist/sdk/history-read.js +1 -96
- package/dist/sdk/history-redact.d.ts +1 -14
- package/dist/sdk/history-redact.js +1 -643
- package/dist/sdk/history-repair.d.ts +5 -0
- package/dist/sdk/history-repair.js +1 -657
- package/dist/sdk/improvement-ledger-validation.js +1 -62
- package/dist/sdk/improvement-ledger.js +2 -257
- package/dist/sdk/index.d.ts +4 -0
- package/dist/sdk/index.js +1 -183
- package/dist/sdk/init-agent-guidance.js +2 -496
- package/dist/sdk/init.js +2 -820
- package/dist/sdk/invocation-author.js +1 -39
- package/dist/sdk/item-children.js +1 -90
- package/dist/sdk/item-metadata-index.js +1 -15
- package/dist/sdk/item-schedule.js +1 -27
- package/dist/sdk/item-transaction.js +1 -396
- package/dist/sdk/learnings.js +1 -29
- package/dist/sdk/lifecycle/append.js +2 -53
- package/dist/sdk/lifecycle/claim.d.ts +2 -0
- package/dist/sdk/lifecycle/claim.js +1 -242
- package/dist/sdk/lifecycle/close-many.js +1 -438
- package/dist/sdk/lifecycle/close.js +1 -468
- package/dist/sdk/lifecycle/copy.js +1 -212
- package/dist/sdk/lifecycle/create.js +1 -1949
- package/dist/sdk/lifecycle/delete.js +1 -45
- package/dist/sdk/lifecycle/event-validation-messages.js +1 -91
- package/dist/sdk/lifecycle/focus.js +1 -91
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +1 -24
- package/dist/sdk/lifecycle/legacy-none-tokens.js +1 -149
- package/dist/sdk/lifecycle/lifecycle-transitions.js +1 -40
- package/dist/sdk/lifecycle/mcp-actions.d.ts +2 -0
- package/dist/sdk/lifecycle/mcp-actions.js +1 -51
- package/dist/sdk/lifecycle/metadata-normalizers.js +1 -46
- package/dist/sdk/lifecycle/mutation-command-options.js +1 -9
- package/dist/sdk/lifecycle/plan.js +1 -1606
- package/dist/sdk/lifecycle/recurrence-parsers.js +1 -147
- package/dist/sdk/lifecycle/reopen.js +1 -68
- package/dist/sdk/lifecycle/repeatable-metadata-parsers.js +1 -143
- package/dist/sdk/lifecycle/restore.d.ts +1 -0
- package/dist/sdk/lifecycle/restore.js +1 -330
- package/dist/sdk/lifecycle/shared-unset-fields.js +1 -295
- package/dist/sdk/lifecycle/update-many.js +1 -861
- package/dist/sdk/lifecycle/update.js +1 -2136
- package/dist/sdk/lifecycle-completion.js +1 -92
- package/dist/sdk/lifecycle-policy.js +1 -120
- package/dist/sdk/linked-artifacts.js +1 -530
- package/dist/sdk/mcp/apps.js +4 -133
- package/dist/sdk/mcp/authorization.js +1 -404
- package/dist/sdk/mcp/discovery.js +1 -494
- package/dist/sdk/mcp/interactions.js +1 -336
- package/dist/sdk/mcp/protocol.d.ts +7 -0
- package/dist/sdk/mcp/protocol.js +1 -184
- package/dist/sdk/mcp/skills.js +1 -389
- package/dist/sdk/mcp/subscriptions.js +1 -211
- package/dist/sdk/mcp/tasks.js +2 -430
- package/dist/sdk/mcp/transport.js +1 -260
- package/dist/sdk/merge/abandoned-receipts.js +1 -46
- package/dist/sdk/merge/driver.js +1 -212
- package/dist/sdk/merge/index.js +1 -16
- package/dist/sdk/merge/install.js +3 -561
- package/dist/sdk/merge/receipt-file-boundary.js +1 -46
- package/dist/sdk/merge/receipt-operation.js +1 -96
- package/dist/sdk/merge/receipt-schema.js +1 -397
- package/dist/sdk/merge/receipts.js +4 -525
- package/dist/sdk/merge/reconcile.js +1 -352
- package/dist/sdk/merge/three-way.js +3 -775
- package/dist/sdk/merge.js +1 -10
- package/dist/sdk/mutation-events.js +1 -292
- package/dist/sdk/mutation-guard.js +1 -216
- package/dist/sdk/notes.js +1 -139
- package/dist/sdk/output-contracts.js +1 -172
- package/dist/sdk/output-projection.js +1 -430
- package/dist/sdk/output-token-accounting.js +1 -140
- package/dist/sdk/output.js +1 -64
- package/dist/sdk/ownership-source.js +1 -21
- package/dist/sdk/package-import-adapters.js +1 -442
- package/dist/sdk/package-migrations.js +1 -20
- package/dist/sdk/package-runtime-options.js +1 -80
- package/dist/sdk/pagination.js +1 -162
- package/dist/sdk/profile.js +1 -454
- package/dist/sdk/provenance.js +1 -258
- package/dist/sdk/public-surface.json +1 -1
- package/dist/sdk/query/activity.js +1 -401
- package/dist/sdk/query/aggregate.d.ts +16 -0
- package/dist/sdk/query/aggregate.js +1 -390
- package/dist/sdk/query/calendar.js +1 -964
- package/dist/sdk/query/complete-list.js +1 -215
- package/dist/sdk/query/context.js +1 -1702
- package/dist/sdk/query/duplicate-candidates.js +1 -70
- package/dist/sdk/query/get.js +1 -450
- package/dist/sdk/query/history.js +1 -186
- package/dist/sdk/query/item-filter-options.js +1 -9
- package/dist/sdk/query/light-metadata.js +1 -18
- package/dist/sdk/query/list-filter-shared.js +1 -81
- package/dist/sdk/query/list.js +1 -1304
- package/dist/sdk/query/multi-value-filters.js +1 -78
- package/dist/sdk/query/next.js +1 -513
- package/dist/sdk/query/parsers.js +1 -44
- package/dist/sdk/query/projection-contracts.js +1 -184
- package/dist/sdk/query/search-contracts.js +1 -230
- package/dist/sdk/query/search-pagination.js +1 -35
- package/dist/sdk/query/search-rendering.js +1 -105
- package/dist/sdk/query/search.js +2 -1987
- package/dist/sdk/query.js +1 -35
- package/dist/sdk/read-output/continuation.js +1 -194
- package/dist/sdk/read-output-budget.js +1 -135
- package/dist/sdk/read-output-contracts.js +1 -1225
- package/dist/sdk/read-output-rows.js +1 -186
- package/dist/sdk/read-output-session.js +1 -208
- package/dist/sdk/relationship-analytics.js +1 -410
- package/dist/sdk/relationship-context.js +1 -284
- package/dist/sdk/relationship-history.js +4 -519
- package/dist/sdk/relationship-kinds/contract.js +1 -22
- package/dist/sdk/relationship-migration.js +1 -77
- package/dist/sdk/relationships.js +1 -579
- package/dist/sdk/reproducibility/process.js +1 -87
- package/dist/sdk/runtime-action-aliases.js +1 -59
- package/dist/sdk/runtime-extended-actions.js +1 -177
- package/dist/sdk/runtime-input.js +1 -614
- package/dist/sdk/runtime-primitives.js +1 -84
- package/dist/sdk/runtime-public-contracts.js +1 -4
- package/dist/sdk/runtime-stats-options.js +1 -38
- package/dist/sdk/runtime.js +1 -1928
- package/dist/sdk/scheduling-shortcuts.js +1 -63
- package/dist/sdk/schema-migration.js +3 -856
- package/dist/sdk/schema.js +1 -1376
- package/dist/sdk/search-refresh-worker.js +1 -18
- package/dist/sdk/similarity-scoring.js +1 -53
- package/dist/sdk/similarity.js +1 -326
- package/dist/sdk/start-task-status.js +1 -14
- package/dist/sdk/stats.js +1 -270
- package/dist/sdk/structured-mutations.js +1 -580
- package/dist/sdk/telemetry-flush.js +1 -13
- package/dist/sdk/telemetry.js +1 -405
- package/dist/sdk/templates.js +2 -292
- package/dist/sdk/test/batch.js +2 -509
- package/dist/sdk/test/entry.js +1 -70
- package/dist/sdk/test/execution.js +6 -2211
- package/dist/sdk/test/linked-command-detection.js +1 -546
- package/dist/sdk/test/measurements.js +1 -91
- package/dist/sdk/test/parsers.js +1 -545
- package/dist/sdk/test/runs.js +1 -193
- package/dist/sdk/test/trust.js +2 -206
- package/dist/sdk/testing.js +4 -1391
- package/dist/sdk/traceability/runtime-files-lookup.js +1 -32
- package/dist/sdk/traceability/source-traceability.js +1 -292
- package/dist/sdk/tracker-root-discovery.js +1 -9
- package/dist/sdk/workspace-contracts-cache.js +1 -28
- package/dist/sdk/workspace-contracts.js +1 -33
- package/dist/sdk/workspace-memory.js +2 -318
- package/dist/sdk/workspace-recipe.js +1 -71
- package/dist/sdk/workspace-snapshot.js +4 -613
- package/dist/sdk/workspace-transaction-gc.js +1 -149
- package/dist/sdk/workspace-transaction.js +2 -363
- package/dist/sdk/workspace.js +3 -127
- package/dist/types/index.js +1 -9
- package/dist/types.js +1 -245
- package/docs/AGENT_GUIDE.md +1 -1
- package/docs/CONTEXT_ALGORITHM_PORTFOLIO.md +167 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +9 -3
- package/docs/EXTENSIONS.md +1 -0
- package/docs/HISTORY_MAINTENANCE.md +125 -0
- package/docs/MCP_2026_07_28_CONFORMANCE.md +20 -10
- package/docs/PACKAGE_EVIDENCE.md +92 -0
- package/docs/PLANNING_MEASUREMENTS.md +183 -0
- package/docs/README.md +3 -0
- package/docs/RELEASING.md +1 -0
- package/docs/SCRIPTING.md +21 -0
- package/docs/TESTING.md +23 -0
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +5 -5
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +2 -2
- package/marketplace.json +2 -2
- package/package.json +1 -1
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/finalize-build.mjs +45 -3
- package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +0 -9
- package/dist/cli-bundle/chunks/chunk-BAX2BYUW.js +0 -2111
- package/dist/cli-bundle/chunks/chunk-CKOL5U7J.js +0 -77
- package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +0 -5
- package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +0 -232
- package/dist/cli-bundle/chunks/chunk-QWRRFYK3.js +0 -2
- package/dist/cli-bundle/chunks/chunk-RWWBOWJ5.js +0 -2
- package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +0 -40
- package/dist/cli-bundle/chunks/chunk-WI2AYPA7.js +0 -2
- package/dist/cli-bundle/chunks/register-list-query-5JL52D33.js +0 -11
- package/dist/cli-bundle/chunks/register-mutation-ZPG7KMVP.js +0 -20
- package/dist/cli-bundle/chunks/register-setup-H4SVAVX7.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +0 -20
- package/dist/cli-bundle/focused-chunks/chunk-EZR3GHFE.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +0 -56
- package/dist/cli-bundle/focused-chunks/chunk-NTPY5GSO.js +0 -3
- package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +0 -177
- package/dist/cli-bundle/focused-chunks/chunk-QTVCLMSZ.js +0 -6
- package/dist/cli-bundle/focused-chunks/chunk-QTZRBUYA.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +0 -12
- package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +0 -10
- package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +0 -2
|
@@ -1,96 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Owner attribution for stale linked paths reported by `pm validate --check-files`.
|
|
3
|
-
*
|
|
4
|
-
* The files check collects, per item, the linked paths (from the item's `files`
|
|
5
|
-
* and `docs` link lists) that no longer resolve on disk. By default those are
|
|
6
|
-
* surfaced as bare path strings + `path:classification` rows, which forces a
|
|
7
|
-
* reverse lookup to discover which item owns each stale link. This module turns
|
|
8
|
-
* the already-collected stale-link rows into owner-attributed, path-grouped rows
|
|
9
|
-
* so an agent can perform evidence-based cleanup (relink/prune) without that
|
|
10
|
-
* reverse lookup.
|
|
11
|
-
*
|
|
12
|
-
* Pure module (GH-210): no filesystem access and no heavy imports — callers pass
|
|
13
|
-
* the already-collected stale-link rows plus a metadata `lookup` closure.
|
|
14
|
-
*/
|
|
15
|
-
/** `malformed` wins over other classifications to prevent unsafe automatic repair. Otherwise `moved` wins over `deleted` when a single path's rows disagree on classification: `moved` means a relink candidate exists, which is the safer, more-actionable signal (relink instead of risk pruning a still-reachable link). In practice all rows for one path share a classification; this is a deterministic tie-break for the degenerate case. */
|
|
16
|
-
|
|
17
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1a4f19cf-56ba-571a-908c-97278a8284f7")}catch(e){}}();
|
|
18
|
-
function preferClassification(current, next) {
|
|
19
|
-
if (current === "malformed" || next === "malformed")
|
|
20
|
-
return "malformed";
|
|
21
|
-
return current === "moved" || next === "moved" ? "moved" : "deleted";
|
|
22
|
-
}
|
|
23
|
-
function ownerKey(input) {
|
|
24
|
-
return `${input.item_id} ${input.link_kind}`;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Group stale-link owner inputs by linked path and attach owning-item metadata.
|
|
28
|
-
*
|
|
29
|
-
* - Paths sorted ascending (`localeCompare`); items within a path sorted by `id`
|
|
30
|
-
* then `field`.
|
|
31
|
-
* - De-duplicates identical `(id, field)` owners for the same path.
|
|
32
|
-
* - `classification` per path follows {@link preferClassification} (moved wins).
|
|
33
|
-
* - Missing metadata falls back: type `"Unknown"`, title `""`, status `""`.
|
|
34
|
-
*/
|
|
35
|
-
export function buildMissingLinkedPathRows(rows, lookup) {
|
|
36
|
-
const buckets = new Map();
|
|
37
|
-
for (const row of rows) {
|
|
38
|
-
const bucket = buckets.get(row.path);
|
|
39
|
-
if (bucket) {
|
|
40
|
-
bucket.classification = preferClassification(bucket.classification, row.classification);
|
|
41
|
-
bucket.owners.set(ownerKey(row), row);
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
buckets.set(row.path, {
|
|
45
|
-
classification: row.classification,
|
|
46
|
-
owners: new Map([[ownerKey(row), row]]),
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
return [...buckets.entries()]
|
|
51
|
-
.sort(([left], [right]) => left.localeCompare(right))
|
|
52
|
-
.map(([path, bucket]) => ({
|
|
53
|
-
path,
|
|
54
|
-
classification: bucket.classification,
|
|
55
|
-
items: [...bucket.owners.values()]
|
|
56
|
-
.map((owner) => {
|
|
57
|
-
const metadata = lookup(owner.item_id);
|
|
58
|
-
return {
|
|
59
|
-
id: owner.item_id,
|
|
60
|
-
type: metadata?.type ?? "Unknown",
|
|
61
|
-
title: metadata?.title ?? "",
|
|
62
|
-
status: metadata?.status ?? "",
|
|
63
|
-
field: owner.link_kind,
|
|
64
|
-
};
|
|
65
|
-
})
|
|
66
|
-
.sort((leftOwner, rightOwner) => {
|
|
67
|
-
const byId = leftOwner.id.localeCompare(rightOwner.id);
|
|
68
|
-
return byId !== 0
|
|
69
|
-
? byId
|
|
70
|
-
: leftOwner.field.localeCompare(rightOwner.field);
|
|
71
|
-
}),
|
|
72
|
-
}));
|
|
73
|
-
}
|
|
74
|
-
function escapeTitle(title) {
|
|
75
|
-
return title.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Token-efficient one-line-per-owner serialization for the files-check details
|
|
79
|
-
* (compact text counterpart to the full {@link MissingLinkedPathRow} objects).
|
|
80
|
-
* Format per owner row:
|
|
81
|
-
* `<path>:<classification> owner=<id> status=<status> field=<field> title="<title>"`
|
|
82
|
-
* Title is double-quoted with backslash/quote escaping; empty status/title still
|
|
83
|
-
* render (`status=` and `title=""`). Order follows
|
|
84
|
-
* {@link buildMissingLinkedPathRows} output order.
|
|
85
|
-
*/
|
|
86
|
-
export function summarizeMissingLinkedPathRows(rows) {
|
|
87
|
-
const lines = [];
|
|
88
|
-
for (const row of rows) {
|
|
89
|
-
for (const owner of row.items) {
|
|
90
|
-
lines.push(`${row.path}:${row.classification} owner=${owner.id} status=${owner.status} field=${owner.field} title="${escapeTitle(owner.title)}"`);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return lines;
|
|
94
|
-
}
|
|
1
|
+
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e2cd8850-491a-505c-8709-3dcdb758de75")}catch(e2){}})();function preferClassification(current,next){if(current==="malformed"||next==="malformed")return"malformed";return current==="moved"||next==="moved"?"moved":"deleted"}function ownerKey(input){return`${input.item_id} ${input.link_kind}`}function buildMissingLinkedPathRows(rows,lookup){const buckets=new Map;for(const row of rows){const bucket=buckets.get(row.path);if(bucket){bucket.classification=preferClassification(bucket.classification,row.classification);bucket.owners.set(ownerKey(row),row)}else{buckets.set(row.path,{classification:row.classification,owners:new Map([[ownerKey(row),row]])})}}return[...buckets.entries()].sort(([left],[right])=>left.localeCompare(right)).map(([path,bucket])=>({path,classification:bucket.classification,items:[...bucket.owners.values()].map(owner=>{const metadata=lookup(owner.item_id);return{id:owner.item_id,type:metadata?.type??"Unknown",title:metadata?.title??"",status:metadata?.status??"",field:owner.link_kind}}).sort((leftOwner,rightOwner)=>{const byId=leftOwner.id.localeCompare(rightOwner.id);return byId!==0?byId:leftOwner.field.localeCompare(rightOwner.field)})}))}function escapeTitle(title){return title.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function summarizeMissingLinkedPathRows(rows){const lines=[];for(const row of rows){for(const owner of row.items){lines.push(`${row.path}:${row.classification} owner=${owner.id} status=${owner.status} field=${owner.field} title="${escapeTitle(owner.title)}"`)}}return lines}export{buildMissingLinkedPathRows,summarizeMissingLinkedPathRows};
|
|
95
2
|
//# sourceMappingURL=missing-link-owners.js.map
|
|
96
|
-
//# debugId=1a4f19cf-56ba-571a-908c-97278a8284f7
|
|
@@ -1,83 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
* Classification of stale linked paths reported by `pm validate --check-files`.
|
|
3
|
-
*
|
|
4
|
-
* A linked file path that no longer exists is either:
|
|
5
|
-
* - `moved`: a file with the same basename still exists elsewhere in the
|
|
6
|
-
* scanned candidate set — the candidates are reported so an agent can relink
|
|
7
|
-
* the item to the new location instead of dropping the link, or
|
|
8
|
-
* - `deleted`: no candidate with that basename exists anywhere in the scan,
|
|
9
|
-
* making it eligible for an explicitly requested prune, or
|
|
10
|
-
* - `malformed`: an ambiguous missing CSV or path:note literal which must be
|
|
11
|
-
* reviewed before any relocation or removal is inferred.
|
|
12
|
-
*
|
|
13
|
-
* Pure module (pm-0v2m / GH-184): no filesystem access — callers pass the
|
|
14
|
-
* already-collected candidate file list from the files check scan.
|
|
15
|
-
*/
|
|
16
|
-
/** Fallback stale path candidate limit used when callers do not provide an override. */
|
|
17
|
-
|
|
18
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="eb4fe9bd-31b5-5ed3-b401-3e3776ec12e9")}catch(e){}}();
|
|
19
|
-
export const DEFAULT_STALE_PATH_CANDIDATE_LIMIT = 3;
|
|
20
|
-
/** Extract a basename from either portable separator convention. */
|
|
21
|
-
function basenameOf(relativePath) {
|
|
22
|
-
const lastSlash = Math.max(relativePath.lastIndexOf("/"), relativePath.lastIndexOf("\\"));
|
|
23
|
-
return lastSlash === -1 ? relativePath : relativePath.slice(lastSlash + 1);
|
|
24
|
-
}
|
|
25
|
-
/** Classify each stale (missing) linked path as `moved`, `deleted`, or `malformed` by matching its basename against the candidate file list. Output preserves the input order of `stalePaths` (callers pass an already-sorted unique list). A candidate equal to the stale path itself never matches (the path is known missing; an identical candidate would be self-referential noise). */
|
|
26
|
-
export function classifyStaleLinkedPaths(stalePaths, candidateFiles, candidateLimit = DEFAULT_STALE_PATH_CANDIDATE_LIMIT) {
|
|
27
|
-
const limit = Number.isFinite(candidateLimit) && candidateLimit >= 1
|
|
28
|
-
? Math.floor(candidateLimit)
|
|
29
|
-
: DEFAULT_STALE_PATH_CANDIDATE_LIMIT;
|
|
30
|
-
const candidatesByBasename = new Map();
|
|
31
|
-
for (const candidate of candidateFiles) {
|
|
32
|
-
const basename = basenameOf(candidate);
|
|
33
|
-
if (basename.length === 0) {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
const bucket = candidatesByBasename.get(basename);
|
|
37
|
-
if (bucket) {
|
|
38
|
-
bucket.push(candidate);
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
candidatesByBasename.set(basename, [candidate]);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return stalePaths.map((stalePath) => {
|
|
45
|
-
// Historical CSV and path:note input must not become a confident basename
|
|
46
|
-
// relocation. Existing files are checked before classification; this only
|
|
47
|
-
// rejects ambiguous missing references, never an existing literal filename.
|
|
48
|
-
if (stalePath.includes(",") ||
|
|
49
|
-
stalePath.replace(/^[a-z]:[\\/]/i, "").includes(":")) {
|
|
50
|
-
return {
|
|
51
|
-
path: stalePath,
|
|
52
|
-
classification: "malformed",
|
|
53
|
-
candidates: [],
|
|
54
|
-
candidates_truncated: false,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const matches = (candidatesByBasename.get(basenameOf(stalePath)) ?? [])
|
|
58
|
-
.filter((candidate) => candidate !== stalePath)
|
|
59
|
-
.sort((left, right) => left.localeCompare(right));
|
|
60
|
-
if (matches.length === 0) {
|
|
61
|
-
return {
|
|
62
|
-
path: stalePath,
|
|
63
|
-
classification: "deleted",
|
|
64
|
-
candidates: [],
|
|
65
|
-
candidates_truncated: false,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
return {
|
|
69
|
-
path: stalePath,
|
|
70
|
-
classification: "moved",
|
|
71
|
-
candidates: matches.slice(0, limit),
|
|
72
|
-
candidates_truncated: matches.length > limit,
|
|
73
|
-
};
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
/** Render compact `<path>:moved:<top-candidate>` / `<path>:deleted` rows for the files check details (token-efficient counterpart to the full classification objects). */
|
|
77
|
-
export function summarizeStaleLinkedPathClassifications(classified) {
|
|
78
|
-
return classified.map((entry) => entry.classification === "moved"
|
|
79
|
-
? `${entry.path}:moved:${entry.candidates[0]}`
|
|
80
|
-
: `${entry.path}:${entry.classification}`);
|
|
81
|
-
}
|
|
1
|
+
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ede22770-cb10-5054-85a7-89bb2758c25f")}catch(e2){}})();const DEFAULT_STALE_PATH_CANDIDATE_LIMIT=3;function basenameOf(relativePath){const lastSlash=Math.max(relativePath.lastIndexOf("/"),relativePath.lastIndexOf("\\"));return lastSlash===-1?relativePath:relativePath.slice(lastSlash+1)}function classifyStaleLinkedPaths(stalePaths,candidateFiles,candidateLimit=DEFAULT_STALE_PATH_CANDIDATE_LIMIT){const limit=Number.isFinite(candidateLimit)&&candidateLimit>=1?Math.floor(candidateLimit):DEFAULT_STALE_PATH_CANDIDATE_LIMIT;const candidatesByBasename=new Map;for(const candidate of candidateFiles){const basename=basenameOf(candidate);if(basename.length===0){continue}const bucket=candidatesByBasename.get(basename);if(bucket){bucket.push(candidate)}else{candidatesByBasename.set(basename,[candidate])}}return stalePaths.map(stalePath=>{if(stalePath.includes(",")||stalePath.replace(/^[a-z]:[\\/]/i,"").includes(":")){return{path:stalePath,classification:"malformed",candidates:[],candidates_truncated:false}}const matches=(candidatesByBasename.get(basenameOf(stalePath))??[]).filter(candidate=>candidate!==stalePath).sort((left,right)=>left.localeCompare(right));if(matches.length===0){return{path:stalePath,classification:"deleted",candidates:[],candidates_truncated:false}}return{path:stalePath,classification:"moved",candidates:matches.slice(0,limit),candidates_truncated:matches.length>limit}})}function summarizeStaleLinkedPathClassifications(classified){return classified.map(entry=>entry.classification==="moved"?`${entry.path}:moved:${entry.candidates[0]}`:`${entry.path}:${entry.classification}`)}export{DEFAULT_STALE_PATH_CANDIDATE_LIMIT,classifyStaleLinkedPaths,summarizeStaleLinkedPathClassifications};
|
|
82
2
|
//# sourceMappingURL=stale-file-classification.js.map
|
|
83
|
-
//# debugId=eb4fe9bd-31b5-5ed3-b401-3e3776ec12e9
|
package/dist/mcp/http-server.js
CHANGED
|
@@ -1,451 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* @module mcp/http-server
|
|
4
|
-
*
|
|
5
|
-
* Serves the pm MCP dispatcher through the sessionless 2026-07-28 Streamable
|
|
6
|
-
* HTTP POST binding with request-scoped JSON/SSE responses.
|
|
7
|
-
*/
|
|
2
|
+
!(function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ad8ab3b3-7b07-565a-be09-2d1c2ba6133d")}catch(e2){}})();import{createServer}from"node:http";import{PM_MCP_ERROR_CODES,PmMcpProtocolError}from"../sdk/mcp/protocol.js";import{PmMcpAuthorizationError,authorizeMcpHttpRequest,buildMcpProtectedResourceMetadata,createMcpStaticBearerVerifier}from"../sdk/mcp/authorization.js";import{validateMcpHttpRequestHeaders}from"../sdk/mcp/transport.js";import{buildMcpToolCallErrorResult,closeMcpSubscription,handleRequest,isInvokedAsMcpMainModule,openMcpSubscription,resolveMcpToolSchemaForRequest}from"./server.js";const DEFAULT_MAXIMUM_BODY_BYTES=1024*1024;const DEFAULT_KEEP_ALIVE_MS=15e3;const PM_MCP_HTTP_RUNTIMES=new WeakMap;function writePmMcpSseEvent(response,payload){return new Promise((resolve,reject)=>{let settled=false;const cleanup=()=>{response.off("drain",onDrain);response.off("close",onClose)};const onDrain=()=>{settled=true;cleanup();resolve()};const onClose=()=>{settled=true;cleanup();reject(new Error("MCP response stream closed during backpressure"))};response.once("drain",onDrain);response.once("close",onClose);try{if(response.write(`data: ${JSON.stringify(payload)}
|
|
8
3
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { validateMcpHttpRequestHeaders } from "../sdk/mcp/transport.js";
|
|
14
|
-
import { buildMcpToolCallErrorResult, closeMcpSubscription, handleRequest, isInvokedAsMcpMainModule, openMcpSubscription, resolveMcpToolSchemaForRequest, } from "./server.js";
|
|
15
|
-
const DEFAULT_MAXIMUM_BODY_BYTES = 1024 * 1024;
|
|
16
|
-
const DEFAULT_KEEP_ALIVE_MS = 15_000;
|
|
17
|
-
const PM_MCP_HTTP_RUNTIMES = new WeakMap();
|
|
18
|
-
/** Write one SSE event and wait for transport backpressure to clear. */
|
|
19
|
-
export function writePmMcpSseEvent(response, payload) {
|
|
20
|
-
return new Promise((resolve, reject) => {
|
|
21
|
-
let settled = false;
|
|
22
|
-
const cleanup = () => {
|
|
23
|
-
response.off("drain", onDrain);
|
|
24
|
-
response.off("close", onClose);
|
|
25
|
-
};
|
|
26
|
-
const onDrain = () => {
|
|
27
|
-
settled = true;
|
|
28
|
-
cleanup();
|
|
29
|
-
resolve();
|
|
30
|
-
};
|
|
31
|
-
const onClose = () => {
|
|
32
|
-
settled = true;
|
|
33
|
-
cleanup();
|
|
34
|
-
reject(new Error("MCP response stream closed during backpressure"));
|
|
35
|
-
};
|
|
36
|
-
response.once("drain", onDrain);
|
|
37
|
-
response.once("close", onClose);
|
|
38
|
-
try {
|
|
39
|
-
if (response.write(`data: ${JSON.stringify(payload)}\n\n`) && !settled) {
|
|
40
|
-
settled = true;
|
|
41
|
-
cleanup();
|
|
42
|
-
resolve();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
cleanup();
|
|
47
|
-
reject(error);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
function writeJson(response, status, payload, headers = {}) {
|
|
52
|
-
response.writeHead(status, {
|
|
53
|
-
"Cache-Control": "no-store",
|
|
54
|
-
"Content-Type": "application/json",
|
|
55
|
-
...headers,
|
|
56
|
-
});
|
|
57
|
-
response.end(`${JSON.stringify(payload)}\n`);
|
|
58
|
-
}
|
|
59
|
-
function writeJsonRpcError(response, id, error) {
|
|
60
|
-
const authorizationError = error instanceof PmMcpAuthorizationError ? error : undefined;
|
|
61
|
-
const protocolError = error instanceof PmMcpProtocolError ? error : undefined;
|
|
62
|
-
const code = protocolError?.code ?? -32603;
|
|
63
|
-
const clientErrorCodes = new Set([
|
|
64
|
-
-32700,
|
|
65
|
-
-32600,
|
|
66
|
-
PM_MCP_ERROR_CODES.headerMismatch,
|
|
67
|
-
PM_MCP_ERROR_CODES.unsupportedProtocolVersion,
|
|
68
|
-
PM_MCP_ERROR_CODES.invalidParams,
|
|
69
|
-
]);
|
|
70
|
-
const status = authorizationError?.httpStatus ??
|
|
71
|
-
(code === -32601 ? 404 : clientErrorCodes.has(code) ? 400 : 500);
|
|
72
|
-
writeJson(response, status, {
|
|
73
|
-
jsonrpc: "2.0",
|
|
74
|
-
id: id ?? null,
|
|
75
|
-
error: {
|
|
76
|
-
code,
|
|
77
|
-
message: error instanceof Error ? error.message : "Internal MCP error",
|
|
78
|
-
...(protocolError ? { data: protocolError.data } : {}),
|
|
79
|
-
},
|
|
80
|
-
}, authorizationError?.challenge
|
|
81
|
-
? { "WWW-Authenticate": authorizationError.challenge }
|
|
82
|
-
: {});
|
|
83
|
-
}
|
|
84
|
-
function finishCommittedMcpResponse(response) {
|
|
85
|
-
if (!response.headersSent && !response.writableEnded && !response.destroyed) {
|
|
86
|
-
return false;
|
|
87
|
-
}
|
|
88
|
-
if (!response.writableEnded && !response.destroyed)
|
|
89
|
-
response.end();
|
|
90
|
-
return true;
|
|
91
|
-
}
|
|
92
|
-
function writeMcpHttpDispatchError(response, rpcRequest, error) {
|
|
93
|
-
if (finishCommittedMcpResponse(response))
|
|
94
|
-
return;
|
|
95
|
-
const toolError = rpcRequest
|
|
96
|
-
? buildMcpToolCallErrorResult(rpcRequest, error)
|
|
97
|
-
: undefined;
|
|
98
|
-
if (toolError && rpcRequest) {
|
|
99
|
-
writeJson(response, 200, {
|
|
100
|
-
jsonrpc: "2.0",
|
|
101
|
-
id: rpcRequest.id ?? null,
|
|
102
|
-
result: toolError,
|
|
103
|
-
});
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
writeJsonRpcError(response, rpcRequest?.id, error);
|
|
107
|
-
}
|
|
108
|
-
function destroyFailedMcpHttpResponse(response, error) {
|
|
109
|
-
response.destroy(new Error("Unhandled MCP HTTP request failure", { cause: error }));
|
|
110
|
-
}
|
|
111
|
-
async function readRequestBody(request, maximumBytes) {
|
|
112
|
-
const chunks = [];
|
|
113
|
-
let observed = 0;
|
|
114
|
-
for await (const chunk of request) {
|
|
115
|
-
const buffer = Buffer.from(chunk);
|
|
116
|
-
observed += buffer.length;
|
|
117
|
-
if (observed > maximumBytes) {
|
|
118
|
-
throw new PmMcpProtocolError("MCP HTTP request body exceeds the configured limit", PM_MCP_ERROR_CODES.invalidParams, { maximumBytes });
|
|
119
|
-
}
|
|
120
|
-
chunks.push(buffer);
|
|
121
|
-
}
|
|
122
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
123
|
-
}
|
|
124
|
-
function parseJsonRpcRequest(source) {
|
|
125
|
-
let value;
|
|
126
|
-
try {
|
|
127
|
-
value = JSON.parse(source);
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
throw new PmMcpProtocolError("Invalid JSON-RPC request body", -32700);
|
|
131
|
-
}
|
|
132
|
-
if (typeof value !== "object" ||
|
|
133
|
-
value === null ||
|
|
134
|
-
Array.isArray(value) ||
|
|
135
|
-
("jsonrpc" in value && value.jsonrpc !== "2.0") ||
|
|
136
|
-
("method" in value && typeof value.method !== "string")) {
|
|
137
|
-
throw new PmMcpProtocolError("Invalid JSON-RPC request", -32600);
|
|
138
|
-
}
|
|
139
|
-
return value;
|
|
140
|
-
}
|
|
141
|
-
function protectedResourcePaths(endpointPath) {
|
|
142
|
-
return new Set([
|
|
143
|
-
"/.well-known/oauth-protected-resource",
|
|
144
|
-
`/.well-known/oauth-protected-resource${endpointPath}`,
|
|
145
|
-
]);
|
|
146
|
-
}
|
|
147
|
-
function routeMcpHttpBoundary(request, response, requestUrl, runtime) {
|
|
148
|
-
if (runtime.options.protectedResourceMetadata &&
|
|
149
|
-
request.method === "GET" &&
|
|
150
|
-
protectedResourcePaths(runtime.endpointPath).has(requestUrl.pathname)) {
|
|
151
|
-
writeJson(response, 200, { ...runtime.options.protectedResourceMetadata });
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
|
-
if (requestUrl.pathname !== runtime.endpointPath) {
|
|
155
|
-
writeJson(response, 404, { error: "Not found" });
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
if (request.method !== "POST") {
|
|
159
|
-
response.setHeader("Allow", "POST");
|
|
160
|
-
writeJson(response, 405, { error: "Method not allowed" });
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
const origin = request.headers.origin;
|
|
164
|
-
if (origin !== undefined && !runtime.allowedOrigins.has(origin)) {
|
|
165
|
-
writeJson(response, 403, { error: "Origin is not allowed" });
|
|
166
|
-
return true;
|
|
167
|
-
}
|
|
168
|
-
const accept = request.headers.accept;
|
|
169
|
-
const contentType = request.headers["content-type"];
|
|
170
|
-
if (typeof accept !== "string" ||
|
|
171
|
-
!accept.includes("application/json") ||
|
|
172
|
-
!accept.includes("text/event-stream") ||
|
|
173
|
-
typeof contentType !== "string" ||
|
|
174
|
-
!contentType.startsWith("application/json")) {
|
|
175
|
-
writeJson(response, 406, {
|
|
176
|
-
error: "MCP requires JSON and SSE content negotiation",
|
|
177
|
-
});
|
|
178
|
-
return true;
|
|
179
|
-
}
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
async function openHttpSubscription(input) {
|
|
183
|
-
if (typeof input.request.id !== "string" &&
|
|
184
|
-
typeof input.request.id !== "number") {
|
|
185
|
-
throw new PmMcpProtocolError("subscriptions/listen requires a JSON-RPC id", PM_MCP_ERROR_CODES.invalidParams);
|
|
186
|
-
}
|
|
187
|
-
const subscriptionId = input.request.id;
|
|
188
|
-
const subscriptionKey = Symbol("pm-mcp-http-subscription");
|
|
189
|
-
const active = {
|
|
190
|
-
id: subscriptionId,
|
|
191
|
-
key: subscriptionKey,
|
|
192
|
-
response: input.response,
|
|
193
|
-
};
|
|
194
|
-
let disconnected = input.response.destroyed || input.response.writableEnded;
|
|
195
|
-
let subscriptionOpened = false;
|
|
196
|
-
const closeActiveSubscription = () => {
|
|
197
|
-
disconnected = true;
|
|
198
|
-
if (active.timer)
|
|
199
|
-
clearInterval(active.timer);
|
|
200
|
-
input.runtime.activeSubscriptions.delete(subscriptionKey);
|
|
201
|
-
if (subscriptionOpened) {
|
|
202
|
-
closeMcpSubscription(subscriptionId, subscriptionKey);
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
input.response.once("close", closeActiveSubscription);
|
|
206
|
-
let responseStarted = false;
|
|
207
|
-
try {
|
|
208
|
-
await openMcpSubscription({
|
|
209
|
-
request: input.request,
|
|
210
|
-
key: subscriptionKey,
|
|
211
|
-
sink: (notification) => {
|
|
212
|
-
if (input.response.destroyed || input.response.writableEnded) {
|
|
213
|
-
throw new Error("MCP response stream closed before acknowledgment");
|
|
214
|
-
}
|
|
215
|
-
if (!responseStarted) {
|
|
216
|
-
responseStarted = true;
|
|
217
|
-
input.response.setHeader("Cache-Control", "no-cache, no-store");
|
|
218
|
-
input.response.setHeader("Connection", "keep-alive");
|
|
219
|
-
input.response.setHeader("Content-Type", "text/event-stream");
|
|
220
|
-
input.response.setHeader("X-Accel-Buffering", "no");
|
|
221
|
-
}
|
|
222
|
-
return writePmMcpSseEvent(input.response, notification);
|
|
223
|
-
},
|
|
224
|
-
});
|
|
225
|
-
subscriptionOpened = true;
|
|
226
|
-
}
|
|
227
|
-
catch (error) {
|
|
228
|
-
input.response.off("close", closeActiveSubscription);
|
|
229
|
-
throw error;
|
|
230
|
-
}
|
|
231
|
-
if (disconnected ||
|
|
232
|
-
input.response.destroyed ||
|
|
233
|
-
input.response.writableEnded) {
|
|
234
|
-
closeActiveSubscription();
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
if (input.runtime.keepAliveMs > 0) {
|
|
238
|
-
active.timer = setInterval(() => input.response.write(":\r\n\r\n"), input.runtime.keepAliveMs);
|
|
239
|
-
active.timer.unref();
|
|
240
|
-
}
|
|
241
|
-
input.runtime.activeSubscriptions.set(subscriptionKey, active);
|
|
242
|
-
}
|
|
243
|
-
async function dispatchMcpHttpRpc(input) {
|
|
244
|
-
let rpcRequest;
|
|
245
|
-
try {
|
|
246
|
-
if (input.runtime.options.authorization) {
|
|
247
|
-
await authorizeMcpHttpRequest({
|
|
248
|
-
headers: input.request.headers,
|
|
249
|
-
requestUrl: input.requestUrl.href,
|
|
250
|
-
policy: input.runtime.options.authorization,
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
rpcRequest = parseJsonRpcRequest(await readRequestBody(input.request, input.runtime.maximumBodyBytes));
|
|
254
|
-
validateMcpHttpRequestHeaders({
|
|
255
|
-
headers: input.request.headers,
|
|
256
|
-
request: rpcRequest,
|
|
257
|
-
toolSchema: await resolveMcpToolSchemaForRequest(rpcRequest),
|
|
258
|
-
});
|
|
259
|
-
if (rpcRequest.method === "subscriptions/listen") {
|
|
260
|
-
await openHttpSubscription({
|
|
261
|
-
request: rpcRequest,
|
|
262
|
-
response: input.response,
|
|
263
|
-
runtime: input.runtime,
|
|
264
|
-
});
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
const result = await (input.runtime.options.requestHandler ?? handleRequest)(rpcRequest);
|
|
268
|
-
if (!Object.prototype.hasOwnProperty.call(rpcRequest, "id")) {
|
|
269
|
-
input.response.writeHead(202);
|
|
270
|
-
input.response.end();
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
writeJson(input.response, 200, {
|
|
274
|
-
jsonrpc: "2.0",
|
|
275
|
-
id: rpcRequest.id ?? null,
|
|
276
|
-
result: result ?? {},
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
catch (error) {
|
|
280
|
-
writeMcpHttpDispatchError(input.response, rpcRequest, error);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
async function handleMcpHttpRequest(request, response, runtime) {
|
|
284
|
-
const requestUrl = new URL(request.url, "http://localhost");
|
|
285
|
-
if (routeMcpHttpBoundary(request, response, requestUrl, runtime))
|
|
286
|
-
return;
|
|
287
|
-
await dispatchMcpHttpRpc({ request, response, requestUrl, runtime });
|
|
288
|
-
}
|
|
289
|
-
/** Create a configured HTTP server without binding it. */
|
|
290
|
-
export function createPmMcpHttpServer(options = {}) {
|
|
291
|
-
const runtime = {
|
|
292
|
-
activeSubscriptions: new Map(),
|
|
293
|
-
allowedOrigins: new Set(options.allowedOrigins ?? []),
|
|
294
|
-
endpointPath: options.endpointPath ?? "/mcp",
|
|
295
|
-
keepAliveMs: options.keepAliveMs ?? DEFAULT_KEEP_ALIVE_MS,
|
|
296
|
-
maximumBodyBytes: options.maximumBodyBytes ?? DEFAULT_MAXIMUM_BODY_BYTES,
|
|
297
|
-
options,
|
|
298
|
-
};
|
|
299
|
-
const server = createServer((request, response) => {
|
|
300
|
-
void handleMcpHttpRequest(request, response, runtime).catch(destroyFailedMcpHttpResponse.bind(undefined, response));
|
|
301
|
-
});
|
|
302
|
-
PM_MCP_HTTP_RUNTIMES.set(server, runtime);
|
|
303
|
-
server.on("close", () => {
|
|
304
|
-
closeActiveHttpSubscriptions(runtime);
|
|
305
|
-
PM_MCP_HTTP_RUNTIMES.delete(server);
|
|
306
|
-
});
|
|
307
|
-
return server;
|
|
308
|
-
}
|
|
309
|
-
function closeActiveHttpSubscriptions(runtime) {
|
|
310
|
-
for (const [key, active] of runtime.activeSubscriptions) {
|
|
311
|
-
if (active.timer)
|
|
312
|
-
clearInterval(active.timer);
|
|
313
|
-
const result = closeMcpSubscription(active.id, key);
|
|
314
|
-
if (result) {
|
|
315
|
-
active.response.write(`data: ${JSON.stringify({ jsonrpc: "2.0", id: active.id, result })}\n\n`);
|
|
316
|
-
}
|
|
317
|
-
active.response.end();
|
|
318
|
-
}
|
|
319
|
-
runtime.activeSubscriptions.clear();
|
|
320
|
-
}
|
|
321
|
-
/** Gracefully close subscriptions before stopping a Streamable HTTP server. */
|
|
322
|
-
export async function closePmMcpHttpServer(server) {
|
|
323
|
-
const runtime = PM_MCP_HTTP_RUNTIMES.get(server);
|
|
324
|
-
if (runtime)
|
|
325
|
-
closeActiveHttpSubscriptions(runtime);
|
|
326
|
-
await new Promise((resolve, reject) => {
|
|
327
|
-
server.close((error) => (error ? reject(error) : resolve()));
|
|
328
|
-
});
|
|
329
|
-
server.closeAllConnections();
|
|
330
|
-
}
|
|
331
|
-
/** Bind the configured Streamable HTTP server and return its actual address. */
|
|
332
|
-
export async function startPmMcpHttpServer(options = {}) {
|
|
333
|
-
const server = createPmMcpHttpServer(options);
|
|
334
|
-
const address = resolvePmMcpHttpListenAddress(options);
|
|
335
|
-
await new Promise((resolve, reject) => {
|
|
336
|
-
server.once("error", reject);
|
|
337
|
-
server.listen(address.port, address.host, () => {
|
|
338
|
-
server.off("error", reject);
|
|
339
|
-
resolve();
|
|
340
|
-
});
|
|
341
|
-
});
|
|
342
|
-
return server;
|
|
343
|
-
}
|
|
344
|
-
/** Resolve loopback-safe bind defaults without opening a socket. */
|
|
345
|
-
export function resolvePmMcpHttpListenAddress(options = {}) {
|
|
346
|
-
return {
|
|
347
|
-
host: options.host ?? "127.0.0.1",
|
|
348
|
-
port: options.port ?? 3000,
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
function readMcpHttpEnvironment(environment) {
|
|
352
|
-
const configuredPort = environment.PM_MCP_HTTP_PORT?.trim();
|
|
353
|
-
const port = Number(configuredPort || "3000");
|
|
354
|
-
if (!Number.isInteger(port) || port < 0 || port > 65_535) {
|
|
355
|
-
throw new Error("PM_MCP_HTTP_PORT must be an integer from 0 through 65535");
|
|
356
|
-
}
|
|
357
|
-
return {
|
|
358
|
-
host: environment.PM_MCP_HTTP_HOST?.trim() || "127.0.0.1",
|
|
359
|
-
port,
|
|
360
|
-
allowedOrigins: (environment.PM_MCP_HTTP_ALLOWED_ORIGINS ?? "")
|
|
361
|
-
.split(",")
|
|
362
|
-
.map((entry) => entry.trim())
|
|
363
|
-
.filter(Boolean),
|
|
364
|
-
token: environment.PM_MCP_HTTP_BEARER_TOKEN?.trim() || undefined,
|
|
365
|
-
issuer: environment.PM_MCP_HTTP_AUTH_ISSUER?.trim() || undefined,
|
|
366
|
-
resource: environment.PM_MCP_HTTP_RESOURCE?.trim() || undefined,
|
|
367
|
-
scopes: (environment.PM_MCP_HTTP_SCOPES ?? "pm:read pm:write")
|
|
368
|
-
.split(/\s+/u)
|
|
369
|
-
.filter(Boolean),
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
function buildMcpHttpAuthorizationOptions(environment) {
|
|
373
|
-
const metadata = buildMcpProtectedResourceMetadata({
|
|
374
|
-
resource: environment.resource,
|
|
375
|
-
authorizationServers: [environment.issuer],
|
|
376
|
-
scopes: environment.scopes,
|
|
377
|
-
});
|
|
378
|
-
const acceptedIssuer = environment.issuer;
|
|
379
|
-
return {
|
|
380
|
-
protectedResourceMetadata: metadata,
|
|
381
|
-
authorization: {
|
|
382
|
-
issuer: acceptedIssuer,
|
|
383
|
-
resource: metadata.resource,
|
|
384
|
-
requiredScopes: environment.scopes,
|
|
385
|
-
resourceMetadataUrl: new URL("/.well-known/oauth-protected-resource", metadata.resource).href,
|
|
386
|
-
verifyAccessToken: createMcpStaticBearerVerifier({
|
|
387
|
-
token: environment.token,
|
|
388
|
-
claims: {
|
|
389
|
-
principal: "configured-remote-client",
|
|
390
|
-
issuer: acceptedIssuer,
|
|
391
|
-
audience: metadata.resource,
|
|
392
|
-
scopes: environment.scopes,
|
|
393
|
-
},
|
|
394
|
-
}),
|
|
395
|
-
},
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
function hasCompleteMcpHttpAuthorization(environment) {
|
|
399
|
-
return Boolean(environment.token && environment.issuer && environment.resource);
|
|
400
|
-
}
|
|
401
|
-
/** Resolve and harden executable HTTP options from an environment map. */
|
|
402
|
-
export function resolvePmMcpHttpServerOptionsFromEnvironment(processEnvironment = process.env) {
|
|
403
|
-
const environment = readMcpHttpEnvironment(processEnvironment);
|
|
404
|
-
const hasAuthorization = hasCompleteMcpHttpAuthorization(environment);
|
|
405
|
-
if (environment.host !== "127.0.0.1" &&
|
|
406
|
-
environment.host !== "localhost" &&
|
|
407
|
-
!hasAuthorization) {
|
|
408
|
-
throw new Error("Non-loopback MCP HTTP requires PM_MCP_HTTP_BEARER_TOKEN, PM_MCP_HTTP_AUTH_ISSUER, and PM_MCP_HTTP_RESOURCE");
|
|
409
|
-
}
|
|
410
|
-
const base = {
|
|
411
|
-
host: environment.host,
|
|
412
|
-
port: environment.port,
|
|
413
|
-
allowedOrigins: environment.allowedOrigins,
|
|
414
|
-
};
|
|
415
|
-
return hasAuthorization
|
|
416
|
-
? {
|
|
417
|
-
...base,
|
|
418
|
-
...buildMcpHttpAuthorizationOptions({
|
|
419
|
-
issuer: environment.issuer,
|
|
420
|
-
resource: environment.resource,
|
|
421
|
-
token: environment.token,
|
|
422
|
-
scopes: environment.scopes,
|
|
423
|
-
}),
|
|
424
|
-
}
|
|
425
|
-
: base;
|
|
426
|
-
}
|
|
427
|
-
/** Internal HTTP transport seams used only by direct integration tests. */
|
|
428
|
-
export const _testOnly = {
|
|
429
|
-
/** Return the first active request-scoped transport key for one server. */
|
|
430
|
-
activeSubscriptionKey: (server) => PM_MCP_HTTP_RUNTIMES.get(server).activeSubscriptions.keys().next().value,
|
|
431
|
-
/** Open a stream against one server runtime without a network socket. */
|
|
432
|
-
openHttpSubscription: (server, request, response) => openHttpSubscription({
|
|
433
|
-
request,
|
|
434
|
-
response,
|
|
435
|
-
runtime: PM_MCP_HTTP_RUNTIMES.get(server),
|
|
436
|
-
}),
|
|
437
|
-
/** Exercise committed-response handling without a network race. */
|
|
438
|
-
writeMcpHttpDispatchError,
|
|
439
|
-
/** Exercise the terminal request rejection handler without a live socket. */
|
|
440
|
-
destroyFailedMcpHttpResponse,
|
|
441
|
-
};
|
|
442
|
-
/* c8 ignore start -- executable guard and process lifecycle are integration-tested */
|
|
443
|
-
if (isInvokedAsMcpMainModule(process.argv[1], import.meta.url)) {
|
|
444
|
-
startPmMcpHttpServer(resolvePmMcpHttpServerOptionsFromEnvironment()).catch((error) => {
|
|
445
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
446
|
-
process.exit(1);
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
/* c8 ignore stop */
|
|
4
|
+
`)&&!settled){settled=true;cleanup();resolve()}}catch(error){cleanup();reject(error)}})}function writeJson(response,status,payload,headers={}){response.writeHead(status,{"Cache-Control":"no-store","Content-Type":"application/json",...headers});response.end(`${JSON.stringify(payload)}
|
|
5
|
+
`)}function writeJsonRpcError(response,id,error){const authorizationError=error instanceof PmMcpAuthorizationError?error:void 0;const protocolError=error instanceof PmMcpProtocolError?error:void 0;const code=protocolError?.code??-32603;const clientErrorCodes=new Set([-32700,-32600,PM_MCP_ERROR_CODES.headerMismatch,PM_MCP_ERROR_CODES.unsupportedProtocolVersion,PM_MCP_ERROR_CODES.invalidParams]);const status=authorizationError?.httpStatus??(code===-32601?404:clientErrorCodes.has(code)?400:500);writeJson(response,status,{jsonrpc:"2.0",id:id??null,error:{code,message:error instanceof Error?error.message:"Internal MCP error",...protocolError?{data:protocolError.data}:{}}},authorizationError?.challenge?{"WWW-Authenticate":authorizationError.challenge}:{})}function finishCommittedMcpResponse(response){if(!response.headersSent&&!response.writableEnded&&!response.destroyed){return false}if(!response.writableEnded&&!response.destroyed)response.end();return true}function writeMcpHttpDispatchError(response,rpcRequest,error){if(finishCommittedMcpResponse(response))return;const toolError=rpcRequest?buildMcpToolCallErrorResult(rpcRequest,error):void 0;if(toolError&&rpcRequest){writeJson(response,200,{jsonrpc:"2.0",id:rpcRequest.id??null,result:toolError});return}writeJsonRpcError(response,rpcRequest?.id,error)}function destroyFailedMcpHttpResponse(response,error){response.destroy(new Error("Unhandled MCP HTTP request failure",{cause:error}))}async function readRequestBody(request,maximumBytes){const chunks=[];let observed=0;for await(const chunk of request){const buffer=Buffer.from(chunk);observed+=buffer.length;if(observed>maximumBytes){throw new PmMcpProtocolError("MCP HTTP request body exceeds the configured limit",PM_MCP_ERROR_CODES.invalidParams,{maximumBytes})}chunks.push(buffer)}return Buffer.concat(chunks).toString("utf8")}function parseJsonRpcRequest(source){let value;try{value=JSON.parse(source)}catch{throw new PmMcpProtocolError("Invalid JSON-RPC request body",-32700)}if(typeof value!=="object"||value===null||Array.isArray(value)||"jsonrpc"in value&&value.jsonrpc!=="2.0"||"method"in value&&typeof value.method!=="string"){throw new PmMcpProtocolError("Invalid JSON-RPC request",-32600)}return value}function protectedResourcePaths(endpointPath){return new Set(["/.well-known/oauth-protected-resource",`/.well-known/oauth-protected-resource${endpointPath}`])}function routeMcpHttpBoundary(request,response,requestUrl,runtime){if(runtime.options.protectedResourceMetadata&&request.method==="GET"&&protectedResourcePaths(runtime.endpointPath).has(requestUrl.pathname)){writeJson(response,200,{...runtime.options.protectedResourceMetadata});return true}if(requestUrl.pathname!==runtime.endpointPath){writeJson(response,404,{error:"Not found"});return true}if(request.method!=="POST"){response.setHeader("Allow","POST");writeJson(response,405,{error:"Method not allowed"});return true}const origin=request.headers.origin;if(origin!==void 0&&!runtime.allowedOrigins.has(origin)){writeJson(response,403,{error:"Origin is not allowed"});return true}const accept=request.headers.accept;const contentType=request.headers["content-type"];if(typeof accept!=="string"||!accept.includes("application/json")||!accept.includes("text/event-stream")||typeof contentType!=="string"||!contentType.startsWith("application/json")){writeJson(response,406,{error:"MCP requires JSON and SSE content negotiation"});return true}return false}async function openHttpSubscription(input){if(typeof input.request.id!=="string"&&typeof input.request.id!=="number"){throw new PmMcpProtocolError("subscriptions/listen requires a JSON-RPC id",PM_MCP_ERROR_CODES.invalidParams)}const subscriptionId=input.request.id;const subscriptionKey=Symbol("pm-mcp-http-subscription");const active={id:subscriptionId,key:subscriptionKey,response:input.response};let disconnected=input.response.destroyed||input.response.writableEnded;let subscriptionOpened=false;const closeActiveSubscription=()=>{disconnected=true;if(active.timer)clearInterval(active.timer);input.runtime.activeSubscriptions.delete(subscriptionKey);if(subscriptionOpened){closeMcpSubscription(subscriptionId,subscriptionKey)}};input.response.once("close",closeActiveSubscription);let responseStarted=false;try{await openMcpSubscription({request:input.request,key:subscriptionKey,sink:notification=>{if(input.response.destroyed||input.response.writableEnded){throw new Error("MCP response stream closed before acknowledgment")}if(!responseStarted){responseStarted=true;input.response.setHeader("Cache-Control","no-cache, no-store");input.response.setHeader("Connection","keep-alive");input.response.setHeader("Content-Type","text/event-stream");input.response.setHeader("X-Accel-Buffering","no")}return writePmMcpSseEvent(input.response,notification)}});subscriptionOpened=true}catch(error){input.response.off("close",closeActiveSubscription);throw error}if(disconnected||input.response.destroyed||input.response.writableEnded){closeActiveSubscription();return}if(input.runtime.keepAliveMs>0){active.timer=setInterval(()=>input.response.write(":\r\n\r\n"),input.runtime.keepAliveMs);active.timer.unref()}input.runtime.activeSubscriptions.set(subscriptionKey,active)}async function dispatchMcpHttpRpc(input){let rpcRequest;try{if(input.runtime.options.authorization){await authorizeMcpHttpRequest({headers:input.request.headers,requestUrl:input.requestUrl.href,policy:input.runtime.options.authorization})}rpcRequest=parseJsonRpcRequest(await readRequestBody(input.request,input.runtime.maximumBodyBytes));validateMcpHttpRequestHeaders({headers:input.request.headers,request:rpcRequest,toolSchema:await resolveMcpToolSchemaForRequest(rpcRequest)});if(rpcRequest.method==="subscriptions/listen"){await openHttpSubscription({request:rpcRequest,response:input.response,runtime:input.runtime});return}const result=await(input.runtime.options.requestHandler??handleRequest)(rpcRequest);if(!Object.prototype.hasOwnProperty.call(rpcRequest,"id")){input.response.writeHead(202);input.response.end();return}writeJson(input.response,200,{jsonrpc:"2.0",id:rpcRequest.id??null,result:result??{}})}catch(error){writeMcpHttpDispatchError(input.response,rpcRequest,error)}}async function handleMcpHttpRequest(request,response,runtime){const requestUrl=new URL(request.url,"http://localhost");if(routeMcpHttpBoundary(request,response,requestUrl,runtime))return;await dispatchMcpHttpRpc({request,response,requestUrl,runtime})}function createPmMcpHttpServer(options={}){const runtime={activeSubscriptions:new Map,allowedOrigins:new Set(options.allowedOrigins??[]),endpointPath:options.endpointPath??"/mcp",keepAliveMs:options.keepAliveMs??DEFAULT_KEEP_ALIVE_MS,maximumBodyBytes:options.maximumBodyBytes??DEFAULT_MAXIMUM_BODY_BYTES,options};const server=createServer((request,response)=>{void handleMcpHttpRequest(request,response,runtime).catch(destroyFailedMcpHttpResponse.bind(void 0,response))});PM_MCP_HTTP_RUNTIMES.set(server,runtime);server.on("close",()=>{closeActiveHttpSubscriptions(runtime);PM_MCP_HTTP_RUNTIMES.delete(server)});return server}function closeActiveHttpSubscriptions(runtime){for(const[key,active]of runtime.activeSubscriptions){if(active.timer)clearInterval(active.timer);const result=closeMcpSubscription(active.id,key);if(result){active.response.write(`data: ${JSON.stringify({jsonrpc:"2.0",id:active.id,result})}
|
|
6
|
+
|
|
7
|
+
`)}active.response.end()}runtime.activeSubscriptions.clear()}async function closePmMcpHttpServer(server){const runtime=PM_MCP_HTTP_RUNTIMES.get(server);if(runtime)closeActiveHttpSubscriptions(runtime);await new Promise((resolve,reject)=>{server.close(error=>error?reject(error):resolve())});server.closeAllConnections()}async function startPmMcpHttpServer(options={}){const server=createPmMcpHttpServer(options);const address=resolvePmMcpHttpListenAddress(options);await new Promise((resolve,reject)=>{server.once("error",reject);server.listen(address.port,address.host,()=>{server.off("error",reject);resolve()})});return server}function resolvePmMcpHttpListenAddress(options={}){return{host:options.host??"127.0.0.1",port:options.port??3e3}}function readMcpHttpEnvironment(environment){const configuredPort=environment.PM_MCP_HTTP_PORT?.trim();const port=Number(configuredPort||"3000");if(!Number.isInteger(port)||port<0||port>65535){throw new Error("PM_MCP_HTTP_PORT must be an integer from 0 through 65535")}return{host:environment.PM_MCP_HTTP_HOST?.trim()||"127.0.0.1",port,allowedOrigins:(environment.PM_MCP_HTTP_ALLOWED_ORIGINS??"").split(",").map(entry=>entry.trim()).filter(Boolean),token:environment.PM_MCP_HTTP_BEARER_TOKEN?.trim()||void 0,issuer:environment.PM_MCP_HTTP_AUTH_ISSUER?.trim()||void 0,resource:environment.PM_MCP_HTTP_RESOURCE?.trim()||void 0,scopes:(environment.PM_MCP_HTTP_SCOPES??"pm:read pm:write").split(/\s+/u).filter(Boolean)}}function buildMcpHttpAuthorizationOptions(environment){const metadata=buildMcpProtectedResourceMetadata({resource:environment.resource,authorizationServers:[environment.issuer],scopes:environment.scopes});const acceptedIssuer=environment.issuer;return{protectedResourceMetadata:metadata,authorization:{issuer:acceptedIssuer,resource:metadata.resource,requiredScopes:environment.scopes,resourceMetadataUrl:new URL("/.well-known/oauth-protected-resource",metadata.resource).href,verifyAccessToken:createMcpStaticBearerVerifier({token:environment.token,claims:{principal:"configured-remote-client",issuer:acceptedIssuer,audience:metadata.resource,scopes:environment.scopes}})}}}function hasCompleteMcpHttpAuthorization(environment){return Boolean(environment.token&&environment.issuer&&environment.resource)}function resolvePmMcpHttpServerOptionsFromEnvironment(processEnvironment=process.env){const environment=readMcpHttpEnvironment(processEnvironment);const hasAuthorization=hasCompleteMcpHttpAuthorization(environment);if(environment.host!=="127.0.0.1"&&environment.host!=="localhost"&&!hasAuthorization){throw new Error("Non-loopback MCP HTTP requires PM_MCP_HTTP_BEARER_TOKEN, PM_MCP_HTTP_AUTH_ISSUER, and PM_MCP_HTTP_RESOURCE")}const base={host:environment.host,port:environment.port,allowedOrigins:environment.allowedOrigins};return hasAuthorization?{...base,...buildMcpHttpAuthorizationOptions({issuer:environment.issuer,resource:environment.resource,token:environment.token,scopes:environment.scopes})}:base}const _testOnly={activeSubscriptionKey:server=>PM_MCP_HTTP_RUNTIMES.get(server).activeSubscriptions.keys().next().value,openHttpSubscription:(server,request,response)=>openHttpSubscription({request,response,runtime:PM_MCP_HTTP_RUNTIMES.get(server)}),writeMcpHttpDispatchError,destroyFailedMcpHttpResponse};if(isInvokedAsMcpMainModule(process.argv[1],import.meta.url)){startPmMcpHttpServer(resolvePmMcpHttpServerOptionsFromEnvironment()).catch(error=>{console.error(error instanceof Error?error.message:String(error));process.exit(1)})}export{_testOnly,closePmMcpHttpServer,createPmMcpHttpServer,resolvePmMcpHttpListenAddress,resolvePmMcpHttpServerOptionsFromEnvironment,startPmMcpHttpServer,writePmMcpSseEvent};
|
|
450
8
|
//# sourceMappingURL=http-server.js.map
|
|
451
|
-
//# debugId=7c5d2b34-e2ab-52a9-80a9-c5a28ce09dc7
|