@the-open-engine/zeroshot 6.38.0 → 6.39.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/cli/event-copy.js +8 -7
- package/cli/event-copy.ts +12 -0
- package/cli/index.js +7 -31
- package/cli/json-export.js +61 -64
- package/cli/json-export.ts +112 -0
- package/cli/message-formatter-utils.js +68 -56
- package/cli/message-formatter-utils.ts +121 -0
- package/cli/message-formatters-normal.js +124 -259
- package/cli/message-formatters-normal.ts +250 -0
- package/cli/message-formatters-watch.js +81 -84
- package/cli/message-formatters-watch.ts +189 -0
- package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -1
- package/lib/agent-cli-provider/adapters/codex.js +3 -1
- package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
- package/lib/cluster/generated/protocol-schema.cjs +1 -1
- package/lib/cluster/generated/protocol-schema.mjs +1 -1
- package/lib/cluster/generated/protocol.d.cts +8 -0
- package/lib/cluster/generated/protocol.d.mts +8 -0
- package/lib/cluster/generated/protocol.d.ts +8 -0
- package/lib/clusters-registry.d.ts +23 -0
- package/lib/clusters-registry.js +17 -29
- package/lib/completion.d.ts +12 -0
- package/lib/completion.js +84 -94
- package/lib/compose-utils.d.ts +32 -0
- package/lib/compose-utils.js +57 -72
- package/lib/detached-startup.d.ts +83 -0
- package/lib/detached-startup.js +231 -302
- package/lib/docker-config.d.ts +43 -0
- package/lib/docker-config.js +150 -325
- package/lib/docker-env-auth.d.ts +17 -0
- package/lib/docker-env-auth.js +75 -0
- package/lib/git-remote-utils.d.ts +48 -0
- package/lib/git-remote-utils.js +147 -213
- package/lib/id-detector.d.ts +15 -0
- package/lib/id-detector.js +37 -41
- package/lib/path-check.d.ts +30 -0
- package/lib/path-check.js +42 -45
- package/lib/process-liveness.d.ts +16 -0
- package/lib/process-liveness.js +19 -12
- package/lib/provider-credential-path.d.ts +16 -0
- package/lib/provider-credential-path.js +31 -29
- package/lib/provider-defaults.d.ts +30 -0
- package/lib/provider-defaults.js +47 -42
- package/lib/provider-detection.d.ts +11 -0
- package/lib/provider-detection.js +91 -54
- package/lib/provider-names.d.ts +38 -0
- package/lib/provider-names.js +56 -64
- package/lib/repo-settings.d.ts +28 -0
- package/lib/repo-settings.js +83 -59
- package/lib/run-mode.d.ts +21 -0
- package/lib/run-mode.js +21 -20
- package/lib/run-plan.d.ts +28 -0
- package/lib/run-plan.js +17 -16
- package/lib/settings/claude-auth.d.ts +35 -0
- package/lib/settings/claude-auth.js +30 -47
- package/lib/settings-defaults.d.ts +20 -0
- package/lib/settings-defaults.js +149 -0
- package/lib/settings-error.d.ts +7 -0
- package/lib/settings-error.js +8 -0
- package/lib/settings-issue-providers.d.ts +10 -0
- package/lib/settings-issue-providers.js +12 -0
- package/lib/settings-models.d.ts +22 -0
- package/lib/settings-models.js +93 -0
- package/lib/settings-storage.d.ts +23 -0
- package/lib/settings-storage.js +205 -0
- package/lib/settings-validation.d.ts +7 -0
- package/lib/settings-validation.js +182 -0
- package/lib/settings.d.ts +29 -0
- package/lib/settings.js +41 -736
- package/lib/setup-apply-types.d.ts +66 -0
- package/lib/setup-apply-types.js +2 -0
- package/lib/setup-apply.d.ts +39 -0
- package/lib/setup-apply.js +267 -264
- package/lib/setup-journal.d.ts +41 -0
- package/lib/setup-journal.js +119 -76
- package/lib/setup-plan-types.d.ts +102 -0
- package/lib/setup-plan-types.js +2 -0
- package/lib/setup-plan.d.ts +30 -0
- package/lib/setup-plan.js +300 -324
- package/lib/setup-undo.d.ts +44 -0
- package/lib/setup-undo.js +61 -74
- package/lib/start-cluster-config.d.ts +26 -0
- package/lib/start-cluster-config.js +56 -0
- package/lib/start-cluster-environment.d.ts +40 -0
- package/lib/start-cluster-environment.js +134 -0
- package/lib/start-cluster-run-options.d.ts +53 -0
- package/lib/start-cluster-run-options.js +147 -0
- package/lib/start-cluster.d.ts +64 -0
- package/lib/start-cluster.js +98 -454
- package/lib/stream-json-parser.d.ts +17 -0
- package/lib/stream-json-parser.js +51 -52
- package/npm-shrinkwrap.json +2 -2
- package/package.json +12 -6
- package/scripts/postinstall.js +27 -0
- package/scripts/rust-distribution.js +23 -14
- package/src/agent/agent-command-proofs-context.js +35 -45
- package/src/agent/agent-command-proofs-context.ts +87 -0
- package/src/agent/agent-config-settings.js +19 -0
- package/src/agent/agent-config-settings.ts +41 -0
- package/src/agent/agent-config.js +122 -231
- package/src/agent/agent-config.ts +285 -0
- package/src/agent/agent-context-builder.js +38 -273
- package/src/agent/agent-context-builder.ts +51 -0
- package/src/agent/agent-context-environment-sections.js +105 -0
- package/src/agent/agent-context-environment-sections.ts +134 -0
- package/src/agent/agent-context-packs.js +165 -0
- package/src/agent/agent-context-packs.ts +296 -0
- package/src/agent/agent-context-prompt-sections.js +100 -0
- package/src/agent/agent-context-prompt-sections.ts +148 -0
- package/src/agent/agent-context-sections.js +25 -334
- package/src/agent/agent-context-sections.ts +36 -0
- package/src/agent/agent-context-sources.js +96 -149
- package/src/agent/agent-context-sources.ts +253 -0
- package/src/agent/agent-context-types.js +2 -0
- package/src/agent/agent-context-types.ts +132 -0
- package/src/agent/agent-context-validation-sections.js +73 -0
- package/src/agent/agent-context-validation-sections.ts +129 -0
- package/src/agent/agent-input-injector.js +99 -118
- package/src/agent/agent-input-injector.ts +195 -0
- package/src/agent/agent-liveness-poll.js +74 -78
- package/src/agent/agent-liveness-poll.ts +163 -0
- package/src/agent/agent-quality-gate-schema.js +77 -86
- package/src/agent/agent-quality-gate-schema.ts +135 -0
- package/src/agent/agent-quality-gates-context.js +44 -50
- package/src/agent/agent-quality-gates-context.ts +91 -0
- package/src/agent/agent-stuck-detector.js +171 -239
- package/src/agent/agent-stuck-detector.ts +288 -0
- package/src/agent/agent-trigger-evaluator.js +29 -46
- package/src/agent/agent-trigger-evaluator.ts +98 -0
- package/src/agent/context-metrics.js +110 -141
- package/src/agent/context-metrics.ts +261 -0
- package/src/agent/context-pack-builder.js +72 -358
- package/src/agent/context-pack-builder.ts +105 -0
- package/src/agent/context-pack-core.js +70 -0
- package/src/agent/context-pack-core.ts +96 -0
- package/src/agent/context-pack-selection.js +119 -0
- package/src/agent/context-pack-selection.ts +187 -0
- package/src/agent/context-pack-truncation.js +139 -0
- package/src/agent/context-pack-truncation.ts +208 -0
- package/src/agent/context-pack-types.js +2 -0
- package/src/agent/context-pack-types.ts +98 -0
- package/src/agent/context-replay-policy.js +30 -39
- package/src/agent/context-replay-policy.ts +71 -0
- package/src/agent/critical-agent-policy.js +6 -10
- package/src/agent/critical-agent-policy.ts +20 -0
- package/src/agent/guidance-queue.js +74 -87
- package/src/agent/guidance-queue.ts +166 -0
- package/src/agent/output-extraction-error-detail.js +45 -0
- package/src/agent/output-extraction-error-detail.ts +49 -0
- package/src/agent/output-extraction-failures.js +125 -0
- package/src/agent/output-extraction-failures.ts +149 -0
- package/src/agent/output-extraction-json.js +234 -0
- package/src/agent/output-extraction-json.ts +235 -0
- package/src/agent/output-extraction-pi.js +124 -0
- package/src/agent/output-extraction-pi.ts +137 -0
- package/src/agent/output-extraction-types.js +2 -0
- package/src/agent/output-extraction-types.ts +49 -0
- package/src/agent/output-extraction.js +17 -617
- package/src/agent/output-extraction.ts +30 -0
- package/src/agent/output-reformatter-errors.js +83 -0
- package/src/agent/output-reformatter-errors.ts +106 -0
- package/src/agent/output-reformatter-types.js +2 -0
- package/src/agent/output-reformatter-types.ts +86 -0
- package/src/agent/output-reformatter.js +140 -185
- package/src/agent/output-reformatter.ts +238 -0
- package/src/agent/pi-terminal-lifecycle-types.js +2 -0
- package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
- package/src/agent/pi-terminal-lifecycle.js +186 -206
- package/src/agent/pi-terminal-lifecycle.ts +297 -0
- package/src/agent/provider-control-plane.js +22 -21
- package/src/agent/provider-control-plane.ts +52 -0
- package/src/agent/provider-terminal-failure-types.js +2 -0
- package/src/agent/provider-terminal-failure-types.ts +60 -0
- package/src/agent/provider-terminal-failure.js +194 -191
- package/src/agent/provider-terminal-failure.ts +262 -0
- package/src/agent/rate-limit-backoff.js +31 -74
- package/src/agent/rate-limit-backoff.ts +71 -0
- package/src/agent/schema-utils.js +85 -125
- package/src/agent/schema-utils.ts +148 -0
- package/src/agent/structured-output-error.js +34 -33
- package/src/agent/structured-output-error.ts +105 -0
- package/src/agent/validation-platform.js +27 -27
- package/src/agent/validation-platform.ts +49 -0
- package/src/agent-cli-provider/adapters/codex.ts +3 -1
- package/src/attach/attach-client.js +232 -405
- package/src/attach/attach-client.ts +300 -0
- package/src/attach/attach-server-cleanup.js +43 -0
- package/src/attach/attach-server-cleanup.ts +39 -0
- package/src/attach/attach-server-clients.js +117 -0
- package/src/attach/attach-server-clients.ts +122 -0
- package/src/attach/attach-server-events.js +38 -0
- package/src/attach/attach-server-events.ts +36 -0
- package/src/attach/attach-server-pty.js +45 -0
- package/src/attach/attach-server-pty.ts +64 -0
- package/src/attach/attach-server-runtime.js +73 -0
- package/src/attach/attach-server-runtime.ts +62 -0
- package/src/attach/attach-server-socket.js +28 -0
- package/src/attach/attach-server-socket.ts +23 -0
- package/src/attach/attach-server-types.js +2 -0
- package/src/attach/attach-server-types.ts +82 -0
- package/src/attach/attach-server.js +106 -523
- package/src/attach/attach-server.ts +158 -0
- package/src/attach/index.js +18 -35
- package/src/attach/index.ts +18 -0
- package/src/attach/protocol.js +95 -184
- package/src/attach/protocol.ts +181 -0
- package/src/attach/ring-buffer.js +76 -102
- package/src/attach/ring-buffer.ts +109 -0
- package/src/attach/send-input.js +64 -75
- package/src/attach/send-input.ts +94 -0
- package/src/attach/socket-discovery.js +164 -218
- package/src/attach/socket-discovery.ts +230 -0
- package/src/attach/socket-paths.js +42 -61
- package/src/attach/socket-paths.ts +81 -0
- package/src/claude-credentials.js +51 -54
- package/src/claude-credentials.ts +89 -0
- package/src/cluster/generated/protocol-schema.ts +1 -1
- package/src/cluster/generated/protocol.ts +2 -1
- package/src/command-proofs.js +110 -141
- package/src/command-proofs.ts +216 -0
- package/src/config-router.js +81 -73
- package/src/config-router.ts +131 -0
- package/src/copy-worker.js +53 -29
- package/src/copy-worker.ts +75 -0
- package/src/darwin-keychain-boundary.js +80 -111
- package/src/darwin-keychain-boundary.ts +148 -0
- package/src/guidance-topics.js +4 -5
- package/src/guidance-topics.ts +10 -0
- package/src/input-helpers.js +33 -54
- package/src/input-helpers.ts +58 -0
- package/src/ledger-sequence.js +45 -48
- package/src/ledger-sequence.ts +63 -0
- package/src/legacy-lib/clusters-registry.ts +40 -0
- package/src/legacy-lib/completion.ts +148 -0
- package/src/legacy-lib/compose-utils.ts +102 -0
- package/src/legacy-lib/detached-startup.ts +449 -0
- package/src/legacy-lib/docker-config.ts +282 -0
- package/src/legacy-lib/docker-env-auth.ts +116 -0
- package/src/legacy-lib/git-remote-utils.ts +244 -0
- package/src/legacy-lib/id-detector.ts +57 -0
- package/src/legacy-lib/js-yaml.d.ts +3 -0
- package/src/legacy-lib/omelette.d.ts +15 -0
- package/src/legacy-lib/path-check.ts +89 -0
- package/src/legacy-lib/process-liveness.ts +36 -0
- package/src/legacy-lib/provider-credential-path.ts +57 -0
- package/src/legacy-lib/provider-defaults.ts +114 -0
- package/src/legacy-lib/provider-detection.ts +67 -0
- package/src/legacy-lib/provider-names.ts +126 -0
- package/src/legacy-lib/repo-settings.ts +88 -0
- package/src/legacy-lib/run-mode.ts +58 -0
- package/src/legacy-lib/run-plan.ts +49 -0
- package/src/legacy-lib/settings/claude-auth.ts +80 -0
- package/src/legacy-lib/settings-defaults.ts +212 -0
- package/src/legacy-lib/settings-error.ts +8 -0
- package/src/legacy-lib/settings-issue-providers.ts +18 -0
- package/src/legacy-lib/settings-models.ts +124 -0
- package/src/legacy-lib/settings-storage.ts +277 -0
- package/src/legacy-lib/settings-validation.ts +220 -0
- package/src/legacy-lib/settings.ts +87 -0
- package/src/legacy-lib/setup-apply-types.ts +70 -0
- package/src/legacy-lib/setup-apply.ts +456 -0
- package/src/legacy-lib/setup-journal.ts +185 -0
- package/src/legacy-lib/setup-plan-types.ts +96 -0
- package/src/legacy-lib/setup-plan.ts +500 -0
- package/src/legacy-lib/setup-undo.ts +142 -0
- package/src/legacy-lib/start-cluster-config.ts +124 -0
- package/src/legacy-lib/start-cluster-environment.ts +165 -0
- package/src/legacy-lib/start-cluster-run-options.ts +279 -0
- package/src/legacy-lib/start-cluster.ts +237 -0
- package/src/legacy-lib/stream-json-parser.ts +88 -0
- package/src/message-buffer.js +55 -71
- package/src/message-buffer.ts +107 -0
- package/src/message-bus-bridge.js +92 -133
- package/src/message-bus-bridge.ts +149 -0
- package/src/name-generator-shared.js +220 -0
- package/src/name-generator-shared.ts +231 -0
- package/src/name-generator.js +8 -217
- package/src/name-generator.ts +27 -0
- package/src/omp-blob-root.js +83 -64
- package/src/omp-blob-root.ts +116 -0
- package/src/omp-config-overlay.js +65 -38
- package/src/omp-config-overlay.ts +110 -0
- package/src/omp-execution-fingerprint.js +38 -43
- package/src/omp-execution-fingerprint.ts +92 -0
- package/src/omp-session-limits.js +10 -15
- package/src/omp-session-limits.ts +53 -0
- package/src/omp-session-partition.js +2 -2
- package/src/omp-session-verifier.js +1 -1
- package/src/orchestrator.js +19 -4
- package/src/providers/anthropic/index.js +3 -1
- package/src/providers/anthropic/index.ts +13 -0
- package/src/providers/capabilities.js +19 -27
- package/src/providers/capabilities.ts +44 -0
- package/src/providers/google/index.js +3 -1
- package/src/providers/google/index.ts +13 -0
- package/src/providers/openai/index.js +3 -1
- package/src/providers/openai/index.ts +13 -0
- package/src/providers/opencode/index.js +3 -1
- package/src/providers/opencode/index.ts +13 -0
- package/src/quality-gates.js +67 -127
- package/src/quality-gates.ts +149 -0
- package/src/repo-settings-access.js +40 -0
- package/src/repo-settings-access.ts +64 -0
- package/src/schemas/sub-cluster.js +127 -183
- package/src/schemas/sub-cluster.ts +238 -0
- package/src/state-snapshot-normalization.js +224 -0
- package/src/state-snapshot-normalization.ts +222 -0
- package/src/state-snapshot.js +192 -359
- package/src/state-snapshot.ts +291 -0
- package/src/state-snapshotter.js +118 -130
- package/src/state-snapshotter.ts +167 -0
- package/src/sub-cluster-wrapper.js +4 -13
- package/src/task-run-model-args.js +87 -124
- package/src/task-run-model-args.ts +204 -0
- package/src/task-runner.js +5 -25
- package/src/task-runner.ts +28 -0
- package/src/task-startup-error.js +73 -58
- package/src/task-startup-error.ts +126 -0
- package/src/template-validation/consensus-gate-contracts.js +2 -0
- package/src/template-validation/consensus-gate-contracts.ts +70 -0
- package/src/template-validation/consensus-gate-scenarios.js +76 -0
- package/src/template-validation/consensus-gate-scenarios.ts +130 -0
- package/src/template-validation/consensus-gate-stage.js +34 -0
- package/src/template-validation/consensus-gate-stage.ts +56 -0
- package/src/template-validation/random-topology-contracts.js +2 -0
- package/src/template-validation/random-topology-contracts.ts +54 -0
- package/src/template-validation/random-topology-dispatch.js +25 -0
- package/src/template-validation/random-topology-dispatch.ts +33 -0
- package/src/template-validation/random-topology-message-loop.js +53 -0
- package/src/template-validation/random-topology-message-loop.ts +73 -0
- package/src/template-validation/random-topology-operations.js +79 -0
- package/src/template-validation/random-topology-operations.ts +101 -0
- package/src/template-validation/random-topology-runtime.js +25 -0
- package/src/template-validation/random-topology-runtime.ts +43 -0
- package/src/template-validation/random-topology-scenario.js +52 -0
- package/src/template-validation/random-topology-scenario.ts +57 -0
- package/src/template-validation/random-topology-schema.js +159 -0
- package/src/template-validation/random-topology-schema.ts +190 -0
- package/src/template-validation/random-topology-state.js +28 -0
- package/src/template-validation/random-topology-state.ts +30 -0
- package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
- package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
- package/src/template-validation/random-topology-trigger.js +75 -0
- package/src/template-validation/random-topology-trigger.ts +88 -0
- package/src/template-validation/report-formatter.js +40 -46
- package/src/template-validation/report-formatter.ts +101 -0
- package/src/template-validation/simulate-consensus-gates.js +111 -302
- package/src/template-validation/simulate-consensus-gates.ts +196 -0
- package/src/template-validation/simulate-random-topology.js +26 -519
- package/src/template-validation/simulate-random-topology.ts +57 -0
- package/src/template-validation/simulate-two-stage-validation.js +41 -265
- package/src/template-validation/simulate-two-stage-validation.ts +55 -0
- package/src/template-validation/simulation-agent-runtime.js +25 -0
- package/src/template-validation/simulation-agent-runtime.ts +40 -0
- package/src/template-validation/simulation-agent.js +29 -0
- package/src/template-validation/simulation-agent.ts +73 -0
- package/src/template-validation/simulation-runtime.js +34 -0
- package/src/template-validation/simulation-runtime.ts +72 -0
- package/src/template-validation/two-stage-contracts.js +2 -0
- package/src/template-validation/two-stage-contracts.ts +41 -0
- package/src/template-validation/two-stage-inputs.js +21 -0
- package/src/template-validation/two-stage-inputs.ts +29 -0
- package/src/template-validation/two-stage-results.js +30 -0
- package/src/template-validation/two-stage-results.ts +40 -0
- package/src/template-validation/two-stage-scenario.js +86 -0
- package/src/template-validation/two-stage-scenario.ts +120 -0
- package/src/worktree-claude-config.js +182 -220
- package/src/worktree-claude-config.ts +272 -0
- package/src/worktree-tooling-env.js +103 -125
- package/src/worktree-tooling-env.ts +142 -0
- package/task-lib/completion.js +2 -3
- package/task-lib/completion.ts +9 -0
- package/task-lib/config.js +1 -4
- package/task-lib/config.ts +11 -0
- package/task-lib/name-generator.js +4 -226
- package/task-lib/name-generator.ts +11 -0
- package/task-lib/omp-session-cleanup.js +1 -1
- package/task-lib/omp-storage-root.js +8 -12
- package/task-lib/omp-storage-root.ts +62 -0
- package/task-lib/process-termination.js +143 -166
- package/task-lib/process-termination.ts +268 -0
package/lib/docker-config.js
CHANGED
|
@@ -1,353 +1,178 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* Uses $HOME placeholder - resolved at runtime based on dockerContainerHome setting
|
|
12
|
-
* Host paths use ~ (expanded to host user's home)
|
|
13
|
-
* Container paths use $HOME (expanded to configured container home)
|
|
14
|
-
*/
|
|
1
|
+
"use strict";
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
3
|
+
const providerNames = require('./provider-names');
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
5
|
+
const credentialPaths = require('./provider-credential-path');
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
7
|
+
const dockerEnvAuth = require('./docker-env-auth');
|
|
8
|
+
const { listProviderMetadata } = providerNames;
|
|
9
|
+
const { expandProviderCredentialPath } = credentialPaths;
|
|
10
|
+
const { isUsableEnvValue, isUsableHttpUrl, validateEnvPassthrough, validateProviderEnvAuth, } = dockerEnvAuth;
|
|
15
11
|
const BASE_MOUNT_PRESETS = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
gh: { host: '~/.config/gh', container: '$HOME/.config/gh', readonly: false },
|
|
13
|
+
git: { host: '~/.gitconfig', container: '$HOME/.gitconfig', readonly: true },
|
|
14
|
+
ssh: { host: '~/.ssh', container: '$HOME/.ssh', readonly: true },
|
|
15
|
+
aws: { host: '~/.aws', container: '$HOME/.aws', readonly: true },
|
|
16
|
+
azure: { host: '~/.azure', container: '$HOME/.azure', readonly: true },
|
|
17
|
+
kube: { host: '~/.kube', container: '$HOME/.kube', readonly: true },
|
|
18
|
+
terraform: { host: '~/.terraform.d', container: '$HOME/.terraform.d', readonly: false },
|
|
19
|
+
gcloud: { host: '~/.config/gcloud', container: '$HOME/.config/gcloud', readonly: true },
|
|
24
20
|
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Environment variables to auto-pass for each preset
|
|
28
|
-
* Supports:
|
|
29
|
-
* - Simple: 'VAR_NAME' (pass if set in host env)
|
|
30
|
-
* - Pattern: 'VAR_*' (pass all matching vars)
|
|
31
|
-
* - Forced: 'VAR=value' (always set to value)
|
|
32
|
-
* - Empty: 'VAR=' (always set to empty string)
|
|
33
|
-
*/
|
|
34
21
|
const BASE_ENV_PRESETS = {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
aws: ['AWS_REGION', 'AWS_DEFAULT_REGION', 'AWS_PROFILE', 'AWS_PAGER='],
|
|
23
|
+
azure: ['AZURE_SUBSCRIPTION_ID', 'AZURE_TENANT_ID', 'AZURE_CLIENT_ID'],
|
|
24
|
+
gcloud: ['CLOUDSDK_CORE_PROJECT', 'GOOGLE_CLOUD_PROJECT'],
|
|
25
|
+
kube: ['KUBECONFIG'],
|
|
26
|
+
terraform: ['TF_VAR_*'],
|
|
40
27
|
};
|
|
41
|
-
|
|
42
28
|
function listProviderDockerPresetEntries() {
|
|
43
|
-
|
|
29
|
+
return listProviderMetadata().map((metadata) => [metadata.id, metadata.docker]);
|
|
30
|
+
}
|
|
31
|
+
function listProviderMountEntries() {
|
|
32
|
+
const entries = [];
|
|
33
|
+
for (const [providerId, docker] of listProviderDockerPresetEntries()) {
|
|
34
|
+
if (docker.mount) {
|
|
35
|
+
entries.push([providerId, docker.mount]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return entries;
|
|
44
39
|
}
|
|
45
|
-
|
|
46
40
|
const MOUNT_PRESETS = Object.freeze({
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
listProviderDockerPresetEntries()
|
|
50
|
-
.filter(([, docker]) => docker.mount)
|
|
51
|
-
.map(([providerId, docker]) => [providerId, docker.mount])
|
|
52
|
-
),
|
|
41
|
+
...BASE_MOUNT_PRESETS,
|
|
42
|
+
...Object.fromEntries(listProviderMountEntries()),
|
|
53
43
|
});
|
|
54
|
-
|
|
55
44
|
const ENV_PRESETS = Object.freeze({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
])
|
|
62
|
-
),
|
|
45
|
+
...BASE_ENV_PRESETS,
|
|
46
|
+
...Object.fromEntries(listProviderDockerPresetEntries().map(([providerId, docker]) => [
|
|
47
|
+
providerId,
|
|
48
|
+
[...docker.envPassthrough],
|
|
49
|
+
])),
|
|
63
50
|
});
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
.filter(([, docker]) => !docker.mount && docker.envPassthrough.length > 0)
|
|
72
|
-
.map(([providerId]) => providerId)
|
|
73
|
-
)
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Resolve mount config to actual mount specs
|
|
78
|
-
* @param {Array<string|object>} config - Preset names or {host, container, readonly?} objects
|
|
79
|
-
* @param {object} options - Resolution options
|
|
80
|
-
* @param {string} [options.containerHome='/root'] - Container home directory for $HOME expansion
|
|
81
|
-
* @returns {Array<{host: string, container: string, readonly: boolean}>}
|
|
82
|
-
*/
|
|
83
|
-
function resolveMounts(config, options = {}) {
|
|
84
|
-
if (!Array.isArray(config)) {
|
|
85
|
-
throw new Error('dockerMounts must be an array');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const containerHome = options.containerHome || '/root';
|
|
89
|
-
|
|
90
|
-
return config.flatMap((item) => {
|
|
51
|
+
const PROVIDER_ENV_ONLY_PRESETS = Object.freeze(new Set(listProviderDockerPresetEntries()
|
|
52
|
+
.filter(([, docker]) => !docker.mount && docker.envPassthrough.length > 0)
|
|
53
|
+
.map(([providerId]) => providerId)));
|
|
54
|
+
function isCustomMount(value) {
|
|
55
|
+
return typeof value === 'object' && value !== null;
|
|
56
|
+
}
|
|
57
|
+
function resolveMountItem(item, containerHome) {
|
|
91
58
|
if (typeof item === 'string') {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
59
|
+
const preset = MOUNT_PRESETS[item];
|
|
60
|
+
if (!preset) {
|
|
61
|
+
if (PROVIDER_ENV_ONLY_PRESETS.has(item)) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
throw new Error(`Unknown mount preset: "${item}". Valid presets: ${Object.keys(MOUNT_PRESETS).join(', ')}. ` +
|
|
65
|
+
`Env-only presets (no mount): ${[...PROVIDER_ENV_ONLY_PRESETS].join(', ')}`);
|
|
96
66
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
host: overriddenHost,
|
|
108
|
-
container: preset.container.replace(/\$HOME/g, containerHome),
|
|
109
|
-
readonly: preset.readonly,
|
|
110
|
-
};
|
|
67
|
+
const overriddenHost = typeof preset.hostEnv === 'string' && process.env[preset.hostEnv]?.trim()
|
|
68
|
+
? expandProviderCredentialPath(`$${preset.hostEnv}`)
|
|
69
|
+
: preset.host;
|
|
70
|
+
return [
|
|
71
|
+
{
|
|
72
|
+
host: overriddenHost,
|
|
73
|
+
container: preset.container.replace(/\$HOME/g, containerHome),
|
|
74
|
+
readonly: preset.readonly,
|
|
75
|
+
},
|
|
76
|
+
];
|
|
111
77
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
78
|
+
if (isCustomMount(item)) {
|
|
79
|
+
if (!item.host || !item.container) {
|
|
80
|
+
throw new Error('Custom mount must have "host" and "container" properties');
|
|
81
|
+
}
|
|
82
|
+
return [
|
|
83
|
+
{
|
|
84
|
+
host: item.host,
|
|
85
|
+
container: item.container.replace(/\$HOME/g, containerHome),
|
|
86
|
+
readonly: item.readonly !== false,
|
|
87
|
+
},
|
|
88
|
+
];
|
|
122
89
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
)
|
|
127
|
-
|
|
90
|
+
throw new Error(`Invalid mount config: ${JSON.stringify(item)}. Use preset name or {host, container, readonly?}`);
|
|
91
|
+
}
|
|
92
|
+
function resolveMounts(config, options = {}) {
|
|
93
|
+
if (!Array.isArray(config)) {
|
|
94
|
+
throw new Error('dockerMounts must be an array');
|
|
95
|
+
}
|
|
96
|
+
const containerHome = options.containerHome || '/root';
|
|
97
|
+
return config.flatMap((item) => resolveMountItem(item, containerHome));
|
|
128
98
|
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Resolve env vars to pass based on enabled presets + explicit additions
|
|
132
|
-
* @param {Array<string|object>} mountConfig - The mount config (to detect presets)
|
|
133
|
-
* @param {Array<string>} extraEnvs - Additional env vars to pass
|
|
134
|
-
* @returns {Array<string>} - List of env var specs
|
|
135
|
-
*/
|
|
136
99
|
function resolveEnvs(mountConfig, extraEnvs = []) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
100
|
+
const envs = new Set(extraEnvs);
|
|
101
|
+
for (const item of mountConfig) {
|
|
102
|
+
if (typeof item === 'string') {
|
|
103
|
+
const preset = ENV_PRESETS[item];
|
|
104
|
+
if (preset) {
|
|
105
|
+
for (const envVar of preset) {
|
|
106
|
+
envs.add(envVar);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
144
110
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return [...envs];
|
|
111
|
+
return [...envs];
|
|
148
112
|
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Expand env var patterns and resolve values
|
|
152
|
-
* Supports:
|
|
153
|
-
* - Simple: 'VAR_NAME' (use value from env if set)
|
|
154
|
-
* - Pattern: 'VAR_*' (expand to all matching vars)
|
|
155
|
-
* - Forced: 'VAR=value' (always set to value)
|
|
156
|
-
* - Empty: 'VAR=' (always set to empty string)
|
|
157
|
-
*
|
|
158
|
-
* @param {Array<string>} envVars - List of env var specs
|
|
159
|
-
* @param {object} env - Environment object (defaults to process.env)
|
|
160
|
-
* @returns {Array<{name: string, value: string|null, forced: boolean}>}
|
|
161
|
-
*/
|
|
162
113
|
function expandEnvPatterns(envVars, env = process.env) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
114
|
+
const result = [];
|
|
115
|
+
for (const envVar of envVars) {
|
|
116
|
+
if (envVar.includes('=')) {
|
|
117
|
+
const separator = envVar.indexOf('=');
|
|
118
|
+
result.push({
|
|
119
|
+
name: envVar.slice(0, separator),
|
|
120
|
+
value: envVar.slice(separator + 1),
|
|
121
|
+
forced: true,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else if (envVar.endsWith('*')) {
|
|
125
|
+
const prefix = envVar.slice(0, -1);
|
|
126
|
+
for (const key of Object.keys(env)) {
|
|
127
|
+
if (key.startsWith(prefix)) {
|
|
128
|
+
result.push({ name: key, value: null, forced: false });
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
result.push({ name: envVar, value: null, forced: false });
|
|
178
134
|
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
// Simple: VAR_NAME
|
|
182
|
-
else {
|
|
183
|
-
result.push({ name: envVar, value: null, forced: false });
|
|
184
135
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return result;
|
|
136
|
+
return result;
|
|
188
137
|
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Validate mount config
|
|
192
|
-
* @param {unknown} value - Value to validate
|
|
193
|
-
* @returns {string|null} - Error message if invalid, null if valid
|
|
194
|
-
*/
|
|
195
138
|
function validateMountConfig(value) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
for (const item of value) {
|
|
201
|
-
if (typeof item === 'string') {
|
|
202
|
-
if (!MOUNT_PRESETS[item] && !PROVIDER_ENV_ONLY_PRESETS.has(item)) {
|
|
203
|
-
return (
|
|
204
|
-
`Unknown mount preset: "${item}". Valid: ${Object.keys(MOUNT_PRESETS).join(', ')}. ` +
|
|
205
|
-
`Env-only presets (no mount): ${[...PROVIDER_ENV_ONLY_PRESETS].join(', ')}`
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
} else if (typeof item === 'object' && item !== null) {
|
|
209
|
-
if (!item.host) {
|
|
210
|
-
return 'Custom mount missing "host" property';
|
|
211
|
-
}
|
|
212
|
-
if (!item.container) {
|
|
213
|
-
return 'Custom mount missing "container" property';
|
|
214
|
-
}
|
|
215
|
-
if (item.readonly !== undefined && typeof item.readonly !== 'boolean') {
|
|
216
|
-
return '"readonly" must be a boolean';
|
|
217
|
-
}
|
|
218
|
-
} else {
|
|
219
|
-
return `Invalid mount: ${JSON.stringify(item)}. Use preset name or {host, container, readonly?}`;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Validate env passthrough config
|
|
228
|
-
* @param {unknown} value - Value to validate
|
|
229
|
-
* @returns {string|null} - Error message if invalid, null if valid
|
|
230
|
-
*/
|
|
231
|
-
function validateEnvPassthrough(value) {
|
|
232
|
-
if (!Array.isArray(value)) {
|
|
233
|
-
return 'dockerEnvPassthrough must be an array';
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
for (const item of value) {
|
|
237
|
-
if (typeof item !== 'string') {
|
|
238
|
-
return `Invalid env var: ${JSON.stringify(item)}. Must be a string`;
|
|
239
|
-
}
|
|
240
|
-
// Allow: VAR, VAR_*, VAR=value, VAR=
|
|
241
|
-
if (!/^[A-Z_][A-Z0-9_]*(\*|=.*)?$/i.test(item)) {
|
|
242
|
-
return `Invalid env var spec: "${item}". Use VAR, VAR_*, or VAR=value`;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* A credential env var counts as present only when the container would actually receive a
|
|
251
|
-
* usable value. An absent, non-string, empty, or whitespace-only value is NOT a credential —
|
|
252
|
-
* `dockerEnvPassthrough: ["OPENAI_API_KEY="]` forces an empty value into `docker run -e`, which
|
|
253
|
-
* would otherwise read as "authenticated" while the CLI inside the container has nothing to use.
|
|
254
|
-
* @param {unknown} value
|
|
255
|
-
* @returns {boolean}
|
|
256
|
-
*/
|
|
257
|
-
function isUsableEnvValue(value) {
|
|
258
|
-
return typeof value === 'string' && value.trim() !== '';
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* A broker/base-URL env var is usable only when it parses as an absolute http(s) URL. Anything
|
|
263
|
-
* else (a bare host, a `file:` URL, a token pasted into the URL slot) fails closed rather than
|
|
264
|
-
* being handed to the provider to blow up on inside the container.
|
|
265
|
-
* @param {unknown} value
|
|
266
|
-
* @returns {boolean}
|
|
267
|
-
*/
|
|
268
|
-
function isUsableHttpUrl(value) {
|
|
269
|
-
if (!isUsableEnvValue(value)) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
let parsed;
|
|
273
|
-
try {
|
|
274
|
-
parsed = new URL(value.trim());
|
|
275
|
-
} catch {
|
|
276
|
-
return false;
|
|
277
|
-
}
|
|
278
|
-
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Validate a provider's fail-closed env/broker auth requirement (registry `docker.envAuth`)
|
|
283
|
-
* against the env vars actually forwarded into the container, using their ACTUAL values (a
|
|
284
|
-
* presence flag cannot distinguish a real key from a forced-empty one). Providers with no
|
|
285
|
-
* `envAuth` declared always pass (their auth is validated by mount/credential presence instead).
|
|
286
|
-
*
|
|
287
|
-
* Never includes a value in its output — only variable NAMES.
|
|
288
|
-
*
|
|
289
|
-
* @param {string} providerId
|
|
290
|
-
* @param {Record<string, string|undefined>} forwardedEnv - NAME -> the exact value the container
|
|
291
|
-
* would receive
|
|
292
|
-
* @returns {{ok: boolean, satisfiedOneOf: boolean, malformed: string[], message: string}}
|
|
293
|
-
* `satisfiedOneOf` reports whether an *automatic allowlist* credential is usable; `malformed`
|
|
294
|
-
* lists hard plan defects (partial required pair, unusable URL) that no other credential can
|
|
295
|
-
* compensate for. `ok` is the combination of both.
|
|
296
|
-
*/
|
|
297
|
-
function validateProviderEnvAuth(providerId, forwardedEnv) {
|
|
298
|
-
const metadata = getProviderMetadata(providerId);
|
|
299
|
-
const envAuth = metadata.docker && metadata.docker.envAuth;
|
|
300
|
-
if (!envAuth) {
|
|
301
|
-
return { ok: true, satisfiedOneOf: true, malformed: [], message: '' };
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
const requireUrl = new Set(envAuth.requireUrl || []);
|
|
305
|
-
const valueOf = (name) => (forwardedEnv ? forwardedEnv[name] : undefined);
|
|
306
|
-
// A URL-shaped var counts as "set" only when it is a usable http(s) URL; a malformed one is
|
|
307
|
-
// reported separately below so the remediation says "malformed", not "missing".
|
|
308
|
-
const isSet = (name) =>
|
|
309
|
-
requireUrl.has(name) ? isUsableHttpUrl(valueOf(name)) : isUsableEnvValue(valueOf(name));
|
|
310
|
-
|
|
311
|
-
const requireOneOf = envAuth.requireOneOf || [];
|
|
312
|
-
const satisfiedOneOf = requireOneOf.length === 0 || requireOneOf.some(isSet);
|
|
313
|
-
|
|
314
|
-
const malformed = [];
|
|
315
|
-
for (const name of requireUrl) {
|
|
316
|
-
if (isUsableEnvValue(valueOf(name)) && !isUsableHttpUrl(valueOf(name))) {
|
|
317
|
-
malformed.push(`${name} is set but is not a usable http(s) URL`);
|
|
139
|
+
if (!Array.isArray(value)) {
|
|
140
|
+
return 'dockerMounts must be an array';
|
|
318
141
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
142
|
+
for (const item of value) {
|
|
143
|
+
if (typeof item === 'string') {
|
|
144
|
+
if (!MOUNT_PRESETS[item] && !PROVIDER_ENV_ONLY_PRESETS.has(item)) {
|
|
145
|
+
return (`Unknown mount preset: "${item}". Valid: ${Object.keys(MOUNT_PRESETS).join(', ')}. ` +
|
|
146
|
+
`Env-only presets (no mount): ${[...PROVIDER_ENV_ONLY_PRESETS].join(', ')}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (isCustomMount(item)) {
|
|
150
|
+
if (!item.host) {
|
|
151
|
+
return 'Custom mount missing "host" property';
|
|
152
|
+
}
|
|
153
|
+
if (!item.container) {
|
|
154
|
+
return 'Custom mount missing "container" property';
|
|
155
|
+
}
|
|
156
|
+
if (item.readonly !== undefined && typeof item.readonly !== 'boolean') {
|
|
157
|
+
return '"readonly" must be a boolean';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
return `Invalid mount: ${JSON.stringify(item)}. Use preset name or {host, container, readonly?}`;
|
|
162
|
+
}
|
|
325
163
|
}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
const reasons = [...malformed];
|
|
329
|
-
if (!satisfiedOneOf) {
|
|
330
|
-
reasons.push(`one of ${requireOneOf.join(', ')} must be set to a non-empty value`);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
return {
|
|
334
|
-
ok: malformed.length === 0 && satisfiedOneOf,
|
|
335
|
-
satisfiedOneOf,
|
|
336
|
-
malformed,
|
|
337
|
-
message: reasons.join('; '),
|
|
338
|
-
};
|
|
164
|
+
return null;
|
|
339
165
|
}
|
|
340
|
-
|
|
341
166
|
module.exports = {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
167
|
+
MOUNT_PRESETS,
|
|
168
|
+
ENV_PRESETS,
|
|
169
|
+
PROVIDER_ENV_ONLY_PRESETS,
|
|
170
|
+
resolveMounts,
|
|
171
|
+
resolveEnvs,
|
|
172
|
+
expandEnvPatterns,
|
|
173
|
+
isUsableEnvValue,
|
|
174
|
+
isUsableHttpUrl,
|
|
175
|
+
validateMountConfig,
|
|
176
|
+
validateEnvPassthrough,
|
|
177
|
+
validateProviderEnvAuth,
|
|
353
178
|
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface ProviderEnvAuthResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
satisfiedOneOf: boolean;
|
|
4
|
+
malformed: string[];
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
declare function validateEnvPassthrough(value: unknown): string | null;
|
|
8
|
+
declare function isUsableEnvValue(value: unknown): value is string;
|
|
9
|
+
declare function isUsableHttpUrl(value: unknown): boolean;
|
|
10
|
+
declare function validateProviderEnvAuth(providerId: string, forwardedEnv: Readonly<Record<string, string | undefined>> | null | undefined): ProviderEnvAuthResult;
|
|
11
|
+
declare const _default: {
|
|
12
|
+
isUsableEnvValue: typeof isUsableEnvValue;
|
|
13
|
+
isUsableHttpUrl: typeof isUsableHttpUrl;
|
|
14
|
+
validateEnvPassthrough: typeof validateEnvPassthrough;
|
|
15
|
+
validateProviderEnvAuth: typeof validateProviderEnvAuth;
|
|
16
|
+
};
|
|
17
|
+
export = _default;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const url_1 = require("url");
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
4
|
+
const providerNames = require('./provider-names');
|
|
5
|
+
const ENV_SPEC_PATTERN = /^[A-Z_][A-Z0-9_]*(\*|=.*)?$/i;
|
|
6
|
+
function validateEnvPassthrough(value) {
|
|
7
|
+
if (!Array.isArray(value)) {
|
|
8
|
+
return 'dockerEnvPassthrough must be an array';
|
|
9
|
+
}
|
|
10
|
+
for (const item of value) {
|
|
11
|
+
if (typeof item !== 'string') {
|
|
12
|
+
return `Invalid env var: ${JSON.stringify(item)}. Must be a string`;
|
|
13
|
+
}
|
|
14
|
+
if (!ENV_SPEC_PATTERN.test(item)) {
|
|
15
|
+
return `Invalid env var spec: "${item}". Use VAR, VAR_*, or VAR=value`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
function isUsableEnvValue(value) {
|
|
21
|
+
return typeof value === 'string' && value.trim() !== '';
|
|
22
|
+
}
|
|
23
|
+
function isUsableHttpUrl(value) {
|
|
24
|
+
if (!isUsableEnvValue(value)) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
let parsed;
|
|
28
|
+
try {
|
|
29
|
+
parsed = new url_1.URL(value.trim());
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
35
|
+
}
|
|
36
|
+
function validateProviderEnvAuth(providerId, forwardedEnv) {
|
|
37
|
+
const metadata = providerNames.getProviderMetadata(providerId);
|
|
38
|
+
const envAuth = metadata.docker && metadata.docker.envAuth;
|
|
39
|
+
if (!envAuth) {
|
|
40
|
+
return { ok: true, satisfiedOneOf: true, malformed: [], message: '' };
|
|
41
|
+
}
|
|
42
|
+
const requireUrl = new Set(envAuth.requireUrl || []);
|
|
43
|
+
const valueOf = (name) => forwardedEnv ? forwardedEnv[name] : undefined;
|
|
44
|
+
const isSet = (name) => requireUrl.has(name) ? isUsableHttpUrl(valueOf(name)) : isUsableEnvValue(valueOf(name));
|
|
45
|
+
const requireOneOf = envAuth.requireOneOf || [];
|
|
46
|
+
const satisfiedOneOf = requireOneOf.length === 0 || requireOneOf.some(isSet);
|
|
47
|
+
const malformed = [];
|
|
48
|
+
for (const name of requireUrl) {
|
|
49
|
+
if (isUsableEnvValue(valueOf(name)) && !isUsableHttpUrl(valueOf(name))) {
|
|
50
|
+
malformed.push(`${name} is set but is not a usable http(s) URL`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const group of envAuth.requireTogether || []) {
|
|
54
|
+
const missing = group.filter((name) => !isSet(name));
|
|
55
|
+
if (missing.length > 0 && missing.length < group.length) {
|
|
56
|
+
malformed.push(`${group.join(' + ')} must be set together (missing ${missing.join(', ')})`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const reasons = [...malformed];
|
|
60
|
+
if (!satisfiedOneOf) {
|
|
61
|
+
reasons.push(`one of ${requireOneOf.join(', ')} must be set to a non-empty value`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
ok: malformed.length === 0 && satisfiedOneOf,
|
|
65
|
+
satisfiedOneOf,
|
|
66
|
+
malformed,
|
|
67
|
+
message: reasons.join('; '),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
module.exports = {
|
|
71
|
+
isUsableEnvValue,
|
|
72
|
+
isUsableHttpUrl,
|
|
73
|
+
validateEnvPassthrough,
|
|
74
|
+
validateProviderEnvAuth,
|
|
75
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git remote URL parsing and provider detection.
|
|
3
|
+
* Automatically detects issue provider from git remote URL.
|
|
4
|
+
*/
|
|
5
|
+
interface HostedGitContext {
|
|
6
|
+
provider: 'github' | 'gitlab';
|
|
7
|
+
host: string;
|
|
8
|
+
org: string;
|
|
9
|
+
repo: string;
|
|
10
|
+
fullRepo: string;
|
|
11
|
+
}
|
|
12
|
+
interface AzureDevOpsGitContext {
|
|
13
|
+
provider: 'azure-devops';
|
|
14
|
+
host: string;
|
|
15
|
+
azureOrg: string;
|
|
16
|
+
azureProject: string;
|
|
17
|
+
repo: string;
|
|
18
|
+
}
|
|
19
|
+
type GitContext = HostedGitContext | AzureDevOpsGitContext;
|
|
20
|
+
type GitContextWithRemote = GitContext & {
|
|
21
|
+
remote: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Normalize a Git remote name using the same ref-format rules Git applies to
|
|
25
|
+
* refs/remotes/<name>. Keeping this next to detection prevents a discovered
|
|
26
|
+
* remote from being rejected later by a narrower consumer-specific allowlist.
|
|
27
|
+
*/
|
|
28
|
+
declare function normalizeGitRemoteName(value: unknown): string | null;
|
|
29
|
+
/** Quote one argument for the POSIX shell snippets embedded in agent prompts. */
|
|
30
|
+
declare function quoteShellArgument(value: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Parse git remote URL into structured provider context.
|
|
33
|
+
* Supports GitHub, GitLab, and Azure DevOps (cloud + self-hosted).
|
|
34
|
+
* Handles both HTTPS and SSH URL formats.
|
|
35
|
+
*/
|
|
36
|
+
declare function parseGitRemoteUrl(remoteUrl: unknown): GitContext | null;
|
|
37
|
+
/**
|
|
38
|
+
* Detect git repository context from current working directory.
|
|
39
|
+
* Returns provider context extracted from git remote URL.
|
|
40
|
+
*/
|
|
41
|
+
declare function detectGitContext(cwd?: string): GitContextWithRemote | null;
|
|
42
|
+
declare const _default: {
|
|
43
|
+
normalizeGitRemoteName: typeof normalizeGitRemoteName;
|
|
44
|
+
quoteShellArgument: typeof quoteShellArgument;
|
|
45
|
+
parseGitRemoteUrl: typeof parseGitRemoteUrl;
|
|
46
|
+
detectGitContext: typeof detectGitContext;
|
|
47
|
+
};
|
|
48
|
+
export = _default;
|