@the-open-engine/zeroshot 6.38.1 → 6.39.1
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/README.md +6 -0
- package/cli/event-copy.js +8 -7
- package/cli/event-copy.ts +12 -0
- package/cli/index.js +67 -48
- 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/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 +84 -0
- package/lib/detached-startup.js +232 -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 +41 -0
- package/lib/start-cluster-environment.js +134 -0
- package/lib/start-cluster-run-options.d.ts +54 -0
- package/lib/start-cluster-run-options.js +148 -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 +6 -8
- package/package.json +14 -8
- package/scripts/postinstall.js +27 -0
- package/scripts/rust-distribution.js +36 -45
- 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/agents/git-pusher-template.js +17 -34
- 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-containment.js +191 -0
- package/src/copy-containment.ts +259 -0
- package/src/copy-worker.js +53 -30
- package/src/copy-worker.ts +88 -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/isolation-manager.js +59 -20
- 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 +451 -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 +166 -0
- package/src/legacy-lib/start-cluster-run-options.ts +281 -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 +32 -7
- package/src/pr-body-template.js +71 -0
- 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,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy Worker - Worker thread for parallel file copying
|
|
3
|
+
*
|
|
4
|
+
* Handles copying a batch of files from source to destination.
|
|
5
|
+
* Used by IsolationManager._copyDirExcluding() for parallel copying.
|
|
6
|
+
*/
|
|
7
|
+
import fs = require('fs');
|
|
8
|
+
import { parentPort, workerData } from 'worker_threads';
|
|
9
|
+
import {
|
|
10
|
+
copyErrorCode,
|
|
11
|
+
createCopyBoundary,
|
|
12
|
+
isCopyContainmentError,
|
|
13
|
+
isCopyRecord,
|
|
14
|
+
resolveCopyPath,
|
|
15
|
+
} from './copy-containment';
|
|
16
|
+
import type { CopyBoundary } from './copy-containment';
|
|
17
|
+
interface CopyWorkerData {
|
|
18
|
+
files: string[];
|
|
19
|
+
sourceBase: string;
|
|
20
|
+
destBase: string;
|
|
21
|
+
expectedBoundary: CopyBoundary;
|
|
22
|
+
}
|
|
23
|
+
interface CopyError {
|
|
24
|
+
file: string;
|
|
25
|
+
name: string;
|
|
26
|
+
code: string | null;
|
|
27
|
+
message: string;
|
|
28
|
+
relativePath: unknown;
|
|
29
|
+
}
|
|
30
|
+
function isCopyWorkerData(value: unknown): value is CopyWorkerData {
|
|
31
|
+
if (!isCopyRecord(value)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return (
|
|
35
|
+
Array.isArray(value.files) &&
|
|
36
|
+
value.files.every((entry: unknown) => typeof entry === 'string') &&
|
|
37
|
+
typeof value.sourceBase === 'string' &&
|
|
38
|
+
typeof value.destBase === 'string' &&
|
|
39
|
+
isCopyRecord(value.expectedBoundary)
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function errorMessage(error: unknown): string {
|
|
43
|
+
return error instanceof Error ? error.message : String(error);
|
|
44
|
+
}
|
|
45
|
+
const rawWorkerData: unknown = workerData;
|
|
46
|
+
if (!isCopyWorkerData(rawWorkerData)) {
|
|
47
|
+
throw new TypeError('copy worker requires files, sourceBase, and destBase');
|
|
48
|
+
}
|
|
49
|
+
const { files, sourceBase, destBase, expectedBoundary } = rawWorkerData;
|
|
50
|
+
const copyBoundary = createCopyBoundary(sourceBase, destBase, expectedBoundary);
|
|
51
|
+
let copied = 0;
|
|
52
|
+
let skipped = 0;
|
|
53
|
+
let error: CopyError | null = null;
|
|
54
|
+
for (const relativePath of files) {
|
|
55
|
+
try {
|
|
56
|
+
// Phase two creates every parent directory. Re-resolve the source and
|
|
57
|
+
// destination immediately before the only worker filesystem effect.
|
|
58
|
+
const { sourcePath, destinationPath } = resolveCopyPath(copyBoundary, relativePath);
|
|
59
|
+
fs.copyFileSync(sourcePath, destinationPath);
|
|
60
|
+
copied++;
|
|
61
|
+
} catch (caughtError: unknown) {
|
|
62
|
+
// Skip files we can't copy (permission denied, broken symlinks, etc.)
|
|
63
|
+
const code = copyErrorCode(caughtError);
|
|
64
|
+
if (
|
|
65
|
+
!isCopyContainmentError(caughtError) &&
|
|
66
|
+
(code === 'EACCES' || code === 'EPERM' || code === 'ENOENT')
|
|
67
|
+
) {
|
|
68
|
+
skipped++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
error = {
|
|
72
|
+
file: relativePath,
|
|
73
|
+
name: caughtError instanceof Error ? caughtError.name : 'Error',
|
|
74
|
+
code,
|
|
75
|
+
message: errorMessage(caughtError),
|
|
76
|
+
relativePath:
|
|
77
|
+
isCopyRecord(caughtError) && 'relativePath' in caughtError
|
|
78
|
+
? caughtError.relativePath
|
|
79
|
+
: relativePath,
|
|
80
|
+
};
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Report results back to main thread
|
|
85
|
+
if (!parentPort) {
|
|
86
|
+
throw new Error('copy worker requires a parent port');
|
|
87
|
+
}
|
|
88
|
+
parentPort.postMessage({ copied, skipped, error });
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
/**
|
|
2
3
|
* Darwin worker Keychain boundary (issue #704).
|
|
3
4
|
*
|
|
@@ -15,46 +16,41 @@
|
|
|
15
16
|
* Docker isolation never reaches this code path, and non-darwin platforms are
|
|
16
17
|
* left untouched. Set ZEROSHOT_ALLOW_INTERACTIVE_KEYCHAIN=1 to opt out.
|
|
17
18
|
*/
|
|
18
|
-
|
|
19
|
-
const fs = require(
|
|
20
|
-
const os = require(
|
|
21
|
-
const path = require(
|
|
22
|
-
const { randomUUID } = require('node:crypto');
|
|
23
|
-
|
|
19
|
+
const node_crypto_1 = require("node:crypto");
|
|
20
|
+
const fs = require("fs");
|
|
21
|
+
const os = require("os");
|
|
22
|
+
const path = require("path");
|
|
24
23
|
const SHIM_DIR_RELATIVE_PATH = path.join('.zeroshot', 'keychain-shim');
|
|
25
24
|
const REAL_SECURITY_PATH = '/usr/bin/security';
|
|
26
25
|
const OPT_OUT_ENV_VAR = 'ZEROSHOT_ALLOW_INTERACTIVE_KEYCHAIN';
|
|
27
|
-
|
|
28
26
|
function shellQuote(value) {
|
|
29
|
-
|
|
27
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
28
|
+
}
|
|
29
|
+
function errorMessage(error) {
|
|
30
|
+
return error instanceof Error ? error.message : String(error);
|
|
30
31
|
}
|
|
31
|
-
|
|
32
32
|
function buildSecurityShimScript(realSecurityPath) {
|
|
33
|
-
|
|
33
|
+
return `#!/bin/sh
|
|
34
34
|
# Managed by Zeroshot (src/darwin-keychain-boundary.js). Do not edit.
|
|
35
35
|
#
|
|
36
36
|
# Non-interactive Zeroshot workers must not open the logged-in user's GUI
|
|
37
37
|
# Keychain session (SecurityAgent). Interactive \`security\` invocations fail
|
|
38
38
|
# closed here; every other subcommand is passed through to the real binary so
|
|
39
39
|
# provider authentication keeps working.
|
|
40
|
-
|
|
41
40
|
REAL_SECURITY=${shellQuote(realSecurityPath)}
|
|
42
|
-
|
|
43
41
|
if [ "\${${OPT_OUT_ENV_VAR}:-0}" = "1" ]; then
|
|
44
42
|
exec "$REAL_SECURITY" "$@"
|
|
45
43
|
fi
|
|
46
|
-
|
|
47
44
|
fail_closed() {
|
|
48
45
|
echo "zeroshot: blocked interactive 'security' invocation from a non-interactive worker (argv: $*)." >&2
|
|
49
46
|
echo "zeroshot: this cluster has no interactive Keychain session, so SecurityAgent prompts are disabled." >&2
|
|
50
|
-
echo "zeroshot: run the cluster with Docker isolation or configure explicit credentials for the tool that
|
|
47
|
+
echo "zeroshot: run the cluster with Docker isolation or configure explicit credentials for the tool that "\
|
|
48
|
+
"attempted Keychain access." >&2
|
|
51
49
|
echo "zeroshot: set ${OPT_OUT_ENV_VAR}=1 to restore interactive Keychain access." >&2
|
|
52
50
|
exit 1
|
|
53
51
|
}
|
|
54
|
-
|
|
55
52
|
# \`security\` without arguments enters interactive mode.
|
|
56
53
|
[ "$#" -eq 0 ] && fail_closed
|
|
57
|
-
|
|
58
54
|
# Global options precede the subcommand. -i (interactive) and -p (prompt,
|
|
59
55
|
# implies -i) must not reach the real binary; option letters may be bundled
|
|
60
56
|
# (e.g. -qi). Scanning stops at the first non-option token (the subcommand).
|
|
@@ -65,110 +61,83 @@ for arg in "$@"; do
|
|
|
65
61
|
*) break ;;
|
|
66
62
|
esac
|
|
67
63
|
done
|
|
68
|
-
|
|
69
64
|
exec "$REAL_SECURITY" "$@"
|
|
70
65
|
`;
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Create (or refresh) the managed shim directory containing the `security`
|
|
75
|
-
* wrapper. Idempotent: the script is only rewritten when its content changes.
|
|
76
|
-
*
|
|
77
|
-
* @param {object} [options]
|
|
78
|
-
* @param {string} [options.shimBaseDir] - Shim directory (tests only); defaults to ~/.zeroshot/keychain-shim.
|
|
79
|
-
* @param {string} [options.realSecurityPath] - Real binary to exec (tests only); defaults to /usr/bin/security.
|
|
80
|
-
* @returns {string} Absolute path of the shim directory.
|
|
81
|
-
*/
|
|
67
|
+
/** Create or refresh the managed directory containing the `security` shim. */
|
|
82
68
|
function ensureDarwinKeychainShimDir(options = {}) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
let existing = null;
|
|
90
|
-
try {
|
|
91
|
-
existing = fs.readFileSync(shimPath, 'utf8');
|
|
92
|
-
} catch {
|
|
93
|
-
// Missing or unreadable: (re)write below.
|
|
94
|
-
}
|
|
95
|
-
if (existing !== script) {
|
|
96
|
-
const tempPath = path.join(shimDir, `.security.${process.pid}.${randomUUID()}.tmp`);
|
|
69
|
+
const shimDir = options.shimBaseDir || path.join(os.homedir(), SHIM_DIR_RELATIVE_PATH);
|
|
70
|
+
const script = buildSecurityShimScript(options.realSecurityPath || REAL_SECURITY_PATH);
|
|
71
|
+
const shimPath = path.join(shimDir, 'security');
|
|
72
|
+
fs.mkdirSync(shimDir, { recursive: true });
|
|
73
|
+
let existing = null;
|
|
97
74
|
try {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
fs.renameSync(tempPath, shimPath);
|
|
103
|
-
} catch (error) {
|
|
104
|
-
try {
|
|
105
|
-
// Remove any unpublished partial file without masking the publication
|
|
106
|
-
// failure that caused this cleanup path.
|
|
107
|
-
fs.rmSync(tempPath, { force: true });
|
|
108
|
-
} catch (cleanupError) {
|
|
109
|
-
error.message += ` Cleanup also failed: ${cleanupError.message}.`;
|
|
110
|
-
}
|
|
111
|
-
throw error;
|
|
75
|
+
existing = fs.readFileSync(shimPath, 'utf8');
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Missing or unreadable: (re)write below.
|
|
112
79
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
80
|
+
if (existing !== script) {
|
|
81
|
+
const tempPath = path.join(shimDir, `.security.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`);
|
|
82
|
+
try {
|
|
83
|
+
fs.writeFileSync(tempPath, script, { mode: 0o755, flag: 'wx' });
|
|
84
|
+
// The creation mode is subject to umask. Set the final mode before the
|
|
85
|
+
// rename so the live path is never observable as non-executable.
|
|
86
|
+
fs.chmodSync(tempPath, 0o755);
|
|
87
|
+
fs.renameSync(tempPath, shimPath);
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
try {
|
|
91
|
+
// Remove any unpublished partial file without masking the publication
|
|
92
|
+
// failure that caused this cleanup path.
|
|
93
|
+
fs.rmSync(tempPath, { force: true });
|
|
94
|
+
}
|
|
95
|
+
catch (cleanupError) {
|
|
96
|
+
if (error instanceof Error) {
|
|
97
|
+
error.message += ` Cleanup also failed: ${errorMessage(cleanupError)}.`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// An existing matching shim may have drifted permissions.
|
|
105
|
+
fs.chmodSync(shimPath, 0o755);
|
|
106
|
+
}
|
|
107
|
+
return shimDir;
|
|
119
108
|
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Prepend the Keychain boundary shim to a worker spawn env's PATH.
|
|
123
|
-
*
|
|
124
|
-
* No-op off darwin and when the operator opted out via
|
|
125
|
-
* ZEROSHOT_ALLOW_INTERACTIVE_KEYCHAIN=1. Fails closed (throws) when the shim
|
|
126
|
-
* cannot be installed: spawning the worker anyway would silently re-expose the
|
|
127
|
-
* interactive Keychain session.
|
|
128
|
-
*
|
|
129
|
-
* @param {object} env - Spawn env to mutate (also returned).
|
|
130
|
-
* @param {object} [options]
|
|
131
|
-
* @param {string} [options.platform] - Platform override (tests only).
|
|
132
|
-
* @param {string} [options.shimBaseDir] - See ensureDarwinKeychainShimDir.
|
|
133
|
-
* @param {string} [options.realSecurityPath] - See ensureDarwinKeychainShimDir.
|
|
134
|
-
* @returns {object} The same env object.
|
|
135
|
-
*/
|
|
109
|
+
/** Prepend the Keychain boundary shim to a worker spawn environment's PATH. */
|
|
136
110
|
function applyDarwinKeychainBoundaryToEnv(env, options = {}) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
111
|
+
const platform = options.platform || process.platform;
|
|
112
|
+
if (platform !== 'darwin') {
|
|
113
|
+
return env;
|
|
114
|
+
}
|
|
115
|
+
if (env[OPT_OUT_ENV_VAR] === '1' || process.env[OPT_OUT_ENV_VAR] === '1') {
|
|
116
|
+
return env;
|
|
117
|
+
}
|
|
118
|
+
let shimDir;
|
|
119
|
+
try {
|
|
120
|
+
shimDir = ensureDarwinKeychainShimDir(options);
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new Error(`Failed to install the darwin Keychain boundary shim: ${errorMessage(error)}. ` +
|
|
124
|
+
`Non-interactive workers must not reach the interactive Keychain session; ` +
|
|
125
|
+
`use Docker isolation or set ${OPT_OUT_ENV_VAR}=1 to opt out.`);
|
|
126
|
+
}
|
|
127
|
+
// Darwin environment keys are case-sensitive: descendants consult PATH,
|
|
128
|
+
// never a differently-cased key such as Path. Preserve empty components
|
|
129
|
+
// because POSIX interprets them as the current directory. An absent PATH
|
|
130
|
+
// retains Node/libuv's default Unix search path after the shim, while an
|
|
131
|
+
// explicitly empty PATH retains its empty component (`<shim>:`).
|
|
132
|
+
const existingEntries = env.PATH === undefined
|
|
133
|
+
? ['/usr/bin', '/bin']
|
|
134
|
+
: String(env.PATH)
|
|
135
|
+
.split(path.delimiter)
|
|
136
|
+
.filter((entry) => entry !== shimDir);
|
|
137
|
+
env.PATH = [shimDir, ...existingEntries].join(path.delimiter);
|
|
142
138
|
return env;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
let shimDir;
|
|
146
|
-
try {
|
|
147
|
-
shimDir = ensureDarwinKeychainShimDir(options);
|
|
148
|
-
} catch (error) {
|
|
149
|
-
throw new Error(
|
|
150
|
-
`Failed to install the darwin Keychain boundary shim: ${error.message}. ` +
|
|
151
|
-
`Non-interactive workers must not reach the interactive Keychain session; ` +
|
|
152
|
-
`use Docker isolation or set ${OPT_OUT_ENV_VAR}=1 to opt out.`
|
|
153
|
-
);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// Darwin environment keys are case-sensitive: descendants consult PATH,
|
|
157
|
-
// never a differently-cased key such as Path. Preserve empty components
|
|
158
|
-
// because POSIX interprets them as the current directory. An absent PATH
|
|
159
|
-
// retains Node/libuv's default Unix search path after the shim, while an
|
|
160
|
-
// explicitly empty PATH retains its empty component (`<shim>:`).
|
|
161
|
-
const existingEntries =
|
|
162
|
-
env.PATH === undefined
|
|
163
|
-
? ['/usr/bin', '/bin']
|
|
164
|
-
: String(env.PATH)
|
|
165
|
-
.split(path.delimiter)
|
|
166
|
-
.filter((entry) => entry !== shimDir);
|
|
167
|
-
env.PATH = [shimDir, ...existingEntries].join(path.delimiter);
|
|
168
|
-
return env;
|
|
169
139
|
}
|
|
170
|
-
|
|
171
140
|
module.exports = {
|
|
172
|
-
|
|
173
|
-
|
|
141
|
+
applyDarwinKeychainBoundaryToEnv,
|
|
142
|
+
ensureDarwinKeychainShimDir,
|
|
174
143
|
};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Darwin worker Keychain boundary (issue #704).
|
|
3
|
+
*
|
|
4
|
+
* Non-interactive local/worktree workers are spawned with the host environment,
|
|
5
|
+
* so worker descendants (e.g. `claude doctor` probing Keychain writes through
|
|
6
|
+
* `security -i`) reach the logged-in user's GUI Keychain session and launch
|
|
7
|
+
* SecurityAgent dialogs from a supposedly non-interactive cluster.
|
|
8
|
+
*
|
|
9
|
+
* On darwin, worker spawn envs get a managed shim directory prepended to PATH
|
|
10
|
+
* containing a `security` wrapper that fails closed on interactive invocations
|
|
11
|
+
* (`-i`, `-p`, or no arguments) with a deterministic diagnostic, and execs the
|
|
12
|
+
* real /usr/bin/security for every other subcommand so provider authentication
|
|
13
|
+
* (e.g. `security find-generic-password`) keeps working.
|
|
14
|
+
*
|
|
15
|
+
* Docker isolation never reaches this code path, and non-darwin platforms are
|
|
16
|
+
* left untouched. Set ZEROSHOT_ALLOW_INTERACTIVE_KEYCHAIN=1 to opt out.
|
|
17
|
+
*/
|
|
18
|
+
import { randomUUID } from 'node:crypto';
|
|
19
|
+
import fs = require('fs');
|
|
20
|
+
import os = require('os');
|
|
21
|
+
import path = require('path');
|
|
22
|
+
interface DarwinKeychainBoundaryOptions {
|
|
23
|
+
platform?: string;
|
|
24
|
+
shimBaseDir?: string;
|
|
25
|
+
realSecurityPath?: string;
|
|
26
|
+
}
|
|
27
|
+
const SHIM_DIR_RELATIVE_PATH = path.join('.zeroshot', 'keychain-shim');
|
|
28
|
+
const REAL_SECURITY_PATH = '/usr/bin/security';
|
|
29
|
+
const OPT_OUT_ENV_VAR = 'ZEROSHOT_ALLOW_INTERACTIVE_KEYCHAIN';
|
|
30
|
+
function shellQuote(value: unknown): string {
|
|
31
|
+
return `'${String(value).replace(/'/g, `'\\''`)}'`;
|
|
32
|
+
}
|
|
33
|
+
function errorMessage(error: unknown): string {
|
|
34
|
+
return error instanceof Error ? error.message : String(error);
|
|
35
|
+
}
|
|
36
|
+
function buildSecurityShimScript(realSecurityPath: string): string {
|
|
37
|
+
return `#!/bin/sh
|
|
38
|
+
# Managed by Zeroshot (src/darwin-keychain-boundary.js). Do not edit.
|
|
39
|
+
#
|
|
40
|
+
# Non-interactive Zeroshot workers must not open the logged-in user's GUI
|
|
41
|
+
# Keychain session (SecurityAgent). Interactive \`security\` invocations fail
|
|
42
|
+
# closed here; every other subcommand is passed through to the real binary so
|
|
43
|
+
# provider authentication keeps working.
|
|
44
|
+
REAL_SECURITY=${shellQuote(realSecurityPath)}
|
|
45
|
+
if [ "\${${OPT_OUT_ENV_VAR}:-0}" = "1" ]; then
|
|
46
|
+
exec "$REAL_SECURITY" "$@"
|
|
47
|
+
fi
|
|
48
|
+
fail_closed() {
|
|
49
|
+
echo "zeroshot: blocked interactive 'security' invocation from a non-interactive worker (argv: $*)." >&2
|
|
50
|
+
echo "zeroshot: this cluster has no interactive Keychain session, so SecurityAgent prompts are disabled." >&2
|
|
51
|
+
echo "zeroshot: run the cluster with Docker isolation or configure explicit credentials for the tool that "\
|
|
52
|
+
"attempted Keychain access." >&2
|
|
53
|
+
echo "zeroshot: set ${OPT_OUT_ENV_VAR}=1 to restore interactive Keychain access." >&2
|
|
54
|
+
exit 1
|
|
55
|
+
}
|
|
56
|
+
# \`security\` without arguments enters interactive mode.
|
|
57
|
+
[ "$#" -eq 0 ] && fail_closed
|
|
58
|
+
# Global options precede the subcommand. -i (interactive) and -p (prompt,
|
|
59
|
+
# implies -i) must not reach the real binary; option letters may be bundled
|
|
60
|
+
# (e.g. -qi). Scanning stops at the first non-option token (the subcommand).
|
|
61
|
+
for arg in "$@"; do
|
|
62
|
+
case "$arg" in
|
|
63
|
+
-*i*|-*p*) fail_closed "$@" ;;
|
|
64
|
+
-*) ;;
|
|
65
|
+
*) break ;;
|
|
66
|
+
esac
|
|
67
|
+
done
|
|
68
|
+
exec "$REAL_SECURITY" "$@"
|
|
69
|
+
`;
|
|
70
|
+
}
|
|
71
|
+
/** Create or refresh the managed directory containing the `security` shim. */
|
|
72
|
+
function ensureDarwinKeychainShimDir(options: DarwinKeychainBoundaryOptions = {}): string {
|
|
73
|
+
const shimDir = options.shimBaseDir || path.join(os.homedir(), SHIM_DIR_RELATIVE_PATH);
|
|
74
|
+
const script = buildSecurityShimScript(options.realSecurityPath || REAL_SECURITY_PATH);
|
|
75
|
+
const shimPath = path.join(shimDir, 'security');
|
|
76
|
+
fs.mkdirSync(shimDir, { recursive: true });
|
|
77
|
+
let existing: string | null = null;
|
|
78
|
+
try {
|
|
79
|
+
existing = fs.readFileSync(shimPath, 'utf8');
|
|
80
|
+
} catch {
|
|
81
|
+
// Missing or unreadable: (re)write below.
|
|
82
|
+
}
|
|
83
|
+
if (existing !== script) {
|
|
84
|
+
const tempPath = path.join(shimDir, `.security.${process.pid}.${randomUUID()}.tmp`);
|
|
85
|
+
try {
|
|
86
|
+
fs.writeFileSync(tempPath, script, { mode: 0o755, flag: 'wx' });
|
|
87
|
+
// The creation mode is subject to umask. Set the final mode before the
|
|
88
|
+
// rename so the live path is never observable as non-executable.
|
|
89
|
+
fs.chmodSync(tempPath, 0o755);
|
|
90
|
+
fs.renameSync(tempPath, shimPath);
|
|
91
|
+
} catch (error: unknown) {
|
|
92
|
+
try {
|
|
93
|
+
// Remove any unpublished partial file without masking the publication
|
|
94
|
+
// failure that caused this cleanup path.
|
|
95
|
+
fs.rmSync(tempPath, { force: true });
|
|
96
|
+
} catch (cleanupError: unknown) {
|
|
97
|
+
if (error instanceof Error) {
|
|
98
|
+
error.message += ` Cleanup also failed: ${errorMessage(cleanupError)}.`;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// An existing matching shim may have drifted permissions.
|
|
105
|
+
fs.chmodSync(shimPath, 0o755);
|
|
106
|
+
}
|
|
107
|
+
return shimDir;
|
|
108
|
+
}
|
|
109
|
+
/** Prepend the Keychain boundary shim to a worker spawn environment's PATH. */
|
|
110
|
+
function applyDarwinKeychainBoundaryToEnv(
|
|
111
|
+
env: NodeJS.ProcessEnv,
|
|
112
|
+
options: DarwinKeychainBoundaryOptions = {}
|
|
113
|
+
): NodeJS.ProcessEnv {
|
|
114
|
+
const platform = options.platform || process.platform;
|
|
115
|
+
if (platform !== 'darwin') {
|
|
116
|
+
return env;
|
|
117
|
+
}
|
|
118
|
+
if (env[OPT_OUT_ENV_VAR] === '1' || process.env[OPT_OUT_ENV_VAR] === '1') {
|
|
119
|
+
return env;
|
|
120
|
+
}
|
|
121
|
+
let shimDir: string;
|
|
122
|
+
try {
|
|
123
|
+
shimDir = ensureDarwinKeychainShimDir(options);
|
|
124
|
+
} catch (error: unknown) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`Failed to install the darwin Keychain boundary shim: ${errorMessage(error)}. ` +
|
|
127
|
+
`Non-interactive workers must not reach the interactive Keychain session; ` +
|
|
128
|
+
`use Docker isolation or set ${OPT_OUT_ENV_VAR}=1 to opt out.`
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
// Darwin environment keys are case-sensitive: descendants consult PATH,
|
|
132
|
+
// never a differently-cased key such as Path. Preserve empty components
|
|
133
|
+
// because POSIX interprets them as the current directory. An absent PATH
|
|
134
|
+
// retains Node/libuv's default Unix search path after the shim, while an
|
|
135
|
+
// explicitly empty PATH retains its empty component (`<shim>:`).
|
|
136
|
+
const existingEntries =
|
|
137
|
+
env.PATH === undefined
|
|
138
|
+
? ['/usr/bin', '/bin']
|
|
139
|
+
: String(env.PATH)
|
|
140
|
+
.split(path.delimiter)
|
|
141
|
+
.filter((entry) => entry !== shimDir);
|
|
142
|
+
env.PATH = [shimDir, ...existingEntries].join(path.delimiter);
|
|
143
|
+
return env;
|
|
144
|
+
}
|
|
145
|
+
export = {
|
|
146
|
+
applyDarwinKeychainBoundaryToEnv,
|
|
147
|
+
ensureDarwinKeychainShimDir,
|
|
148
|
+
};
|
package/src/guidance-topics.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
1
2
|
const USER_GUIDANCE_CLUSTER = 'USER_GUIDANCE_CLUSTER';
|
|
2
3
|
const USER_GUIDANCE_AGENT = 'USER_GUIDANCE_AGENT';
|
|
3
|
-
|
|
4
4
|
const GUIDANCE_TOPICS = [USER_GUIDANCE_CLUSTER, USER_GUIDANCE_AGENT];
|
|
5
|
-
|
|
6
5
|
module.exports = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
USER_GUIDANCE_CLUSTER,
|
|
7
|
+
USER_GUIDANCE_AGENT,
|
|
8
|
+
GUIDANCE_TOPICS,
|
|
10
9
|
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const USER_GUIDANCE_CLUSTER = 'USER_GUIDANCE_CLUSTER';
|
|
2
|
+
const USER_GUIDANCE_AGENT = 'USER_GUIDANCE_AGENT';
|
|
3
|
+
|
|
4
|
+
const GUIDANCE_TOPICS = [USER_GUIDANCE_CLUSTER, USER_GUIDANCE_AGENT] as const;
|
|
5
|
+
|
|
6
|
+
export = {
|
|
7
|
+
USER_GUIDANCE_CLUSTER,
|
|
8
|
+
USER_GUIDANCE_AGENT,
|
|
9
|
+
GUIDANCE_TOPICS,
|
|
10
|
+
};
|
package/src/input-helpers.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
1
4
|
/**
|
|
2
5
|
* Input Helpers - Create input data from text or files
|
|
3
6
|
*
|
|
@@ -5,61 +8,37 @@
|
|
|
5
8
|
* - Plain text input
|
|
6
9
|
* - File input (markdown)
|
|
7
10
|
*/
|
|
8
|
-
|
|
9
|
-
const fs = require('fs');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
11
|
class InputHelpers {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
12
|
+
static createTextInput(text) {
|
|
13
|
+
return {
|
|
14
|
+
number: null,
|
|
15
|
+
title: 'Manual Input',
|
|
16
|
+
body: text,
|
|
17
|
+
labels: [],
|
|
18
|
+
comments: [],
|
|
19
|
+
url: null,
|
|
20
|
+
context: `# Manual Input\n\n${text}\n`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
static createFileInput(filePath) {
|
|
24
|
+
const resolvedPath = path.resolve(filePath);
|
|
25
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
26
|
+
throw new Error(`File not found: ${filePath}`);
|
|
27
|
+
}
|
|
28
|
+
const fileContent = fs.readFileSync(resolvedPath, 'utf8');
|
|
29
|
+
const headerMatch = /^#\s+(.+)$/m.exec(fileContent);
|
|
30
|
+
const extractedTitle = headerMatch?.[1]?.trim() ?? null;
|
|
31
|
+
const fallbackTitle = path.basename(filePath, path.extname(filePath));
|
|
32
|
+
const title = extractedTitle || fallbackTitle;
|
|
33
|
+
return {
|
|
34
|
+
number: null,
|
|
35
|
+
title,
|
|
36
|
+
body: fileContent,
|
|
37
|
+
labels: [],
|
|
38
|
+
comments: [],
|
|
39
|
+
url: null,
|
|
40
|
+
context: `# ${title}\n\n${fileContent}\n`,
|
|
41
|
+
};
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
// Read file content
|
|
45
|
-
const fileContent = fs.readFileSync(resolvedPath, 'utf8');
|
|
46
|
-
|
|
47
|
-
// Extract title from first header or use filename
|
|
48
|
-
const headerMatch = fileContent.match(/^#\s+(.+)$/m);
|
|
49
|
-
const extractedTitle = headerMatch ? headerMatch[1].trim() : null;
|
|
50
|
-
const fallbackTitle = path.basename(filePath, path.extname(filePath));
|
|
51
|
-
const title = extractedTitle || fallbackTitle;
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
number: null,
|
|
55
|
-
title,
|
|
56
|
-
body: fileContent,
|
|
57
|
-
labels: [],
|
|
58
|
-
comments: [],
|
|
59
|
-
url: null,
|
|
60
|
-
context: `# ${title}\n\n${fileContent}\n`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
43
|
}
|
|
64
|
-
|
|
65
44
|
module.exports = InputHelpers;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs = require('fs');
|
|
2
|
+
import path = require('path');
|
|
3
|
+
|
|
4
|
+
interface ManualInput {
|
|
5
|
+
number: null;
|
|
6
|
+
title: string;
|
|
7
|
+
body: string;
|
|
8
|
+
labels: unknown[];
|
|
9
|
+
comments: unknown[];
|
|
10
|
+
url: null;
|
|
11
|
+
context: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Input Helpers - Create input data from text or files
|
|
16
|
+
*
|
|
17
|
+
* Provides fallback input methods for non-issue-based input:
|
|
18
|
+
* - Plain text input
|
|
19
|
+
* - File input (markdown)
|
|
20
|
+
*/
|
|
21
|
+
class InputHelpers {
|
|
22
|
+
static createTextInput(text: string): ManualInput {
|
|
23
|
+
return {
|
|
24
|
+
number: null,
|
|
25
|
+
title: 'Manual Input',
|
|
26
|
+
body: text,
|
|
27
|
+
labels: [],
|
|
28
|
+
comments: [],
|
|
29
|
+
url: null,
|
|
30
|
+
context: `# Manual Input\n\n${text}\n`,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static createFileInput(filePath: string): ManualInput {
|
|
35
|
+
const resolvedPath = path.resolve(filePath);
|
|
36
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
37
|
+
throw new Error(`File not found: ${filePath}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const fileContent = fs.readFileSync(resolvedPath, 'utf8');
|
|
41
|
+
const headerMatch = /^#\s+(.+)$/m.exec(fileContent);
|
|
42
|
+
const extractedTitle = headerMatch?.[1]?.trim() ?? null;
|
|
43
|
+
const fallbackTitle = path.basename(filePath, path.extname(filePath));
|
|
44
|
+
const title = extractedTitle || fallbackTitle;
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
number: null,
|
|
48
|
+
title,
|
|
49
|
+
body: fileContent,
|
|
50
|
+
labels: [],
|
|
51
|
+
comments: [],
|
|
52
|
+
url: null,
|
|
53
|
+
context: `# ${title}\n\n${fileContent}\n`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export = InputHelpers;
|