@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
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
declare module 'omelette' {
|
|
2
|
+
interface CompletionData {
|
|
3
|
+
line: string;
|
|
4
|
+
reply(candidates: string[]): void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Completion {
|
|
8
|
+
init(): void;
|
|
9
|
+
on(event: 'complete', listener: (fragment: string, data: CompletionData) => void): this;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function omelette(template: string): Completion;
|
|
13
|
+
|
|
14
|
+
export = omelette;
|
|
15
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects whether the npm global bin directory is on PATH, so we can warn
|
|
3
|
+
* the user when `npm install -g` succeeds but the `zeroshot` binary is
|
|
4
|
+
* unreachable (e.g. non-standard Node installs whose global bin dir isn't
|
|
5
|
+
* exported).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path = require('path');
|
|
9
|
+
|
|
10
|
+
interface PathCheckOptions {
|
|
11
|
+
readonly installPrefix?: string;
|
|
12
|
+
readonly pathEnv?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface UpdateCheckerModule {
|
|
16
|
+
readonly getInstallPrefix: (options: PathCheckOptions) => string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type PathCheckResult =
|
|
20
|
+
| { readonly onPath: true; readonly binDir: null }
|
|
21
|
+
| { readonly onPath: boolean; readonly binDir: string };
|
|
22
|
+
|
|
23
|
+
function isUpdateCheckerModule(value: unknown): value is UpdateCheckerModule {
|
|
24
|
+
return (
|
|
25
|
+
typeof value === 'object' &&
|
|
26
|
+
value !== null &&
|
|
27
|
+
'getInstallPrefix' in value &&
|
|
28
|
+
typeof value.getInstallPrefix === 'function'
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function getGlobalBinDir(installPrefix: string): string {
|
|
33
|
+
if (process.platform === 'win32') {
|
|
34
|
+
return installPrefix;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return path.join(installPrefix, 'bin');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function isDirOnPath(dir: string, pathEnv: string = process.env.PATH || ''): boolean {
|
|
41
|
+
const resolvedDir = path.resolve(dir);
|
|
42
|
+
|
|
43
|
+
return pathEnv
|
|
44
|
+
.split(path.delimiter)
|
|
45
|
+
.filter((entry) => entry.length > 0)
|
|
46
|
+
.some((entry) => path.resolve(entry) === resolvedDir);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getPathExportLine(dir: string): string {
|
|
50
|
+
return `export PATH="${dir}:$PATH"`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function checkBinDirOnPath(options: PathCheckOptions = {}): PathCheckResult {
|
|
54
|
+
if (process.platform === 'win32') {
|
|
55
|
+
return { onPath: true, binDir: null };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const updateChecker: unknown = require('../cli/lib/update-checker');
|
|
60
|
+
if (!isUpdateCheckerModule(updateChecker)) {
|
|
61
|
+
throw new TypeError('update-checker must export getInstallPrefix');
|
|
62
|
+
}
|
|
63
|
+
const { getInstallPrefix } = updateChecker;
|
|
64
|
+
const installPrefix = options.installPrefix || getInstallPrefix(options);
|
|
65
|
+
const binDir = getGlobalBinDir(installPrefix);
|
|
66
|
+
|
|
67
|
+
return { onPath: isDirOnPath(binDir, options.pathEnv), binDir };
|
|
68
|
+
} catch {
|
|
69
|
+
return { onPath: true, binDir: null };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function printPathWarning(binDir: string): void {
|
|
74
|
+
console.error(
|
|
75
|
+
`[zeroshot] Warning: ${binDir} is not on your PATH — the 'zeroshot' command may not be found.`
|
|
76
|
+
);
|
|
77
|
+
console.error(` ${getPathExportLine(binDir)}`);
|
|
78
|
+
console.error(
|
|
79
|
+
' Add this line to your shell profile (~/.zshrc, ~/.bashrc, or ~/.profile) to fix this permanently.'
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export = {
|
|
84
|
+
getGlobalBinDir,
|
|
85
|
+
isDirOnPath,
|
|
86
|
+
getPathExportLine,
|
|
87
|
+
checkBinDirOnPath,
|
|
88
|
+
printPathWarning,
|
|
89
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for "is this PID actually alive?"
|
|
3
|
+
*
|
|
4
|
+
* Previously this check was reimplemented separately in src/orchestrator.js
|
|
5
|
+
* (_isProcessRunning) and lib/detached-startup.js (isProcessAlive), plus an
|
|
6
|
+
* inline copy in _getActiveClustersForIssue. Four of those call sites agreed
|
|
7
|
+
* on the answer; the resume() eligibility guard trusted persisted cluster
|
|
8
|
+
* state instead of asking the OS, which is what let a dead-PID cluster be
|
|
9
|
+
* simultaneously reported as "zombie" by status and "still running" by
|
|
10
|
+
* resume. Consolidating avoids a sixth call site reintroducing that split.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
function hasErrorCode(error: unknown, code: string): boolean {
|
|
14
|
+
return (
|
|
15
|
+
typeof error === 'object' &&
|
|
16
|
+
error !== null &&
|
|
17
|
+
'code' in error &&
|
|
18
|
+
error.code === code
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isProcessRunning(pid: unknown): boolean {
|
|
23
|
+
if (!pid || typeof pid !== 'number' || !Number.isInteger(pid) || pid <= 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
// Signal 0 doesn't kill, just checks if the process exists.
|
|
28
|
+
process.kill(pid, 0);
|
|
29
|
+
return true;
|
|
30
|
+
} catch (error: unknown) {
|
|
31
|
+
// ESRCH = no such process, EPERM = process exists but we lack permission.
|
|
32
|
+
return hasErrorCode(error, 'EPERM');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export = { isProcessRunning };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import os = require('node:os');
|
|
2
|
+
import path = require('node:path');
|
|
3
|
+
|
|
4
|
+
type Environment = Readonly<Record<string, string | undefined>>;
|
|
5
|
+
|
|
6
|
+
interface ProviderCredentialMetadata {
|
|
7
|
+
readonly credentialPaths: readonly string[];
|
|
8
|
+
readonly docker?: {
|
|
9
|
+
readonly mount?: {
|
|
10
|
+
readonly hostEnv?: unknown;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function expandHome(value: string): string {
|
|
16
|
+
if (value === '~') return os.homedir();
|
|
17
|
+
return value.startsWith('~/') ? path.join(os.homedir(), value.slice(2)) : value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function expandProviderCredentialPath(
|
|
21
|
+
value: string,
|
|
22
|
+
env: Environment = process.env
|
|
23
|
+
): string | null {
|
|
24
|
+
const homeExpanded = expandHome(value);
|
|
25
|
+
if (homeExpanded !== value) return homeExpanded;
|
|
26
|
+
const variable = /^\$([A-Z_][A-Z0-9_]*)(\/.*)?$/.exec(value);
|
|
27
|
+
if (!variable) return value;
|
|
28
|
+
const variableName = variable[1];
|
|
29
|
+
if (!variableName) return value;
|
|
30
|
+
const root = env[variableName];
|
|
31
|
+
return typeof root === 'string' && root.trim()
|
|
32
|
+
? path.resolve(expandHome(root), `.${variable[2] || ''}`)
|
|
33
|
+
: null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveProviderCredentialPaths(
|
|
37
|
+
metadata: ProviderCredentialMetadata,
|
|
38
|
+
env: Environment = process.env
|
|
39
|
+
): string[] {
|
|
40
|
+
const overrideName = metadata.docker?.mount?.hostEnv;
|
|
41
|
+
const overrideSet =
|
|
42
|
+
typeof overrideName === 'string' &&
|
|
43
|
+
typeof env[overrideName] === 'string' &&
|
|
44
|
+
env[overrideName].trim();
|
|
45
|
+
const candidates = overrideName
|
|
46
|
+
? metadata.credentialPaths.filter((value) =>
|
|
47
|
+
overrideSet
|
|
48
|
+
? value.startsWith(`$${overrideName}/`)
|
|
49
|
+
: !value.startsWith(`$${overrideName}/`)
|
|
50
|
+
)
|
|
51
|
+
: metadata.credentialPaths;
|
|
52
|
+
return candidates
|
|
53
|
+
.map((value) => expandProviderCredentialPath(value, env))
|
|
54
|
+
.filter((value): value is string => value !== null);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export = { expandProviderCredentialPath, resolveProviderCredentialPaths };
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider defaults module
|
|
3
|
+
*
|
|
4
|
+
* Separated from settings.js to break circular dependency:
|
|
5
|
+
* - settings.js requires provider defaults
|
|
6
|
+
* - providers require settings.js (for loadSettings, getClaudeCommand, etc.)
|
|
7
|
+
*
|
|
8
|
+
* CRITICAL: This module should NOT import from settings.js
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
interface ProviderDefaultSettings {
|
|
12
|
+
defaultLevel?: string;
|
|
13
|
+
levelOverrides?: Record<string, string>;
|
|
14
|
+
maxLevel?: string;
|
|
15
|
+
minLevel?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ProviderMetadata {
|
|
20
|
+
defaultLevels: {
|
|
21
|
+
default: string;
|
|
22
|
+
max: string;
|
|
23
|
+
min: string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface ProviderNamesFacade {
|
|
28
|
+
VALID_PROVIDERS: readonly string[];
|
|
29
|
+
getProviderMetadata(name: string): ProviderMetadata;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface ProviderFacade {
|
|
33
|
+
getDefaultSettings(): ProviderDefaultSettings;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ProvidersFacade {
|
|
37
|
+
getProvider(name: string): ProviderFacade;
|
|
38
|
+
listProviders(): string[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type ProviderDefaults = Record<string, ProviderDefaultSettings>;
|
|
42
|
+
|
|
43
|
+
// Cache provider defaults to avoid repeated instantiation
|
|
44
|
+
let _providerDefaultsCache: ProviderDefaults | null = null;
|
|
45
|
+
// The emitted CommonJS module resolves this maintained JavaScript facade from lib/.
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
47
|
+
const { VALID_PROVIDERS, getProviderMetadata }: ProviderNamesFacade = require('./provider-names');
|
|
48
|
+
|
|
49
|
+
function errorMessage(error: unknown): string | undefined {
|
|
50
|
+
if (typeof error !== 'object' || error === null || !('message' in error)) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
return typeof error.message === 'string' ? error.message : String(error.message);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Build provider default settings by instantiating each provider
|
|
58
|
+
* and calling getDefaultSettings()
|
|
59
|
+
*/
|
|
60
|
+
function buildProviderDefaults(): ProviderDefaults {
|
|
61
|
+
// Keep this require lazy to preserve the settings/provider circular-dependency boundary.
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
63
|
+
const { listProviders, getProvider }: ProvidersFacade = require('../src/providers');
|
|
64
|
+
|
|
65
|
+
const defaults: ProviderDefaults = {};
|
|
66
|
+
for (const providerName of listProviders()) {
|
|
67
|
+
try {
|
|
68
|
+
const provider = getProvider(providerName);
|
|
69
|
+
defaults[providerName] = provider.getDefaultSettings();
|
|
70
|
+
} catch (error: unknown) {
|
|
71
|
+
const metadata = getProviderMetadata(providerName);
|
|
72
|
+
console.warn(`Warning: Could not get defaults for ${providerName}: ${errorMessage(error)}`);
|
|
73
|
+
defaults[providerName] = {
|
|
74
|
+
maxLevel: metadata.defaultLevels.max,
|
|
75
|
+
minLevel: metadata.defaultLevels.min,
|
|
76
|
+
defaultLevel: metadata.defaultLevels.default,
|
|
77
|
+
levelOverrides: {},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
for (const providerName of VALID_PROVIDERS) {
|
|
82
|
+
if (defaults[providerName]) continue;
|
|
83
|
+
const metadata = getProviderMetadata(providerName);
|
|
84
|
+
defaults[providerName] = {
|
|
85
|
+
maxLevel: metadata.defaultLevels.max,
|
|
86
|
+
minLevel: metadata.defaultLevels.min,
|
|
87
|
+
defaultLevel: metadata.defaultLevels.default,
|
|
88
|
+
levelOverrides: {},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return defaults;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Get or build cached provider defaults
|
|
96
|
+
*/
|
|
97
|
+
function getProviderDefaults(): ProviderDefaults {
|
|
98
|
+
if (!_providerDefaultsCache) {
|
|
99
|
+
_providerDefaultsCache = buildProviderDefaults();
|
|
100
|
+
}
|
|
101
|
+
return _providerDefaultsCache;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Clear the provider defaults cache (primarily for testing)
|
|
106
|
+
*/
|
|
107
|
+
function clearProviderDefaultsCache(): void {
|
|
108
|
+
_providerDefaultsCache = null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export = {
|
|
112
|
+
getProviderDefaults,
|
|
113
|
+
clearProviderDefaultsCache,
|
|
114
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as childProcess from 'child_process';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
const { execSync, spawnSync } = childProcess;
|
|
6
|
+
|
|
7
|
+
function commandExists(command: string): boolean {
|
|
8
|
+
if (!command) return false;
|
|
9
|
+
if (command.includes(path.sep)) {
|
|
10
|
+
return fs.existsSync(command);
|
|
11
|
+
}
|
|
12
|
+
const probe = process.platform === 'win32' ? `where ${command}` : `command -v ${command}`;
|
|
13
|
+
try {
|
|
14
|
+
execSync(probe, { stdio: 'pipe' });
|
|
15
|
+
return true;
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getCommandPath(command: string): string | null {
|
|
22
|
+
if (!command) return null;
|
|
23
|
+
if (command.includes(path.sep)) {
|
|
24
|
+
return fs.existsSync(command) ? command : null;
|
|
25
|
+
}
|
|
26
|
+
const probe = process.platform === 'win32' ? `where ${command}` : `command -v ${command}`;
|
|
27
|
+
try {
|
|
28
|
+
const output = execSync(probe, { encoding: 'utf8', stdio: 'pipe' });
|
|
29
|
+
// `where` can return multiple matches (one per line); take the first.
|
|
30
|
+
const [firstMatch = ''] = output.split(/\r?\n/);
|
|
31
|
+
return firstMatch.trim() || null;
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function getHelpOutput(command: string, args: string[] = []): string {
|
|
38
|
+
if (!commandExists(command)) return '';
|
|
39
|
+
|
|
40
|
+
const attempt = (flag: string): string => {
|
|
41
|
+
const result = spawnSync(command, [...args, flag], { encoding: 'utf8' });
|
|
42
|
+
if (result.status !== 0) return '';
|
|
43
|
+
const output = `${result.stdout || ''}${result.stderr || ''}`;
|
|
44
|
+
return output.trim();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const help = attempt('--help');
|
|
48
|
+
if (help) return help;
|
|
49
|
+
|
|
50
|
+
const alt = attempt('-h');
|
|
51
|
+
return alt || '';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getVersionOutput(command: string, args: string[] = []): string {
|
|
55
|
+
if (!commandExists(command)) return '';
|
|
56
|
+
const result = spawnSync(command, [...args, '--version'], { encoding: 'utf8' });
|
|
57
|
+
if (result.status !== 0) return '';
|
|
58
|
+
const output = `${result.stdout || ''}${result.stderr || ''}`;
|
|
59
|
+
return output.trim();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export = {
|
|
63
|
+
commandExists,
|
|
64
|
+
getCommandPath,
|
|
65
|
+
getHelpOutput,
|
|
66
|
+
getVersionOutput,
|
|
67
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
type ProviderCapabilityState = boolean | 'experimental';
|
|
2
|
+
type ProviderCapabilities = Readonly<Record<string, ProviderCapabilityState>>;
|
|
3
|
+
|
|
4
|
+
interface ProviderRegistryEntry {
|
|
5
|
+
readonly capabilities: ProviderCapabilities;
|
|
6
|
+
readonly docker: {
|
|
7
|
+
readonly envPassthrough: readonly string[];
|
|
8
|
+
};
|
|
9
|
+
readonly id: string;
|
|
10
|
+
readonly [key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ProviderRegistryFacade {
|
|
14
|
+
getDefaultProviderId(): string;
|
|
15
|
+
getProviderRegistryEntry(name: string): ProviderRegistryEntry;
|
|
16
|
+
knownProviderNames: readonly string[];
|
|
17
|
+
listProviderRegistryEntries(): readonly ProviderRegistryEntry[];
|
|
18
|
+
normalizeProviderName(name: string): string;
|
|
19
|
+
providerAliasMap: Readonly<Record<string, string>>;
|
|
20
|
+
providerIds: readonly string[];
|
|
21
|
+
resolveProviderCommand(name: string): {
|
|
22
|
+
readonly args: readonly string[];
|
|
23
|
+
readonly command: string;
|
|
24
|
+
};
|
|
25
|
+
supportsProviderCapability(name: string, capability: string): boolean;
|
|
26
|
+
supportsProviderOutputReformatting(name: string): boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// The emitted CommonJS facade resolves the built registry beside this module.
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
31
|
+
const registry: ProviderRegistryFacade = require('./agent-cli-provider/provider-registry');
|
|
32
|
+
|
|
33
|
+
const VALID_PROVIDERS = [...registry.providerIds];
|
|
34
|
+
const KNOWN_PROVIDER_NAMES = [...registry.knownProviderNames];
|
|
35
|
+
const PROVIDER_ALIASES = Object.freeze({ ...registry.providerAliasMap });
|
|
36
|
+
const PROVIDER_CAPABILITIES: Readonly<Record<string, ProviderCapabilities>> = Object.freeze(
|
|
37
|
+
Object.fromEntries(
|
|
38
|
+
registry.listProviderRegistryEntries().map((entry) => [entry.id, entry.capabilities])
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Non-string legacy inputs intentionally pass through unchanged.
|
|
43
|
+
// eslint-disable-next-line sonarjs/function-return-type
|
|
44
|
+
function normalizeProviderName<T>(name: T): T | string {
|
|
45
|
+
if (!name || typeof name !== 'string') return name;
|
|
46
|
+
return registry.normalizeProviderName(name);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Non-record legacy settings intentionally pass through unchanged.
|
|
50
|
+
// eslint-disable-next-line sonarjs/function-return-type
|
|
51
|
+
function normalizeProviderSettings<T>(providerSettings: T): T | Record<string, unknown> {
|
|
52
|
+
if (
|
|
53
|
+
!providerSettings ||
|
|
54
|
+
typeof providerSettings !== 'object' ||
|
|
55
|
+
Array.isArray(providerSettings)
|
|
56
|
+
) {
|
|
57
|
+
return providerSettings;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const normalized: Record<string, unknown> = {};
|
|
61
|
+
const entries = Object.entries(providerSettings);
|
|
62
|
+
entries.sort(([left], [right]) => {
|
|
63
|
+
const leftIsCanonical = normalizeProviderName(left) === left;
|
|
64
|
+
const rightIsCanonical = normalizeProviderName(right) === right;
|
|
65
|
+
if (leftIsCanonical === rightIsCanonical) return 0;
|
|
66
|
+
return leftIsCanonical ? 1 : -1;
|
|
67
|
+
});
|
|
68
|
+
const aliasFirst = entries;
|
|
69
|
+
|
|
70
|
+
for (const [key, value] of aliasFirst) {
|
|
71
|
+
const canonical = normalizeProviderName(key);
|
|
72
|
+
if (!VALID_PROVIDERS.includes(canonical)) {
|
|
73
|
+
normalized[key] = value;
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Preserve JavaScript object-spread coercion for malformed legacy values.
|
|
77
|
+
normalized[canonical] = {
|
|
78
|
+
...Object(normalized[canonical] || {}),
|
|
79
|
+
...Object(value || {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function getProviderMetadata(name: string): ProviderRegistryEntry {
|
|
87
|
+
return registry.getProviderRegistryEntry(name);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function listProviderMetadata(): readonly ProviderRegistryEntry[] {
|
|
91
|
+
return registry.listProviderRegistryEntries();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function resolveProviderCommand(name: string): {
|
|
95
|
+
readonly args: readonly string[];
|
|
96
|
+
readonly command: string;
|
|
97
|
+
} {
|
|
98
|
+
return registry.resolveProviderCommand(name);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function providerSupportsCapability(name: string, capability: string): boolean {
|
|
102
|
+
return registry.supportsProviderCapability(name, capability);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function providerSupportsOutputReformatting(name: string): boolean {
|
|
106
|
+
return registry.supportsProviderOutputReformatting(name);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function getDefaultProviderId(): string {
|
|
110
|
+
return registry.getDefaultProviderId();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export = {
|
|
114
|
+
KNOWN_PROVIDER_NAMES,
|
|
115
|
+
PROVIDER_ALIASES,
|
|
116
|
+
PROVIDER_CAPABILITIES,
|
|
117
|
+
VALID_PROVIDERS,
|
|
118
|
+
getDefaultProviderId,
|
|
119
|
+
getProviderMetadata,
|
|
120
|
+
listProviderMetadata,
|
|
121
|
+
normalizeProviderName,
|
|
122
|
+
normalizeProviderSettings,
|
|
123
|
+
providerSupportsCapability,
|
|
124
|
+
providerSupportsOutputReformatting,
|
|
125
|
+
resolveProviderCommand,
|
|
126
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Repo-local settings for zeroshot
|
|
3
|
+
*
|
|
4
|
+
* Optional per-repository config file:
|
|
5
|
+
* <repoRoot>/.zeroshot/settings.json
|
|
6
|
+
*
|
|
7
|
+
* This complements the global user settings at:
|
|
8
|
+
* ~/.zeroshot/settings.json
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as childProcess from 'child_process';
|
|
12
|
+
import * as fs from 'fs';
|
|
13
|
+
import * as path from 'path';
|
|
14
|
+
|
|
15
|
+
const { execSync } = childProcess;
|
|
16
|
+
|
|
17
|
+
type RepoSettings = object;
|
|
18
|
+
|
|
19
|
+
interface RepoSettingsResult {
|
|
20
|
+
repoRoot: string | null;
|
|
21
|
+
settings: RepoSettings | null;
|
|
22
|
+
settingsPath: string | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function safeJsonParse(text: string): unknown | null {
|
|
26
|
+
try {
|
|
27
|
+
const parsed: unknown = JSON.parse(text);
|
|
28
|
+
return parsed;
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getGitRoot(dir: string): string | null {
|
|
35
|
+
try {
|
|
36
|
+
return execSync('git rev-parse --show-toplevel', {
|
|
37
|
+
cwd: dir,
|
|
38
|
+
encoding: 'utf8',
|
|
39
|
+
stdio: 'pipe',
|
|
40
|
+
}).trim();
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function readSettingsFile(filePath: string): RepoSettings | null {
|
|
47
|
+
try {
|
|
48
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
49
|
+
const parsed = safeJsonParse(raw);
|
|
50
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return parsed;
|
|
54
|
+
} catch {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Read repo-local settings if present.
|
|
61
|
+
*/
|
|
62
|
+
function readRepoSettings(startDir: string): RepoSettingsResult {
|
|
63
|
+
const repoRoot = getGitRoot(startDir);
|
|
64
|
+
if (!repoRoot) {
|
|
65
|
+
return { repoRoot: null, settings: null, settingsPath: null };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const settingsPath = path.join(repoRoot, '.zeroshot', 'settings.json');
|
|
69
|
+
if (!fs.existsSync(settingsPath)) {
|
|
70
|
+
return { repoRoot, settings: null, settingsPath };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const settings = readSettingsFile(settingsPath);
|
|
74
|
+
return { repoRoot, settings, settingsPath };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Write repo-local settings.
|
|
79
|
+
*/
|
|
80
|
+
function writeRepoSettings(repoRoot: string, settings: object): string {
|
|
81
|
+
const settingsPath = path.join(repoRoot, '.zeroshot', 'settings.json');
|
|
82
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
83
|
+
const serialized = JSON.stringify(settings, null, 2);
|
|
84
|
+
fs.writeFileSync(settingsPath, serialized, 'utf8');
|
|
85
|
+
return settingsPath;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export = { readRepoSettings, writeRepoSettings };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import runPlan = require('./run-plan');
|
|
2
|
+
|
|
3
|
+
type RunMode =
|
|
4
|
+
| 'ship'
|
|
5
|
+
| 'ship+docker'
|
|
6
|
+
| 'pr'
|
|
7
|
+
| 'pr+docker'
|
|
8
|
+
| 'docker'
|
|
9
|
+
| 'worktree'
|
|
10
|
+
| null;
|
|
11
|
+
interface RunModePlan {
|
|
12
|
+
isolation: 'none' | 'worktree' | 'docker';
|
|
13
|
+
delivery: 'none' | 'pr' | 'ship';
|
|
14
|
+
}
|
|
15
|
+
interface RunModeOptions {
|
|
16
|
+
worktree?: unknown;
|
|
17
|
+
docker?: unknown;
|
|
18
|
+
pr?: unknown;
|
|
19
|
+
ship?: unknown;
|
|
20
|
+
autoMerge?: unknown;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { resolveRunPlan } = runPlan as {
|
|
24
|
+
resolveRunPlan(options?: RunModeOptions): Readonly<RunModePlan & { autoMerge: boolean }>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// The run-mode label is a VIEW of the canonical plan, never an independent
|
|
28
|
+
// cascade. Deriving it from the plan is what keeps the user-facing label and the
|
|
29
|
+
// actual isolation/delivery/autoMerge behavior from drifting apart. Callers that
|
|
30
|
+
// already hold a plan (e.g. the effective plan with env/settings folded in) use
|
|
31
|
+
// runModeFromPlan directly so the label reflects the SAME plan as behavior.
|
|
32
|
+
function runModeFromPlan({ isolation, delivery }: RunModePlan): RunMode {
|
|
33
|
+
const dockerSuffix = isolation === 'docker' ? '+docker' : '';
|
|
34
|
+
if (delivery === 'ship') return `ship${dockerSuffix}`;
|
|
35
|
+
if (delivery === 'pr') return `pr${dockerSuffix}`;
|
|
36
|
+
if (isolation === 'docker') return 'docker';
|
|
37
|
+
if (isolation === 'worktree') return 'worktree';
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resolveRunMode(options?: RunModeOptions): RunMode {
|
|
42
|
+
return runModeFromPlan(resolveRunPlan(options));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const RUN_MODE_LABELS: Partial<Record<PropertyKey, string>> = {
|
|
46
|
+
ship: 'ship (worktree + PR + auto-merge)',
|
|
47
|
+
'ship+docker': 'ship (docker + PR + auto-merge)',
|
|
48
|
+
pr: 'pr (worktree + PR)',
|
|
49
|
+
'pr+docker': 'pr (docker + PR)',
|
|
50
|
+
docker: 'docker (isolated container)',
|
|
51
|
+
worktree: 'worktree (isolated branch)',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function describeRunMode(mode: PropertyKey | null | undefined): string {
|
|
55
|
+
return RUN_MODE_LABELS[mode ?? ''] || 'local (no isolation)';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export = { resolveRunMode, runModeFromPlan, describeRunMode };
|