@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.
- package/dist/build/index.js +215 -0
- package/dist/chunk-7hwhxthh.js +1055 -0
- package/dist/chunk-zp7s46pz.js +3966 -0
- package/dist/loop/index.js +193 -0
- package/dist/program/index.js +30 -0
- package/package.json +29 -4
- package/types/packages/core/src/a2a.d.ts +577 -0
- package/types/packages/core/src/agent-capabilities.d.ts +1434 -0
- package/types/packages/core/src/agent-environment.d.ts +2429 -0
- package/types/packages/core/src/agent-launch-snapshot.d.ts +44 -0
- package/types/packages/core/src/agent-sandbox-policy.d.ts +33 -0
- package/types/packages/core/src/approval-queue.d.ts +126 -0
- package/types/packages/core/src/audit.d.ts +52 -0
- package/types/packages/core/src/change-delivery.d.ts +39 -0
- package/types/packages/core/src/change-request-review.d.ts +146 -0
- package/types/packages/core/src/change-request.d.ts +432 -0
- package/types/packages/core/src/common.d.ts +6 -0
- package/types/packages/core/src/connection.d.ts +33 -0
- package/types/packages/core/src/context-feedback.d.ts +89 -0
- package/types/packages/core/src/context-pack.d.ts +182 -0
- package/types/packages/core/src/crypto.d.ts +11 -0
- package/types/packages/core/src/data-lifecycle.d.ts +195 -0
- package/types/packages/core/src/decision.d.ts +48 -0
- package/types/packages/core/src/delivery-operation.d.ts +125 -0
- package/types/packages/core/src/delivery-policy.d.ts +174 -0
- package/types/packages/core/src/engineering-resources.d.ts +26 -0
- package/types/packages/core/src/enterprise-code-host.d.ts +18 -0
- package/types/packages/core/src/epic-delivery.d.ts +38 -0
- package/types/packages/core/src/extension.d.ts +35 -0
- package/types/packages/core/src/external-effect.d.ts +313 -0
- package/types/packages/core/src/fix-flow.d.ts +149 -0
- package/types/packages/core/src/following.d.ts +59 -0
- package/types/packages/core/src/github-delivery-fixtures.d.ts +28 -0
- package/types/packages/core/src/github-delivery.d.ts +78 -0
- package/types/packages/core/src/gitlab-delivery-fixtures.d.ts +26 -0
- package/types/packages/core/src/gitlab-delivery.d.ts +76 -0
- package/types/packages/core/src/global-search.d.ts +42 -0
- package/types/packages/core/src/id.d.ts +1 -0
- package/types/packages/core/src/index.d.ts +74 -0
- package/types/packages/core/src/integration.d.ts +255 -0
- package/types/packages/core/src/intent.d.ts +260 -0
- package/types/packages/core/src/json.d.ts +10 -0
- package/types/packages/core/src/kit-taxonomy.d.ts +21 -0
- package/types/packages/core/src/kit.d.ts +1489 -0
- package/types/packages/core/src/live.d.ts +8309 -0
- package/types/packages/core/src/loop-layers.d.ts +59 -0
- package/types/packages/core/src/loop-version.d.ts +59 -0
- package/types/packages/core/src/loop.d.ts +3076 -0
- package/types/packages/core/src/me.d.ts +31 -0
- package/types/packages/core/src/memory.d.ts +88 -0
- package/types/packages/core/src/my-teams.d.ts +1230 -0
- package/types/packages/core/src/notification.d.ts +181 -0
- package/types/packages/core/src/observability.d.ts +175 -0
- package/types/packages/core/src/package-declarations.d.ts +435 -0
- package/types/packages/core/src/package.d.ts +369 -0
- package/types/packages/core/src/personal-development-profile.d.ts +11 -0
- package/types/packages/core/src/platform-release.d.ts +60 -0
- package/types/packages/core/src/program-credential.d.ts +10 -0
- package/types/packages/core/src/project.d.ts +66 -0
- package/types/packages/core/src/proposal.d.ts +292 -0
- package/types/packages/core/src/provider-safe-text.d.ts +2 -0
- package/types/packages/core/src/redaction.d.ts +73 -0
- package/types/packages/core/src/repo-binding.d.ts +131 -0
- package/types/packages/core/src/run-journal.d.ts +28 -0
- package/types/packages/core/src/run-launch.d.ts +67 -0
- package/types/packages/core/src/run.d.ts +566 -0
- package/types/packages/core/src/runner-eligibility.d.ts +43 -0
- package/types/packages/core/src/runner-routing.d.ts +11 -0
- package/types/packages/core/src/runner-trust.d.ts +67 -0
- package/types/packages/core/src/runner.d.ts +3750 -0
- package/types/packages/core/src/runtime-type.d.ts +36 -0
- package/types/packages/core/src/schedule.d.ts +136 -0
- package/types/packages/core/src/schema.d.ts +89 -0
- package/types/packages/core/src/scope-directory.d.ts +100 -0
- package/types/packages/core/src/secret.d.ts +37 -0
- package/types/packages/core/src/session.d.ts +90 -0
- package/types/packages/core/src/step-brief.d.ts +50 -0
- package/types/packages/core/src/sync-kit.d.ts +587 -0
- package/types/packages/core/src/task-detail.d.ts +491 -0
- package/types/packages/core/src/task-execution-record.d.ts +620 -0
- package/types/packages/core/src/task-key.d.ts +9 -0
- package/types/packages/core/src/task.d.ts +543 -0
- package/types/packages/core/src/trigger-dispatch.d.ts +421 -0
- package/types/packages/core/src/work-unit.d.ts +740 -0
- package/types/packages/core/src/workspace.d.ts +96 -0
- package/types/packages/live/src/rpc/runner-client.d.ts +947 -0
- package/types/packages/live/src/rpc/runner-group.d.ts +733 -0
- package/types/packages/sdk/src/build/index.d.ts +45 -0
- package/types/packages/sdk/src/loop/activities.d.ts +187 -0
- package/types/packages/sdk/src/loop/check.d.ts +39 -0
- package/types/packages/sdk/src/loop/config.d.ts +68 -0
- package/types/packages/sdk/src/loop/define.d.ts +76 -0
- package/types/packages/sdk/src/loop/evidence.d.ts +66 -0
- package/types/packages/sdk/src/loop/index.d.ts +9 -0
- package/types/packages/sdk/src/loop/plan.d.ts +43 -0
- package/types/packages/sdk/src/loop/review.d.ts +86 -0
- package/types/packages/sdk/src/loop/steps.d.ts +224 -0
- package/types/packages/sdk/src/loop/test-loop.d.ts +112 -0
- package/types/packages/sdk/src/program/engine.d.ts +144 -0
- package/types/packages/sdk/src/program/host.d.ts +70 -0
- package/types/packages/sdk/src/program/index.d.ts +2 -0
- 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 };
|