@kitman-sh/sdk 0.9.0 → 0.10.53

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.
Files changed (63) hide show
  1. package/dist/build/index.js +531 -116
  2. package/dist/{chunk-36jhc745.js → chunk-tcbgb4wm.js} +1841 -1574
  3. package/dist/{chunk-e1tqypyy.js → chunk-zvzw3zs4.js} +824 -419
  4. package/dist/loop/index.js +117 -3
  5. package/dist/program/index.js +8 -4
  6. package/package.json +6 -6
  7. package/types/packages/core/src/agent-capabilities.d.ts +6 -0
  8. package/types/packages/core/src/agent-environment.d.ts +32 -216
  9. package/types/packages/core/src/agent-sandbox-policy.d.ts +17 -3
  10. package/types/packages/core/src/change-request-review.d.ts +20 -5
  11. package/types/packages/core/src/change-request.d.ts +33 -208
  12. package/types/packages/core/src/crypto.d.ts +2 -0
  13. package/types/packages/core/src/index.d.ts +8 -4
  14. package/types/packages/core/src/{package-declarations.d.ts → kit-declarations.d.ts} +84 -180
  15. package/types/packages/core/src/kit-install.d.ts +130 -0
  16. package/types/packages/core/src/kit-setup.d.ts +316 -0
  17. package/types/packages/core/src/kit.d.ts +302 -1444
  18. package/types/packages/core/src/loop-layers.d.ts +33 -4
  19. package/types/packages/core/src/loop.d.ts +325 -55
  20. package/types/packages/core/src/marketplace.d.ts +51 -10
  21. package/types/packages/core/src/my-teams.d.ts +135 -20
  22. package/types/packages/core/src/network-host.d.ts +41 -0
  23. package/types/packages/core/src/notification.d.ts +8 -0
  24. package/types/packages/core/src/npm-registry.d.ts +65 -0
  25. package/types/packages/core/src/proposal.d.ts +0 -76
  26. package/types/packages/core/src/push.d.ts +68 -0
  27. package/types/packages/core/src/question-recommendation.d.ts +28 -0
  28. package/types/packages/core/src/redaction.d.ts +15 -3
  29. package/types/packages/core/src/resource-claim.d.ts +79 -0
  30. package/types/packages/core/src/run-display.d.ts +7 -1
  31. package/types/packages/core/src/run-graph.d.ts +1 -1
  32. package/types/packages/core/src/run-launch.d.ts +15 -2
  33. package/types/packages/core/src/run-queue.d.ts +28 -0
  34. package/types/packages/core/src/runner-eligibility.d.ts +21 -2
  35. package/types/packages/core/src/runner.d.ts +46 -15
  36. package/types/packages/core/src/secret.d.ts +18 -1
  37. package/types/packages/core/src/step-brief.d.ts +21 -7
  38. package/types/packages/core/src/sync-kit.d.ts +8 -0
  39. package/types/packages/core/src/task-detail.d.ts +15 -2
  40. package/types/packages/core/src/task.d.ts +9 -0
  41. package/types/packages/core/src/transcript.d.ts +24 -4
  42. package/types/packages/core/src/trust-panel.d.ts +1 -1
  43. package/types/packages/core/src/waiting-on.d.ts +14 -0
  44. package/types/packages/core/src/work-unit.d.ts +339 -8
  45. package/types/packages/live/src/rpc/runner-client.d.ts +505 -10
  46. package/types/packages/live/src/rpc/runner-group.d.ts +958 -28
  47. package/types/packages/sdk/src/build/index.d.ts +45 -9
  48. package/types/packages/sdk/src/loop/activities.d.ts +382 -2
  49. package/types/packages/sdk/src/loop/claims.d.ts +57 -0
  50. package/types/packages/sdk/src/loop/config.d.ts +38 -31
  51. package/types/packages/sdk/src/loop/continuing.d.ts +22 -0
  52. package/types/packages/sdk/src/loop/define.d.ts +30 -5
  53. package/types/packages/sdk/src/loop/evidence.d.ts +18 -3
  54. package/types/packages/sdk/src/loop/index.d.ts +4 -0
  55. package/types/packages/sdk/src/loop/measure.d.ts +132 -0
  56. package/types/packages/sdk/src/loop/plan.d.ts +2 -2
  57. package/types/packages/sdk/src/loop/steps.d.ts +127 -17
  58. package/types/packages/sdk/src/loop/sync.d.ts +53 -0
  59. package/types/packages/sdk/src/loop/test-loop.d.ts +25 -5
  60. package/types/packages/sdk/src/program/engine.d.ts +95 -3
  61. package/types/packages/sdk/src/program/host.d.ts +198 -36
  62. package/types/packages/core/src/engineering-resources.d.ts +0 -24
  63. package/types/packages/core/src/package.d.ts +0 -369
@@ -1,81 +1,229 @@
1
1
  // @bun
2
2
  import {
3
+ canonicalJson,
4
+ KitDigest,
3
5
  AgentDeclaration,
4
- KitInstallationDeclaration,
5
- KitAssignmentDeclaration,
6
- PackageDeclarations
7
- } from "../chunk-36jhc745.js";
6
+ KitDeclarations
7
+ } from "../chunk-tcbgb4wm.js";
8
8
  import {
9
9
  digestSha256,
10
+ digestSha512,
11
+ digestWith,
12
+ kitmanMcpServer,
10
13
  RunnerRpcProtocolVersion,
11
14
  describeFlag2,
12
15
  Described2
13
- } from "../chunk-e1tqypyy.js";
16
+ } from "../chunk-zvzw3zs4.js";
14
17
 
15
- // packages/sdk/src/build/index.ts
18
+ // packages/core/src/json.ts
19
+ import * as Schema from "effect/Schema";
20
+ var JsonFromString = Schema.fromJsonString(Schema.Json);
21
+ var decodeJsonString = Schema.decodeUnknownEffect(JsonFromString);
22
+ var decodeJsonStringOption = Schema.decodeUnknownOption(JsonFromString);
23
+ var encodeJsonStringSync = Schema.encodeSync(JsonFromString);
24
+ var encodePrettyJsonString = Schema.encodeEffect(Schema.fromJsonString(Schema.Json, { space: 2 }));
25
+ var decodeJsonStringSync = Schema.decodeUnknownSync(JsonFromString);
26
+ var encodeUnknownJsonStringSync = Schema.encodeSync(Schema.fromJsonString(Schema.Unknown));
27
+
28
+ // packages/core/src/npm-registry.ts
29
+ import * as Config from "effect/Config";
30
+ import * as Context from "effect/Context";
31
+ import * as Data from "effect/Data";
16
32
  import * as Effect from "effect/Effect";
33
+ import * as Option from "effect/Option";
34
+ import * as Predicate from "effect/Predicate";
35
+ import * as Schema2 from "effect/Schema";
36
+ import * as FetchHttpClient from "effect/http/FetchHttpClient";
37
+ import * as HttpClient from "effect/http/HttpClient";
38
+ import * as HttpClientResponse from "effect/http/HttpClientResponse";
39
+ var KitManifest = Schema2.Struct({
40
+ bundle: Schema2.String,
41
+ digest: KitDigest,
42
+ protocolVersion: Schema2.Int,
43
+ declarations: Schema2.String,
44
+ setup: Schema2.Record(KitDigest, Schema2.String)
45
+ });
46
+
47
+ class NpmRegistryError extends Data.TaggedError("NpmRegistryError") {
48
+ }
49
+ var Dist = Schema2.Struct({
50
+ tarball: Schema2.String,
51
+ integrity: Schema2.optionalKey(Schema2.String),
52
+ shasum: Schema2.optionalKey(Schema2.String)
53
+ });
54
+ var Packument = Schema2.Struct({
55
+ "dist-tags": Schema2.Record(Schema2.String, Schema2.String),
56
+ versions: Schema2.Record(Schema2.String, Schema2.Struct({ dist: Dist }))
57
+ });
58
+ var integrityAlgorithms = ["sha512", "sha384", "sha256", "sha1"];
59
+ var tarballMatches = (tarball, dist) => {
60
+ if (dist.integrity === undefined)
61
+ return dist.shasum === digestWith("sha1", tarball, "hex");
62
+ const hashes = dist.integrity.split(/\s+/u).map((hash) => /^([^-]+)-([^?]+)/u.exec(hash));
63
+ const algorithm = integrityAlgorithms.find((candidate) => hashes.some((hash) => hash?.[1] === candidate));
64
+ return algorithm !== undefined && hashes.some((hash) => hash?.[1] === algorithm && hash[2] === digestWith(algorithm, tarball, "base64"));
65
+ };
66
+ var PackageJson = Schema2.Struct({ kitman: Schema2.optionalKey(Schema2.Unknown) });
67
+ var decodePackageJson = Schema2.decodeUnknownOption(Schema2.fromJsonString(PackageJson));
68
+ var decodeManifest = Schema2.decodeUnknownOption(KitManifest);
69
+ var decodeJson = Schema2.decodeUnknownOption(Schema2.fromJsonString(Schema2.Unknown));
70
+ var gunzip = (bytes) => Effect.tryPromise(() => new Response(new Blob([new Uint8Array(bytes)]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer()).pipe(Effect.map((buffer) => new Uint8Array(buffer)));
71
+ var text = (bytes) => new TextDecoder().decode(bytes).replace(/\0.*$/su, "");
72
+ var untar = (tar) => {
73
+ const files = new Map;
74
+ let longName;
75
+ for (let offset = 0;offset + 512 <= tar.length; ) {
76
+ const header = tar.subarray(offset, offset + 512);
77
+ if (header.every((byte) => byte === 0))
78
+ break;
79
+ const size = Number.parseInt(text(header.subarray(124, 136)).trim() || "0", 8);
80
+ if (!Number.isSafeInteger(size) || size < 0 || offset + 512 + size > tar.length)
81
+ return;
82
+ const type = String.fromCharCode(header[156] ?? 0);
83
+ const prefix = text(header.subarray(345, 500));
84
+ const body = tar.subarray(offset + 512, offset + 512 + size);
85
+ const name = longName ?? (prefix === "" ? text(header.subarray(0, 100)) : `${prefix}/${text(header.subarray(0, 100))}`);
86
+ longName = undefined;
87
+ if (type === "x")
88
+ longName = /(?:^|\n)\d+ path=([^\n]*)\n/u.exec(new TextDecoder().decode(body))?.[1];
89
+ else if (type === "L")
90
+ longName = text(body);
91
+ else if (type === "0" || type === "\x00")
92
+ files.set(name.replace(/^[^/]*\//u, ""), body);
93
+ offset += 512 + Math.ceil(size / 512) * 512;
94
+ }
95
+ return files;
96
+ };
97
+ var registryUrl = Config.String("NPM_CONFIG_REGISTRY").pipe(Config.withDefault("https://registry.npmjs.org"));
98
+ var npmRegistryAt = (url = registryUrl) => {
99
+ const base = (Predicate.isString(url) ? Effect.succeed(url) : Effect.orDie(url)).pipe(Effect.map((value) => value.replace(/\/+$/u, "")));
100
+ const unreachable = (name, version) => (error) => new NpmRegistryError({
101
+ kind: "unreachable",
102
+ message: `npm did not answer for ${name}@${version}: ${error.message}; try again`
103
+ });
104
+ const packument = (name, version) => Effect.gen(function* () {
105
+ const response = yield* HttpClient.get(`${yield* base}/${name.replace("/", "%2F")}`).pipe(Effect.mapError(unreachable(name, version)), Effect.provide(FetchHttpClient.layer));
106
+ if (response.status === 404)
107
+ return yield* new NpmRegistryError({ kind: "not_found", message: `npm has no package ${name}` });
108
+ return yield* HttpClientResponse.filterStatusOk(response).pipe(Effect.flatMap(HttpClientResponse.schemaBodyJson(Packument)), Effect.mapError(unreachable(name, version)));
109
+ });
110
+ return {
111
+ latest: (name) => Effect.flatMap(packument(name, "latest"), (found) => {
112
+ const latest = found["dist-tags"].latest;
113
+ return latest === undefined ? Effect.fail(new NpmRegistryError({ kind: "not_found", message: `npm has no latest ${name}` })) : Effect.succeed(latest);
114
+ }),
115
+ kit: (name, wanted) => Effect.gen(function* () {
116
+ const found = yield* packument(name, wanted);
117
+ const version = found["dist-tags"][wanted] ?? wanted;
118
+ const dist = found.versions[version]?.dist;
119
+ if (dist === undefined)
120
+ return yield* new NpmRegistryError({ kind: "not_found", message: `npm has no ${name}@${wanted}` });
121
+ const tarball = yield* HttpClient.get(dist.tarball).pipe(Effect.flatMap(HttpClientResponse.filterStatusOk), Effect.flatMap((response) => response.arrayBuffer), Effect.map((buffer) => new Uint8Array(buffer)), Effect.mapError(unreachable(name, version)), Effect.provide(FetchHttpClient.layer));
122
+ if (!tarballMatches(tarball, dist))
123
+ return yield* new NpmRegistryError({
124
+ kind: "integrity",
125
+ message: `${name}@${version}'s tarball does not match npm's integrity: expected ${dist.integrity ?? `sha1 ${dist.shasum}`}, got sha512-${digestSha512(tarball, "base64")}; its publisher must publish a new version`
126
+ });
127
+ const notAKit = new NpmRegistryError({
128
+ kind: "not_a_kit",
129
+ message: `${name}@${version} is not a Kitman Kit: add \`kitman kit build\` to its prepack and publish again`
130
+ });
131
+ const files = untar(yield* gunzip(tarball).pipe(Effect.mapError(() => notAKit)));
132
+ if (files === undefined)
133
+ return yield* notAKit;
134
+ const file = (path) => Option.fromUndefinedOr(files.get(path.replace(/^\.\//u, "")));
135
+ const manifest = Option.flatMap(file("package.json"), (bytes) => Option.flatMap(decodePackageJson(new TextDecoder().decode(bytes)), (json) => decodeManifest(json.kitman)));
136
+ if (Option.isNone(manifest))
137
+ return yield* notAKit;
138
+ const bundle = file(manifest.value.bundle);
139
+ const declarations = file(manifest.value.declarations);
140
+ const setupArchives = Object.entries(manifest.value.setup).flatMap(([digest, path]) => Option.match(file(path), {
141
+ onNone: () => [],
142
+ onSome: (archive) => digestSha256(archive, "hex") === digest ? [{ digest, archive }] : []
143
+ }));
144
+ if (Option.isNone(bundle) || Option.isNone(declarations) || digestSha256(bundle.value, "hex") !== manifest.value.digest || setupArchives.length !== Object.keys(manifest.value.setup).length)
145
+ return yield* notAKit;
146
+ const parsed = decodeJson(new TextDecoder().decode(declarations.value));
147
+ if (Option.isNone(parsed))
148
+ return yield* notAKit;
149
+ return {
150
+ name,
151
+ version,
152
+ integrity: dist.integrity ?? `sha1-${digestWith("sha1", tarball, "base64")}`,
153
+ bundle: bundle.value,
154
+ digest: manifest.value.digest,
155
+ protocolVersion: manifest.value.protocolVersion,
156
+ declarations: parsed.value,
157
+ setupArchives
158
+ };
159
+ })
160
+ };
161
+ };
162
+ var NpmRegistry = Context.Reference("kitman/core/NpmRegistry", {
163
+ defaultValue: () => npmRegistryAt()
164
+ });
165
+
166
+ // packages/sdk/src/build/index.ts
167
+ import * as Config2 from "effect/Config";
168
+ import * as Context2 from "effect/Context";
169
+ import * as Effect2 from "effect/Effect";
17
170
  import * as FileSystem from "effect/FileSystem";
18
171
  import * as Path from "effect/Path";
19
- import * as Predicate from "effect/Predicate";
20
- import * as Schema from "effect/Schema";
172
+ import * as Predicate2 from "effect/Predicate";
173
+ import * as Schema3 from "effect/Schema";
21
174
  import * as Stream from "effect/Stream";
175
+ import { Base64 } from "effect/encoding";
176
+ import * as FetchHttpClient2 from "effect/http/FetchHttpClient";
177
+ import * as HttpClient2 from "effect/http/HttpClient";
178
+ import * as HttpClientResponse2 from "effect/http/HttpClientResponse";
22
179
  import { ChildProcess, ChildProcessSpawner } from "effect/process";
23
- class DependencyInstallFailed extends Schema.TaggedError()("DependencyInstallFailed", {
24
- reason: Schema.String
180
+ class DependencyInstallFailed extends Schema3.TaggedError()("DependencyInstallFailed", {
181
+ reason: Schema3.String
25
182
  }) {
26
183
  get message() {
27
184
  return `Dependencies do not install from the lockfile: ${this.reason}`;
28
185
  }
29
186
  }
30
187
 
31
- class BundleFailed extends Schema.TaggedError()("BundleFailed", { reason: Schema.String }) {
188
+ class BundleFailed extends Schema3.TaggedError()("BundleFailed", { reason: Schema3.String }) {
32
189
  get message() {
33
- return `The Package does not bundle: ${this.reason}`;
190
+ return `The Kit does not bundle: ${this.reason}`;
34
191
  }
35
192
  }
36
193
 
37
- class DeclarationsInvalid extends Schema.TaggedError()("DeclarationsInvalid", {
38
- reason: Schema.String
194
+ class DeclarationsInvalid extends Schema3.TaggedError()("DeclarationsInvalid", {
195
+ reason: Schema3.String
39
196
  }) {
40
197
  get message() {
41
- return `The Package's declarations are invalid: ${this.reason}`;
198
+ return `The Kit's declarations are invalid: ${this.reason}`;
42
199
  }
43
200
  }
44
- var RepositoryText = Schema.Union([Schema.String, Schema.Struct({ file: Schema.String })]);
45
- var ConfigAgents = Schema.Record(Schema.String, Schema.Struct({
46
- extends: Schema.optionalKey(Schema.String),
47
- instructions: Schema.optionalKey(RepositoryText),
48
- harness: Schema.optionalKey(Schema.String),
49
- model: Schema.optionalKey(Schema.String),
50
- effort: AgentDeclaration.fields.effort,
51
- kits: Schema.optionalKey(Schema.Array(Schema.String)),
52
- network: Schema.optionalKey(Schema.Union([Schema.Struct({ hosts: Schema.Array(Schema.String) }), Schema.Literal("open")])),
53
- sandbox: Schema.optionalKey(Schema.Literal("docker"))
201
+
202
+ class SourceFetchFailed extends Schema3.TaggedError()("SourceFetchFailed", {
203
+ reason: Schema3.String
204
+ }) {
205
+ get message() {
206
+ return `A setup source does not fetch: ${this.reason}`;
207
+ }
208
+ }
209
+ var RepositoryText = Schema3.Union([Schema3.String, Schema3.Struct({ file: Schema3.String })]);
210
+ var ConfigAgents = Schema3.Record(Schema3.String, Schema3.Struct({
211
+ ...AgentDeclaration.fields,
212
+ instructions: Schema3.optionalKey(RepositoryText)
54
213
  }));
55
- var ConfigKits = Schema.Record(Schema.String, Schema.Union([
56
- KitInstallationDeclaration,
57
- KitAssignmentDeclaration,
58
- Schema.Struct({
59
- name: Schema.String,
60
- kind: Schema.optionalKey(Schema.Literals(["technology", "brand", "domain", "process", "other"])),
61
- description: Schema.optionalKey(Schema.String),
62
- context: RepositoryText,
63
- skills: Schema.optionalKey(Schema.Array(Schema.String))
64
- })
65
- ]));
66
- var run = (command, args, cwd) => Effect.gen(function* () {
214
+ var run = (command, args, cwd) => Effect2.gen(function* () {
67
215
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
68
216
  const handle = yield* spawner.spawn(ChildProcess.make(command, args, { cwd, stdin: "ignore" }));
69
- const [stdout, stderr, exitCode] = yield* Effect.all([
217
+ const [stdout, stderr, exitCode] = yield* Effect2.all([
70
218
  Stream.mkString(Stream.decodeText(handle.stdout)),
71
219
  Stream.mkString(Stream.decodeText(handle.stderr)),
72
220
  handle.exitCode
73
221
  ], { concurrency: 3 });
74
222
  return { stdout, stderr, ok: exitCode === 0 };
75
- }).pipe(Effect.scoped);
223
+ }).pipe(Effect2.scoped);
76
224
  var failure = (result) => (result.stderr.trim() || result.stdout.trim()).slice(-2000);
77
- var provenance = (directory) => Effect.gen(function* () {
78
- const git = (...args) => run("git", args, directory).pipe(Effect.map((result) => result.ok ? result.stdout.trim() : undefined), Effect.orElseSucceed(() => {
225
+ var provenance = (directory) => Effect2.gen(function* () {
226
+ const git = (...args) => run("git", args, directory).pipe(Effect2.map((result) => result.ok ? result.stdout.trim() : undefined), Effect2.orElseSucceed(() => {
79
227
  return;
80
228
  }));
81
229
  const repository = yield* git("remote", "get-url", "origin");
@@ -87,128 +235,395 @@ var provenance = (directory) => Effect.gen(function* () {
87
235
  clean: commit !== undefined && status === ""
88
236
  };
89
237
  });
90
- var inRepository = (directory, file, what) => Effect.gen(function* () {
238
+ var inKit = (directory, file, what) => Effect2.gen(function* () {
91
239
  const path = yield* Path.Path;
92
240
  const resolved = path.resolve(directory, file);
93
241
  if (path.relative(directory, resolved).startsWith(".."))
94
- return yield* new DeclarationsInvalid({ reason: `${what} ${file} is outside the repository` });
242
+ return yield* new DeclarationsInvalid({ reason: `${what} ${file} is outside the Kit` });
95
243
  return resolved;
96
244
  });
97
- var readText = (directory, text, what) => Effect.gen(function* () {
98
- if (Predicate.isString(text))
245
+ var readText = (directory, text, what) => Effect2.gen(function* () {
246
+ if (Predicate2.isString(text))
99
247
  return text;
100
248
  const fs = yield* FileSystem.FileSystem;
101
- const file = yield* inRepository(directory, text.file, what);
102
- return yield* fs.readFileString(file).pipe(Effect.mapError(() => new DeclarationsInvalid({ reason: `${what} ${text.file} does not read` })));
249
+ const file = yield* inKit(directory, text.file, what);
250
+ return yield* fs.readFileString(file).pipe(Effect2.mapError(() => new DeclarationsInvalid({ reason: `${what} ${text.file} does not read` })));
103
251
  });
104
- var readAgents = (directory, agents) => Effect.forEach(Object.entries(agents), ([id, { instructions, ...agent }]) => instructions === undefined ? Effect.succeed([id, agent]) : Effect.map(readText(directory, instructions, `Agent "${id}" instructions`), (text) => [id, { ...agent, instructions: text.trim() }])).pipe(Effect.map(Object.fromEntries));
252
+ var readAgents = (directory, agents) => Effect2.forEach(Object.entries(agents), ([id, { instructions, ...agent }]) => instructions === undefined ? Effect2.succeed([id, agent]) : Effect2.map(readText(directory, instructions, `Agent "${id}" instructions`), (text) => [id, { ...agent, instructions: text.trim() }])).pipe(Effect2.map(Object.fromEntries));
105
253
  var utf8 = new TextDecoder("utf-8", { fatal: true });
106
- var readSkill = (directory, skill, what) => Effect.gen(function* () {
254
+ var setupFile = (bytes) => {
255
+ try {
256
+ const text = utf8.decode(bytes);
257
+ return text.includes("\x00") ? { base64: Base64.encode(bytes) } : { utf8: text };
258
+ } catch {
259
+ return { base64: Base64.encode(bytes) };
260
+ }
261
+ };
262
+ var confined = (boundary, file, what) => Effect2.gen(function* () {
263
+ const fs = yield* FileSystem.FileSystem;
264
+ const path = yield* Path.Path;
265
+ const unreadable = () => new DeclarationsInvalid({ reason: `${what} does not read` });
266
+ const real = yield* fs.realPath(path.join(boundary, file)).pipe(Effect2.mapError(unreadable));
267
+ if (path.relative(yield* fs.realPath(boundary).pipe(Effect2.mapError(unreadable)), real).startsWith(".."))
268
+ return yield* new DeclarationsInvalid({ reason: `${what}: ${file} links outside its source` });
269
+ return real;
270
+ });
271
+ var readTree = (root, what, fetched = false) => Effect2.gen(function* () {
107
272
  const fs = yield* FileSystem.FileSystem;
108
273
  const path = yield* Path.Path;
109
- const root = yield* inRepository(directory, skill, what);
110
- const unreadable = () => new DeclarationsInvalid({ reason: `${what} ${skill} does not read` });
111
- const entries = yield* fs.readDirectory(root, { recursive: true }).pipe(Effect.mapError(unreadable));
274
+ const unreadable = () => new DeclarationsInvalid({ reason: `${what} does not read` });
275
+ const entries = yield* fs.readDirectory(root, { recursive: true }).pipe(Effect2.mapError(unreadable));
112
276
  const files = {};
113
277
  for (const entry of entries.toSorted()) {
114
- const file = path.join(root, entry);
115
- if ((yield* fs.stat(file).pipe(Effect.mapError(unreadable))).type !== "File")
278
+ const relative = entry.split(path.sep).join("/");
279
+ if (relative === ".git" || relative.startsWith(".git/"))
116
280
  continue;
117
- const bytes = yield* fs.readFile(file).pipe(Effect.mapError(unreadable));
118
- const text = yield* Effect.try({
119
- try: () => utf8.decode(bytes),
120
- catch: () => new DeclarationsInvalid({ reason: `${what} ${skill} holds a binary file, ${entry}` })
121
- });
122
- if (text.includes("\x00"))
123
- return yield* new DeclarationsInvalid({ reason: `${what} ${skill} holds a binary file, ${entry}` });
124
- files[entry.split(path.sep).join("/")] = text;
281
+ const file = fetched ? yield* confined(root, entry, what) : path.join(root, entry);
282
+ if ((yield* fs.stat(file).pipe(Effect2.mapError(unreadable))).type !== "File")
283
+ continue;
284
+ files[relative] = yield* fs.readFile(file).pipe(Effect2.mapError(unreadable));
125
285
  }
126
- if (files["SKILL.md"] === undefined)
127
- return yield* new DeclarationsInvalid({ reason: `${what} ${skill} has no SKILL.md` });
128
- return [path.basename(root), files];
129
- });
130
- var readKits = (directory, kits) => Effect.forEach(Object.entries(kits), ([key, kit]) => Effect.gen(function* () {
131
- if (!("context" in kit))
132
- return [key, kit];
133
- const { context, skills, ...authored } = kit;
134
- const what = `Kit "${key}"`;
135
- return [
136
- key,
137
- {
138
- ...authored,
139
- context: yield* readText(directory, context, `${what} context`),
140
- ...skills === undefined ? undefined : {
141
- skills: Object.fromEntries(yield* Effect.forEach(skills, (skill) => readSkill(directory, skill, `${what} skill`)))
142
- }
286
+ return files;
287
+ });
288
+ var licenseFiles = ["LICENSE", "LICENSE.md", "LICENSE.txt", "COPYING"];
289
+ var fetchedTree = (root, path, what) => Effect2.gen(function* () {
290
+ const fs = yield* FileSystem.FileSystem;
291
+ const paths = yield* Path.Path;
292
+ const tree = yield* readTree(path === undefined ? root : yield* confined(root, path, what), what, true);
293
+ if (path === undefined)
294
+ return tree;
295
+ for (const license of licenseFiles)
296
+ if (tree[license] === undefined && (yield* fs.exists(paths.join(root, license))))
297
+ return { ...tree, [license]: yield* fs.readFile(yield* confined(root, license, what)).pipe(Effect2.orDie) };
298
+ return tree;
299
+ });
300
+ var GitSourceLocation = Context2.Reference("kitman/sdk/build/GitSourceLocation", { defaultValue: () => (declared) => declared });
301
+ var fetchGit = (declared, what) => Effect2.gen(function* () {
302
+ const fs = yield* FileSystem.FileSystem;
303
+ const { url, ref } = (yield* GitSourceLocation)(declared);
304
+ const checkout = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-git-" });
305
+ for (const args of [
306
+ ["init", "--quiet"],
307
+ ["fetch", "--quiet", "--depth", "1", "--", url, ref ?? "HEAD"],
308
+ ["checkout", "--quiet", "FETCH_HEAD"]
309
+ ]) {
310
+ const result = yield* run("git", args, checkout);
311
+ if (!result.ok)
312
+ return yield* new SourceFetchFailed({
313
+ reason: `${what}: git ${url}${ref === undefined ? "" : ` at ${ref}`}: ${failure(result)}`
314
+ });
315
+ }
316
+ return checkout;
317
+ });
318
+ var fetchNpm = (name, wanted, what) => Effect2.gen(function* () {
319
+ const fs = yield* FileSystem.FileSystem;
320
+ const path = yield* Path.Path;
321
+ const registry = yield* Config2.String("NPM_CONFIG_REGISTRY").pipe(Config2.withDefault("https://registry.npmjs.org"), Effect2.orDie);
322
+ const failed = (reason) => new SourceFetchFailed({ reason: `${what}: npm ${name}@${wanted}: ${reason}` });
323
+ const packument = yield* HttpClient2.get(`${registry.replace(/\/+$/, "")}/${name.replace("/", "%2F")}`).pipe(Effect2.flatMap(HttpClientResponse2.filterStatusOk), Effect2.flatMap(HttpClientResponse2.schemaBodyJson(Packument)), Effect2.mapError((error) => failed(error.message)));
324
+ const dist = packument.versions[packument["dist-tags"][wanted] ?? wanted]?.dist;
325
+ if (dist === undefined)
326
+ return yield* failed("npm has no such version or dist-tag");
327
+ const tarball = yield* HttpClient2.get(dist.tarball).pipe(Effect2.flatMap(HttpClientResponse2.filterStatusOk), Effect2.flatMap((response) => response.arrayBuffer), Effect2.map((buffer) => new Uint8Array(buffer)), Effect2.mapError((error) => failed(error.message)));
328
+ if (!tarballMatches(tarball, dist))
329
+ return yield* failed(`the tarball does not match its integrity ${dist.integrity ?? `sha1 ${dist.shasum}`}`);
330
+ const directory = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-npm-" });
331
+ yield* fs.writeFile(path.join(directory, "package.tgz"), tarball).pipe(Effect2.orDie);
332
+ const extracted = yield* run("tar", ["-xzf", "package.tgz"], directory);
333
+ if (!extracted.ok)
334
+ return yield* failed(`the tarball does not extract: ${failure(extracted)}`);
335
+ return yield* confined(directory, "package", what);
336
+ }).pipe(Effect2.provide(FetchHttpClient2.layer));
337
+ var sourceTree = (directory, source, what, checkouts) => Effect2.gen(function* () {
338
+ switch (source.kind) {
339
+ case "local_path":
340
+ return yield* readTree(yield* inKit(directory, source.path, what), what);
341
+ case "git": {
342
+ const key = `${source.url}#${source.ref ?? ""}`;
343
+ const checkout = checkouts.get(key) ?? (yield* fetchGit({ url: source.url, ref: source.ref }, what));
344
+ checkouts.set(key, checkout);
345
+ return yield* fetchedTree(checkout, "path" in source ? source.path : undefined, what);
143
346
  }
144
- ];
145
- })).pipe(Effect.map(Object.fromEntries));
146
- var PackageJson = Schema.fromJsonString(Schema.Struct({ name: Schema.String }));
147
- var packageName = (root) => Effect.gen(function* () {
347
+ case "package":
348
+ return yield* fetchedTree(yield* fetchNpm(source.packageName, source.version ?? "latest", what), "path" in source ? source.path : undefined, what);
349
+ default:
350
+ return yield* new DeclarationsInvalid({
351
+ reason: `${what} comes from a ${source.kind} source, which a build cannot copy in; use a local path, git or npm`
352
+ });
353
+ }
354
+ });
355
+ var setupArchive = (directory, kit, setup, checkouts) => Effect2.gen(function* () {
356
+ const fs = yield* FileSystem.FileSystem;
357
+ const files = {};
358
+ const place = (prefix, tree) => {
359
+ for (const [file, bytes] of Object.entries(tree))
360
+ files[`${prefix}/${file}`] = setupFile(bytes);
361
+ return { kind: "local_path", path: prefix };
362
+ };
363
+ if (setup.instructions !== undefined) {
364
+ const what = `Kit ${kit} instructions`;
365
+ const file = yield* inKit(directory, setup.instructions, what);
366
+ files["instructions.md"] = setupFile(yield* fs.readFile(file).pipe(Effect2.mapError(() => new DeclarationsInvalid({ reason: `${what} do not read` }))));
367
+ }
368
+ const skills = setup.skills === undefined ? undefined : yield* Effect2.forEach(setup.skills, (skill) => Effect2.map(sourceTree(directory, skill.source, `Kit ${kit} skill ${skill.name}`, checkouts), (tree) => ({
369
+ ...skill,
370
+ source: place(`skills/${skill.name}`, tree)
371
+ })));
372
+ const plugins = setup.plugins === undefined ? undefined : yield* Effect2.forEach(setup.plugins, (plugin) => Effect2.map(sourceTree(directory, plugin.sources[0], `Kit ${kit} plugin ${plugin.name}`, checkouts), (tree) => ({
373
+ ...plugin,
374
+ sources: [place(`plugins/${plugin.name}`, tree)]
375
+ })));
376
+ const archive = {
377
+ setup: {
378
+ ...setup,
379
+ ...setup.instructions === undefined ? undefined : { instructions: "instructions.md" },
380
+ ...skills === undefined ? undefined : { skills },
381
+ ...plugins === undefined ? undefined : { plugins }
382
+ },
383
+ files
384
+ };
385
+ const bytes = new TextEncoder().encode(canonicalJson(archive));
386
+ return { digest: digestSha256(bytes, "hex"), archive: bytes };
387
+ });
388
+ var PackageJson2 = Schema3.fromJsonString(Schema3.Struct({
389
+ name: Schema3.String,
390
+ version: Schema3.optionalKey(Schema3.String),
391
+ dependencies: Schema3.optionalKey(Schema3.Record(Schema3.String, Schema3.String))
392
+ }));
393
+ var readPackageJson = (directory) => Effect2.gen(function* () {
394
+ const fs = yield* FileSystem.FileSystem;
395
+ const path = yield* Path.Path;
396
+ return yield* fs.readFileString(path.join(directory, "package.json")).pipe(Effect2.flatMap(Schema3.decodeEffect(PackageJson2)), Effect2.mapError(() => new DeclarationsInvalid({ reason: `${directory}/package.json has no name` })));
397
+ });
398
+ var identityOf = (manifest) => ({
399
+ name: manifest.name,
400
+ version: manifest.version ?? "0.0.0"
401
+ });
402
+ var installedPackage = (name, directory) => Effect2.gen(function* () {
403
+ const fs = yield* FileSystem.FileSystem;
404
+ const path = yield* Path.Path;
405
+ for (let at = directory;; at = path.dirname(at)) {
406
+ const candidate = path.join(at, "node_modules", name);
407
+ if (yield* fs.exists(path.join(candidate, "package.json")))
408
+ return yield* fs.realPath(candidate);
409
+ if (path.dirname(at) === at)
410
+ return;
411
+ }
412
+ });
413
+ var importedFile = (file, specifier) => Effect2.gen(function* () {
414
+ const fs = yield* FileSystem.FileSystem;
415
+ const path = yield* Path.Path;
416
+ const target = path.resolve(path.dirname(file), specifier);
417
+ for (const candidate of [target, `${target}.ts`, path.join(target, "kitman.config.ts")])
418
+ if (yield* fs.stat(candidate).pipe(Effect2.map((info) => info.type === "File"), Effect2.orElseSucceed(() => false)))
419
+ return candidate;
420
+ return;
421
+ });
422
+ var packageDirectory = (file) => Effect2.gen(function* () {
423
+ const fs = yield* FileSystem.FileSystem;
424
+ const path = yield* Path.Path;
425
+ for (let at = path.dirname(file);; at = path.dirname(at)) {
426
+ if (yield* fs.exists(path.join(at, "package.json")).pipe(Effect2.orElseSucceed(() => false)))
427
+ return at;
428
+ if (path.dirname(at) === at)
429
+ return;
430
+ }
431
+ });
432
+ var kitModules = (root) => Effect2.gen(function* () {
148
433
  const fs = yield* FileSystem.FileSystem;
149
434
  const path = yield* Path.Path;
150
- return yield* fs.readFileString(path.join(root, "package.json")).pipe(Effect.flatMap(Schema.decodeEffect(PackageJson)), Effect.map((manifest) => manifest.name), Effect.mapError(() => new DeclarationsInvalid({ reason: "package.json has no name" })));
435
+ const found = [];
436
+ const visited = new Set;
437
+ const packages = new Set([root]);
438
+ const known = (directory) => packages.has(directory);
439
+ const visitPackage = (directory) => Effect2.gen(function* () {
440
+ for (const name of Object.keys((yield* readPackageJson(directory)).dependencies ?? {})) {
441
+ const installed = yield* installedPackage(name, directory).pipe(Effect2.orElseSucceed(() => {
442
+ return;
443
+ }));
444
+ const module = installed === undefined ? undefined : path.join(installed, "kitman.config.ts");
445
+ if (installed === undefined || module === undefined || known(installed))
446
+ continue;
447
+ if (!(yield* fs.exists(module).pipe(Effect2.orElseSucceed(() => false))))
448
+ continue;
449
+ packages.add(installed);
450
+ found.push({ directory: installed, module, identity: identityOf(yield* readPackageJson(installed)) });
451
+ yield* visitPackage(installed);
452
+ yield* visitImports(module);
453
+ }
454
+ });
455
+ const visitImports = (file) => Effect2.gen(function* () {
456
+ if (visited.has(file))
457
+ return;
458
+ visited.add(file);
459
+ const transpiled = yield* run("bun", ["build", "--no-bundle", file], root).pipe(Effect2.map((result) => result.ok ? result.stdout : ""), Effect2.orElseSucceed(() => ""));
460
+ for (const [, specifier] of transpiled.matchAll(/\b(?:from|import)\s*"(\.{1,2}\/[^"]+)"/gu)) {
461
+ const module = specifier === undefined ? undefined : yield* importedFile(file, specifier);
462
+ if (module === undefined || visited.has(module))
463
+ continue;
464
+ const directory = yield* packageDirectory(module);
465
+ if (directory !== undefined && directory !== root) {
466
+ found.push({ directory, module, identity: identityOf(yield* readPackageJson(directory)) });
467
+ if (!known(directory)) {
468
+ packages.add(directory);
469
+ yield* visitPackage(directory);
470
+ }
471
+ }
472
+ yield* visitImports(module);
473
+ }
474
+ });
475
+ yield* visitPackage(root);
476
+ yield* visitImports(path.join(root, "kitman.config.ts"));
477
+ return found;
151
478
  });
479
+ var buildEntry = (identity, modules) => [
480
+ "import config from './kitman.config.ts'",
481
+ "import { runKit } from '@kitman-sh/sdk/program'",
482
+ ...modules.map((kit, index) => `import * as kit${index} from ${JSON.stringify(kit.module)}`),
483
+ "",
484
+ `runKit(config, ${JSON.stringify(identity)}, [${modules.map((kit, index) => `[kit${index}.default, ${JSON.stringify(kit.identity)}]`).join(", ")}])`,
485
+ ""
486
+ ].join(`
487
+ `);
152
488
  var renamedKey = (declarations, what, from, to) => {
153
- const key = Object.keys(declarations ?? {}).find((key) => Predicate.hasProperty(declarations?.[key], from));
489
+ const key = Object.keys(declarations ?? {}).find((key) => Predicate2.hasProperty(declarations?.[key], from));
154
490
  return key === undefined ? undefined : new DeclarationsInvalid({ reason: `${what} "${key}" names \`${from}\`, which is now \`${to}\`` });
155
491
  };
156
- var duplicateLoopId = (loops) => loops.map((loop) => loop.id).find((id, index, ids) => ids.indexOf(id) !== index);
157
- var buildPackage = (directory) => Effect.gen(function* () {
492
+ var resolveNames = (names) => {
493
+ const winners = new Map;
494
+ const overrides = [];
495
+ for (const named of names) {
496
+ const key = `${named.what}\x00${named.name}`;
497
+ const winner = winners.get(key);
498
+ if (winner === undefined)
499
+ winners.set(key, named.kit);
500
+ else if (winner === named.kit)
501
+ return new DeclarationsInvalid({ reason: `Kit ${named.kit} names ${named.what} ${named.name} twice` });
502
+ else
503
+ overrides.push({ what: named.what, name: named.name, winner, replaced: named.kit });
504
+ }
505
+ return { wins: (named) => winners.get(`${named.what}\x00${named.name}`) === named.kit, overrides };
506
+ };
507
+ var buildKit = (directory, options = {}) => Effect2.gen(function* () {
158
508
  const fs = yield* FileSystem.FileSystem;
159
509
  const path = yield* Path.Path;
160
510
  const root = path.resolve(directory);
161
511
  const source = yield* provenance(root);
162
- const name = yield* packageName(root);
163
- const installed = yield* run("bun", ["install", "--frozen-lockfile", "--ignore-scripts"], root).pipe(Effect.mapError((error) => new DependencyInstallFailed({ reason: error.message })));
512
+ const identity = { ...identityOf(yield* readPackageJson(root)), ...options };
513
+ const installed = yield* run("bun", ["install", "--frozen-lockfile", "--ignore-scripts"], root).pipe(Effect2.mapError((error) => new DependencyInstallFailed({ reason: error.message })));
164
514
  if (!installed.ok)
165
515
  return yield* new DependencyInstallFailed({ reason: failure(installed) });
516
+ const packages = yield* kitModules(root);
166
517
  const entry = path.join(root, ".kitman-build-entry.ts");
167
- yield* Effect.acquireRelease(fs.writeFileString(entry, `import config from './kitman.config.ts'
168
- import { runPackage } from '@kitman-sh/sdk/program'
169
-
170
- runPackage(config)
171
- `), () => Effect.ignore(fs.remove(entry)));
172
- const out = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-package-" });
518
+ yield* Effect2.acquireRelease(fs.writeFileString(entry, buildEntry(identity, packages)), () => Effect2.ignore(fs.remove(entry)));
519
+ const out = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-kit-" });
173
520
  const bundleFile = path.join(out, "bundle.js");
174
521
  const bundled = yield* run("bun", ["build", entry, "--target=bun", "--format=esm", "--outfile", bundleFile], root);
175
522
  if (!bundled.ok)
176
- return yield* new BundleFailed({ reason: failure(bundled) });
523
+ return yield* failure(bundled).includes('"defineConfig"') ? new DeclarationsInvalid({
524
+ reason: "defineConfig is now defineKit; import defineKit from @kitman-sh/sdk/loop"
525
+ }) : new BundleFailed({ reason: failure(bundled) });
177
526
  const described = yield* run("bun", [bundleFile, describeFlag2], out);
178
527
  if (!described.ok)
179
528
  return yield* new BundleFailed({ reason: `the bundle does not load: ${failure(described)}` });
180
- const result = yield* Schema.decodeEffect(Schema.fromJsonString(Schema.toCodecJson(Described2)))(described.stdout).pipe(Effect.mapError((error) => new BundleFailed({ reason: `the bundle described itself wrongly: ${error.message}` })));
181
- if (Predicate.isTagged(result, "Refused"))
529
+ const result = yield* Schema3.decodeEffect(Schema3.fromJsonString(Schema3.toCodecJson(Described2)))(described.stdout).pipe(Effect2.mapError((error) => new BundleFailed({ reason: `the bundle described itself wrongly: ${error.message}` })));
530
+ if (Predicate2.isTagged(result, "Refused"))
182
531
  return yield* result.error;
183
- const duplicate = duplicateLoopId(result.loops);
184
- if (duplicate !== undefined)
185
- return yield* new DeclarationsInvalid({ reason: `Loop "${duplicate}" is declared twice` });
186
- const renamed = renamedKey(result.schedules, "Schedule", "project", "team") ?? renamedKey(result.schedules, "Schedule", "codebase", "team") ?? renamedKey(result.kits, "Kit", "projects", "teams") ?? renamedKey(result.kits, "Kit", "codebases", "teams");
532
+ const [own] = result.kits;
533
+ if (own === undefined)
534
+ return yield* new BundleFailed({ reason: "the bundle described no Kit" });
535
+ const renamed = renamedKey(own.schedules, "Schedule", "project", "team") ?? renamedKey(own.schedules, "Schedule", "codebase", "team");
187
536
  if (renamed !== undefined)
188
537
  return yield* renamed;
189
- const agents = yield* Schema.decodeUnknownEffect(ConfigAgents)(result.agents).pipe(Effect.mapError((error) => new DeclarationsInvalid({ reason: error.message })));
190
- const kits = result.kits === undefined ? undefined : yield* Schema.decodeUnknownEffect(ConfigKits)(result.kits).pipe(Effect.mapError((error) => new DeclarationsInvalid({ reason: error.message })));
191
- const declarations = yield* Schema.decodeUnknownEffect(PackageDeclarations)({
192
- loops: result.loops,
193
- agents: yield* readAgents(root, agents),
194
- ...result.schedules === undefined ? undefined : { schedules: result.schedules },
195
- ...kits === undefined ? undefined : { kits: yield* readKits(root, kits) }
196
- }).pipe(Effect.mapError((error) => new DeclarationsInvalid({ reason: error.message })));
197
- const bundle = yield* fs.readFile(bundleFile).pipe(Effect.mapError((error) => new BundleFailed({ reason: error.message })));
538
+ const directories = new Map([
539
+ [`${identity.name}@${identity.version}`, root],
540
+ ...packages.map((kit) => [`${kit.identity.name}@${kit.identity.version}`, kit.directory])
541
+ ]);
542
+ const kits = yield* Effect2.forEach(result.kits, (kit) => Effect2.gen(function* () {
543
+ const at = directories.get(`${kit.name}@${kit.version}`) ?? root;
544
+ const invalid = (error) => new DeclarationsInvalid({ reason: `Kit ${kit.name}: ${error.message}` });
545
+ const agents = yield* Schema3.decodeUnknownEffect(ConfigAgents)(kit.agents).pipe(Effect2.mapError(invalid));
546
+ return { ...kit, directory: at, agents: yield* readAgents(at, agents), setup: kit.setup ?? {} };
547
+ }));
548
+ const named = kits.flatMap((kit) => [
549
+ ...kit.loops.map((loop) => ({ kit: kit.name, what: "Loop", name: loop.id })),
550
+ ...Object.keys(kit.agents).map((agent) => ({ kit: kit.name, what: "Agent", name: agent })),
551
+ ...(kit.setup.skills ?? []).map((skill) => ({ kit: kit.name, what: "skill", name: skill.name })),
552
+ ...(kit.setup.plugins ?? []).map((plugin) => ({ kit: kit.name, what: "plugin", name: plugin.name })),
553
+ ...(kit.setup.mcpServers ?? []).map((server) => ({ kit: kit.name, what: "MCP server", name: server.name }))
554
+ ]);
555
+ const kitman = named.find((entry) => entry.what === "MCP server" && entry.name === kitmanMcpServer);
556
+ if (kitman !== undefined)
557
+ return yield* new DeclarationsInvalid({
558
+ reason: `Kit ${kitman.kit} declares an MCP server named ${kitmanMcpServer}, which Kitman provides`
559
+ });
560
+ const names = resolveNames(named);
561
+ if (Predicate2.isTagged(names, "DeclarationsInvalid"))
562
+ return yield* names;
563
+ const winning = kits.map((kit) => ({
564
+ ...kit,
565
+ loops: kit.loops.filter((loop) => names.wins({ kit: kit.name, what: "Loop", name: loop.id })),
566
+ agents: Object.fromEntries(Object.entries(kit.agents).filter(([agent]) => names.wins({ kit: kit.name, what: "Agent", name: agent })))
567
+ }));
568
+ const checkouts = new Map;
569
+ const archives = yield* Effect2.forEach(kits, (kit) => setupArchive(kit.directory, kit.name, kit.setup, checkouts));
570
+ const carried = winning.map((kit, index) => ({
571
+ name: kit.name,
572
+ version: kit.version,
573
+ setup: archives[index]?.digest ?? "",
574
+ loops: kit.loops.map((loop) => loop.id),
575
+ agents: Object.keys(kit.agents)
576
+ }));
577
+ const declarations = yield* Schema3.decodeUnknownEffect(KitDeclarations)({
578
+ loops: winning.flatMap((kit) => kit.loops),
579
+ agents: Object.assign({}, ...winning.map((kit) => kit.agents)),
580
+ ...own.schedules === undefined ? undefined : { schedules: own.schedules },
581
+ carried
582
+ }).pipe(Effect2.mapError((error) => new DeclarationsInvalid({ reason: error.message })));
583
+ const bundle = yield* fs.readFile(bundleFile).pipe(Effect2.mapError((error) => new BundleFailed({ reason: error.message })));
198
584
  return {
199
- name,
585
+ ...identity,
200
586
  bundle,
201
587
  digest: digestSha256(bundle, "hex"),
202
588
  declarations,
589
+ setupArchives: archives,
203
590
  protocolVersion: RunnerRpcProtocolVersion,
204
- provenance: source
591
+ provenance: source,
592
+ overrides: names.overrides
205
593
  };
206
- }).pipe(Effect.scoped, Effect.catchTags({
207
- PlatformError: (error) => Effect.fail(new BundleFailed({ reason: error.message }))
594
+ }).pipe(Effect2.scoped, Effect2.catchTags({
595
+ PlatformError: (error) => Effect2.fail(new BundleFailed({ reason: error.message }))
208
596
  }));
597
+ var writeKit = (directory, built, out) => Effect2.gen(function* () {
598
+ const fs = yield* FileSystem.FileSystem;
599
+ const path = yield* Path.Path;
600
+ const inKit = (file) => path.relative(directory, path.join(out, file));
601
+ const setup = {};
602
+ yield* fs.makeDirectory(path.join(out, "setup"), { recursive: true });
603
+ yield* fs.writeFile(path.join(out, "bundle.js"), built.bundle);
604
+ yield* fs.writeFileString(path.join(out, "declarations.json"), yield* encodePrettyJsonString(built.declarations));
605
+ for (const { digest, archive } of built.setupArchives) {
606
+ yield* fs.writeFile(path.join(out, "setup", `${digest}.json`), archive);
607
+ setup[digest] = inKit(`setup/${digest}.json`);
608
+ }
609
+ const manifestPath = path.join(directory, "package.json");
610
+ const manifest = yield* fs.readFileString(manifestPath).pipe(Effect2.flatMap(Schema3.decodeEffect(Schema3.fromJsonString(Schema3.Record(Schema3.String, Schema3.Json)))));
611
+ const kitman = {
612
+ bundle: inKit("bundle.js"),
613
+ digest: built.digest,
614
+ protocolVersion: built.protocolVersion,
615
+ declarations: inKit("declarations.json"),
616
+ setup
617
+ };
618
+ yield* fs.writeFileString(manifestPath, `${yield* encodePrettyJsonString({ ...manifest, kitman })}
619
+ `);
620
+ });
209
621
  export {
210
622
  BundleFailed,
211
623
  DeclarationsInvalid,
212
624
  DependencyInstallFailed,
213
- buildPackage
625
+ GitSourceLocation,
626
+ SourceFetchFailed,
627
+ buildKit,
628
+ writeKit
214
629
  };