@scarn/sdk 0.0.0-stage → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-0y2fy5en.js +166 -0
- package/dist/chunk-3ctaaseb.js +1456 -0
- package/dist/chunk-4ggr8af6.js +30 -0
- package/dist/chunk-5zsavw98.js +91 -0
- package/dist/chunk-63f90zky.js +39 -0
- package/dist/chunk-700xe701.js +100 -0
- package/dist/chunk-ar6hcj1r.js +35 -0
- package/dist/chunk-cdanncng.js +74 -0
- package/dist/chunk-dp86pa6m.js +68 -0
- package/dist/chunk-e1h021kq.js +86 -0
- package/dist/chunk-gds7w7zh.js +330 -0
- package/dist/chunk-k4y5qt4y.js +14 -0
- package/dist/chunk-mz53r914.js +300 -0
- package/dist/chunk-ngy1fdcx.js +57 -0
- package/dist/chunk-p7yrcmqm.js +322 -0
- package/dist/chunk-rt9tq4j6.js +116 -0
- package/dist/chunk-skzxcba3.js +14282 -0
- package/dist/chunk-vfeytkqx.js +1687 -0
- package/dist/chunk-y2pv8d6a.js +162 -0
- package/dist/chunk-y64skrwp.js +17 -0
- package/dist/chunk-yjtaq94c.js +1094 -0
- package/dist/chunk-zm72ksz0.js +256 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.js +58 -0
- package/dist/contracts/artifact-markers.d.ts +42 -0
- package/dist/contracts/artifact-markers.js +16 -0
- package/dist/contracts/artifacts.d.ts +67 -0
- package/dist/contracts/artifacts.js +27 -0
- package/dist/contracts/pipeline-document/built-ins.d.ts +23 -0
- package/dist/contracts/pipeline-document/conditions/operators.d.ts +8 -0
- package/dist/contracts/pipeline-document/index.d.ts +11 -0
- package/dist/contracts/pipeline-document/index.js +99 -0
- package/dist/contracts/pipeline-document/json.d.ts +35 -0
- package/dist/contracts/pipeline-document/routes.d.ts +16 -0
- package/dist/contracts/pipeline-document/schema.d.ts +780 -0
- package/dist/contracts/pipeline-document/step-contract.d.ts +11 -0
- package/dist/contracts/step-artifact-submissions.d.ts +71 -0
- package/dist/contracts/step-artifact-submissions.js +171 -0
- package/dist/defaults/atomic-json-file.d.ts +10 -0
- package/dist/defaults/auth-file.d.ts +14 -0
- package/dist/defaults/base-url.d.ts +1 -0
- package/dist/defaults/config-file.d.ts +46 -0
- package/dist/defaults/home-dir.d.ts +3 -0
- package/dist/defaults/index.d.ts +12 -0
- package/dist/defaults/index.js +1240 -0
- package/dist/defaults/legacy-config-migration.d.ts +27 -0
- package/dist/defaults/load-push-defaults.d.ts +25 -0
- package/dist/defaults/project-config.d.ts +32 -0
- package/dist/defaults/project-ref.d.ts +34 -0
- package/dist/definitions/artifacts/artifact.d.ts +62 -0
- package/dist/definitions/artifacts/index.d.ts +1 -0
- package/dist/definitions/pipelines/define-default-pipeline-assignment.d.ts +263 -0
- package/dist/definitions/pipelines/index.d.ts +3 -0
- package/dist/definitions/pipelines/index.js +26 -0
- package/dist/definitions/pipelines/pipeline-definitions-client.d.ts +208 -0
- package/dist/definitions/pipelines/work-item-fields.d.ts +93 -0
- package/dist/definitions/steps/compile-mcps.d.ts +34 -0
- package/dist/definitions/steps/define-code-step.d.ts +84 -0
- package/dist/definitions/steps/define-mcp.d.ts +79 -0
- package/dist/definitions/steps/define-step.d.ts +137 -0
- package/dist/definitions/steps/env.d.ts +136 -0
- package/dist/definitions/steps/index.d.ts +14 -0
- package/dist/definitions/steps/index.js +76 -0
- package/dist/definitions/steps/mcp-server-config.d.ts +102 -0
- package/dist/definitions/steps/prompt-template.d.ts +24 -0
- package/dist/definitions/steps/repo.d.ts +67 -0
- package/dist/definitions/steps/runtime.d.ts +115 -0
- package/dist/definitions/steps/step-definitions-client.d.ts +400 -0
- package/dist/definitions/steps/step-features.d.ts +109 -0
- package/dist/definitions/steps/step-handle.d.ts +25 -0
- package/dist/definitions/steps/step-ref.d.ts +19 -0
- package/dist/definitions/validation/index.d.ts +2 -0
- package/dist/definitions/validation/index.js +19 -0
- package/dist/definitions/validation/validate-artifact-markers.d.ts +3 -0
- package/dist/definitions/validation/validate-artifacts.d.ts +7 -0
- package/dist/definitions/validation/validate-definition-specs.d.ts +16 -0
- package/dist/definitions/validation/validate-env.d.ts +15 -0
- package/dist/definitions/validation/validate-repo.d.ts +13 -0
- package/dist/definitions/validation/validate-runtime.d.ts +12 -0
- package/dist/definitions/validation/validation-issue.d.ts +11 -0
- package/dist/devcontainer-config-path.d.ts +21 -0
- package/dist/devcontainer-config-path.js +15 -0
- package/dist/env-vars.d.ts +136 -0
- package/dist/env-vars.js +37 -0
- package/dist/eslint.d.ts +42 -0
- package/dist/eslint.js +127 -0
- package/dist/generated/client/client.gen.d.ts +2 -0
- package/dist/generated/client/index.d.ts +8 -0
- package/dist/generated/client/types.gen.d.ts +117 -0
- package/dist/generated/client/utils.gen.d.ts +33 -0
- package/dist/generated/client.gen.d.ts +12 -0
- package/dist/generated/core/auth.gen.d.ts +18 -0
- package/dist/generated/core/bodySerializer.gen.d.ts +25 -0
- package/dist/generated/core/params.gen.d.ts +43 -0
- package/dist/generated/core/pathSerializer.gen.d.ts +33 -0
- package/dist/generated/core/queryKeySerializer.gen.d.ts +18 -0
- package/dist/generated/core/serverSentEvents.gen.d.ts +71 -0
- package/dist/generated/core/types.gen.d.ts +78 -0
- package/dist/generated/core/utils.gen.d.ts +19 -0
- package/dist/generated/index.d.ts +2 -0
- package/dist/generated/sdk.gen.d.ts +302 -0
- package/dist/generated/types.gen.d.ts +18375 -0
- package/dist/git-url/git-remote.d.ts +30 -0
- package/dist/git-url/git-repo-identity.d.ts +44 -0
- package/dist/git-url/git-repo-identity.js +161 -0
- package/dist/git-url/parse-git-host.d.ts +23 -0
- package/dist/health-checks.d.ts +169 -0
- package/dist/health-checks.js +21 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +296 -0
- package/dist/jsonc.d.ts +3 -0
- package/dist/jsonc.js +12 -0
- package/dist/managed-runtimes.d.ts +20 -0
- package/dist/managed-runtimes.js +15 -0
- package/dist/opencode-mcp.d.ts +313 -0
- package/dist/opencode-mcp.js +31 -0
- package/dist/pipelines/chain.d.ts +7 -0
- package/dist/pipelines/compile-args.d.ts +12 -0
- package/dist/pipelines/compile-chain.d.ts +9 -0
- package/dist/pipelines/compile-checks.d.ts +16 -0
- package/dist/pipelines/compile-state.d.ts +30 -0
- package/dist/pipelines/condition-data.d.ts +78 -0
- package/dist/pipelines/conditions.d.ts +47 -0
- package/dist/pipelines/context.d.ts +16 -0
- package/dist/pipelines/define-pipeline.d.ts +32 -0
- package/dist/pipelines/each.d.ts +5 -0
- package/dist/pipelines/errors.d.ts +26 -0
- package/dist/pipelines/handles.d.ts +29 -0
- package/dist/pipelines/index.d.ts +18 -0
- package/dist/pipelines/index.js +83 -0
- package/dist/pipelines/model.d.ts +103 -0
- package/dist/pipelines/nodes.d.ts +54 -0
- package/dist/pipelines/ref-types.d.ts +54 -0
- package/dist/pipelines/refs.d.ts +80 -0
- package/dist/pipelines/registry.d.ts +12 -0
- package/dist/pipelines/source.d.ts +17 -0
- package/dist/pipelines/types.d.ts +160 -0
- package/dist/push/code-step-lookup.d.ts +32 -0
- package/dist/push/code-step-lookup.js +12 -0
- package/dist/push/collect-definitions.d.ts +70 -0
- package/dist/push/collect-pipeline-documents.d.ts +14 -0
- package/dist/push/index.d.ts +6 -0
- package/dist/push/index.js +327 -0
- package/dist/push/push-from-directory.d.ts +37 -0
- package/dist/repo-config.d.ts +80 -0
- package/dist/repo-config.js +25 -0
- package/dist/scarn-config-parser.d.ts +29 -0
- package/dist/scarn-config-parser.js +10 -0
- package/dist/task-plane-client.d.ts +489 -0
- package/dist/z.d.ts +7 -0
- package/package.json +132 -4
- package/README.md +0 -3
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
envVarsSchema
|
|
4
|
+
} from "./chunk-5zsavw98.js";
|
|
5
|
+
import {
|
|
6
|
+
devcontainerConfigPathSchema
|
|
7
|
+
} from "./chunk-4ggr8af6.js";
|
|
8
|
+
import {
|
|
9
|
+
MANAGED_RUNTIME_IDS,
|
|
10
|
+
isManagedRuntimeId
|
|
11
|
+
} from "./chunk-k4y5qt4y.js";
|
|
12
|
+
import {
|
|
13
|
+
repoConfigInputSchema,
|
|
14
|
+
repoRuntimeMismatch
|
|
15
|
+
} from "./chunk-cdanncng.js";
|
|
16
|
+
import {
|
|
17
|
+
findArtifactMarkers
|
|
18
|
+
} from "./chunk-ngy1fdcx.js";
|
|
19
|
+
import {
|
|
20
|
+
EMBEDDABLE_ARTIFACT_EXTENSIONS,
|
|
21
|
+
artifactPlatforms,
|
|
22
|
+
findArtifactFields
|
|
23
|
+
} from "./chunk-y2pv8d6a.js";
|
|
24
|
+
|
|
25
|
+
// src/definitions/validation/validate-artifacts.ts
|
|
26
|
+
function checkArtifactFields(steps) {
|
|
27
|
+
const issues = [];
|
|
28
|
+
for (const step of steps) {
|
|
29
|
+
for (const field of findArtifactFields(step.resultSchemaJson ?? null)) {
|
|
30
|
+
if (!field.inArray)
|
|
31
|
+
continue;
|
|
32
|
+
issues.push({
|
|
33
|
+
check: "artifact-field",
|
|
34
|
+
severity: "error",
|
|
35
|
+
message: `Step "${step.key}" declares artifact field "${field.path}" inside an ` + `array. Artifact fields in arrays aren't supported; declare a fixed ` + `number of named artifact fields instead.`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return issues;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// src/definitions/validation/validation-issue.ts
|
|
43
|
+
function listPaths(paths, limit = 24) {
|
|
44
|
+
if (paths.length === 0)
|
|
45
|
+
return "";
|
|
46
|
+
if (paths.length <= limit)
|
|
47
|
+
return paths.join(", ");
|
|
48
|
+
return `${paths.slice(0, limit).join(", ")}, \u2026 (${String(paths.length - limit)} more)`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/definitions/validation/validate-artifact-markers.ts
|
|
52
|
+
var isPlaceholder = (key) => /^<[^<>]*>$/.test(key);
|
|
53
|
+
function stepMarkers(step) {
|
|
54
|
+
if (!step.prompt)
|
|
55
|
+
return [];
|
|
56
|
+
return findArtifactMarkers(step.prompt).flatMap((marker) => marker.ref.type === "signal" && !isPlaceholder(marker.ref.stepKey) && !isPlaceholder(marker.ref.signalKey) ? [
|
|
57
|
+
{
|
|
58
|
+
kind: marker.kind,
|
|
59
|
+
stepKey: marker.ref.stepKey,
|
|
60
|
+
resultPath: marker.ref.signalKey
|
|
61
|
+
}
|
|
62
|
+
] : []);
|
|
63
|
+
}
|
|
64
|
+
var markerLabel = (marker) => `${marker.kind === "embed" ? "Artifact.embed" : "Artifact.link"}(` + `"signal/${marker.stepKey}/${marker.resultPath}")`;
|
|
65
|
+
function checkMarkerTargets(steps, stepsByKey) {
|
|
66
|
+
const issues = [];
|
|
67
|
+
const embeddable = new Set(artifactPlatforms.flatMap((platform) => [
|
|
68
|
+
...EMBEDDABLE_ARTIFACT_EXTENSIONS[platform]
|
|
69
|
+
]));
|
|
70
|
+
for (const step of steps) {
|
|
71
|
+
for (const marker of stepMarkers(step)) {
|
|
72
|
+
const targets = stepsByKey.get(marker.stepKey);
|
|
73
|
+
if (!targets)
|
|
74
|
+
continue;
|
|
75
|
+
const where = `Step "${step.key}" uses ${markerLabel(marker)}`;
|
|
76
|
+
for (const target of targets) {
|
|
77
|
+
if (!target.resultSchemaJson)
|
|
78
|
+
continue;
|
|
79
|
+
const fields = findArtifactFields(target.resultSchemaJson);
|
|
80
|
+
const field = fields.find((candidate) => candidate.path === marker.resultPath);
|
|
81
|
+
if (!field) {
|
|
82
|
+
const declared = fields.map((candidate) => candidate.path);
|
|
83
|
+
issues.push({
|
|
84
|
+
check: "artifact-marker",
|
|
85
|
+
severity: "error",
|
|
86
|
+
message: `${where}, but step "${target.key}" has no artifact field at ` + `"${marker.resultPath}". Artifact fields on "${target.key}": ` + `${declared.length > 0 ? listPaths(declared) : "(none)"}.`
|
|
87
|
+
});
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (marker.kind !== "embed")
|
|
91
|
+
continue;
|
|
92
|
+
const { accept } = field;
|
|
93
|
+
if (accept.length === 0)
|
|
94
|
+
continue;
|
|
95
|
+
if (accept.some((extension) => embeddable.has(extension)))
|
|
96
|
+
continue;
|
|
97
|
+
issues.push({
|
|
98
|
+
check: "artifact-marker",
|
|
99
|
+
severity: "warning",
|
|
100
|
+
message: `${where}, but the field accepts only ${accept.join(", ")}, which ` + `no platform can embed, so it will always be linked. Embeddable ` + `extensions: ${[...embeddable].join(", ")}.`
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return issues;
|
|
106
|
+
}
|
|
107
|
+
function checkArtifactMarkers(steps, stepsByKey) {
|
|
108
|
+
return checkMarkerTargets(steps, stepsByKey);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/definitions/validation/validate-env.ts
|
|
112
|
+
function checkEnv(steps) {
|
|
113
|
+
const issues = [];
|
|
114
|
+
for (const step of steps) {
|
|
115
|
+
if (!step.envJson)
|
|
116
|
+
continue;
|
|
117
|
+
issues.push(...checkEnvMcpOwners(step));
|
|
118
|
+
issues.push(...checkEnvApplies(step));
|
|
119
|
+
const result = envVarsSchema.safeParse(step.envJson);
|
|
120
|
+
if (result.success)
|
|
121
|
+
continue;
|
|
122
|
+
for (const issue of result.error.issues) {
|
|
123
|
+
const [index, ...field] = issue.path;
|
|
124
|
+
const entry = typeof index === "number" ? step.envJson[index] : undefined;
|
|
125
|
+
const where = typeof index === "number" && entry ? `Step "${step.key}" env var #${String(index + 1)} ("${entry.name}")` : `Step "${step.key}" env`;
|
|
126
|
+
const fieldLabel = field.length > 0 ? ` ${field.map(String).join(".")}` : "";
|
|
127
|
+
issues.push({
|
|
128
|
+
check: "env-var",
|
|
129
|
+
severity: "error",
|
|
130
|
+
message: `${where}${fieldLabel}: ${issue.message}`
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return issues;
|
|
135
|
+
}
|
|
136
|
+
function checkEnvMcpOwners(step) {
|
|
137
|
+
const serverKeys = Object.keys(step.opencodeMcpJson ?? {}).sort();
|
|
138
|
+
const serverKeySet = new Set(serverKeys);
|
|
139
|
+
const issues = [];
|
|
140
|
+
(step.envJson ?? []).forEach((entry, index) => {
|
|
141
|
+
if (entry.source !== "inherit" || entry.mcp === undefined)
|
|
142
|
+
return;
|
|
143
|
+
if (serverKeySet.has(entry.mcp))
|
|
144
|
+
return;
|
|
145
|
+
issues.push({
|
|
146
|
+
check: "env-var-mcp",
|
|
147
|
+
severity: "error",
|
|
148
|
+
message: `Step "${step.key}" env var #${String(index + 1)} ("${entry.name}") ` + `belongs to MCP server "${entry.mcp}", but the step declares no MCP ` + `server with that key. Declared servers: ` + `${serverKeys.length > 0 ? listPaths(serverKeys) : "(none)"}.`
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
return issues;
|
|
152
|
+
}
|
|
153
|
+
function checkEnvApplies(step) {
|
|
154
|
+
const issues = [];
|
|
155
|
+
(step.envJson ?? []).forEach((entry, index) => {
|
|
156
|
+
const applies = entry.applies ?? "agent";
|
|
157
|
+
if (applies === "agent")
|
|
158
|
+
return;
|
|
159
|
+
const where = `Step "${step.key}" env var #${String(index + 1)} ("${entry.name}") applies "${applies}"`;
|
|
160
|
+
if (step.executionMode === "no_workspace") {
|
|
161
|
+
issues.push({
|
|
162
|
+
check: "env-var-applies",
|
|
163
|
+
severity: "error",
|
|
164
|
+
message: `${where}: setup variables reach devcontainer up, but the step runs on the host (executionMode "no_workspace") with no container to set up. Use applies "agent" or Runtime.devcontainer().`
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
if (entry.source === "inherit" && entry.mcp !== undefined) {
|
|
168
|
+
issues.push({
|
|
169
|
+
check: "env-var-applies",
|
|
170
|
+
severity: "error",
|
|
171
|
+
message: `${where}: it belongs to MCP server "${entry.mcp}", and MCP servers run inside the agent. Use applies "agent".`
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
return issues;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// src/definitions/validation/validate-repo.ts
|
|
179
|
+
function checkRepo(steps) {
|
|
180
|
+
const issues = [];
|
|
181
|
+
for (const step of steps) {
|
|
182
|
+
if (!step.repo)
|
|
183
|
+
continue;
|
|
184
|
+
const where = `Step "${step.key}" repo`;
|
|
185
|
+
const parsed = repoConfigInputSchema.safeParse(step.repo);
|
|
186
|
+
if (!parsed.success) {
|
|
187
|
+
for (const issue of parsed.error.issues) {
|
|
188
|
+
const field = issue.path.map(String).join(".");
|
|
189
|
+
issues.push({
|
|
190
|
+
check: "repo",
|
|
191
|
+
severity: "error",
|
|
192
|
+
message: `${where}${field ? ` ${field}` : ""}: ${issue.message}`
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const executionMode = step.executionMode ?? "workspace";
|
|
198
|
+
const mismatch = repoRuntimeMismatch(executionMode, parsed.data.mode);
|
|
199
|
+
if (mismatch === null)
|
|
200
|
+
continue;
|
|
201
|
+
issues.push({
|
|
202
|
+
check: "repo",
|
|
203
|
+
severity: "error",
|
|
204
|
+
message: `${where} "${parsed.data.mode}" cannot be used with executionMode "${executionMode}": ${mismatch}.`
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return issues;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/definitions/validation/validate-runtime.ts
|
|
211
|
+
function checkRuntime(steps) {
|
|
212
|
+
const issues = [];
|
|
213
|
+
for (const step of steps) {
|
|
214
|
+
if (step.kind === "code" && step.executionMode === "no_workspace") {
|
|
215
|
+
issues.push({
|
|
216
|
+
check: "runtime",
|
|
217
|
+
severity: "error",
|
|
218
|
+
message: `Step "${step.key}": code steps run repo code and need a workspace, so Runtime.host() (executionMode "no_workspace") is not supported for codeStep. Use Runtime.managed.<id>() or Runtime.devcontainer(), or drop the runtime.`
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
issues.push(...checkManagedRuntime(step));
|
|
222
|
+
if (step.devcontainerConfigPath == null)
|
|
223
|
+
continue;
|
|
224
|
+
const where = `Step "${step.key}" devcontainerConfigPath "${step.devcontainerConfigPath}"`;
|
|
225
|
+
if (step.executionMode === "no_workspace") {
|
|
226
|
+
issues.push({
|
|
227
|
+
check: "runtime",
|
|
228
|
+
severity: "error",
|
|
229
|
+
message: `${where}: a devcontainer config needs a workspace, but the step runs on the host (executionMode "no_workspace"). Use Runtime.devcontainer({ config }) or drop the config.`
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
const result = devcontainerConfigPathSchema.safeParse(step.devcontainerConfigPath);
|
|
233
|
+
if (result.success)
|
|
234
|
+
continue;
|
|
235
|
+
for (const issue of result.error.issues) {
|
|
236
|
+
issues.push({
|
|
237
|
+
check: "runtime",
|
|
238
|
+
severity: "error",
|
|
239
|
+
message: `${where}: ${issue.message}`
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return issues;
|
|
244
|
+
}
|
|
245
|
+
function checkManagedRuntime(step) {
|
|
246
|
+
if (step.managedRuntime == null)
|
|
247
|
+
return [];
|
|
248
|
+
const where = `Step "${step.key}" managedRuntime "${step.managedRuntime}"`;
|
|
249
|
+
const problems = [];
|
|
250
|
+
if (!isManagedRuntimeId(step.managedRuntime)) {
|
|
251
|
+
problems.push(`unknown managed runtime; expected one of ${MANAGED_RUNTIME_IDS.join(", ")}`);
|
|
252
|
+
}
|
|
253
|
+
if (step.kind !== "code") {
|
|
254
|
+
problems.push("managed runtimes are only supported for code steps. Use Runtime.devcontainer() or Runtime.host() for defineStep");
|
|
255
|
+
}
|
|
256
|
+
if (step.executionMode === "no_workspace") {
|
|
257
|
+
problems.push('a managed runtime needs a workspace, but the step runs on the host (executionMode "no_workspace")');
|
|
258
|
+
}
|
|
259
|
+
if (step.devcontainerConfigPath != null) {
|
|
260
|
+
problems.push("cannot be combined with devcontainerConfigPath. Use either Runtime.managed.<id>() or Runtime.devcontainer({ config })");
|
|
261
|
+
}
|
|
262
|
+
return problems.map((problem) => ({
|
|
263
|
+
check: "runtime",
|
|
264
|
+
severity: "error",
|
|
265
|
+
message: `${where}: ${problem}.`
|
|
266
|
+
}));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/definitions/validation/validate-definition-specs.ts
|
|
270
|
+
function checkHealthChecks(steps) {
|
|
271
|
+
const issues = [];
|
|
272
|
+
for (const step of steps) {
|
|
273
|
+
const checks = step.healthChecksJson ?? [];
|
|
274
|
+
if (checks.length === 0)
|
|
275
|
+
continue;
|
|
276
|
+
const mcpServerKeys = Object.keys(step.opencodeMcpJson ?? {});
|
|
277
|
+
const mcpServerKeySet = new Set(mcpServerKeys);
|
|
278
|
+
checks.forEach((check, index) => {
|
|
279
|
+
if (check.kind === "cli")
|
|
280
|
+
return;
|
|
281
|
+
const label = check.name ?? check.tool;
|
|
282
|
+
const where = `Step "${step.key}" health check #${String(index + 1)} ("${label}")`;
|
|
283
|
+
if (!check.mcp)
|
|
284
|
+
return;
|
|
285
|
+
if (!mcpServerKeySet.has(check.mcp)) {
|
|
286
|
+
issues.push({
|
|
287
|
+
check: "health-check-mcp-server",
|
|
288
|
+
severity: "error",
|
|
289
|
+
message: `${where} names MCP server "${check.mcp}", but the step declares no ` + `such server in mcps. Declared servers: ${mcpServerKeys.length > 0 ? listPaths([...mcpServerKeys].sort()) : "(none)"}.`
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
const prefix = `${check.mcp}_`;
|
|
293
|
+
if (check.tool.startsWith(prefix)) {
|
|
294
|
+
issues.push({
|
|
295
|
+
check: "health-check-double-qualified",
|
|
296
|
+
severity: "error",
|
|
297
|
+
message: `${where} sets mcp "${check.mcp}" and tool "${check.tool}", which already ` + `starts with "${prefix}". When "mcp" is set, "tool" should be the bare tool ` + `name \u2014 OpenCode resolves it to "${prefix}${check.tool}". Did you mean ` + `tool: "${check.tool.slice(prefix.length)}"?`
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return issues;
|
|
303
|
+
}
|
|
304
|
+
function validateDefinitionSpecs(steps) {
|
|
305
|
+
const stepsByKey = new Map;
|
|
306
|
+
for (const step of steps) {
|
|
307
|
+
const existing = stepsByKey.get(step.key);
|
|
308
|
+
if (existing)
|
|
309
|
+
existing.push(step);
|
|
310
|
+
else
|
|
311
|
+
stepsByKey.set(step.key, [step]);
|
|
312
|
+
}
|
|
313
|
+
return [
|
|
314
|
+
...checkArtifactFields(steps),
|
|
315
|
+
...checkArtifactMarkers(steps, stepsByKey),
|
|
316
|
+
...checkHealthChecks(steps),
|
|
317
|
+
...checkEnv(steps),
|
|
318
|
+
...checkRuntime(steps),
|
|
319
|
+
...checkRepo(steps)
|
|
320
|
+
];
|
|
321
|
+
}
|
|
322
|
+
function assertValidDefinitionSpecs(steps) {
|
|
323
|
+
const issues = validateDefinitionSpecs(steps).filter((issue) => issue.severity === "error");
|
|
324
|
+
if (issues.length === 0)
|
|
325
|
+
return;
|
|
326
|
+
const header = issues.length === 1 ? "Definition validation failed:" : `Definition validation failed with ${String(issues.length)} problems:`;
|
|
327
|
+
throw new Error([header, ...issues.map((issue) => ` \u2022 ${issue.message}`)].join(`
|
|
328
|
+
`));
|
|
329
|
+
}
|
|
330
|
+
export { listPaths, validateDefinitionSpecs, assertValidDefinitionSpecs };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
exports_external
|
|
4
|
+
} from "./chunk-skzxcba3.js";
|
|
5
|
+
|
|
6
|
+
// src/managed-runtimes.ts
|
|
7
|
+
var MANAGED_RUNTIME_IDS = ["bun1", "node24"];
|
|
8
|
+
var DEFAULT_CODE_STEP_RUNTIME_ID = "bun1";
|
|
9
|
+
var managedRuntimeIdSchema = exports_external.enum(MANAGED_RUNTIME_IDS);
|
|
10
|
+
function isManagedRuntimeId(value) {
|
|
11
|
+
return MANAGED_RUNTIME_IDS.includes(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { MANAGED_RUNTIME_IDS, DEFAULT_CODE_STEP_RUNTIME_ID, managedRuntimeIdSchema, isManagedRuntimeId };
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/pipelines/source.ts
|
|
3
|
+
var FRAME = /\(?((?:file:\/\/)?[^\s()]+):(\d+):(\d+)\)?\s*$/;
|
|
4
|
+
function sdkRoot() {
|
|
5
|
+
const here = new URL(import.meta.url).pathname;
|
|
6
|
+
const parts = here.split("/");
|
|
7
|
+
return parts.slice(0, -2).join("/") + "/";
|
|
8
|
+
}
|
|
9
|
+
var SDK_ROOT = sdkRoot();
|
|
10
|
+
function toPath(file) {
|
|
11
|
+
return file.startsWith("file://") ? new URL(file).pathname : file;
|
|
12
|
+
}
|
|
13
|
+
function parseFrame(frame) {
|
|
14
|
+
const match = FRAME.exec(frame.trim());
|
|
15
|
+
if (match === null) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const [, file, line, column] = match;
|
|
19
|
+
if (file === undefined || line === undefined || column === undefined) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return { file: toPath(file), line: Number(line), column: Number(column) };
|
|
23
|
+
}
|
|
24
|
+
function captureSite(stack = new Error().stack) {
|
|
25
|
+
for (const frame of (stack ?? "").split(`
|
|
26
|
+
`).slice(1)) {
|
|
27
|
+
const site = parseFrame(frame);
|
|
28
|
+
if (site !== null && !site.file.startsWith(SDK_ROOT) && !site.file.startsWith("node:") && site.file.includes("/")) {
|
|
29
|
+
return site;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
function cwd() {
|
|
35
|
+
const proc = globalThis.process;
|
|
36
|
+
return typeof proc?.cwd === "function" ? proc.cwd() : null;
|
|
37
|
+
}
|
|
38
|
+
function formatSite(site) {
|
|
39
|
+
if (site === null) {
|
|
40
|
+
return "<unknown>";
|
|
41
|
+
}
|
|
42
|
+
const base = cwd();
|
|
43
|
+
const file = base !== null && site.file.startsWith(`${base}/`) ? site.file.slice(base.length + 1) : site.file;
|
|
44
|
+
return `${file}:${String(site.line)}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/pipelines/errors.ts
|
|
48
|
+
function formatIssue(issue) {
|
|
49
|
+
return `${formatSite(issue.site)} (${issue.pointer === "" ? "/" : issue.pointer}): ${issue.message}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
class PipelineBuildError extends Error {
|
|
53
|
+
issues;
|
|
54
|
+
constructor(key, issues) {
|
|
55
|
+
super(`Pipeline "${key}" has ${String(issues.length)} build error${issues.length === 1 ? "" : "s"}:
|
|
56
|
+
${issues.map((issue) => ` ${formatIssue(issue)}`).join(`
|
|
57
|
+
`)}`);
|
|
58
|
+
this.name = "PipelineBuildError";
|
|
59
|
+
this.issues = issues;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class AuthoringError extends Error {
|
|
64
|
+
site;
|
|
65
|
+
constructor(message, site = captureSite()) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "AuthoringError";
|
|
68
|
+
this.site = site;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/pipelines/registry.ts
|
|
73
|
+
var nodes = new WeakMap;
|
|
74
|
+
var targets = new WeakMap;
|
|
75
|
+
var eaches = new WeakMap;
|
|
76
|
+
var chains = new WeakMap;
|
|
77
|
+
var pendingChains = new Set;
|
|
78
|
+
function registerNode(value, node) {
|
|
79
|
+
nodes.set(value, node);
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
function registerTarget(value, target) {
|
|
83
|
+
targets.set(value, target);
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
function registerEach(value, each) {
|
|
87
|
+
eaches.set(value, each);
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
function registerChain(value, chain) {
|
|
91
|
+
chains.set(value, chain);
|
|
92
|
+
if (chain.next !== undefined) {
|
|
93
|
+
pendingChains.add(chain);
|
|
94
|
+
}
|
|
95
|
+
return value;
|
|
96
|
+
}
|
|
97
|
+
function isObject(value) {
|
|
98
|
+
return (typeof value === "object" || typeof value === "function") && value !== null;
|
|
99
|
+
}
|
|
100
|
+
function nodeOf(value) {
|
|
101
|
+
return isObject(value) ? nodes.get(value) : undefined;
|
|
102
|
+
}
|
|
103
|
+
function targetOf(value) {
|
|
104
|
+
return isObject(value) ? targets.get(value) : undefined;
|
|
105
|
+
}
|
|
106
|
+
function eachOf(value) {
|
|
107
|
+
return isObject(value) ? eaches.get(value) : undefined;
|
|
108
|
+
}
|
|
109
|
+
function chainOf(value) {
|
|
110
|
+
return isObject(value) ? chains.get(value) : undefined;
|
|
111
|
+
}
|
|
112
|
+
function requireNode(value, what) {
|
|
113
|
+
const node = nodeOf(value);
|
|
114
|
+
if (node === undefined) {
|
|
115
|
+
throw new AuthoringError(`${what} must be a step, decision or reply handle`);
|
|
116
|
+
}
|
|
117
|
+
return node;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// src/pipelines/model.ts
|
|
121
|
+
function emptyChain(node) {
|
|
122
|
+
return {
|
|
123
|
+
node,
|
|
124
|
+
settings: {},
|
|
125
|
+
retry: [],
|
|
126
|
+
catch: [],
|
|
127
|
+
next: undefined,
|
|
128
|
+
site: captureSite()
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/pipelines/chain.ts
|
|
133
|
+
function next(data, change) {
|
|
134
|
+
return chainValue({ ...data, ...change, site: captureSite() });
|
|
135
|
+
}
|
|
136
|
+
function assertOpen(data, method) {
|
|
137
|
+
if (data.next !== undefined) {
|
|
138
|
+
throw new AuthoringError(`.${method}() can't follow .next(): the chain for "${data.node.id}" is already finished`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function isTargetSpec(value) {
|
|
142
|
+
return typeof value === "function" || nodeOf(value) !== undefined || targetOf(value) !== undefined || eachOf(value) !== undefined || chainOf(value) !== undefined;
|
|
143
|
+
}
|
|
144
|
+
function nextData(id, arg) {
|
|
145
|
+
const site = captureSite();
|
|
146
|
+
if (isTargetSpec(arg) || !("routes" in arg)) {
|
|
147
|
+
return {
|
|
148
|
+
match: undefined,
|
|
149
|
+
routes: [{ when: undefined, target: arg }],
|
|
150
|
+
otherwise: undefined,
|
|
151
|
+
site
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
const options = arg;
|
|
155
|
+
if (options.match !== undefined && options.match !== "first" && options.match !== "all") {
|
|
156
|
+
throw new AuthoringError(`.next() for "${id}": match "${options.match}" isn't supported; use "first" or "all"`);
|
|
157
|
+
}
|
|
158
|
+
if (options.routes === undefined || options.routes.length === 0) {
|
|
159
|
+
throw new AuthoringError(`.next() for "${id}" needs at least one route in "routes"`);
|
|
160
|
+
}
|
|
161
|
+
const routes = options.routes.map((route, index) => {
|
|
162
|
+
if (route.to === undefined) {
|
|
163
|
+
throw new AuthoringError(`.next() for "${id}": route ${String(index)} has no "to"`);
|
|
164
|
+
}
|
|
165
|
+
return { when: route.when, target: route.to };
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
match: options.match === "all" ? "all" : undefined,
|
|
169
|
+
routes,
|
|
170
|
+
otherwise: options.otherwise,
|
|
171
|
+
site
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function chainMethods(data) {
|
|
175
|
+
return {
|
|
176
|
+
settings: (settings) => {
|
|
177
|
+
const current = data();
|
|
178
|
+
assertOpen(current, "settings");
|
|
179
|
+
return next(current, { settings: { ...settings } });
|
|
180
|
+
},
|
|
181
|
+
retry: (options) => {
|
|
182
|
+
const current = data();
|
|
183
|
+
assertOpen(current, "retry");
|
|
184
|
+
if (current.node.kind !== "step") {
|
|
185
|
+
throw new AuthoringError(`"${current.node.id}" is a wait and can't retry`);
|
|
186
|
+
}
|
|
187
|
+
return next(current, {
|
|
188
|
+
retry: [
|
|
189
|
+
...current.retry,
|
|
190
|
+
{ on: [...options.on], maxAttempts: options.maxAttempts }
|
|
191
|
+
]
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
catch: (on, target) => {
|
|
195
|
+
const current = data();
|
|
196
|
+
assertOpen(current, "catch");
|
|
197
|
+
return next(current, {
|
|
198
|
+
catch: [...current.catch, { on: [...on], target, site: captureSite() }]
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
next: (arg) => {
|
|
202
|
+
const current = data();
|
|
203
|
+
assertOpen(current, "next");
|
|
204
|
+
return next(current, { next: nextData(current.node.id, arg) });
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function chainValue(data) {
|
|
209
|
+
return registerChain(Object.freeze({
|
|
210
|
+
_tag: "pipeline_chain",
|
|
211
|
+
node: data.node.id,
|
|
212
|
+
...chainMethods(() => data)
|
|
213
|
+
}), data);
|
|
214
|
+
}
|
|
215
|
+
var HANDLE_METHODS = ["settings", "retry", "catch", "next"];
|
|
216
|
+
function attachChainMethods(handle, node) {
|
|
217
|
+
const methods = chainMethods(() => emptyChain(node));
|
|
218
|
+
for (const name of HANDLE_METHODS) {
|
|
219
|
+
if (node.kind !== "step" && name === "retry") {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
Object.defineProperty(handle, name, {
|
|
223
|
+
value: methods[name],
|
|
224
|
+
enumerable: false,
|
|
225
|
+
configurable: true
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// src/pipelines/handles.ts
|
|
231
|
+
function checkArgs(node, args) {
|
|
232
|
+
if (args !== undefined && (typeof args !== "object" || args === null)) {
|
|
233
|
+
throw new AuthoringError(`args for "${node.id}" must be an object`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function targetFn(node) {
|
|
237
|
+
return (args) => {
|
|
238
|
+
checkArgs(node, args);
|
|
239
|
+
return registerTarget(Object.freeze({ _tag: "pipeline_target", to: node.id }), { node, args, site: captureSite() });
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function partialFn(node) {
|
|
243
|
+
return (args) => {
|
|
244
|
+
checkArgs(node, args);
|
|
245
|
+
return registerTarget(Object.freeze({ _tag: "pipeline_partial", to: node.id }), { node, args, site: captureSite(), partial: true });
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function makeHandle(handle, node) {
|
|
249
|
+
attachChainMethods(handle, node);
|
|
250
|
+
registerNode(handle, node);
|
|
251
|
+
Object.defineProperty(handle, "partial", {
|
|
252
|
+
value: partialFn(node),
|
|
253
|
+
enumerable: false,
|
|
254
|
+
configurable: true
|
|
255
|
+
});
|
|
256
|
+
if (node.kind === "step") {
|
|
257
|
+
Object.defineProperty(handle, "as", {
|
|
258
|
+
value: (id) => stepHandleFor({ ...node, id, site: captureSite() }),
|
|
259
|
+
enumerable: false,
|
|
260
|
+
configurable: true
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
return handle;
|
|
264
|
+
}
|
|
265
|
+
function stepHandleFor(node) {
|
|
266
|
+
const handle = targetFn(node);
|
|
267
|
+
if (node.kind === "step") {
|
|
268
|
+
Object.defineProperties(handle, {
|
|
269
|
+
key: { value: node.step, enumerable: true },
|
|
270
|
+
inputSchemaJson: { value: node.inputSchema, enumerable: true },
|
|
271
|
+
resultSchemaJson: { value: node.resultSchema, enumerable: true },
|
|
272
|
+
errors: { value: node.errors, enumerable: true }
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return makeHandle(handle, node);
|
|
276
|
+
}
|
|
277
|
+
function stepNode(source, local = true) {
|
|
278
|
+
return {
|
|
279
|
+
kind: "step",
|
|
280
|
+
id: source.key,
|
|
281
|
+
step: source.key,
|
|
282
|
+
local,
|
|
283
|
+
inputSchema: source.inputSchemaJson ?? null,
|
|
284
|
+
resultSchema: source.resultSchemaJson ?? null,
|
|
285
|
+
conversation: local && source.kind !== "code" && source.resultSchemaJson === null,
|
|
286
|
+
errors: [...source.errors ?? []],
|
|
287
|
+
site: captureSite()
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
function stepCall(node) {
|
|
291
|
+
return targetFn(node);
|
|
292
|
+
}
|
|
293
|
+
function waitHandle(node) {
|
|
294
|
+
return makeHandle(targetFn(node), node);
|
|
295
|
+
}
|
|
296
|
+
function bareStepHandle(source, local) {
|
|
297
|
+
return stepHandleFor(stepNode(source, local));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { captureSite, formatIssue, PipelineBuildError, AuthoringError, pendingChains, registerNode, registerTarget, registerEach, nodeOf, targetOf, eachOf, chainOf, requireNode, makeHandle, stepNode, stepCall, waitHandle, bareStepHandle };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/contracts/artifact-markers.ts
|
|
3
|
+
var ARTIFACT_MARKER_SCHEME = "artifact:";
|
|
4
|
+
var SIGNAL_REF_PREFIX = "signal/";
|
|
5
|
+
var MARKER_PATTERN = /(!?)\[((?:\\.|[^\\\]\n])*)\]\((?:<artifact:((?:\\.|[^\\<>\n])*)>|artifact:((?:\\.|[^\\()\s])*))\)/g;
|
|
6
|
+
var unescapeMarkerText = (value) => value.replace(/\\(.)/g, "$1");
|
|
7
|
+
var escapeMarkerText = (value) => value.replace(/\s+/g, " ").trim().replace(/[\\[\]]/g, "\\$&");
|
|
8
|
+
var formatMarkerDestination = (rawRef) => {
|
|
9
|
+
if (/[\s<>]/.test(rawRef)) {
|
|
10
|
+
if (/[\n\r]/.test(rawRef)) {
|
|
11
|
+
throw new Error("Artifact marker refs cannot contain line breaks.");
|
|
12
|
+
}
|
|
13
|
+
return `<${ARTIFACT_MARKER_SCHEME}${rawRef.replace(/[\\<>]/g, "\\$&")}>`;
|
|
14
|
+
}
|
|
15
|
+
return `${ARTIFACT_MARKER_SCHEME}${rawRef.replace(/[\\()]/g, "\\$&")}`;
|
|
16
|
+
};
|
|
17
|
+
function parseArtifactMarkerRef(rawRef) {
|
|
18
|
+
if (!rawRef.startsWith(SIGNAL_REF_PREFIX)) {
|
|
19
|
+
return { type: "path", pattern: rawRef };
|
|
20
|
+
}
|
|
21
|
+
const rest = rawRef.slice(SIGNAL_REF_PREFIX.length);
|
|
22
|
+
const slash = rest.indexOf("/");
|
|
23
|
+
return slash === -1 ? { type: "signal", stepKey: rest, signalKey: "" } : {
|
|
24
|
+
type: "signal",
|
|
25
|
+
stepKey: rest.slice(0, slash),
|
|
26
|
+
signalKey: rest.slice(slash + 1)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function formatArtifactMarkerRef(ref) {
|
|
30
|
+
return ref.type === "signal" ? `${SIGNAL_REF_PREFIX}${ref.stepKey}/${ref.signalKey}` : ref.pattern;
|
|
31
|
+
}
|
|
32
|
+
function buildArtifactMarker(kind, ref, text) {
|
|
33
|
+
const rawRef = formatArtifactMarkerRef(ref);
|
|
34
|
+
if (rawRef.length === 0) {
|
|
35
|
+
throw new Error("Artifact marker refs cannot be empty.");
|
|
36
|
+
}
|
|
37
|
+
const bang = kind === "embed" ? "!" : "";
|
|
38
|
+
return `${bang}[${escapeMarkerText(text)}](${formatMarkerDestination(rawRef)})`;
|
|
39
|
+
}
|
|
40
|
+
function findArtifactMarkers(text) {
|
|
41
|
+
const matches = [];
|
|
42
|
+
for (const match of text.matchAll(MARKER_PATTERN)) {
|
|
43
|
+
const [whole, bang, label, bracketedRef, bareRef] = match;
|
|
44
|
+
const rawRef = unescapeMarkerText(bracketedRef ?? bareRef ?? "");
|
|
45
|
+
matches.push({
|
|
46
|
+
kind: bang === "!" ? "embed" : "link",
|
|
47
|
+
text: unescapeMarkerText(label ?? ""),
|
|
48
|
+
rawRef,
|
|
49
|
+
ref: parseArtifactMarkerRef(rawRef),
|
|
50
|
+
start: match.index,
|
|
51
|
+
end: match.index + whole.length
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return matches;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { ARTIFACT_MARKER_SCHEME, parseArtifactMarkerRef, formatArtifactMarkerRef, buildArtifactMarker, findArtifactMarkers };
|