@kitman-sh/sdk 0.0.0-stage → 0.7.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.
Files changed (102) hide show
  1. package/dist/build/index.js +215 -0
  2. package/dist/chunk-7hwhxthh.js +1055 -0
  3. package/dist/chunk-zp7s46pz.js +3966 -0
  4. package/dist/loop/index.js +193 -0
  5. package/dist/program/index.js +30 -0
  6. package/package.json +29 -4
  7. package/types/packages/core/src/a2a.d.ts +577 -0
  8. package/types/packages/core/src/agent-capabilities.d.ts +1434 -0
  9. package/types/packages/core/src/agent-environment.d.ts +2429 -0
  10. package/types/packages/core/src/agent-launch-snapshot.d.ts +44 -0
  11. package/types/packages/core/src/agent-sandbox-policy.d.ts +33 -0
  12. package/types/packages/core/src/approval-queue.d.ts +126 -0
  13. package/types/packages/core/src/audit.d.ts +52 -0
  14. package/types/packages/core/src/change-delivery.d.ts +39 -0
  15. package/types/packages/core/src/change-request-review.d.ts +146 -0
  16. package/types/packages/core/src/change-request.d.ts +432 -0
  17. package/types/packages/core/src/common.d.ts +6 -0
  18. package/types/packages/core/src/connection.d.ts +33 -0
  19. package/types/packages/core/src/context-feedback.d.ts +89 -0
  20. package/types/packages/core/src/context-pack.d.ts +182 -0
  21. package/types/packages/core/src/crypto.d.ts +11 -0
  22. package/types/packages/core/src/data-lifecycle.d.ts +195 -0
  23. package/types/packages/core/src/decision.d.ts +48 -0
  24. package/types/packages/core/src/delivery-operation.d.ts +125 -0
  25. package/types/packages/core/src/delivery-policy.d.ts +174 -0
  26. package/types/packages/core/src/engineering-resources.d.ts +26 -0
  27. package/types/packages/core/src/enterprise-code-host.d.ts +18 -0
  28. package/types/packages/core/src/epic-delivery.d.ts +38 -0
  29. package/types/packages/core/src/extension.d.ts +35 -0
  30. package/types/packages/core/src/external-effect.d.ts +313 -0
  31. package/types/packages/core/src/fix-flow.d.ts +149 -0
  32. package/types/packages/core/src/following.d.ts +59 -0
  33. package/types/packages/core/src/github-delivery-fixtures.d.ts +28 -0
  34. package/types/packages/core/src/github-delivery.d.ts +78 -0
  35. package/types/packages/core/src/gitlab-delivery-fixtures.d.ts +26 -0
  36. package/types/packages/core/src/gitlab-delivery.d.ts +76 -0
  37. package/types/packages/core/src/global-search.d.ts +42 -0
  38. package/types/packages/core/src/id.d.ts +1 -0
  39. package/types/packages/core/src/index.d.ts +74 -0
  40. package/types/packages/core/src/integration.d.ts +255 -0
  41. package/types/packages/core/src/intent.d.ts +260 -0
  42. package/types/packages/core/src/json.d.ts +10 -0
  43. package/types/packages/core/src/kit-taxonomy.d.ts +21 -0
  44. package/types/packages/core/src/kit.d.ts +1489 -0
  45. package/types/packages/core/src/live.d.ts +8309 -0
  46. package/types/packages/core/src/loop-layers.d.ts +59 -0
  47. package/types/packages/core/src/loop-version.d.ts +59 -0
  48. package/types/packages/core/src/loop.d.ts +3076 -0
  49. package/types/packages/core/src/me.d.ts +31 -0
  50. package/types/packages/core/src/memory.d.ts +88 -0
  51. package/types/packages/core/src/my-teams.d.ts +1230 -0
  52. package/types/packages/core/src/notification.d.ts +181 -0
  53. package/types/packages/core/src/observability.d.ts +175 -0
  54. package/types/packages/core/src/package-declarations.d.ts +435 -0
  55. package/types/packages/core/src/package.d.ts +369 -0
  56. package/types/packages/core/src/personal-development-profile.d.ts +11 -0
  57. package/types/packages/core/src/platform-release.d.ts +60 -0
  58. package/types/packages/core/src/program-credential.d.ts +10 -0
  59. package/types/packages/core/src/project.d.ts +66 -0
  60. package/types/packages/core/src/proposal.d.ts +292 -0
  61. package/types/packages/core/src/provider-safe-text.d.ts +2 -0
  62. package/types/packages/core/src/redaction.d.ts +73 -0
  63. package/types/packages/core/src/repo-binding.d.ts +131 -0
  64. package/types/packages/core/src/run-journal.d.ts +28 -0
  65. package/types/packages/core/src/run-launch.d.ts +67 -0
  66. package/types/packages/core/src/run.d.ts +566 -0
  67. package/types/packages/core/src/runner-eligibility.d.ts +43 -0
  68. package/types/packages/core/src/runner-routing.d.ts +11 -0
  69. package/types/packages/core/src/runner-trust.d.ts +67 -0
  70. package/types/packages/core/src/runner.d.ts +3750 -0
  71. package/types/packages/core/src/runtime-type.d.ts +36 -0
  72. package/types/packages/core/src/schedule.d.ts +136 -0
  73. package/types/packages/core/src/schema.d.ts +89 -0
  74. package/types/packages/core/src/scope-directory.d.ts +100 -0
  75. package/types/packages/core/src/secret.d.ts +37 -0
  76. package/types/packages/core/src/session.d.ts +90 -0
  77. package/types/packages/core/src/step-brief.d.ts +50 -0
  78. package/types/packages/core/src/sync-kit.d.ts +587 -0
  79. package/types/packages/core/src/task-detail.d.ts +491 -0
  80. package/types/packages/core/src/task-execution-record.d.ts +620 -0
  81. package/types/packages/core/src/task-key.d.ts +9 -0
  82. package/types/packages/core/src/task.d.ts +543 -0
  83. package/types/packages/core/src/trigger-dispatch.d.ts +421 -0
  84. package/types/packages/core/src/work-unit.d.ts +740 -0
  85. package/types/packages/core/src/workspace.d.ts +96 -0
  86. package/types/packages/live/src/rpc/runner-client.d.ts +947 -0
  87. package/types/packages/live/src/rpc/runner-group.d.ts +733 -0
  88. package/types/packages/sdk/src/build/index.d.ts +45 -0
  89. package/types/packages/sdk/src/loop/activities.d.ts +187 -0
  90. package/types/packages/sdk/src/loop/check.d.ts +39 -0
  91. package/types/packages/sdk/src/loop/config.d.ts +68 -0
  92. package/types/packages/sdk/src/loop/define.d.ts +76 -0
  93. package/types/packages/sdk/src/loop/evidence.d.ts +66 -0
  94. package/types/packages/sdk/src/loop/index.d.ts +9 -0
  95. package/types/packages/sdk/src/loop/plan.d.ts +43 -0
  96. package/types/packages/sdk/src/loop/review.d.ts +86 -0
  97. package/types/packages/sdk/src/loop/steps.d.ts +224 -0
  98. package/types/packages/sdk/src/loop/test-loop.d.ts +112 -0
  99. package/types/packages/sdk/src/program/engine.d.ts +144 -0
  100. package/types/packages/sdk/src/program/host.d.ts +70 -0
  101. package/types/packages/sdk/src/program/index.d.ts +2 -0
  102. package/README.md +0 -3
@@ -0,0 +1,1055 @@
1
+ // @bun
2
+ import {
3
+ AgentSandboxNetwork,
4
+ guard,
5
+ Id,
6
+ Timestamp,
7
+ LoopStepOutput,
8
+ StepBrief,
9
+ LoopManifest,
10
+ ManifestInvalid2,
11
+ loopManifest2,
12
+ StepFailed2,
13
+ agentWorkDeferred2,
14
+ answerDeferred2,
15
+ childDeferred2,
16
+ eventDeferred2,
17
+ verifyDeferred2,
18
+ loopWorkflow2,
19
+ executeLoop2,
20
+ LoopCheckError2,
21
+ checkLoop2
22
+ } from "./chunk-zp7s46pz.js";
23
+ // packages/core/src/repo-binding.ts
24
+ import * as Schema from "effect/Schema";
25
+ var RepoBindingPathPrefixPattern = "^(?!/)(?!.*\\\\)(?!.*(?:^|/)\\.\\.?(?:/|$))(?!.*//)\\S+$";
26
+ var RepoBindingProvider = Schema.Union([
27
+ Schema.Literal("github"),
28
+ Schema.Literal("gitlab"),
29
+ Schema.Literal("generic_git")
30
+ ]);
31
+ var RepoBindingStatus = Schema.Union([Schema.Literal("active"), Schema.Literal("disabled")]);
32
+ var RepoBindingCredentialProviderType = Schema.Union([
33
+ Schema.Literal("env"),
34
+ Schema.Literal("file"),
35
+ Schema.Literal("exec")
36
+ ]);
37
+ var RepoBindingAccessMode = Schema.Union([
38
+ Schema.Literal("local_checkout"),
39
+ Schema.Literal("managed_clone"),
40
+ Schema.Literal("runner_secret_provider")
41
+ ]);
42
+ var RepoBindingCredentialRef = Schema.Union([
43
+ Schema.Struct({ kind: Schema.Literal("none") }),
44
+ Schema.Struct({ kind: Schema.Literal("local_env"), envName: Schema.String.check(Schema.isMinLength(1)) }),
45
+ Schema.Struct({
46
+ kind: Schema.Literal("runner_secret"),
47
+ runnerSecretName: Schema.String.check(Schema.isMinLength(1)),
48
+ providerType: RepoBindingCredentialProviderType
49
+ }),
50
+ Schema.Struct({ kind: Schema.Literal("ssh_agent") })
51
+ ]);
52
+ var RepoBinding = Schema.Struct({
53
+ id: Id,
54
+ workspaceId: Id,
55
+ projectId: Id,
56
+ provider: RepoBindingProvider,
57
+ host: Schema.String.check(Schema.isMinLength(1)),
58
+ owner: Schema.String.check(Schema.isMinLength(1)),
59
+ name: Schema.String.check(Schema.isMinLength(1)),
60
+ repositoryUrl: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
61
+ pathPrefix: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1), Schema.isPattern(new RegExp(RepoBindingPathPrefixPattern, "u")))),
62
+ defaultTargetBranch: Schema.String.check(Schema.isMinLength(1)),
63
+ expectedBranch: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
64
+ expectedCommitSha: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
65
+ credentialRefs: Schema.Array(RepoBindingCredentialRef),
66
+ status: RepoBindingStatus,
67
+ webhook: Schema.optionalKey(Schema.Struct({
68
+ status: Schema.Literals(["active", "missing"]),
69
+ message: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(240)))
70
+ })),
71
+ createdAt: Timestamp,
72
+ updatedAt: Timestamp
73
+ });
74
+ var RepoBindingCreate = Schema.Struct({
75
+ provider: RepoBindingProvider,
76
+ host: Schema.String.check(Schema.isMinLength(1)),
77
+ owner: Schema.String.check(Schema.isMinLength(1)),
78
+ name: Schema.String.check(Schema.isMinLength(1)),
79
+ repositoryUrl: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
80
+ pathPrefix: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1), Schema.isPattern(new RegExp(RepoBindingPathPrefixPattern, "u")))),
81
+ defaultTargetBranch: Schema.String.check(Schema.isMinLength(1)),
82
+ expectedBranch: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
83
+ expectedCommitSha: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1))),
84
+ credentialRefs: Schema.optionalKey(Schema.Array(RepoBindingCredentialRef))
85
+ });
86
+ var RepoBindingTargetOverride = Schema.Struct({
87
+ targetBranch: Schema.optionalKey(Schema.String.check(Schema.isMinLength(1)))
88
+ });
89
+ var RepoBindingList = Schema.Struct({ items: Schema.Array(RepoBinding) });
90
+ var RunnerRepoBindingCapability = Schema.Struct({
91
+ repoBindingId: Id,
92
+ provider: RepoBindingProvider,
93
+ host: Schema.String.check(Schema.isMinLength(1)),
94
+ accessModes: Schema.Array(RepoBindingAccessMode),
95
+ credentialProviderTypes: Schema.Array(RepoBindingCredentialProviderType),
96
+ authenticated: Schema.Boolean,
97
+ canPush: Schema.optionalKey(Schema.Boolean)
98
+ });
99
+ // packages/core/src/work-unit.ts
100
+ import * as Schema2 from "effect/Schema";
101
+ import * as Struct3 from "effect/Struct";
102
+ var WorkUnitLease = Schema2.Struct({
103
+ leaseOwnerId: Id,
104
+ runnerReplicaId: Id,
105
+ leaseId: Id,
106
+ attempt: Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(1)),
107
+ fencingToken: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240), Schema2.isPattern(new RegExp("^[A-Za-z0-9._:-]+$", "u"))),
108
+ capacitySlot: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
109
+ leaseExpiresAt: Timestamp,
110
+ lastHeartbeatAt: Timestamp
111
+ });
112
+ var WorkUnitLeaseProjection = Schema2.Struct(Struct3.map(WorkUnitLease.fields, Schema2.optionalKey));
113
+ var WorkUnitRepoBinding = Schema2.Struct({
114
+ id: Id,
115
+ provider: RepoBindingProvider,
116
+ host: Schema2.String.check(Schema2.isMinLength(1)),
117
+ owner: Schema2.String.check(Schema2.isMinLength(1)),
118
+ name: Schema2.String.check(Schema2.isMinLength(1)),
119
+ repositoryUrl: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1))),
120
+ pathPrefix: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1))),
121
+ defaultTargetBranch: Schema2.String.check(Schema2.isMinLength(1)),
122
+ expectedBranch: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1))),
123
+ expectedCommitSha: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1)))
124
+ });
125
+ var WorkUnitLeaseInput = Schema2.Struct({
126
+ leaseOwnerId: Id,
127
+ runnerReplicaId: Id,
128
+ leaseId: Id,
129
+ attempt: Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(1)),
130
+ fencingToken: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240), Schema2.isPattern(new RegExp("^[A-Za-z0-9._:-]+$", "u"))),
131
+ capacitySlot: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240))
132
+ });
133
+ var WorkUnitStatus = Schema2.Union([
134
+ Schema2.Literal("pending"),
135
+ Schema2.Literal("claimed"),
136
+ Schema2.Literal("running"),
137
+ Schema2.Literal("waiting"),
138
+ Schema2.Literal("blocked"),
139
+ Schema2.Literal("completed"),
140
+ Schema2.Literal("failed"),
141
+ Schema2.Literal("canceled"),
142
+ Schema2.Literal("expired")
143
+ ]);
144
+ var LoopCheckout = Schema2.Union([Schema2.Literal("none"), Schema2.Literal("read"), Schema2.Literal("write")]);
145
+ var AgentStepWorkUnit = Schema2.Struct({
146
+ kind: Schema2.Literal("agent_step"),
147
+ id: Id,
148
+ projectId: Schema2.optionalKey(Id),
149
+ runId: Id,
150
+ stepKey: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
151
+ attempt: Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(1)),
152
+ lease: WorkUnitLease,
153
+ brief: StepBrief,
154
+ stepCredential: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(512)),
155
+ checkout: LoopCheckout,
156
+ repoBinding: Schema2.optionalKey(WorkUnitRepoBinding),
157
+ branch: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1))),
158
+ baseRevision: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1))),
159
+ network: Schema2.optionalKey(AgentSandboxNetwork),
160
+ sandbox: Schema2.optionalKey(Schema2.Literal("docker")),
161
+ secrets: Schema2.optionalKey(Schema2.Record(Schema2.String, Schema2.String)),
162
+ runBaseRevision: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1)))
163
+ });
164
+ var RunJournal = Schema2.Struct({
165
+ activities: Schema2.Record(Schema2.String, Schema2.Unknown),
166
+ deferreds: Schema2.Record(Schema2.String, Schema2.Unknown)
167
+ });
168
+ var OrchestrationWorkUnit = Schema2.Struct({
169
+ kind: Schema2.Literal("orchestration"),
170
+ id: Id,
171
+ projectId: Schema2.optionalKey(Id),
172
+ runId: Id,
173
+ loopDigest: Schema2.String.check(Schema2.isMinLength(64), Schema2.isMaxLength(64), Schema2.isPattern(new RegExp("^[a-f0-9]{64}$", "u"))),
174
+ input: Schema2.Unknown,
175
+ granted: Schema2.Array(Schema2.String),
176
+ lease: WorkUnitLease,
177
+ journal: RunJournal,
178
+ network: Schema2.optionalKey(AgentSandboxNetwork),
179
+ program: Schema2.Struct({
180
+ loopId: Schema2.String.check(Schema2.isMinLength(1)),
181
+ credential: Schema2.String.check(Schema2.isMinLength(1))
182
+ })
183
+ });
184
+ var ProgramWorkUnit = OrchestrationWorkUnit.mapFields(Struct3.omit(["program"]));
185
+ var ApprovedCheck = Schema2.Struct({
186
+ name: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(120), Schema2.isPattern(new RegExp("^[A-Za-z0-9][A-Za-z0-9._:-]*$", "u"))),
187
+ command: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(2000)),
188
+ workingDirectory: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(500)))
189
+ });
190
+ var VerificationWorkUnit = Schema2.Struct({
191
+ kind: Schema2.Literal("verification"),
192
+ id: Id,
193
+ projectId: Id,
194
+ runId: Id,
195
+ stepKey: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
196
+ lease: WorkUnitLease,
197
+ repoBinding: WorkUnitRepoBinding,
198
+ revision: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
199
+ checks: Schema2.Array(ApprovedCheck).check(Schema2.isMinLength(1), Schema2.isMaxLength(50))
200
+ });
201
+ var WorkUnit = Schema2.Union([OrchestrationWorkUnit, AgentStepWorkUnit, VerificationWorkUnit]);
202
+ var WorkUnitClaimResult = Schema2.Struct({ workUnit: Schema2.optionalKey(WorkUnit) });
203
+ var WorkUnitClaimInput = Schema2.Struct({
204
+ projectId: Schema2.optionalKey(Id),
205
+ runnerReplicaId: Id,
206
+ capacitySlot: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
207
+ idempotencyKey: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
208
+ leaseDurationSeconds: Schema2.optionalKey(Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(1), Schema2.isLessThanOrEqualTo(3600)))
209
+ });
210
+ var WorkUnitHeartbeatInput = Schema2.Struct({
211
+ workUnitId: Id,
212
+ lease: WorkUnitLeaseInput,
213
+ leaseDurationSeconds: Schema2.optionalKey(Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(1), Schema2.isLessThanOrEqualTo(3600)))
214
+ });
215
+ var WorkUnitHeartbeatResult = Schema2.Struct({
216
+ settled: Schema2.Boolean,
217
+ outputSubmitted: Schema2.optionalKey(Schema2.Boolean)
218
+ });
219
+ var WorkUnitReleaseInput = Schema2.Struct({
220
+ workUnitId: Id,
221
+ lease: WorkUnitLeaseInput
222
+ });
223
+ var CheckEvidence = Schema2.Struct({
224
+ name: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(120)),
225
+ command: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(2000)),
226
+ status: Schema2.Union([Schema2.Literal("passed"), Schema2.Literal("failed")]),
227
+ exitCode: Schema2.optionalKey(Schema2.Int),
228
+ durationMs: Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(0)),
229
+ outputTail: Schema2.String.check(Schema2.isMaxLength(8000))
230
+ });
231
+ var TreeEvidence = Schema2.Struct({
232
+ revision: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
233
+ tree: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(120)),
234
+ checks: Schema2.Array(CheckEvidence).check(Schema2.isMaxLength(50))
235
+ });
236
+ var VerificationEvidence = Schema2.Struct({ head: TreeEvidence, baseline: Schema2.optionalKey(TreeEvidence) });
237
+ var BoundaryChange = Schema2.Struct({
238
+ kind: Schema2.Literal("change"),
239
+ changedPaths: Schema2.Array(Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(4096))).check(Schema2.isMaxLength(1000)),
240
+ omittedPaths: Schema2.Int.check(Schema2.isGreaterThanOrEqualTo(0)),
241
+ files: Schema2.Array(Schema2.Struct({
242
+ path: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(4096)),
243
+ excerpt: Schema2.String.check(Schema2.isMaxLength(250000)),
244
+ redacted: Schema2.Boolean,
245
+ truncated: Schema2.Boolean
246
+ })).check(Schema2.isMaxLength(20)),
247
+ truncated: Schema2.Boolean
248
+ });
249
+ var WorkUnitOutcome = Schema2.Struct({
250
+ status: Schema2.Union([
251
+ Schema2.Literal("completed"),
252
+ Schema2.Literal("failed"),
253
+ Schema2.Literal("blocked"),
254
+ Schema2.Literal("canceled")
255
+ ]),
256
+ result: Schema2.optionalKey(LoopStepOutput),
257
+ revision: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(120))),
258
+ evidence: Schema2.optionalKey(VerificationEvidence),
259
+ boundary: Schema2.optionalKey(BoundaryChange),
260
+ failureSummary: Schema2.optionalKey(Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(4000)))
261
+ });
262
+ var WorkUnitCompletion = Schema2.Struct({
263
+ workUnitId: Id,
264
+ lease: WorkUnitLeaseInput,
265
+ idempotencyKey: Schema2.String.check(Schema2.isMinLength(1), Schema2.isMaxLength(240)),
266
+ outcome: WorkUnitOutcome
267
+ });
268
+ // packages/core/src/run-journal.ts
269
+ import * as Effect from "effect/Effect";
270
+ import * as Exit from "effect/Exit";
271
+ import * as Schema3 from "effect/Schema";
272
+ var journalEntryMaxBytes = 256 * 1024;
273
+ var JournalExit = Schema3.toCodecJson(Schema3.Exit(Schema3.Json, Schema3.Json, Schema3.Defect()));
274
+ var encodeJournalExit = (exit) => Schema3.encodeUnknownEffect(JournalExit)(Exit.map(exit, (value) => value ?? null));
275
+ var decodeJournalExit = Schema3.decodeUnknownEffect(JournalExit);
276
+ var JournalStepFailed = Schema3.TaggedStruct("StepFailed", { step: Schema3.String, reason: Schema3.String });
277
+ var JournalChildFailed = Schema3.TaggedStruct("ChildFailed", {
278
+ step: Schema3.String,
279
+ loop: Schema3.String,
280
+ reason: Schema3.String
281
+ });
282
+ var JournalWaitTimedOut = Schema3.TaggedStruct("WaitTimedOut", { step: Schema3.String, event: Schema3.String });
283
+ var journalEntryBytes = (entry) => new TextEncoder().encode(JSON.stringify(entry)).byteLength;
284
+ // packages/sdk/src/program/engine.ts
285
+ import * as Cause from "effect/Cause";
286
+ import * as Data from "effect/Data";
287
+ import * as Duration from "effect/Duration";
288
+ import * as Effect2 from "effect/Effect";
289
+ import * as Exit3 from "effect/Exit";
290
+ import * as Fiber from "effect/Fiber";
291
+ import * as Layer from "effect/Layer";
292
+ import * as Option from "effect/Option";
293
+ import * as Schema5 from "effect/Schema";
294
+
295
+ // packages/live/src/rpc/runner-group.ts
296
+ import * as Schema4 from "effect/Schema";
297
+ import { Rpc, RpcGroup, RpcMiddleware } from "effect/rpc";
298
+ var RunnerHeaders = { runnerId: "x-kitman-runner-id", protocolVersion: "x-kitman-rpc-protocol" };
299
+ var RunnerRpcProtocolVersion = 1;
300
+
301
+ class RunnerRpcError extends Schema4.TaggedError()("RunnerRpcError", {
302
+ code: Schema4.String,
303
+ message: Schema4.String,
304
+ status: Schema4.Finite
305
+ }) {
306
+ }
307
+
308
+ class RunnerAuthentication extends RpcMiddleware.Service()("RunnerAuthentication", {
309
+ error: RunnerRpcError
310
+ }) {
311
+ }
312
+ var EventFilterValue = Schema4.Union([Schema4.String, Schema4.Finite, Schema4.Boolean, Schema4.Null]);
313
+ var WorkAvailable = Schema4.TaggedStruct("WorkAvailable", {});
314
+ var LeaseRevoked = Schema4.TaggedStruct("LeaseRevoked", { workUnitId: Schema4.String });
315
+ var Settled = Schema4.TaggedStruct("Settled", { workUnitId: Schema4.String });
316
+ var Canceled = Schema4.TaggedStruct("Canceled", { workUnitId: Schema4.String });
317
+ var RunSettled = Schema4.TaggedStruct("RunSettled", { runId: Schema4.String });
318
+ var Steer = Schema4.TaggedStruct("Steer", {
319
+ workUnitId: Schema4.String,
320
+ messageId: Schema4.String,
321
+ text: Schema4.String
322
+ });
323
+ var SessionUpdated = Schema4.TaggedStruct("SessionUpdated", { workUnitId: Schema4.String });
324
+ var RunnerSignal = Schema4.Union([
325
+ WorkAvailable,
326
+ LeaseRevoked,
327
+ Settled,
328
+ Canceled,
329
+ RunSettled,
330
+ Steer,
331
+ SessionUpdated
332
+ ]);
333
+ var ProgramLease = Schema4.Struct({
334
+ workUnitId: Schema4.String,
335
+ leaseOwnerId: Schema4.String,
336
+ runnerReplicaId: Schema4.String,
337
+ leaseId: Schema4.String,
338
+ attempt: Schema4.Int,
339
+ fencingToken: Schema4.String,
340
+ capacitySlot: Schema4.String
341
+ });
342
+ var CheckpointSession = Schema4.Struct({
343
+ harness: Schema4.String,
344
+ id: Schema4.String,
345
+ name: Schema4.String,
346
+ content: Schema4.Uint8ArrayFromBase64
347
+ });
348
+ var StepCheckpoint = Schema4.Struct({
349
+ ref: Schema4.optionalKey(Schema4.String),
350
+ revision: Schema4.optionalKey(Schema4.String),
351
+ session: Schema4.optionalKey(CheckpointSession)
352
+ });
353
+ var SuggestedVerification = Schema4.Struct({
354
+ name: Schema4.String,
355
+ command: Schema4.String,
356
+ workingDirectory: Schema4.optional(Schema4.String)
357
+ });
358
+ var ProgramOutcome = Schema4.Union([
359
+ Schema4.Struct({ status: Schema4.Literal("completed"), output: Schema4.Json }),
360
+ Schema4.Struct({ status: Schema4.Literal("failed"), failureSummary: Schema4.String })
361
+ ]);
362
+
363
+ class RunnerRpcs extends RpcGroup.make(Rpc.make("Claim", {
364
+ payload: WorkUnitClaimInput,
365
+ success: WorkUnitClaimResult,
366
+ error: RunnerRpcError
367
+ }), Rpc.make("Heartbeat", {
368
+ payload: WorkUnitHeartbeatInput,
369
+ success: WorkUnitHeartbeatResult,
370
+ error: RunnerRpcError
371
+ }), Rpc.make("Complete", {
372
+ payload: WorkUnitCompletion,
373
+ error: RunnerRpcError
374
+ }), Rpc.make("Release", {
375
+ payload: WorkUnitReleaseInput,
376
+ error: RunnerRpcError
377
+ }), Rpc.make("RecordActivity", {
378
+ payload: { lease: ProgramLease, name: Schema4.String, attempt: Schema4.Int, exit: Schema4.Json },
379
+ error: RunnerRpcError
380
+ }), Rpc.make("DeferredDone", {
381
+ payload: { lease: ProgramLease, name: Schema4.String, exit: Schema4.Json },
382
+ error: RunnerRpcError
383
+ }), Rpc.make("ScheduleClock", {
384
+ payload: { lease: ProgramLease, name: Schema4.String, deferredName: Schema4.String, durationMillis: Schema4.Int },
385
+ error: RunnerRpcError
386
+ }), Rpc.make("PutQuestion", {
387
+ payload: {
388
+ lease: ProgramLease,
389
+ step: Schema4.String,
390
+ prompt: Schema4.String,
391
+ options: Schema4.optional(Schema4.Array(Schema4.String)),
392
+ verification: Schema4.optional(SuggestedVerification),
393
+ deferredName: Schema4.String
394
+ },
395
+ success: Schema4.Struct({ questionId: Schema4.String }),
396
+ error: RunnerRpcError
397
+ }), Rpc.make("StartAgentStep", {
398
+ payload: {
399
+ lease: ProgramLease,
400
+ step: Schema4.String,
401
+ deferredName: Schema4.String,
402
+ role: Schema4.String,
403
+ agentId: Schema4.String,
404
+ prompt: Schema4.String,
405
+ outputSchema: Schema4.Json,
406
+ secrets: Schema4.optionalKey(Schema4.Array(Schema4.String))
407
+ },
408
+ success: Schema4.Struct({ stepAttemptId: Schema4.String }),
409
+ error: RunnerRpcError
410
+ }), Rpc.make("StartVerification", {
411
+ payload: {
412
+ lease: ProgramLease,
413
+ step: Schema4.String,
414
+ deferredName: Schema4.String,
415
+ revision: Schema4.optionalKey(Schema4.String),
416
+ checks: Schema4.optional(Schema4.Array(Schema4.String))
417
+ },
418
+ success: Schema4.Struct({ verificationId: Schema4.String }),
419
+ error: RunnerRpcError
420
+ }), Rpc.make("KnownEvidence", {
421
+ payload: { lease: ProgramLease, trees: Schema4.Array(Schema4.String) },
422
+ success: Schema4.Array(Schema4.Struct({ tree: Schema4.String, name: Schema4.String, command: Schema4.String })),
423
+ error: RunnerRpcError
424
+ }), Rpc.make("AwaitEvent", {
425
+ payload: {
426
+ lease: ProgramLease,
427
+ step: Schema4.String,
428
+ deferredName: Schema4.String,
429
+ event: Schema4.String,
430
+ filter: Schema4.optional(Schema4.Record(Schema4.String, Schema4.Union([EventFilterValue, Schema4.Array(EventFilterValue)]))),
431
+ timeoutMillis: Schema4.Int
432
+ },
433
+ error: RunnerRpcError
434
+ }), Rpc.make("AdmitChild", {
435
+ payload: {
436
+ lease: ProgramLease,
437
+ step: Schema4.String,
438
+ loop: Schema4.String,
439
+ input: Schema4.Json,
440
+ deferredName: Schema4.String
441
+ },
442
+ success: Schema4.Struct({ runId: Schema4.String }),
443
+ error: RunnerRpcError
444
+ }), Rpc.make("StoreArtifact", {
445
+ payload: {
446
+ lease: ProgramLease,
447
+ step: Schema4.String,
448
+ kind: Schema4.String,
449
+ title: Schema4.String,
450
+ text: Schema4.String,
451
+ data: Schema4.optional(Schema4.Json)
452
+ },
453
+ success: Schema4.Struct({ artifactId: Schema4.String }),
454
+ error: RunnerRpcError
455
+ }), Rpc.make("RecordNote", {
456
+ payload: {
457
+ lease: ProgramLease,
458
+ step: Schema4.String,
459
+ text: Schema4.String,
460
+ artifactId: Schema4.optional(Schema4.String)
461
+ },
462
+ error: RunnerRpcError
463
+ }), Rpc.make("PerformHostEffect", {
464
+ payload: {
465
+ lease: ProgramLease,
466
+ step: Schema4.String,
467
+ effect: Schema4.Union([
468
+ Schema4.Struct({ kind: Schema4.Literal("post_comment"), changeRequestId: Schema4.String, body: Schema4.String }),
469
+ Schema4.Struct({
470
+ kind: Schema4.Literal("change_request"),
471
+ title: Schema4.String,
472
+ body: Schema4.String,
473
+ integration: Schema4.optionalKey(Schema4.String)
474
+ }),
475
+ Schema4.Struct({
476
+ kind: Schema4.Literal("write_back"),
477
+ milestone: Schema4.optionalKey(Schema4.Literals(["started", "change_request_opened", "merged", "failed"])),
478
+ changeRequestUrl: Schema4.optionalKey(Schema4.String)
479
+ })
480
+ ])
481
+ },
482
+ success: Schema4.UndefinedOr(Schema4.Struct({ id: Schema4.String, number: Schema4.String, url: Schema4.String })),
483
+ error: RunnerRpcError
484
+ }), Rpc.make("CreatePlanTasks", {
485
+ payload: {
486
+ lease: ProgramLease,
487
+ tickets: Schema4.Array(Schema4.Struct({
488
+ key: Schema4.String,
489
+ title: Schema4.String,
490
+ body: Schema4.String,
491
+ acceptanceCriteria: Schema4.Array(Schema4.String),
492
+ blockedBy: Schema4.Array(Schema4.String),
493
+ outcome: Schema4.optionalKey(Schema4.Literals(["feature", "bug", "refactor", "investigation", "docs", "migration"]))
494
+ }))
495
+ },
496
+ success: Schema4.Array(Schema4.Struct({ key: Schema4.String, taskId: Schema4.String })),
497
+ error: RunnerRpcError
498
+ }), Rpc.make("IntegrationBranch", {
499
+ payload: { lease: ProgramLease, repoBindingId: Schema4.optionalKey(Schema4.String) },
500
+ success: Schema4.Struct({ repoBindingId: Schema4.String, branch: Schema4.String, revision: Schema4.String }),
501
+ error: RunnerRpcError
502
+ }), Rpc.make("MergeChangeRequest", {
503
+ payload: { lease: ProgramLease, step: Schema4.String, changeRequestId: Schema4.String },
504
+ success: Schema4.Union([
505
+ Schema4.Struct({ status: Schema4.Literal("merged"), revision: Schema4.String }),
506
+ Schema4.Struct({ status: Schema4.Literal("conflict") })
507
+ ]),
508
+ error: RunnerRpcError
509
+ }), Rpc.make("PublishRelease", {
510
+ payload: {
511
+ lease: ProgramLease,
512
+ step: Schema4.String,
513
+ tag: Schema4.String,
514
+ revision: Schema4.optionalKey(Schema4.String),
515
+ title: Schema4.String,
516
+ notes: Schema4.String
517
+ },
518
+ success: Schema4.Struct({ tag: Schema4.String, revision: Schema4.String, url: Schema4.String }),
519
+ error: RunnerRpcError
520
+ }), Rpc.make("ReportSteer", {
521
+ payload: { workUnitId: Schema4.String, messageId: Schema4.String, delivered: Schema4.Boolean },
522
+ success: Schema4.Void,
523
+ error: RunnerRpcError
524
+ }), Rpc.make("SaveCheckpoint", {
525
+ payload: { lease: ProgramLease, checkpoint: StepCheckpoint },
526
+ success: Schema4.Void,
527
+ error: RunnerRpcError
528
+ }), Rpc.make("ResumeCheckpoint", {
529
+ payload: { lease: ProgramLease },
530
+ success: Schema4.UndefinedOr(StepCheckpoint),
531
+ error: RunnerRpcError
532
+ }), Rpc.make("SettledCheckpoints", {
533
+ success: Schema4.Array(Schema4.Struct({
534
+ stepAttemptId: Schema4.String,
535
+ ref: Schema4.optionalKey(Schema4.String),
536
+ repoBinding: Schema4.optionalKey(WorkUnitRepoBinding)
537
+ })),
538
+ error: RunnerRpcError
539
+ }), Rpc.make("ForgetCheckpoints", {
540
+ payload: { stepAttemptIds: Schema4.Array(Schema4.String) },
541
+ success: Schema4.Void,
542
+ error: RunnerRpcError
543
+ }), Rpc.make("Bundle", {
544
+ payload: { digest: Schema4.String },
545
+ success: Schema4.Struct({ bundle: Schema4.String }),
546
+ error: RunnerRpcError
547
+ }), Rpc.make("SettledRuns", {
548
+ payload: { runIds: Schema4.Array(Schema4.String) },
549
+ success: Schema4.Array(Schema4.String),
550
+ error: RunnerRpcError
551
+ }), Rpc.make("ProgramSecrets", {
552
+ payload: { lease: ProgramLease },
553
+ success: Schema4.Record(Schema4.String, Schema4.String),
554
+ error: RunnerRpcError
555
+ }), Rpc.make("Suspend", { payload: { lease: ProgramLease }, error: RunnerRpcError }), Rpc.make("FinishProgram", { payload: { lease: ProgramLease, outcome: ProgramOutcome }, error: RunnerRpcError }), Rpc.make("Signals", {
556
+ payload: { runnerReplicaId: Schema4.String },
557
+ success: RunnerSignal,
558
+ error: RunnerRpcError,
559
+ stream: true
560
+ })).middleware(RunnerAuthentication) {
561
+ }
562
+
563
+ // packages/sdk/src/program/engine.ts
564
+ import { Workflow, WorkflowEngine } from "effect/workflow";
565
+
566
+ class JournalWriteFailed2 extends Data.TaggedError("JournalWriteFailed") {
567
+ get message() {
568
+ return `Journal write failed: ${this.cause.message}`;
569
+ }
570
+ }
571
+ var written = (effect) => effect.pipe(Effect2.catch((cause) => Effect2.die(new JournalWriteFailed2({ cause }))));
572
+ var entryFor = (name, exit) => Effect2.gen(function* () {
573
+ const entry = yield* Effect2.orDie(encodeJournalExit(exit));
574
+ const bytes = journalEntryBytes(entry);
575
+ if (bytes > journalEntryMaxBytes)
576
+ return yield* Effect2.die(`"${name}" result is over the ${journalEntryMaxBytes}-byte journal cap (${bytes} bytes); store large content as a Run artifact`);
577
+ return entry;
578
+ });
579
+ var decoded = (entry) => Effect2.orDie(decodeJournalExit(entry));
580
+ var JournalEntries = Schema5.Record(Schema5.String, Schema5.Json);
581
+ var isSuspended = Schema5.is(Workflow.Suspended);
582
+ var makeEncodedEngine = (recorded, journal) => Effect2.gen(function* () {
583
+ const scope2 = yield* Effect2.scope;
584
+ const entries = (journalPart) => Effect2.map(Effect2.orDie(Schema5.decodeUnknownEffect(JournalEntries)(journalPart)), Object.entries);
585
+ const activities = new Map(yield* entries(recorded.activities));
586
+ const deferreds = new Map(yield* entries(recorded.deferreds));
587
+ const workflows = new Map;
588
+ const executions = new Map;
589
+ const start = (executionId, execution) => Effect2.gen(function* () {
590
+ const execute = workflows.get(execution.workflow._tag);
591
+ if (execute === undefined)
592
+ return yield* Effect2.die(`Workflow ${execution.workflow._tag} is not registered`);
593
+ const instance = WorkflowEngine.WorkflowInstance.initial(execution.workflow, executionId);
594
+ execution.fiber = yield* execute(execution.payload, executionId).pipe(Workflow.intoResult, Effect2.provideService(WorkflowEngine.WorkflowEngine, engine), Effect2.provideService(WorkflowEngine.WorkflowInstance, instance), Effect2.forkIn(scope2));
595
+ });
596
+ const encoded = {
597
+ register: (workflow, execute) => Effect2.sync(() => void workflows.set(workflow._tag, execute)),
598
+ execute: (workflow, options) => Effect2.gen(function* () {
599
+ let execution = executions.get(options.executionId);
600
+ if (execution === undefined) {
601
+ execution = { workflow, payload: options.payload, fiber: undefined };
602
+ executions.set(options.executionId, execution);
603
+ yield* start(options.executionId, execution);
604
+ }
605
+ if (options.discard || execution.fiber === undefined)
606
+ return;
607
+ return yield* Fiber.join(execution.fiber);
608
+ }),
609
+ poll: (_workflow, executionId) => Effect2.sync(() => {
610
+ const exit = executions.get(executionId)?.fiber?.pollUnsafe();
611
+ return exit !== undefined && Exit3.isSuccess(exit) ? Option.some(exit.value) : Option.none();
612
+ }),
613
+ interrupt: (_workflow, executionId) => interrupt2(executionId),
614
+ interruptUnsafe: (_workflow, executionId) => interrupt2(executionId),
615
+ resume: (_workflow, executionId) => Effect2.suspend(() => {
616
+ const execution = executions.get(executionId);
617
+ const exit = execution?.fiber?.pollUnsafe();
618
+ return execution !== undefined && exit !== undefined && Exit3.isSuccess(exit) && isSuspended(exit.value) ? start(executionId, execution) : Effect2.void;
619
+ }),
620
+ activityExecute: (activity, attempt) => Effect2.gen(function* () {
621
+ const key = `${activity.name}/${attempt}`;
622
+ const replayed = activities.get(key);
623
+ if (replayed !== undefined)
624
+ return new Workflow.Complete({ exit: yield* decoded(replayed) });
625
+ const instance = yield* WorkflowEngine.WorkflowInstance;
626
+ const result = yield* activity.executeEncoded.pipe(Workflow.intoResult, Effect2.provideService(WorkflowEngine.WorkflowInstance, WorkflowEngine.WorkflowInstance.initial(instance.workflow, instance.executionId)));
627
+ if (result instanceof Workflow.Complete && !(Exit3.isFailure(result.exit) && journalLoss(result.exit.cause))) {
628
+ const entry = yield* entryFor(activity.name, result.exit);
629
+ yield* written(journal.recordActivity({ name: activity.name, attempt, exit: entry }));
630
+ activities.set(key, entry);
631
+ }
632
+ return result;
633
+ }),
634
+ deferredResult: (deferred) => Effect2.suspend(() => {
635
+ const entry = deferreds.get(deferred.name);
636
+ return entry === undefined ? Effect2.succeedNone : Effect2.asSome(decoded(entry));
637
+ }),
638
+ deferredDone: (options) => Effect2.gen(function* () {
639
+ if (deferreds.has(options.deferredName))
640
+ return;
641
+ const entry = yield* entryFor(options.deferredName, options.exit);
642
+ yield* written(journal.deferredDone({ name: options.deferredName, exit: entry }));
643
+ deferreds.set(options.deferredName, entry);
644
+ yield* encoded.resume(executions.get(options.executionId)?.workflow ?? emptyWorkflow, options.executionId);
645
+ }),
646
+ scheduleClock: (_workflow, { clock }) => deferreds.has(clock.deferred.name) ? Effect2.void : written(journal.scheduleClock({
647
+ name: clock.name,
648
+ deferredName: clock.deferred.name,
649
+ durationMillis: Duration.toMillis(clock.duration)
650
+ }))
651
+ };
652
+ const interrupt2 = (executionId) => Effect2.suspend(() => {
653
+ const fiber = executions.get(executionId)?.fiber;
654
+ return fiber === undefined ? Effect2.void : Fiber.interrupt(fiber);
655
+ });
656
+ const engine = WorkflowEngine.makeUnsafe(encoded);
657
+ return { engine, encoded };
658
+ });
659
+ var emptyWorkflow = Workflow.make("kitman-loop/none", { payload: {}, idempotencyKey: () => "none" });
660
+ var replayStatuses = new Set([401, 403, 409, 429]);
661
+ var isRunnerRpcError = Schema5.is(RunnerRpcError);
662
+ var refusedStep2 = (cause) => {
663
+ if ("code" in cause && (cause.code === "capability_denied" || cause.code === "step_refused"))
664
+ return true;
665
+ return isRunnerRpcError(cause) && cause.status >= 400 && cause.status < 500 && !replayStatuses.has(cause.status);
666
+ };
667
+ var requested = (step, request) => request.pipe(Effect2.catch((cause) => refusedStep2(cause) ? Effect2.fail(new StepFailed2({ step, reason: cause.message })) : Effect2.die(new JournalWriteFailed2({ cause }))));
668
+ var runnerHost = (journal) => ({
669
+ putQuestion: (launch) => requested(launch.step, journal.putQuestion({
670
+ step: launch.step,
671
+ prompt: launch.prompt,
672
+ deferredName: answerDeferred2(launch.step).name,
673
+ ...launch.options === undefined ? undefined : { options: launch.options },
674
+ ...launch.verification === undefined ? undefined : { verification: launch.verification }
675
+ })).pipe(Effect2.asVoid),
676
+ startVerification: (launch) => requested(launch.step, journal.startVerification({
677
+ step: launch.step,
678
+ deferredName: verifyDeferred2(launch.step).name,
679
+ ...launch.revision === undefined ? undefined : { revision: launch.revision },
680
+ ...launch.checks === undefined ? undefined : { checks: launch.checks }
681
+ })).pipe(Effect2.asVoid),
682
+ startAgentWork: (launch) => requested(launch.step, journal.startAgentStep({
683
+ step: launch.step,
684
+ deferredName: agentWorkDeferred2(launch.step).name,
685
+ role: launch.role,
686
+ agentId: launch.agent,
687
+ prompt: launch.prompt,
688
+ outputSchema: launch.output,
689
+ ...launch.secrets === undefined ? undefined : { secrets: launch.secrets }
690
+ })).pipe(Effect2.asVoid),
691
+ admitChild: (launch) => requested(launch.step, journal.admitChild({
692
+ step: launch.step,
693
+ loop: launch.loop,
694
+ input: launch.input,
695
+ deferredName: childDeferred2(launch.step).name
696
+ })).pipe(Effect2.asVoid),
697
+ awaitEvent: (launch) => requested(launch.step, journal.awaitEvent({
698
+ step: launch.step,
699
+ deferredName: eventDeferred2(launch.step).name,
700
+ event: launch.event,
701
+ ...launch.filter === undefined ? undefined : { filter: launch.filter },
702
+ timeoutMillis: launch.timeoutMillis
703
+ }))
704
+ });
705
+ var runnerActivities = (journal) => ({
706
+ changeRequest: {
707
+ run: (request, step) => requested(step, journal.performHostEffect({
708
+ step,
709
+ effect: {
710
+ kind: "change_request",
711
+ title: request.title,
712
+ body: request.body,
713
+ ...request.integration === undefined ? undefined : { integration: request.integration }
714
+ }
715
+ })).pipe(Effect2.filterOrFail((opened) => opened !== undefined, () => new StepFailed2({ step, reason: "Kitman opened no ChangeRequest" })))
716
+ },
717
+ writeBack: {
718
+ run: (request, step) => requested(step, journal.performHostEffect({
719
+ step,
720
+ effect: {
721
+ kind: "write_back",
722
+ ...request.milestone === undefined ? undefined : { milestone: request.milestone },
723
+ ...request.changeRequestUrl === undefined ? undefined : { changeRequestUrl: request.changeRequestUrl }
724
+ }
725
+ })).pipe(Effect2.asVoid)
726
+ },
727
+ artifact: { run: (request, step) => requested(step, journal.storeArtifact({ step, ...request })) },
728
+ note: { run: (request, step) => requested(step, journal.recordNote({ step, ...request })) },
729
+ createTasks: {
730
+ run: (request, step) => requested(step, Effect2.map(journal.createPlanTasks(request.tickets), (tasks) => ({ tasks })))
731
+ },
732
+ integrationBranch: {
733
+ run: (request, step) => requested(step, journal.integrationBranch(request.repoBindingId))
734
+ },
735
+ mergeChangeRequest: {
736
+ run: (request, step) => requested(step, journal.mergeChangeRequest({ step, ...request }))
737
+ },
738
+ release: {
739
+ run: ({ revision, ...request }, step) => requested(step, journal.publishRelease({ step, ...request, ...revision === undefined ? undefined : { revision } }))
740
+ },
741
+ comment: {
742
+ run: (request, step) => requested(step, journal.performHostEffect({ step, effect: { kind: "post_comment", ...request } })).pipe(Effect2.asVoid)
743
+ }
744
+ });
745
+ var describeFailure = (cause) => {
746
+ const error = Cause.squash(cause);
747
+ const summary = error instanceof Error ? "_tag" in error ? `${String(error._tag)}: ${error.message}` : error.message : String(error);
748
+ return summary.slice(0, 4000) || "Program failed";
749
+ };
750
+ var journalLoss = (cause) => cause.reasons.flatMap((reason) => Cause.isDieReason(reason) && reason.defect instanceof JournalWriteFailed2 ? [reason.defect] : [])[0];
751
+ var runProgram2 = (loop, work, journal) => Effect2.scoped(Effect2.gen(function* () {
752
+ const { engine, encoded } = yield* makeEncodedEngine(work.journal, journal);
753
+ const workflow = loopWorkflow2(loop);
754
+ const execute = executeLoop2(loop, {
755
+ host: runnerHost(journal),
756
+ activities: runnerActivities(journal),
757
+ granted: new Set(loop.capabilities.filter((capability) => work.granted.includes(capability)))
758
+ });
759
+ yield* Layer.build(workflow.toLayer(execute).pipe(Layer.provide(Layer.succeed(WorkflowEngine.WorkflowEngine)(engine))));
760
+ const result = yield* encoded.execute(workflow, {
761
+ executionId: work.runId,
762
+ payload: { input: work.input },
763
+ discard: false
764
+ });
765
+ if (isSuspended(result)) {
766
+ yield* written(journal.suspend);
767
+ return "suspended";
768
+ }
769
+ if (Exit3.isSuccess(result.exit)) {
770
+ const output = yield* Schema5.encodeUnknownEffect(Schema5.toCodecJson(loop.output))(result.exit.value).pipe(Effect2.flatMap(Schema5.decodeUnknownEffect(Schema5.Json)), Effect2.option);
771
+ if (Option.isSome(output)) {
772
+ yield* written(journal.finish({ status: "completed", output: output.value }));
773
+ return "completed";
774
+ }
775
+ yield* written(journal.finish({ status: "failed", failureSummary: "Program output does not encode as JSON" }));
776
+ return "failed";
777
+ }
778
+ const lost = journalLoss(result.exit.cause);
779
+ if (lost !== undefined)
780
+ return yield* lost;
781
+ yield* written(journal.finish({ status: "failed", failureSummary: describeFailure(result.exit.cause) }));
782
+ return "failed";
783
+ })).pipe(Effect2.catchDefect((defect) => defect instanceof JournalWriteFailed2 ? Effect2.fail(defect) : Effect2.die(defect)));
784
+ var programLease2 = (work) => ({
785
+ workUnitId: work.id,
786
+ leaseOwnerId: work.lease.leaseOwnerId,
787
+ runnerReplicaId: work.lease.runnerReplicaId,
788
+ leaseId: work.lease.leaseId,
789
+ attempt: work.lease.attempt,
790
+ fencingToken: work.lease.fencingToken,
791
+ capacitySlot: work.lease.capacitySlot
792
+ });
793
+ var rpcProgramJournal2 = (rpc, work) => {
794
+ const lease = programLease2(work);
795
+ return {
796
+ recordActivity: (entry) => rpc.recordActivity({ lease, ...entry }),
797
+ deferredDone: (entry) => rpc.deferredDone({ lease, ...entry }),
798
+ scheduleClock: (clock) => rpc.scheduleClock({ lease, ...clock }),
799
+ putQuestion: (question) => rpc.putQuestion({
800
+ lease,
801
+ step: question.step,
802
+ prompt: question.prompt,
803
+ deferredName: question.deferredName,
804
+ ...question.options === undefined ? undefined : { options: [...question.options] },
805
+ ...question.verification === undefined ? undefined : { verification: question.verification }
806
+ }),
807
+ startVerification: (verification) => rpc.startVerification({
808
+ lease,
809
+ step: verification.step,
810
+ deferredName: verification.deferredName,
811
+ ...verification.revision === undefined ? undefined : { revision: verification.revision },
812
+ ...verification.checks === undefined ? undefined : { checks: [...verification.checks] }
813
+ }),
814
+ startAgentStep: ({ secrets, ...step }) => rpc.startAgentStep({ lease, ...step, ...secrets === undefined ? undefined : { secrets: [...secrets] } }),
815
+ awaitEvent: (wait) => rpc.awaitEvent({ lease, ...wait }),
816
+ admitChild: (child) => rpc.admitChild({ lease, ...child }),
817
+ storeArtifact: (artifact) => rpc.storeArtifact({ lease, ...artifact }),
818
+ recordNote: (note) => rpc.recordNote({ lease, ...note }),
819
+ performHostEffect: (request) => rpc.performHostEffect({ lease, ...request }),
820
+ createPlanTasks: (tickets) => rpc.createPlanTasks({
821
+ lease,
822
+ tickets: tickets.map((ticket) => ({
823
+ key: ticket.key,
824
+ title: ticket.title,
825
+ body: ticket.body,
826
+ acceptanceCriteria: ticket.acceptanceCriteria,
827
+ blockedBy: ticket.blockedBy,
828
+ ...ticket.outcome === undefined ? undefined : { outcome: ticket.outcome }
829
+ }))
830
+ }),
831
+ integrationBranch: (repoBindingId) => rpc.integrationBranch({ lease, ...repoBindingId === undefined ? undefined : { repoBindingId } }),
832
+ mergeChangeRequest: (request) => rpc.mergeChangeRequest({ lease, ...request }),
833
+ publishRelease: (request) => rpc.publishRelease({ lease, ...request }),
834
+ suspend: rpc.suspend({ lease }),
835
+ finish: (outcome) => rpc.finishProgram({ lease, outcome })
836
+ };
837
+ };
838
+
839
+ // packages/live/src/rpc/runner-client.ts
840
+ import * as Effect3 from "effect/Effect";
841
+ import * as Layer2 from "effect/Layer";
842
+ import * as Stream from "effect/Stream";
843
+ import { RpcClient, RpcSerialization } from "effect/rpc";
844
+ import * as Socket from "effect/socket/Socket";
845
+ var proxiedWebSocket = (proxy) => Layer2.succeed(Socket.WebSocketConstructor)((target) => {
846
+ const options = { proxy };
847
+ return Reflect.construct(globalThis.WebSocket, [target, options]);
848
+ });
849
+ var runnerWebSocketProtocol = (url, options = {}) => RpcClient.layerProtocolSocket({ retryTransientErrors: true }).pipe(Layer2.provide(Socket.layerWebSocket(url)), Layer2.provide(options.proxy === undefined ? Socket.layerWebSocketConstructorGlobal : proxiedWebSocket(options.proxy)), Layer2.provide(RpcSerialization.layerJson));
850
+ function runnerRpcUrl(apiUrl) {
851
+ const url = new URL("/v1/runners/rpc", apiUrl);
852
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
853
+ return url.toString();
854
+ }
855
+ var makeRunnerRpcClient = (options) => Effect3.gen(function* () {
856
+ const protocol = yield* Layer2.build(options.protocol);
857
+ const client = yield* RpcClient.make(RunnerRpcs).pipe(Effect3.provideContext(protocol));
858
+ const authorized = (call) => Effect3.flatMap(options.bearer, (token) => RpcClient.withHeaders(call, {
859
+ authorization: `Bearer ${token}`,
860
+ [RunnerHeaders.runnerId]: options.runnerId,
861
+ [RunnerHeaders.protocolVersion]: String(RunnerRpcProtocolVersion)
862
+ }));
863
+ return {
864
+ claim: (input) => authorized(client.Claim(input)),
865
+ heartbeat: (input) => authorized(client.Heartbeat(input)),
866
+ complete: (input) => authorized(client.Complete(input)),
867
+ release: (input) => authorized(client.Release(input)),
868
+ recordActivity: (input) => authorized(client.RecordActivity(input)),
869
+ deferredDone: (input) => authorized(client.DeferredDone(input)),
870
+ scheduleClock: (input) => authorized(client.ScheduleClock(input)),
871
+ putQuestion: (input) => authorized(client.PutQuestion(input)),
872
+ programSecrets: (input) => authorized(client.ProgramSecrets(input)),
873
+ suspend: (input) => authorized(client.Suspend(input)),
874
+ finishProgram: (input) => authorized(client.FinishProgram(input)),
875
+ startAgentStep: (input) => authorized(client.StartAgentStep(input)),
876
+ startVerification: (input) => authorized(client.StartVerification(input)),
877
+ knownEvidence: (input) => authorized(client.KnownEvidence(input)),
878
+ awaitEvent: (input) => authorized(client.AwaitEvent(input)),
879
+ admitChild: (input) => authorized(client.AdmitChild(input)),
880
+ storeArtifact: (input) => authorized(client.StoreArtifact(input)),
881
+ recordNote: (input) => authorized(client.RecordNote(input)),
882
+ performHostEffect: (input) => authorized(client.PerformHostEffect(input)),
883
+ createPlanTasks: (input) => authorized(client.CreatePlanTasks(input)),
884
+ integrationBranch: (input) => authorized(client.IntegrationBranch(input)),
885
+ mergeChangeRequest: (input) => authorized(client.MergeChangeRequest(input)),
886
+ publishRelease: (input) => authorized(client.PublishRelease(input)),
887
+ bundle: (digest) => authorized(client.Bundle({ digest })),
888
+ settledRuns: (runIds) => authorized(client.SettledRuns({ runIds })),
889
+ reportSteer: (input) => authorized(client.ReportSteer(input)),
890
+ saveCheckpoint: (input) => authorized(client.SaveCheckpoint(input)),
891
+ resumeCheckpoint: (input) => authorized(client.ResumeCheckpoint(input)),
892
+ settledCheckpoints: authorized(client.SettledCheckpoints()),
893
+ forgetCheckpoints: (stepAttemptIds) => authorized(client.ForgetCheckpoints({ stepAttemptIds })),
894
+ listen: (runnerReplicaId, onSignal) => authorized(Stream.runForEach(client.Signals({ runnerReplicaId }), onSignal))
895
+ };
896
+ });
897
+
898
+ // packages/sdk/src/program/host.ts
899
+ import * as BunRuntime from "@effect/platform-bun/BunRuntime";
900
+ import * as Config from "effect/Config";
901
+ import * as ConfigProvider from "effect/ConfigProvider";
902
+ import * as Effect4 from "effect/Effect";
903
+ import * as Option2 from "effect/Option";
904
+ import * as Redacted2 from "effect/Redacted";
905
+ import * as Schema6 from "effect/Schema";
906
+ var describeFlag2 = "--kitman-describe";
907
+ var Described2 = Schema6.Union([
908
+ Schema6.TaggedStruct("Described", {
909
+ loops: Schema6.Array(LoopManifest),
910
+ agents: Schema6.Record(Schema6.String, Schema6.Json),
911
+ schedules: Schema6.optionalKey(Schema6.Record(Schema6.String, Schema6.Json)),
912
+ kits: Schema6.optionalKey(Schema6.Record(Schema6.String, Schema6.Json))
913
+ }),
914
+ Schema6.TaggedStruct("Refused", { error: Schema6.Union([ManifestInvalid2, LoopCheckError2]) })
915
+ ]);
916
+ var encodeDescribed = Schema6.encodeEffect(Schema6.fromJsonString(Schema6.toCodecJson(Described2)));
917
+
918
+ class ProgramRefused extends Schema6.TaggedError()("ProgramRefused", { reason: Schema6.String }) {
919
+ get message() {
920
+ return this.reason;
921
+ }
922
+ }
923
+ var programSecrets2 = (rpc, lease) => rpc.programSecrets({ lease }).pipe(Effect4.asSome, Effect4.catchIf(refusedStep2, (error) => Effect4.as(rpc.finishProgram({
924
+ lease,
925
+ outcome: { status: "failed", failureSummary: `Kitman refused the Loop its Secrets: ${error.message}` }
926
+ }), Option2.none())));
927
+ var programHostsEnv2 = "KITMAN_PROGRAM_HOSTS";
928
+ var undeclaredHostsEnv2 = "KITMAN_UNDECLARED_HOSTS";
929
+ var allows = (hosts, host) => hosts.some((entry) => entry === host || entry.startsWith("*.") && host.endsWith(entry.slice(1)));
930
+ var redirectStatuses = new Set([301, 302, 303, 307, 308]);
931
+ var maxRedirects = 20;
932
+ var requestBodyHeaders = [
933
+ "content-type",
934
+ "content-length",
935
+ "content-encoding",
936
+ "content-language",
937
+ "content-location"
938
+ ];
939
+ var credentialHeaders = ["authorization", "cookie", "proxy-authorization"];
940
+ var networkGuard2 = (input) => {
941
+ const warned = new Set;
942
+ let refused;
943
+ const refusalOf = (host) => {
944
+ if (allows(input.hosts, host))
945
+ return;
946
+ const undeclared = `The program called ${host}, a host its Loop does not declare. Add it to \`network\` in defineLoop`;
947
+ if (input.undeclared === "fail") {
948
+ refused ??= `${undeclared}.`;
949
+ return new Error(`${undeclared}.`);
950
+ }
951
+ if (!warned.has(host))
952
+ input.warn(`${undeclared}; a shared Runner refuses it.`);
953
+ warned.add(host);
954
+ return;
955
+ };
956
+ const follow = (first) => Effect4.gen(function* () {
957
+ let request = first;
958
+ for (let hops = 0;; hops++) {
959
+ const refusal = refusalOf(new URL(request.url).hostname);
960
+ if (refusal !== undefined)
961
+ return yield* Effect4.die(refusal);
962
+ const sent = request;
963
+ if (sent.redirect !== "follow")
964
+ return yield* Effect4.promise(() => input.fetch(sent));
965
+ const resend = sent.clone();
966
+ const response = yield* Effect4.promise(() => input.fetch(sent, { redirect: "manual" }));
967
+ const location = response.headers.get("location");
968
+ if (!redirectStatuses.has(response.status) || location === null)
969
+ return response;
970
+ if (hops === maxRedirects)
971
+ return yield* Effect4.die(new TypeError("The program followed too many redirects."));
972
+ response.body?.cancel();
973
+ const url = new URL(location, sent.url);
974
+ const asGet = response.status === 303 && sent.method !== "HEAD" || (response.status === 301 || response.status === 302) && sent.method === "POST";
975
+ const headers = new Headers(Array.from(resend.headers));
976
+ if (asGet)
977
+ for (const name of requestBodyHeaders)
978
+ headers.delete(name);
979
+ if (url.origin !== new URL(sent.url).origin)
980
+ for (const name of credentialHeaders)
981
+ headers.delete(name);
982
+ request = new Request(url.href, {
983
+ method: asGet ? "GET" : resend.method,
984
+ headers,
985
+ body: asGet || resend.body === null ? null : yield* Effect4.promise(() => resend.arrayBuffer()),
986
+ signal: sent.signal
987
+ });
988
+ }
989
+ });
990
+ const fetch = (resource, init) => Effect4.runPromise(Effect4.suspend(() => follow(resource instanceof Request ? new Request(resource, init) : new Request(resource instanceof URL ? resource.href : resource, init))));
991
+ const refusal = () => refused === undefined ? undefined : { status: "failed", failureSummary: refused };
992
+ const journal = (journal) => ({
993
+ ...journal,
994
+ suspend: Effect4.suspend(() => {
995
+ const failed = refusal();
996
+ return failed === undefined ? journal.suspend : journal.finish(failed);
997
+ }),
998
+ finish: (outcome) => Effect4.suspend(() => journal.finish(refusal() ?? outcome))
999
+ });
1000
+ return { fetch, journal };
1001
+ };
1002
+ var describe = (config) => Effect4.gen(function* () {
1003
+ const loops = yield* Effect4.forEach(config.loops, loopManifest2);
1004
+ for (const loop of config.loops)
1005
+ for (const check of loop.checks ?? [])
1006
+ yield* checkLoop2(loop, check);
1007
+ return {
1008
+ _tag: "Described",
1009
+ loops,
1010
+ agents: config.agents ?? {},
1011
+ ...config.schedules === undefined ? undefined : { schedules: config.schedules },
1012
+ ...config.kits === undefined ? undefined : { kits: config.kits }
1013
+ };
1014
+ }).pipe(Effect4.catch((error) => Effect4.succeed({ _tag: "Refused", error })), Effect4.flatMap(encodeDescribed), Effect4.flatMap((described) => Effect4.callback((resume) => void process.stdout.write(described, () => resume(Effect4.void)))), Effect4.as(0));
1015
+ var readStdin = Effect4.tryPromise(() => Bun.stdin.text());
1016
+ var isWorkUnit = guard(ProgramWorkUnit);
1017
+ var host = (config) => Effect4.gen(function* () {
1018
+ const loopId = yield* Config.String("KITMAN_LOOP_ID");
1019
+ const apiUrl = yield* Config.String("KITMAN_API_URL");
1020
+ const credential = yield* Config.Redacted("KITMAN_PROGRAM_CREDENTIAL");
1021
+ const work = yield* Schema6.decodeEffect(Schema6.fromJsonString(Schema6.Unknown))(yield* readStdin);
1022
+ if (!isWorkUnit(work))
1023
+ return yield* new ProgramRefused({ reason: "stdin holds no orchestration Work Unit" });
1024
+ const loop = config.loops.find((candidate) => candidate.id === loopId);
1025
+ if (loop === undefined)
1026
+ return yield* new ProgramRefused({ reason: `The Package declares no Loop "${loopId}"` });
1027
+ const hosts = yield* Config.option(Config.String(programHostsEnv2));
1028
+ const undeclared = yield* Config.option(Config.Literals(["fail", "warn"], undeclaredHostsEnv2));
1029
+ const proxy = yield* Config.option(Config.String("HTTPS_PROXY"));
1030
+ const rpc = yield* makeRunnerRpcClient({
1031
+ runnerId: work.lease.leaseOwnerId,
1032
+ bearer: Effect4.sync(() => Redacted2.value(credential)),
1033
+ protocol: runnerWebSocketProtocol(runnerRpcUrl(apiUrl), Option2.isSome(proxy) ? { proxy: proxy.value } : {})
1034
+ });
1035
+ const secrets = (loop.secrets ?? []).length === 0 ? Option2.some({}) : yield* programSecrets2(rpc, programLease2(work));
1036
+ if (Option2.isNone(secrets))
1037
+ return 0;
1038
+ const guard = Option2.isNone(hosts) ? undefined : networkGuard2({
1039
+ hosts: hosts.value.split(",").filter((host) => host.length > 0),
1040
+ undeclared: Option2.getOrElse(undeclared, () => "warn"),
1041
+ fetch: globalThis.fetch,
1042
+ warn: (line) => void process.stderr.write(`${line}
1043
+ `)
1044
+ });
1045
+ if (guard !== undefined)
1046
+ globalThis.fetch = Object.assign(guard.fetch, { preconnect: globalThis.fetch.preconnect });
1047
+ const journal = rpcProgramJournal2(rpc, work);
1048
+ return yield* runProgram2(loop, work, guard === undefined ? journal : guard.journal(journal)).pipe(Effect4.provideService(ConfigProvider.ConfigProvider, ConfigProvider.fromUnknown(secrets.value)), Effect4.as(0), Effect4.catchTag("JournalWriteFailed", (error) => Effect4.as(Effect4.logError(error.message), 1)));
1049
+ }).pipe(Effect4.scoped, Effect4.catch((error) => Effect4.as(Effect4.logError(error.message), 2)));
1050
+ var runPackage2 = (config) => {
1051
+ const program = process.argv.includes(describeFlag2) ? describe(config) : host(config);
1052
+ BunRuntime.runMain(program.pipe(Effect4.flatMap((code) => Effect4.sync(() => process.exit(code)))));
1053
+ };
1054
+
1055
+ export { RunnerRpcProtocolVersion, JournalWriteFailed2, refusedStep2, runProgram2, programLease2, rpcProgramJournal2, describeFlag2, Described2, programSecrets2, programHostsEnv2, undeclaredHostsEnv2, networkGuard2, runPackage2 };