@loucompanion/forge-bridge 0.1.3-dev.b6be5e7f9668 → 0.1.3-dev.ba293ccf876b
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 +98 -3
- package/dist/bridge/bridge.service.js +1445 -48
- package/dist/bridge/bridge.types.d.ts +209 -1
- package/dist/bridge/readiness-result-outbox.d.ts +21 -0
- package/dist/bridge/readiness-result-outbox.js +54 -0
- package/dist/bridge/readiness-result-worker.d.ts +2 -0
- package/dist/bridge/readiness-result-worker.js +100 -0
- 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.d.ts +2 -0
- package/dist/cli/cli.help.js +217 -0
- package/dist/cli/cli.service.d.ts +45 -2
- package/dist/cli/cli.service.js +383 -209
- 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-path-operation.d.ts +21 -0
- package/dist/runtime/attempt-path-operation.js +94 -0
- package/dist/runtime/attempt-private-directory.d.ts +6 -0
- package/dist/runtime/attempt-private-directory.js +54 -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/canonical-source-file.d.ts +3 -0
- package/dist/runtime/canonical-source-file.js +54 -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-diagnostics.d.ts +4 -0
- package/dist/runtime/host-diagnostics.js +95 -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 +56 -0
- package/dist/runtime/host-runtime-contract.js +709 -0
- package/dist/runtime/host-runtime-lease.d.ts +201 -0
- package/dist/runtime/host-runtime-lease.js +2314 -0
- package/dist/runtime/host-runtime-promotion.d.ts +32 -0
- package/dist/runtime/host-runtime-promotion.js +206 -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/pinned-directory-process.d.ts +4 -0
- package/dist/runtime/pinned-directory-process.js +20 -0
- package/dist/runtime/pinned-source-directory.d.ts +9 -0
- package/dist/runtime/pinned-source-directory.js +56 -0
- package/dist/runtime/playwright-host-runtime-adapter.d.ts +21 -0
- package/dist/runtime/playwright-host-runtime-adapter.js +268 -0
- package/dist/runtime/prepared-runtime-identity.d.ts +3 -0
- package/dist/runtime/prepared-runtime-identity.js +191 -0
- package/dist/runtime/prepared-runtime-readiness.d.ts +22 -0
- package/dist/runtime/prepared-runtime-readiness.js +191 -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 +27 -0
- package/dist/session/phase-completion.artifacts.js +829 -0
- package/dist/session/phase-completion.d.ts +44 -46
- package/dist/session/phase-completion.helpers.d.ts +117 -0
- package/dist/session/phase-completion.helpers.js +701 -0
- package/dist/session/phase-completion.js +42 -3488
- package/dist/session/phase-completion.prompts.d.ts +14 -0
- package/dist/session/phase-completion.prompts.js +236 -0
- package/dist/session/phase-completion.runtime.d.ts +48 -0
- package/dist/session/phase-completion.runtime.js +790 -0
- package/dist/session/phase-completion.schemas.d.ts +3 -0
- package/dist/session/phase-completion.schemas.js +820 -0
- package/dist/session/phase-completion.validation.d.ts +37 -0
- package/dist/session/phase-completion.validation.js +855 -0
- package/dist/session/pre-publication-validation.d.ts +47 -0
- package/dist/session/pre-publication-validation.js +249 -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 +94 -0
- package/dist/session/provider-cli/provider-cli.artifacts.js +812 -0
- package/dist/session/provider-cli/provider-cli.base.d.ts +1 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.d.ts +12 -0
- package/dist/session/provider-cli/provider-cli.deterministic-payloads.js +279 -0
- package/dist/session/provider-cli/provider-cli.deterministic.d.ts +14 -0
- package/dist/session/provider-cli/provider-cli.deterministic.js +377 -0
- package/dist/session/provider-cli/provider-cli.process.d.ts +57 -0
- package/dist/session/provider-cli/provider-cli.process.js +716 -0
- package/dist/session/provider-cli/provider-cli.prompts.d.ts +47 -0
- package/dist/session/provider-cli/provider-cli.prompts.js +611 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.d.ts +11 -0
- package/dist/session/provider-cli/provider-cli.qa-sidecars.js +66 -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 +9 -0
- package/dist/session/provider-cli/provider-cli.runtime.js +43 -0
- package/dist/session/provider-cli/provider-cli.service.d.ts +29 -53
- package/dist/session/provider-cli/provider-cli.service.js +640 -2581
- package/dist/session/provider-cli/provider-cli.types.d.ts +6 -0
- package/dist/session/provider-cli/provider-output-state.d.ts +22 -0
- package/dist/session/provider-cli/provider-output-state.js +520 -0
- 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 +550 -58
- package/dist/session/session.types.d.ts +180 -1
- package/dist/session/session.types.js +323 -4
- package/dist/shared/format/format-bytes.d.ts +1 -0
- package/dist/shared/format/format-bytes.js +9 -0
- package/dist/shared/git/git.js +2 -1
- 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 +2 -0
- package/dist/shared/process/process.js +11 -6
- package/dist/shared/process/windows-launch.d.ts +8 -0
- package/dist/shared/process/windows-launch.js +41 -0
- 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 +82 -10
- 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 +16 -3
- package/dist/worktree/worktree.service.js +323 -54
- 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
|
@@ -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,20 +14,163 @@ 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),
|
|
24
28
|
qaRework: parseQaRework(packet.qaRework),
|
|
25
29
|
architectRevision: parseArchitectRevision(packet.architectRevision),
|
|
30
|
+
architectDependencies: parseArchitectDependencies(packet.architectDependencies),
|
|
26
31
|
storyDevelop: parseStoryDevelop(packet.storyDevelop),
|
|
27
32
|
storyQa: parseStoryQa(packet.storyQa),
|
|
33
|
+
designerRefs: parseDesignerRefs(packet.designerRefs ?? packet.designer_refs),
|
|
28
34
|
draft: parseDraftPrompt(packet.draft)
|
|
29
35
|
};
|
|
30
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
|
+
}
|
|
31
174
|
export function failureResult(summary, events = []) {
|
|
32
175
|
return {
|
|
33
176
|
schemaVersion: 1,
|
|
@@ -71,6 +214,7 @@ function parseCycleRun(value) {
|
|
|
71
214
|
requestedBase: optionalString(cycle, "requestedBase") ?? "develop",
|
|
72
215
|
baseBranch: optionalString(cycle, "baseBranch") ?? "develop",
|
|
73
216
|
expectedCurrentBranch: optionalString(cycle, "expectedCurrentBranch"),
|
|
217
|
+
repairHeadSha: optionalString(cycle, "repairHeadSha"),
|
|
74
218
|
attempt: requiredNumber(cycle, "attempt"),
|
|
75
219
|
model: requiredString(cycle, "model")
|
|
76
220
|
};
|
|
@@ -80,7 +224,9 @@ function parseSession(value) {
|
|
|
80
224
|
return {
|
|
81
225
|
id: requiredString(session, "id"),
|
|
82
226
|
model: requiredString(session, "model"),
|
|
83
|
-
lane: requiredString(session, "lane")
|
|
227
|
+
lane: requiredString(session, "lane"),
|
|
228
|
+
resumedFromSessionId: optionalString(session, "resumedFromSessionId"),
|
|
229
|
+
resumeProviderThreadId: optionalString(session, "resumeProviderThreadId")
|
|
84
230
|
};
|
|
85
231
|
}
|
|
86
232
|
function parseLease(value) {
|
|
@@ -119,9 +265,45 @@ function parseDraftPrompt(value) {
|
|
|
119
265
|
return {
|
|
120
266
|
kind: requiredString(draft, "kind"),
|
|
121
267
|
systemPrompt: requiredString(draft, "systemPrompt"),
|
|
122
|
-
userPrompt: requiredString(draft, "userPrompt")
|
|
268
|
+
userPrompt: requiredString(draft, "userPrompt"),
|
|
269
|
+
projectName: optionalString(draft, "projectName"),
|
|
270
|
+
repoName: optionalString(draft, "repoName"),
|
|
271
|
+
attachments: parseDraftAttachments(draft.attachments)
|
|
123
272
|
};
|
|
124
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
|
+
}
|
|
125
307
|
function parseApiKeySecretGrant(value) {
|
|
126
308
|
if (value === undefined || value === null) {
|
|
127
309
|
return null;
|
|
@@ -134,6 +316,16 @@ function parseApiKeySecretGrant(value) {
|
|
|
134
316
|
expiresAt: requiredString(grant, "expiresAt")
|
|
135
317
|
};
|
|
136
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
|
+
}
|
|
137
329
|
function parseServerLocal(value) {
|
|
138
330
|
const serverLocal = asObject(value, "serverLocal");
|
|
139
331
|
return {
|
|
@@ -207,6 +399,7 @@ function parseQaScope(value) {
|
|
|
207
399
|
schema_version: requiredNumber(qaScope, "schema_version"),
|
|
208
400
|
surface: parseOptionalStringArray(qaScope.surface, "qaScope.surface"),
|
|
209
401
|
required_evidence: parseOptionalStringArray(qaScope.required_evidence, "qaScope.required_evidence"),
|
|
402
|
+
required_capabilities: parseOptionalStringArray(qaScope.required_capabilities ?? qaScope.requiredCapabilities, "qaScope.required_capabilities"),
|
|
210
403
|
not_applicable: parseOptionalStringArray(qaScope.not_applicable, "qaScope.not_applicable"),
|
|
211
404
|
browser_required: optionalBoolean(qaScope, "browser_required") ?? optionalBoolean(qaScope, "browserRequired") ?? false,
|
|
212
405
|
api_required: optionalBoolean(qaScope, "api_required") ?? optionalBoolean(qaScope, "apiRequired") ?? false,
|
|
@@ -233,6 +426,7 @@ function parseQaAppLaunchTarget(value) {
|
|
|
233
426
|
command: optionalString(launchTarget, "command"),
|
|
234
427
|
working_directory: optionalString(launchTarget, "working_directory"),
|
|
235
428
|
ready_url: optionalString(launchTarget, "ready_url"),
|
|
429
|
+
managed_runtime_port: optionalString(launchTarget, "managed_runtime_port"),
|
|
236
430
|
routes: Array.isArray(routes)
|
|
237
431
|
? routes.map((entry, index) => {
|
|
238
432
|
if (typeof entry !== "string") {
|
|
@@ -282,6 +476,34 @@ function parseArchitectRevision(value) {
|
|
|
282
476
|
feedback: requiredString(revision, "feedback")
|
|
283
477
|
};
|
|
284
478
|
}
|
|
479
|
+
function parseArchitectDependencies(value) {
|
|
480
|
+
if (value === undefined || value === null) {
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
const context = asObject(value, "architectDependencies");
|
|
484
|
+
const prerequisites = context.prerequisites;
|
|
485
|
+
if (!Array.isArray(prerequisites)) {
|
|
486
|
+
throw new Error("architectDependencies.prerequisites must be an array.");
|
|
487
|
+
}
|
|
488
|
+
return {
|
|
489
|
+
baseBranch: requiredString(context, "baseBranch").trim(),
|
|
490
|
+
prerequisites: prerequisites.map((entry, index) => {
|
|
491
|
+
const prerequisite = asObject(entry, `architectDependencies.prerequisites[${index}]`);
|
|
492
|
+
return {
|
|
493
|
+
storyId: requiredString(prerequisite, "storyId").trim(),
|
|
494
|
+
title: requiredString(prerequisite, "title").trim(),
|
|
495
|
+
scheduleIndex: optionalNonNegativeInteger(prerequisite, "scheduleIndex"),
|
|
496
|
+
waveIndex: optionalNonNegativeInteger(prerequisite, "waveIndex"),
|
|
497
|
+
featureScheduleIndex: optionalNonNegativeInteger(prerequisite, "featureScheduleIndex"),
|
|
498
|
+
expectedOutput: optionalString(prerequisite, "expectedOutput"),
|
|
499
|
+
handoffSummary: optionalString(prerequisite, "handoffSummary"),
|
|
500
|
+
dependencyReason: optionalString(prerequisite, "dependencyReason"),
|
|
501
|
+
pullRequestNumber: optionalPositiveInteger(prerequisite, "pullRequestNumber"),
|
|
502
|
+
targetBranch: requiredString(prerequisite, "targetBranch").trim()
|
|
503
|
+
};
|
|
504
|
+
})
|
|
505
|
+
};
|
|
506
|
+
}
|
|
285
507
|
function parseStoryDevelop(value) {
|
|
286
508
|
if (value === undefined || value === null) {
|
|
287
509
|
return null;
|
|
@@ -387,6 +609,58 @@ function parseStoryQaDependencies(value) {
|
|
|
387
609
|
};
|
|
388
610
|
});
|
|
389
611
|
}
|
|
612
|
+
function parseDesignerRefs(value) {
|
|
613
|
+
if (value === undefined || value === null) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
const context = asObject(value, "designerRefs");
|
|
617
|
+
const refs = context.refs;
|
|
618
|
+
if (!Array.isArray(refs)) {
|
|
619
|
+
throw new Error("designerRefs.refs must be an array.");
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
schemaVersion: requiredNumber(context, "schemaVersion"),
|
|
623
|
+
kind: requiredString(context, "kind"),
|
|
624
|
+
ownerType: requiredString(context, "ownerType"),
|
|
625
|
+
ownerId: requiredString(context, "ownerId"),
|
|
626
|
+
projectId: requiredString(context, "projectId"),
|
|
627
|
+
repoId: requiredString(context, "repoId"),
|
|
628
|
+
title: requiredString(context, "title"),
|
|
629
|
+
refs: refs.map((entry, index) => parseDesignerRefAttachment(entry, index))
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
function parseDesignerRefAttachment(value, index) {
|
|
633
|
+
const attachment = asObject(value, `designerRefs.refs[${index}]`);
|
|
634
|
+
return {
|
|
635
|
+
ref: parseDesignerRef(attachment.ref, index),
|
|
636
|
+
reason: optionalString(attachment, "reason") ?? "",
|
|
637
|
+
required: requiredBoolean(attachment, "required"),
|
|
638
|
+
source: optionalString(attachment, "source") ?? "",
|
|
639
|
+
lineageKind: optionalString(attachment, "lineageKind") ?? optionalString(attachment, "lineage_kind") ?? "",
|
|
640
|
+
inheritedFromItemType: optionalString(attachment, "inheritedFromItemType") ?? optionalString(attachment, "inherited_from_item_type"),
|
|
641
|
+
inheritedFromItemId: optionalString(attachment, "inheritedFromItemId") ?? optionalString(attachment, "inherited_from_item_id"),
|
|
642
|
+
inheritedFromDesignerRefId: optionalString(attachment, "inheritedFromDesignerRefId") ?? optionalString(attachment, "inherited_from_designer_ref_id"),
|
|
643
|
+
addedByLane: optionalString(attachment, "addedByLane") ?? optionalString(attachment, "added_by_lane") ?? "",
|
|
644
|
+
sortOrder: requiredNumber(attachment, "sortOrder"),
|
|
645
|
+
createdAt: requiredString(attachment, "createdAt")
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
function parseDesignerRef(value, index) {
|
|
649
|
+
const designerRef = asObject(value, `designerRefs.refs[${index}].ref`);
|
|
650
|
+
return {
|
|
651
|
+
id: requiredString(designerRef, "id"),
|
|
652
|
+
projectId: requiredString(designerRef, "projectId"),
|
|
653
|
+
repoId: requiredString(designerRef, "repoId"),
|
|
654
|
+
refKey: requiredString(designerRef, "refKey"),
|
|
655
|
+
kind: requiredString(designerRef, "kind"),
|
|
656
|
+
path: requiredString(designerRef, "path"),
|
|
657
|
+
anchor: optionalString(designerRef, "anchor"),
|
|
658
|
+
title: optionalString(designerRef, "title") ?? "",
|
|
659
|
+
contentHash: requiredString(designerRef, "contentHash"),
|
|
660
|
+
commitSha: requiredString(designerRef, "commitSha"),
|
|
661
|
+
createdAt: requiredString(designerRef, "createdAt")
|
|
662
|
+
};
|
|
663
|
+
}
|
|
390
664
|
function parseStringArray(value, label) {
|
|
391
665
|
if (!Array.isArray(value)) {
|
|
392
666
|
throw new Error(`${label} must be an array.`);
|
|
@@ -431,6 +705,34 @@ function parseArtifacts(value) {
|
|
|
431
705
|
};
|
|
432
706
|
});
|
|
433
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
|
+
}
|
|
434
736
|
function asObject(value, label) {
|
|
435
737
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
436
738
|
throw new Error(`${label} must be an object.`);
|
|
@@ -481,6 +783,16 @@ function optionalPositiveInteger(source, key) {
|
|
|
481
783
|
}
|
|
482
784
|
return value;
|
|
483
785
|
}
|
|
786
|
+
function optionalNonNegativeInteger(source, key) {
|
|
787
|
+
const value = source[key];
|
|
788
|
+
if (value === undefined || value === null) {
|
|
789
|
+
return null;
|
|
790
|
+
}
|
|
791
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
792
|
+
throw new Error(`${key} must be a non-negative integer when provided.`);
|
|
793
|
+
}
|
|
794
|
+
return value;
|
|
795
|
+
}
|
|
484
796
|
function requiredNumber(source, key) {
|
|
485
797
|
const value = source[key];
|
|
486
798
|
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
@@ -488,3 +800,10 @@ function requiredNumber(source, key) {
|
|
|
488
800
|
}
|
|
489
801
|
return value;
|
|
490
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
|
+
}
|
package/dist/shared/git/git.js
CHANGED
|
@@ -8,7 +8,8 @@ export class GitClient {
|
|
|
8
8
|
const result = await this.processRunner.run({
|
|
9
9
|
command: "git",
|
|
10
10
|
args,
|
|
11
|
-
cwd
|
|
11
|
+
cwd,
|
|
12
|
+
...(args.includes("-z") ? { rawOutput: true } : {}),
|
|
12
13
|
});
|
|
13
14
|
if (result.exitCode !== 0) {
|
|
14
15
|
throw new Error(`git ${args.join(" ")} failed: ${result.stderr.trim() || result.stdout.trim()}`);
|
|
@@ -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>;
|