@loucompanion/forge-bridge 0.1.3-dev.d1ca67076aa9 → 0.1.3-dev.e7b62d8fdd33
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 +127 -0
- package/dist/bridge/bridge.base.d.ts +8 -1
- package/dist/bridge/bridge.service.d.ts +93 -3
- package/dist/bridge/bridge.service.js +1358 -47
- package/dist/bridge/bridge.types.d.ts +202 -1
- package/dist/bridge/runner-host-capabilities.d.ts +15 -0
- package/dist/bridge/runner-host-capabilities.js +93 -0
- package/dist/cleanup/cleanup.service.d.ts +14 -2
- package/dist/cleanup/cleanup.service.js +496 -3
- package/dist/cleanup/cleanup.types.d.ts +10 -0
- package/dist/cleanup/index.d.ts +1 -1
- package/dist/cleanup/index.js +1 -1
- package/dist/cleanup/internals.d.ts +2 -2
- package/dist/cleanup/internals.js +1 -1
- package/dist/cli/cli.help.js +47 -1
- package/dist/cli/cli.service.d.ts +45 -2
- package/dist/cli/cli.service.js +378 -26
- package/dist/cli/local-config.d.ts +7 -0
- package/dist/cli/local-config.js +51 -3
- package/dist/runtime/aspnet-runtime-prebuild.d.ts +36 -0
- package/dist/runtime/aspnet-runtime-prebuild.js +340 -0
- package/dist/runtime/attempt-node-runtime-launcher.d.ts +17 -0
- package/dist/runtime/attempt-node-runtime-launcher.js +105 -0
- package/dist/runtime/attempt-process-supervisor-registry.d.ts +20 -0
- package/dist/runtime/attempt-process-supervisor-registry.js +64 -0
- package/dist/runtime/attempt-process-supervisor.d.ts +97 -0
- package/dist/runtime/attempt-process-supervisor.js +386 -0
- package/dist/runtime/docker-engine-probe.d.ts +83 -0
- package/dist/runtime/docker-engine-probe.js +300 -0
- package/dist/runtime/generated-output-reset.d.ts +10 -0
- package/dist/runtime/generated-output-reset.js +103 -0
- package/dist/runtime/host-listener-inspector.d.ts +46 -0
- package/dist/runtime/host-listener-inspector.js +349 -0
- package/dist/runtime/host-port-broker.d.ts +76 -0
- package/dist/runtime/host-port-broker.js +333 -0
- package/dist/runtime/host-runtime-contract.d.ts +47 -0
- package/dist/runtime/host-runtime-contract.js +700 -0
- package/dist/runtime/host-runtime-lease.d.ts +197 -0
- package/dist/runtime/host-runtime-lease.js +2203 -0
- package/dist/runtime/host-runtime-promotion.d.ts +23 -0
- package/dist/runtime/host-runtime-promotion.js +159 -0
- package/dist/runtime/memory-capacity.d.ts +68 -0
- package/dist/runtime/memory-capacity.js +121 -0
- package/dist/runtime/node-host-runtime-adapter.d.ts +54 -0
- package/dist/runtime/node-host-runtime-adapter.js +284 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +21 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +231 -0
- package/dist/runtime/runtime-isolation-lease.d.ts +67 -0
- package/dist/runtime/runtime-isolation-lease.js +158 -0
- package/dist/runtime/workspace-resource-estimator.d.ts +17 -0
- package/dist/runtime/workspace-resource-estimator.js +174 -0
- package/dist/sandbox/command-runner.d.ts +4 -0
- package/dist/sandbox/command-runner.js +47 -0
- package/dist/sandbox/contract.d.ts +5 -0
- package/dist/sandbox/contract.js +276 -0
- package/dist/sandbox/event-budget.d.ts +11 -0
- package/dist/sandbox/event-budget.js +27 -0
- package/dist/sandbox/image-policy.d.ts +35 -0
- package/dist/sandbox/image-policy.js +247 -0
- package/dist/sandbox/index.d.ts +5 -0
- package/dist/sandbox/index.js +5 -0
- package/dist/sandbox/lease-watchdog.d.ts +18 -0
- package/dist/sandbox/lease-watchdog.js +67 -0
- package/dist/sandbox/preflight.d.ts +84 -0
- package/dist/sandbox/preflight.js +521 -0
- package/dist/sandbox/process.d.ts +20 -0
- package/dist/sandbox/process.js +209 -0
- package/dist/sandbox/provider-auth/codex.d.ts +26 -0
- package/dist/sandbox/provider-auth/codex.js +212 -0
- package/dist/sandbox/repository-lock.d.ts +5 -0
- package/dist/sandbox/repository-lock.js +121 -0
- package/dist/sandbox/runtime.d.ts +297 -0
- package/dist/sandbox/runtime.js +2338 -0
- package/dist/sandbox/sandbox.types.d.ts +93 -0
- package/dist/sandbox/sandbox.types.js +1 -0
- package/dist/sandbox/smoke.d.ts +76 -0
- package/dist/sandbox/smoke.js +380 -0
- package/dist/sandbox/worker-supervisor.d.ts +13 -0
- package/dist/sandbox/worker-supervisor.js +36 -0
- package/dist/sandbox/worker.d.ts +1 -0
- package/dist/sandbox/worker.js +225 -0
- package/dist/sandbox/workspace.service.d.ts +13 -0
- package/dist/sandbox/workspace.service.js +72 -0
- package/dist/session/managed-attempt-tools.d.ts +21 -0
- package/dist/session/managed-attempt-tools.js +912 -0
- package/dist/session/managed-build-coordinator.d.ts +5 -0
- package/dist/session/managed-build-coordinator.js +105 -0
- package/dist/session/managed-build-receipt.d.ts +21 -0
- package/dist/session/managed-build-receipt.js +335 -0
- package/dist/session/phase-completion.artifacts.d.ts +17 -0
- package/dist/session/phase-completion.artifacts.js +256 -26
- package/dist/session/phase-completion.d.ts +12 -2
- package/dist/session/phase-completion.helpers.d.ts +5 -0
- package/dist/session/phase-completion.helpers.js +51 -10
- package/dist/session/phase-completion.js +14 -3
- package/dist/session/phase-completion.prompts.d.ts +3 -3
- package/dist/session/phase-completion.prompts.js +24 -8
- package/dist/session/phase-completion.runtime.d.ts +13 -1
- package/dist/session/phase-completion.runtime.js +189 -8
- package/dist/session/phase-completion.schemas.js +117 -4
- package/dist/session/phase-completion.validation.d.ts +4 -1
- package/dist/session/phase-completion.validation.js +153 -22
- package/dist/session/pre-publication-validation.d.ts +46 -0
- package/dist/session/pre-publication-validation.js +208 -0
- package/dist/session/provider-cli/ci-repair-readiness.d.ts +16 -0
- package/dist/session/provider-cli/ci-repair-readiness.js +110 -0
- package/dist/session/provider-cli/provider-cli.artifacts.d.ts +3 -2
- package/dist/session/provider-cli/provider-cli.artifacts.js +65 -7
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +2 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +68 -9
- package/dist/session/provider-cli/provider-cli.process.d.ts +26 -0
- package/dist/session/provider-cli/provider-cli.process.js +474 -23
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +16 -2
- package/dist/session/provider-cli/provider-cli.prompts.js +224 -24
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +1 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.d.ts +6 -0
- package/dist/session/provider-cli/provider-cli.repair-epoch.js +11 -0
- package/dist/session/provider-cli/provider-cli.runtime.d.ts +1 -1
- package/dist/session/provider-cli/provider-cli.runtime.js +6 -3
- package/dist/session/provider-cli/provider-cli.service.d.ts +26 -3
- package/dist/session/provider-cli/provider-cli.service.js +650 -108
- package/dist/session/provider-cli/provider-cli.types.d.ts +6 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +2 -0
- package/dist/session/provider-cli/provider-output-state.js +91 -16
- package/dist/session/provider-cli/provider-usage.d.ts +7 -0
- package/dist/session/provider-cli/provider-usage.js +28 -5
- package/dist/session/session-redaction.d.ts +3 -0
- package/dist/session/session-redaction.js +38 -0
- package/dist/session/session.base.d.ts +6 -1
- package/dist/session/session.service.d.ts +8 -2
- package/dist/session/session.service.js +549 -58
- package/dist/session/session.types.d.ts +124 -1
- package/dist/session/session.types.js +231 -4
- package/dist/shared/format/format-bytes.d.ts +1 -0
- package/dist/shared/format/format-bytes.js +9 -0
- package/dist/shared/path/path.d.ts +1 -0
- package/dist/shared/path/path.js +21 -1
- package/dist/shared/process/dotnet-toolchain.d.ts +14 -0
- package/dist/shared/process/dotnet-toolchain.js +179 -0
- package/dist/shared/process/host-process-recovery.d.ts +12 -0
- package/dist/shared/process/host-process-recovery.js +78 -0
- package/dist/shared/process/host-process-supervisor.d.ts +59 -0
- package/dist/shared/process/host-process-supervisor.js +330 -0
- package/dist/shared/process/process.d.ts +1 -0
- package/dist/shared/process/process.js +1 -0
- package/dist/shared/process/windows-launch.d.ts +1 -1
- package/dist/shared/process/windows-launch.js +6 -3
- package/dist/shared/provider-capabilities.d.ts +1 -0
- package/dist/shared/provider-capabilities.js +3 -0
- package/dist/shared/redaction/redaction.js +16 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worktree/artifact-injector.d.ts +3 -2
- package/dist/worktree/artifact-injector.js +43 -4
- package/dist/worktree/dependency-warmer.d.ts +39 -1
- package/dist/worktree/dependency-warmer.js +351 -8
- package/dist/worktree/index.d.ts +2 -1
- package/dist/worktree/index.js +1 -0
- package/dist/worktree/prior-phase-artifact-hydrator.d.ts +2 -0
- package/dist/worktree/prior-phase-artifact-hydrator.js +136 -0
- package/dist/worktree/worktree-paths.d.ts +4 -0
- package/dist/worktree/worktree-paths.js +30 -0
- package/dist/worktree/worktree.base.d.ts +3 -0
- package/dist/worktree/worktree.service.d.ts +13 -2
- package/dist/worktree/worktree.service.js +238 -47
- package/dist/worktree/worktree.types.d.ts +5 -1
- package/package.json +8 -4
- package/runtime/windows-job-supervisor.ps1 +444 -0
- package/runtime/windows-listener-owner.ps1 +33 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface RunOnceDispatchPacket {
|
|
2
|
-
readonly schemaVersion: 1;
|
|
2
|
+
readonly schemaVersion: 1 | 2;
|
|
3
3
|
readonly userId: string;
|
|
4
4
|
readonly workItem: DispatchWorkItem;
|
|
5
5
|
readonly repo: DispatchRepo;
|
|
@@ -7,10 +7,14 @@ export interface RunOnceDispatchPacket {
|
|
|
7
7
|
readonly session: DispatchSession;
|
|
8
8
|
readonly lease: DispatchLease;
|
|
9
9
|
readonly execution: DispatchExecution;
|
|
10
|
+
readonly runtimeIntent: DispatchRuntimeIntent;
|
|
10
11
|
readonly serverLocal: DispatchServerLocalConfig;
|
|
12
|
+
readonly sandbox?: DispatchSandboxContext | null;
|
|
11
13
|
readonly pullRequest?: DispatchPullRequestContext | null;
|
|
12
14
|
readonly apiKeySecretGrant?: ApiKeySecretGrant | null;
|
|
15
|
+
readonly apiKeySecretGrantHandle?: ApiKeySecretGrantHandle | null;
|
|
13
16
|
readonly artifacts: readonly DispatchResolvedArtifact[];
|
|
17
|
+
readonly priorPhaseArtifacts?: readonly DispatchPriorPhaseArtifact[];
|
|
14
18
|
readonly warmPathOverrides?: readonly string[];
|
|
15
19
|
readonly qaBrowser?: DispatchQaBrowserContext | null;
|
|
16
20
|
readonly qaScope?: DispatchQaScope | null;
|
|
@@ -22,12 +26,63 @@ export interface RunOnceDispatchPacket {
|
|
|
22
26
|
readonly designerRefs?: DispatchDesignerRefHandoffContext | null;
|
|
23
27
|
readonly draft?: DispatchDraftPrompt | null;
|
|
24
28
|
}
|
|
29
|
+
export interface DispatchRuntimeIntent {
|
|
30
|
+
readonly executionClass: "analysis_only" | "managed_runtime";
|
|
31
|
+
readonly applicationRuntimeRequired: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface DispatchSandboxContext {
|
|
34
|
+
readonly dispatchAttemptId: string;
|
|
35
|
+
readonly executionLeaseId: string;
|
|
36
|
+
readonly runnerInstanceId: string;
|
|
37
|
+
readonly executionMode: "host" | "docker";
|
|
38
|
+
readonly executionPolicy: "host_allowed" | "sandbox_preferred" | "sandbox_required";
|
|
39
|
+
readonly networkPolicy: DispatchSandboxNetworkPolicy;
|
|
40
|
+
readonly requestedResources: DispatchSandboxResourceRequest;
|
|
41
|
+
readonly runtime?: string | null;
|
|
42
|
+
readonly sandboxConfigCommitSha?: string | null;
|
|
43
|
+
readonly inputCommitSha?: string | null;
|
|
44
|
+
readonly contractDigest?: string | null;
|
|
45
|
+
readonly imageDigest?: string | null;
|
|
46
|
+
readonly publicationMode: "bridge_push" | "shared_filesystem";
|
|
47
|
+
readonly publishGrantHandle?: DispatchPublishGrantHandle | null;
|
|
48
|
+
}
|
|
49
|
+
export interface DispatchPublishGrantHandle {
|
|
50
|
+
readonly grantId: string;
|
|
51
|
+
readonly branch: string;
|
|
52
|
+
readonly expiresAt: string;
|
|
53
|
+
}
|
|
54
|
+
export interface DispatchSandboxResourceRequest {
|
|
55
|
+
readonly sandboxSlots: number;
|
|
56
|
+
readonly cpuMillis: number;
|
|
57
|
+
readonly workerMemoryLimitBytes: number;
|
|
58
|
+
readonly serviceMemoryLimitBytes: number;
|
|
59
|
+
readonly runtimeOverheadBytes: number;
|
|
60
|
+
readonly memoryBytes: number;
|
|
61
|
+
readonly workspaceBytes: number;
|
|
62
|
+
readonly pids: number;
|
|
63
|
+
readonly buildSlots: number;
|
|
64
|
+
}
|
|
65
|
+
export interface DispatchSandboxNetworkPolicy {
|
|
66
|
+
readonly mode: "offline" | "public_allowlist" | "open_public";
|
|
67
|
+
readonly allowedHosts: readonly string[];
|
|
68
|
+
}
|
|
25
69
|
export interface DispatchDraftPrompt {
|
|
26
70
|
readonly kind: string;
|
|
27
71
|
readonly systemPrompt: string;
|
|
28
72
|
readonly userPrompt: string;
|
|
29
73
|
readonly projectName?: string | null;
|
|
30
74
|
readonly repoName?: string | null;
|
|
75
|
+
readonly attachments?: readonly DispatchDraftAttachment[];
|
|
76
|
+
}
|
|
77
|
+
export interface DispatchDraftAttachment {
|
|
78
|
+
readonly index: number;
|
|
79
|
+
readonly fileName: string;
|
|
80
|
+
readonly contentType: string;
|
|
81
|
+
readonly kind: string;
|
|
82
|
+
readonly byteCount: number;
|
|
83
|
+
readonly summary: string;
|
|
84
|
+
readonly textContent?: string | null;
|
|
85
|
+
readonly contentBase64?: string | null;
|
|
31
86
|
}
|
|
32
87
|
export interface DispatchQaBrowserContext {
|
|
33
88
|
readonly required: boolean;
|
|
@@ -39,6 +94,7 @@ export interface DispatchQaScope {
|
|
|
39
94
|
readonly schema_version: number;
|
|
40
95
|
readonly surface: readonly string[];
|
|
41
96
|
readonly required_evidence: readonly string[];
|
|
97
|
+
readonly required_capabilities?: readonly string[];
|
|
42
98
|
readonly not_applicable: readonly string[];
|
|
43
99
|
readonly browser_required: boolean;
|
|
44
100
|
readonly api_required: boolean;
|
|
@@ -55,6 +111,7 @@ export interface DispatchQaAppLaunchTarget {
|
|
|
55
111
|
readonly command?: string | null;
|
|
56
112
|
readonly working_directory?: string | null;
|
|
57
113
|
readonly ready_url?: string | null;
|
|
114
|
+
readonly managed_runtime_port?: string | null;
|
|
58
115
|
readonly routes: readonly string[];
|
|
59
116
|
readonly notes?: string | null;
|
|
60
117
|
}
|
|
@@ -143,6 +200,19 @@ export interface DispatchStoryQaDependencyContext {
|
|
|
143
200
|
readonly fromWorkItemId: string;
|
|
144
201
|
readonly toWorkItemId: string;
|
|
145
202
|
}
|
|
203
|
+
export interface DispatchPriorPhaseArtifact {
|
|
204
|
+
readonly workItemId: string;
|
|
205
|
+
readonly artifactId: string;
|
|
206
|
+
readonly cycleRunId: string;
|
|
207
|
+
readonly phase: "implementation" | "self_review" | "validation";
|
|
208
|
+
readonly status: string;
|
|
209
|
+
readonly producedAt: string;
|
|
210
|
+
readonly sourcePath: string;
|
|
211
|
+
readonly verdictJson: string;
|
|
212
|
+
readonly report: string;
|
|
213
|
+
readonly verdictContentHash: string;
|
|
214
|
+
readonly reportContentHash: string;
|
|
215
|
+
}
|
|
146
216
|
export interface DispatchDesignerRefHandoffContext {
|
|
147
217
|
readonly schemaVersion: number;
|
|
148
218
|
readonly kind: string;
|
|
@@ -232,6 +302,7 @@ export interface DispatchCycleRun {
|
|
|
232
302
|
readonly requestedBase: string;
|
|
233
303
|
readonly baseBranch: string;
|
|
234
304
|
readonly expectedCurrentBranch?: string | null;
|
|
305
|
+
readonly repairHeadSha?: string | null;
|
|
235
306
|
readonly attempt: number;
|
|
236
307
|
readonly model: string;
|
|
237
308
|
}
|
|
@@ -239,6 +310,8 @@ export interface DispatchSession {
|
|
|
239
310
|
readonly id: string;
|
|
240
311
|
readonly model: string;
|
|
241
312
|
readonly lane: string;
|
|
313
|
+
readonly resumedFromSessionId?: string | null;
|
|
314
|
+
readonly resumeProviderThreadId?: string | null;
|
|
242
315
|
}
|
|
243
316
|
export interface DispatchLease {
|
|
244
317
|
readonly id: string;
|
|
@@ -268,6 +341,11 @@ export interface ApiKeySecretGrant {
|
|
|
268
341
|
readonly secret: string;
|
|
269
342
|
readonly expiresAt: string;
|
|
270
343
|
}
|
|
344
|
+
export interface ApiKeySecretGrantHandle {
|
|
345
|
+
readonly grantId: string;
|
|
346
|
+
readonly provider: string;
|
|
347
|
+
readonly expiresAt: string;
|
|
348
|
+
}
|
|
271
349
|
export interface DispatchServerLocalConfig {
|
|
272
350
|
readonly repoRoot: string;
|
|
273
351
|
readonly cleanupWorktrees: boolean;
|
|
@@ -302,6 +380,19 @@ export interface RunnerDispatchArtifact {
|
|
|
302
380
|
readonly producedBy: string;
|
|
303
381
|
readonly status: string;
|
|
304
382
|
readonly phase?: string | null;
|
|
383
|
+
/**
|
|
384
|
+
* QA sidecars are transported with the terminal result because managed
|
|
385
|
+
* worktrees may be released before the API mirrors the result. The API
|
|
386
|
+
* validates these bytes against the canonical evidence metadata and stores
|
|
387
|
+
* only that metadata.
|
|
388
|
+
*/
|
|
389
|
+
readonly sidecars?: readonly RunnerDispatchSidecar[] | null;
|
|
390
|
+
}
|
|
391
|
+
export interface RunnerDispatchSidecar {
|
|
392
|
+
readonly path: string;
|
|
393
|
+
readonly contentBase64: string;
|
|
394
|
+
readonly contentHash: string;
|
|
395
|
+
readonly bytes: number;
|
|
305
396
|
}
|
|
306
397
|
export interface RunOnceResultPacket {
|
|
307
398
|
readonly schemaVersion: 1;
|
|
@@ -317,4 +408,36 @@ export interface RunnerEventLine {
|
|
|
317
408
|
readonly event: RunnerDispatchEvent;
|
|
318
409
|
}
|
|
319
410
|
export declare function parseRunOnceDispatchPacket(value: unknown): RunOnceDispatchPacket;
|
|
411
|
+
export interface HostRuntimeReadinessProbeRequest {
|
|
412
|
+
readonly requestId: string;
|
|
413
|
+
readonly fencingToken: string;
|
|
414
|
+
readonly userId: string;
|
|
415
|
+
readonly projectId: string;
|
|
416
|
+
readonly repoId: string;
|
|
417
|
+
readonly runnerId: string;
|
|
418
|
+
readonly runnerInstanceId: string;
|
|
419
|
+
readonly attempt: number;
|
|
420
|
+
readonly repoName: string;
|
|
421
|
+
readonly remoteUrl: string;
|
|
422
|
+
readonly defaultBranch: string;
|
|
423
|
+
readonly cloneOnDemand: boolean;
|
|
424
|
+
readonly runnerRepoLocalPath: string;
|
|
425
|
+
readonly revision: string;
|
|
426
|
+
readonly expiresAt: string;
|
|
427
|
+
readonly repoRoot: string;
|
|
428
|
+
readonly cleanupWorktrees: boolean;
|
|
429
|
+
}
|
|
430
|
+
export interface HostRuntimeReadinessProbeResult {
|
|
431
|
+
readonly status: "parallel_ready" | "serialized" | "failed";
|
|
432
|
+
readonly runtimeContractFingerprint?: string | null;
|
|
433
|
+
readonly runtimeContractSource?: string | null;
|
|
434
|
+
readonly reasonCode?: string | null;
|
|
435
|
+
readonly reasonMessage?: string | null;
|
|
436
|
+
readonly qaAppLaunchTarget?: HostRuntimeReadinessQaLaunchTarget | null;
|
|
437
|
+
readonly checkedAt: string;
|
|
438
|
+
}
|
|
439
|
+
export interface HostRuntimeReadinessQaLaunchTarget {
|
|
440
|
+
readonly managedRuntimePort: string;
|
|
441
|
+
readonly routes: readonly string[];
|
|
442
|
+
}
|
|
320
443
|
export declare function failureResult(summary: string, events?: readonly RunnerDispatchEvent[]): RunOnceResultPacket;
|
|
@@ -2,11 +2,11 @@ import path from "node:path";
|
|
|
2
2
|
export function parseRunOnceDispatchPacket(value) {
|
|
3
3
|
const packet = asObject(value, "dispatch packet");
|
|
4
4
|
const schemaVersion = requiredNumber(packet, "schemaVersion");
|
|
5
|
-
if (schemaVersion !== 1) {
|
|
5
|
+
if (schemaVersion !== 1 && schemaVersion !== 2) {
|
|
6
6
|
throw new Error(`Unsupported dispatch schemaVersion: ${schemaVersion}`);
|
|
7
7
|
}
|
|
8
8
|
return {
|
|
9
|
-
schemaVersion
|
|
9
|
+
schemaVersion,
|
|
10
10
|
userId: requiredString(packet, "userId"),
|
|
11
11
|
workItem: parseWorkItem(packet.workItem),
|
|
12
12
|
repo: parseRepo(packet.repo),
|
|
@@ -14,10 +14,14 @@ export function parseRunOnceDispatchPacket(value) {
|
|
|
14
14
|
session: parseSession(packet.session),
|
|
15
15
|
lease: parseLease(packet.lease),
|
|
16
16
|
execution: parseExecution(packet.execution),
|
|
17
|
+
runtimeIntent: parseRuntimeIntent(packet.runtimeIntent),
|
|
17
18
|
serverLocal: parseServerLocal(packet.serverLocal),
|
|
19
|
+
sandbox: parseSandbox(packet.sandbox, schemaVersion),
|
|
18
20
|
pullRequest: parsePullRequest(packet.pullRequest),
|
|
19
21
|
apiKeySecretGrant: parseApiKeySecretGrant(packet.apiKeySecretGrant),
|
|
22
|
+
apiKeySecretGrantHandle: parseApiKeySecretGrantHandle(packet.apiKeySecretGrantHandle),
|
|
20
23
|
artifacts: parseArtifacts(packet.artifacts),
|
|
24
|
+
priorPhaseArtifacts: parsePriorPhaseArtifacts(packet.priorPhaseArtifacts),
|
|
21
25
|
warmPathOverrides: parseWarmPathOverrides(packet.warmPathOverrides),
|
|
22
26
|
qaBrowser: parseQaBrowser(packet.qaBrowser),
|
|
23
27
|
qaScope: parseQaScope(packet.qaScope ?? packet.qa_scope),
|
|
@@ -30,6 +34,143 @@ export function parseRunOnceDispatchPacket(value) {
|
|
|
30
34
|
draft: parseDraftPrompt(packet.draft)
|
|
31
35
|
};
|
|
32
36
|
}
|
|
37
|
+
function parseRuntimeIntent(value) {
|
|
38
|
+
if (value === undefined || value === null) {
|
|
39
|
+
return { executionClass: "managed_runtime", applicationRuntimeRequired: true };
|
|
40
|
+
}
|
|
41
|
+
const intent = asObject(value, "runtimeIntent");
|
|
42
|
+
const executionClass = requiredString(intent, "executionClass").trim().toLowerCase();
|
|
43
|
+
if (executionClass !== "analysis_only" && executionClass !== "managed_runtime") {
|
|
44
|
+
throw new Error("runtimeIntent.executionClass must be analysis_only or managed_runtime.");
|
|
45
|
+
}
|
|
46
|
+
const applicationRuntimeRequired = requiredBoolean(intent, "applicationRuntimeRequired");
|
|
47
|
+
if ((executionClass === "analysis_only") === applicationRuntimeRequired) {
|
|
48
|
+
throw new Error("runtimeIntent execution class and application runtime requirement are inconsistent.");
|
|
49
|
+
}
|
|
50
|
+
return { executionClass, applicationRuntimeRequired };
|
|
51
|
+
}
|
|
52
|
+
function parseSandbox(value, schemaVersion) {
|
|
53
|
+
if (value === undefined || value === null) {
|
|
54
|
+
if (schemaVersion === 2) {
|
|
55
|
+
throw new Error("sandbox is required for dispatch schemaVersion 2.");
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const sandbox = asObject(value, "sandbox");
|
|
60
|
+
const executionMode = requiredString(sandbox, "executionMode");
|
|
61
|
+
if (executionMode !== "host" && executionMode !== "docker") {
|
|
62
|
+
throw new Error("sandbox.executionMode must be host or docker.");
|
|
63
|
+
}
|
|
64
|
+
const executionPolicy = requiredString(sandbox, "executionPolicy");
|
|
65
|
+
if (executionPolicy !== "host_allowed" && executionPolicy !== "sandbox_preferred" && executionPolicy !== "sandbox_required") {
|
|
66
|
+
throw new Error("sandbox.executionPolicy is invalid.");
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
dispatchAttemptId: requiredString(sandbox, "dispatchAttemptId"),
|
|
70
|
+
executionLeaseId: requiredString(sandbox, "executionLeaseId"),
|
|
71
|
+
runnerInstanceId: requiredString(sandbox, "runnerInstanceId"),
|
|
72
|
+
executionMode,
|
|
73
|
+
executionPolicy,
|
|
74
|
+
networkPolicy: parseSandboxNetworkPolicy(sandbox.networkPolicy),
|
|
75
|
+
requestedResources: parseSandboxResourceRequest(sandbox.requestedResources),
|
|
76
|
+
runtime: optionalString(sandbox, "runtime"),
|
|
77
|
+
sandboxConfigCommitSha: optionalString(sandbox, "sandboxConfigCommitSha"),
|
|
78
|
+
inputCommitSha: optionalString(sandbox, "inputCommitSha"),
|
|
79
|
+
contractDigest: optionalString(sandbox, "contractDigest"),
|
|
80
|
+
imageDigest: optionalString(sandbox, "imageDigest"),
|
|
81
|
+
publicationMode: parsePublicationMode(sandbox.publicationMode),
|
|
82
|
+
publishGrantHandle: parsePublishGrantHandle(sandbox.publishGrantHandle)
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function parsePublicationMode(value) {
|
|
86
|
+
if (value === undefined || value === null)
|
|
87
|
+
return "shared_filesystem";
|
|
88
|
+
if (value !== "bridge_push" && value !== "shared_filesystem")
|
|
89
|
+
throw new Error("sandbox.publicationMode is invalid.");
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
function parsePublishGrantHandle(value) {
|
|
93
|
+
if (value === undefined || value === null)
|
|
94
|
+
return null;
|
|
95
|
+
const handle = asObject(value, "sandbox.publishGrantHandle");
|
|
96
|
+
const grantId = requiredString(handle, "grantId");
|
|
97
|
+
const branch = requiredString(handle, "branch");
|
|
98
|
+
const expiresAt = requiredString(handle, "expiresAt");
|
|
99
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/iu.test(grantId)) {
|
|
100
|
+
throw new Error("sandbox.publishGrantHandle.grantId is invalid.");
|
|
101
|
+
}
|
|
102
|
+
if (branch.length > 240)
|
|
103
|
+
throw new Error("sandbox.publishGrantHandle.branch is too long.");
|
|
104
|
+
if (!Number.isFinite(Date.parse(expiresAt)))
|
|
105
|
+
throw new Error("sandbox.publishGrantHandle.expiresAt is invalid.");
|
|
106
|
+
return { grantId, branch, expiresAt };
|
|
107
|
+
}
|
|
108
|
+
function parseSandboxResourceRequest(value) {
|
|
109
|
+
if (value === undefined || value === null) {
|
|
110
|
+
return {
|
|
111
|
+
sandboxSlots: 1,
|
|
112
|
+
cpuMillis: 2000,
|
|
113
|
+
workerMemoryLimitBytes: 2 * 1024 ** 3,
|
|
114
|
+
serviceMemoryLimitBytes: 0,
|
|
115
|
+
runtimeOverheadBytes: 128 * 1024 ** 2,
|
|
116
|
+
memoryBytes: 2 * 1024 ** 3 + 128 * 1024 ** 2,
|
|
117
|
+
workspaceBytes: 10 * 1024 ** 3,
|
|
118
|
+
pids: 512,
|
|
119
|
+
buildSlots: 1
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const resources = asObject(value, "sandbox.requestedResources");
|
|
123
|
+
const memoryBytes = boundedInteger(resources, "memoryBytes", 128 * 1024 ** 2, 512 * 1024 ** 3);
|
|
124
|
+
const hasMemoryBreakdown = ["workerMemoryLimitBytes", "serviceMemoryLimitBytes", "runtimeOverheadBytes"]
|
|
125
|
+
.some(key => resources[key] !== undefined && resources[key] !== null);
|
|
126
|
+
const workerMemoryLimitBytes = hasMemoryBreakdown
|
|
127
|
+
? boundedInteger(resources, "workerMemoryLimitBytes", 128 * 1024 ** 2, 512 * 1024 ** 3)
|
|
128
|
+
: memoryBytes;
|
|
129
|
+
const serviceMemoryLimitBytes = hasMemoryBreakdown
|
|
130
|
+
? boundedInteger(resources, "serviceMemoryLimitBytes", 0, 512 * 1024 ** 3)
|
|
131
|
+
: 0;
|
|
132
|
+
const runtimeOverheadBytes = hasMemoryBreakdown
|
|
133
|
+
? boundedInteger(resources, "runtimeOverheadBytes", 0, 64 * 1024 ** 3)
|
|
134
|
+
: 0;
|
|
135
|
+
if (workerMemoryLimitBytes + serviceMemoryLimitBytes + runtimeOverheadBytes !== memoryBytes) {
|
|
136
|
+
throw new Error("sandbox.requestedResources memory breakdown must equal memoryBytes.");
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
sandboxSlots: boundedInteger(resources, "sandboxSlots", 1, 4),
|
|
140
|
+
cpuMillis: boundedInteger(resources, "cpuMillis", 100, 64_000),
|
|
141
|
+
workerMemoryLimitBytes,
|
|
142
|
+
serviceMemoryLimitBytes,
|
|
143
|
+
runtimeOverheadBytes,
|
|
144
|
+
memoryBytes,
|
|
145
|
+
workspaceBytes: boundedInteger(resources, "workspaceBytes", 1024 ** 3, 10 * 1024 ** 4),
|
|
146
|
+
pids: boundedInteger(resources, "pids", 32, 65_536),
|
|
147
|
+
buildSlots: boundedInteger(resources, "buildSlots", 0, 4)
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function parseSandboxNetworkPolicy(value) {
|
|
151
|
+
if (value === undefined || value === null)
|
|
152
|
+
return { mode: "offline", allowedHosts: [] };
|
|
153
|
+
const policy = asObject(value, "sandbox.networkPolicy");
|
|
154
|
+
const mode = requiredString(policy, "mode");
|
|
155
|
+
if (mode !== "offline" && mode !== "public_allowlist" && mode !== "open_public") {
|
|
156
|
+
throw new Error("sandbox.networkPolicy.mode is invalid.");
|
|
157
|
+
}
|
|
158
|
+
const rawHosts = policy.allowedHosts ?? [];
|
|
159
|
+
if (!Array.isArray(rawHosts) || rawHosts.some((host) => typeof host !== "string")) {
|
|
160
|
+
throw new Error("sandbox.networkPolicy.allowedHosts must be a string array.");
|
|
161
|
+
}
|
|
162
|
+
const allowedHosts = [...new Set(rawHosts.map(host => host.trim().toLowerCase()).filter(Boolean))];
|
|
163
|
+
if (allowedHosts.length > 128 || allowedHosts.some(host => !/^(?:\*\.)?(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z](?:[a-z0-9-]{0,61}[a-z0-9])?$/u.test(host))) {
|
|
164
|
+
throw new Error("sandbox.networkPolicy.allowedHosts contains an invalid hostname.");
|
|
165
|
+
}
|
|
166
|
+
if (mode !== "public_allowlist" && allowedHosts.length > 0) {
|
|
167
|
+
throw new Error("sandbox.networkPolicy.allowedHosts requires public_allowlist mode.");
|
|
168
|
+
}
|
|
169
|
+
if (mode === "public_allowlist" && allowedHosts.length === 0) {
|
|
170
|
+
return { mode: "offline", allowedHosts: [] };
|
|
171
|
+
}
|
|
172
|
+
return { mode, allowedHosts };
|
|
173
|
+
}
|
|
33
174
|
export function failureResult(summary, events = []) {
|
|
34
175
|
return {
|
|
35
176
|
schemaVersion: 1,
|
|
@@ -73,6 +214,7 @@ function parseCycleRun(value) {
|
|
|
73
214
|
requestedBase: optionalString(cycle, "requestedBase") ?? "develop",
|
|
74
215
|
baseBranch: optionalString(cycle, "baseBranch") ?? "develop",
|
|
75
216
|
expectedCurrentBranch: optionalString(cycle, "expectedCurrentBranch"),
|
|
217
|
+
repairHeadSha: optionalString(cycle, "repairHeadSha"),
|
|
76
218
|
attempt: requiredNumber(cycle, "attempt"),
|
|
77
219
|
model: requiredString(cycle, "model")
|
|
78
220
|
};
|
|
@@ -82,7 +224,9 @@ function parseSession(value) {
|
|
|
82
224
|
return {
|
|
83
225
|
id: requiredString(session, "id"),
|
|
84
226
|
model: requiredString(session, "model"),
|
|
85
|
-
lane: requiredString(session, "lane")
|
|
227
|
+
lane: requiredString(session, "lane"),
|
|
228
|
+
resumedFromSessionId: optionalString(session, "resumedFromSessionId"),
|
|
229
|
+
resumeProviderThreadId: optionalString(session, "resumeProviderThreadId")
|
|
86
230
|
};
|
|
87
231
|
}
|
|
88
232
|
function parseLease(value) {
|
|
@@ -121,9 +265,45 @@ function parseDraftPrompt(value) {
|
|
|
121
265
|
return {
|
|
122
266
|
kind: requiredString(draft, "kind"),
|
|
123
267
|
systemPrompt: requiredString(draft, "systemPrompt"),
|
|
124
|
-
userPrompt: requiredString(draft, "userPrompt")
|
|
268
|
+
userPrompt: requiredString(draft, "userPrompt"),
|
|
269
|
+
projectName: optionalString(draft, "projectName"),
|
|
270
|
+
repoName: optionalString(draft, "repoName"),
|
|
271
|
+
attachments: parseDraftAttachments(draft.attachments)
|
|
125
272
|
};
|
|
126
273
|
}
|
|
274
|
+
function parseDraftAttachments(value) {
|
|
275
|
+
if (value === undefined || value === null) {
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
if (!Array.isArray(value)) {
|
|
279
|
+
throw new Error("draft.attachments must be an array when provided.");
|
|
280
|
+
}
|
|
281
|
+
return value.map((entry, index) => {
|
|
282
|
+
const attachment = asObject(entry, `draft.attachments[${index}]`);
|
|
283
|
+
const kind = requiredString(attachment, "kind").trim().toLowerCase();
|
|
284
|
+
if (kind !== "text" && kind !== "image") {
|
|
285
|
+
throw new Error(`draft.attachments[${index}].kind must be text or image.`);
|
|
286
|
+
}
|
|
287
|
+
const textContent = optionalString(attachment, "textContent");
|
|
288
|
+
const contentBase64 = optionalString(attachment, "contentBase64");
|
|
289
|
+
if (kind === "text" && textContent === null) {
|
|
290
|
+
throw new Error(`draft.attachments[${index}].textContent is required for text attachments.`);
|
|
291
|
+
}
|
|
292
|
+
if (kind === "image" && contentBase64 === null) {
|
|
293
|
+
throw new Error(`draft.attachments[${index}].contentBase64 is required for image attachments.`);
|
|
294
|
+
}
|
|
295
|
+
return {
|
|
296
|
+
index: optionalNonNegativeInteger(attachment, "index") ?? index,
|
|
297
|
+
fileName: requiredString(attachment, "fileName"),
|
|
298
|
+
contentType: optionalString(attachment, "contentType") ?? "",
|
|
299
|
+
kind,
|
|
300
|
+
byteCount: optionalNonNegativeInteger(attachment, "byteCount") ?? 0,
|
|
301
|
+
summary: optionalString(attachment, "summary") ?? "",
|
|
302
|
+
textContent,
|
|
303
|
+
contentBase64
|
|
304
|
+
};
|
|
305
|
+
});
|
|
306
|
+
}
|
|
127
307
|
function parseApiKeySecretGrant(value) {
|
|
128
308
|
if (value === undefined || value === null) {
|
|
129
309
|
return null;
|
|
@@ -136,6 +316,16 @@ function parseApiKeySecretGrant(value) {
|
|
|
136
316
|
expiresAt: requiredString(grant, "expiresAt")
|
|
137
317
|
};
|
|
138
318
|
}
|
|
319
|
+
function parseApiKeySecretGrantHandle(value) {
|
|
320
|
+
if (value === undefined || value === null)
|
|
321
|
+
return null;
|
|
322
|
+
const grant = asObject(value, "apiKeySecretGrantHandle");
|
|
323
|
+
return {
|
|
324
|
+
grantId: requiredString(grant, "grantId"),
|
|
325
|
+
provider: requiredString(grant, "provider"),
|
|
326
|
+
expiresAt: requiredString(grant, "expiresAt")
|
|
327
|
+
};
|
|
328
|
+
}
|
|
139
329
|
function parseServerLocal(value) {
|
|
140
330
|
const serverLocal = asObject(value, "serverLocal");
|
|
141
331
|
return {
|
|
@@ -209,6 +399,7 @@ function parseQaScope(value) {
|
|
|
209
399
|
schema_version: requiredNumber(qaScope, "schema_version"),
|
|
210
400
|
surface: parseOptionalStringArray(qaScope.surface, "qaScope.surface"),
|
|
211
401
|
required_evidence: parseOptionalStringArray(qaScope.required_evidence, "qaScope.required_evidence"),
|
|
402
|
+
required_capabilities: parseOptionalStringArray(qaScope.required_capabilities ?? qaScope.requiredCapabilities, "qaScope.required_capabilities"),
|
|
212
403
|
not_applicable: parseOptionalStringArray(qaScope.not_applicable, "qaScope.not_applicable"),
|
|
213
404
|
browser_required: optionalBoolean(qaScope, "browser_required") ?? optionalBoolean(qaScope, "browserRequired") ?? false,
|
|
214
405
|
api_required: optionalBoolean(qaScope, "api_required") ?? optionalBoolean(qaScope, "apiRequired") ?? false,
|
|
@@ -235,6 +426,7 @@ function parseQaAppLaunchTarget(value) {
|
|
|
235
426
|
command: optionalString(launchTarget, "command"),
|
|
236
427
|
working_directory: optionalString(launchTarget, "working_directory"),
|
|
237
428
|
ready_url: optionalString(launchTarget, "ready_url"),
|
|
429
|
+
managed_runtime_port: optionalString(launchTarget, "managed_runtime_port"),
|
|
238
430
|
routes: Array.isArray(routes)
|
|
239
431
|
? routes.map((entry, index) => {
|
|
240
432
|
if (typeof entry !== "string") {
|
|
@@ -513,6 +705,34 @@ function parseArtifacts(value) {
|
|
|
513
705
|
};
|
|
514
706
|
});
|
|
515
707
|
}
|
|
708
|
+
function parsePriorPhaseArtifacts(value) {
|
|
709
|
+
if (value === undefined || value === null) {
|
|
710
|
+
return [];
|
|
711
|
+
}
|
|
712
|
+
if (!Array.isArray(value)) {
|
|
713
|
+
throw new Error("priorPhaseArtifacts must be an array when provided.");
|
|
714
|
+
}
|
|
715
|
+
return value.map((entry, index) => {
|
|
716
|
+
const artifact = asObject(entry, `priorPhaseArtifacts[${index}]`);
|
|
717
|
+
const phase = requiredString(artifact, "phase").trim().toLowerCase().replace(/-/g, "_");
|
|
718
|
+
if (phase !== "implementation" && phase !== "self_review" && phase !== "validation") {
|
|
719
|
+
throw new Error(`priorPhaseArtifacts[${index}].phase must be implementation, self_review, or validation.`);
|
|
720
|
+
}
|
|
721
|
+
return {
|
|
722
|
+
workItemId: requiredString(artifact, "workItemId"),
|
|
723
|
+
artifactId: requiredString(artifact, "artifactId"),
|
|
724
|
+
cycleRunId: requiredString(artifact, "cycleRunId"),
|
|
725
|
+
phase,
|
|
726
|
+
status: requiredString(artifact, "status"),
|
|
727
|
+
producedAt: requiredString(artifact, "producedAt"),
|
|
728
|
+
sourcePath: requiredString(artifact, "sourcePath"),
|
|
729
|
+
verdictJson: requiredString(artifact, "verdictJson"),
|
|
730
|
+
report: optionalString(artifact, "report") ?? "",
|
|
731
|
+
verdictContentHash: requiredString(artifact, "verdictContentHash").toLowerCase(),
|
|
732
|
+
reportContentHash: requiredString(artifact, "reportContentHash").toLowerCase()
|
|
733
|
+
};
|
|
734
|
+
});
|
|
735
|
+
}
|
|
516
736
|
function asObject(value, label) {
|
|
517
737
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
518
738
|
throw new Error(`${label} must be an object.`);
|
|
@@ -580,3 +800,10 @@ function requiredNumber(source, key) {
|
|
|
580
800
|
}
|
|
581
801
|
return value;
|
|
582
802
|
}
|
|
803
|
+
function boundedInteger(source, key, minimum, maximum) {
|
|
804
|
+
const value = requiredNumber(source, key);
|
|
805
|
+
if (!Number.isSafeInteger(value) || value < minimum || value > maximum) {
|
|
806
|
+
throw new Error(`${key} must be an integer from ${minimum} through ${maximum}.`);
|
|
807
|
+
}
|
|
808
|
+
return value;
|
|
809
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function formatBytes(bytes: number): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function formatBytes(bytes) {
|
|
2
|
+
if (!Number.isFinite(bytes) || bytes <= 0)
|
|
3
|
+
return "0 B";
|
|
4
|
+
const units = ["B", "KiB", "MiB", "GiB", "TiB"];
|
|
5
|
+
const power = Math.max(0, Math.min(units.length - 1, Math.floor(Math.log(bytes) / Math.log(1024))));
|
|
6
|
+
const value = bytes / 1024 ** power;
|
|
7
|
+
const precision = power === 0 || value >= 100 ? 0 : 1;
|
|
8
|
+
return `${value.toFixed(precision)} ${units[power]}`;
|
|
9
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare function isSubPath(root: string, candidate: string): boolean;
|
|
2
2
|
export declare function resolveExistingDirectoryPath(inputPath: string): Promise<string>;
|
|
3
|
+
export declare function resolvePathIdentity(inputPath: string): Promise<string>;
|
|
3
4
|
export declare function ensureDirectory(inputPath: string): Promise<string>;
|
|
4
5
|
export declare function safeSegment(value: string, fallback: string): string;
|
package/dist/shared/path/path.js
CHANGED
|
@@ -4,7 +4,9 @@ export function isSubPath(root, candidate) {
|
|
|
4
4
|
const normalizedRoot = path.resolve(root);
|
|
5
5
|
const normalizedCandidate = path.resolve(candidate);
|
|
6
6
|
const relative = path.relative(normalizedRoot, normalizedCandidate);
|
|
7
|
-
return relative === "" || (
|
|
7
|
+
return relative === "" || (relative !== ".."
|
|
8
|
+
&& !relative.startsWith(`..${path.sep}`)
|
|
9
|
+
&& !path.isAbsolute(relative));
|
|
8
10
|
}
|
|
9
11
|
export async function resolveExistingDirectoryPath(inputPath) {
|
|
10
12
|
const stat = await fs.stat(inputPath);
|
|
@@ -13,6 +15,24 @@ export async function resolveExistingDirectoryPath(inputPath) {
|
|
|
13
15
|
}
|
|
14
16
|
return await fs.realpath(inputPath);
|
|
15
17
|
}
|
|
18
|
+
export async function resolvePathIdentity(inputPath) {
|
|
19
|
+
let existingAncestor = path.resolve(inputPath);
|
|
20
|
+
const missingSegments = [];
|
|
21
|
+
while (true) {
|
|
22
|
+
try {
|
|
23
|
+
return path.join(await fs.realpath(existingAncestor), ...missingSegments);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
if (error.code !== "ENOENT")
|
|
27
|
+
throw error;
|
|
28
|
+
const parent = path.dirname(existingAncestor);
|
|
29
|
+
if (parent === existingAncestor)
|
|
30
|
+
throw error;
|
|
31
|
+
missingSegments.unshift(path.basename(existingAncestor));
|
|
32
|
+
existingAncestor = parent;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
16
36
|
export async function ensureDirectory(inputPath) {
|
|
17
37
|
await fs.mkdir(inputPath, { recursive: true });
|
|
18
38
|
return await resolveExistingDirectoryPath(inputPath);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface DotNetToolchainSelection {
|
|
2
|
+
readonly executablePath: string;
|
|
3
|
+
readonly rootPath: string;
|
|
4
|
+
readonly sdkVersion: string;
|
|
5
|
+
readonly requiredMajor: number;
|
|
6
|
+
}
|
|
7
|
+
export interface DotNetToolchainOptions {
|
|
8
|
+
readonly environment?: NodeJS.ProcessEnv;
|
|
9
|
+
readonly platform?: NodeJS.Platform;
|
|
10
|
+
readonly homeDirectory?: string;
|
|
11
|
+
readonly fileExists?: (candidate: string) => Promise<boolean>;
|
|
12
|
+
readonly listSdks?: (candidate: string) => Promise<string>;
|
|
13
|
+
}
|
|
14
|
+
export declare function configureDotNetToolchain(repoRoots: readonly string[], options?: DotNetToolchainOptions): Promise<DotNetToolchainSelection | null>;
|