@kitman-sh/cli 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-ztmwmk8t.js → chunk-0296rete.js} +1 -1
- package/dist/{chunk-6kdj8psf.js → chunk-1n61xbaq.js} +2 -2
- package/dist/{chunk-epdajq63.js → chunk-80g9af03.js} +2 -2
- package/dist/{chunk-dwgta18y.js → chunk-84t0s0s2.js} +1 -1
- package/dist/{chunk-704ws2q7.js → chunk-8g2twwm8.js} +29 -6
- package/dist/{chunk-ae7gx971.js → chunk-c5nwtn11.js} +2 -2
- package/dist/{chunk-vjnae06n.js → chunk-kt08et8q.js} +225 -37
- package/dist/{chunk-226sychh.js → chunk-nvf0begz.js} +42 -6
- package/dist/{chunk-6f4anyec.js → chunk-x6j2j12j.js} +1 -1
- package/dist/{chunk-hrd7xmax.js → chunk-yysejjz0.js} +5 -5
- package/dist/{chunk-gzhxsb25.js → chunk-zc0ebz8f.js} +3 -3
- package/dist/index.js +22 -19
- package/package.json +1 -1
|
@@ -100,7 +100,7 @@ import {
|
|
|
100
100
|
toCodecJson,
|
|
101
101
|
Json,
|
|
102
102
|
LoopCapabilities
|
|
103
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-8g2twwm8.js";
|
|
104
104
|
|
|
105
105
|
// packages/sdk/src/loop/define.ts
|
|
106
106
|
var LoopOutcome = Literals(["feature", "bug", "refactor", "investigation", "docs", "migration"]);
|
|
@@ -18,13 +18,13 @@ import {
|
|
|
18
18
|
ProgramWorkUnit,
|
|
19
19
|
LoopManifest,
|
|
20
20
|
RunnerRpcError
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-8g2twwm8.js";
|
|
22
22
|
import {
|
|
23
23
|
ManifestInvalid,
|
|
24
24
|
make,
|
|
25
25
|
Suspended,
|
|
26
26
|
LoopCheckError
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-0296rete.js";
|
|
28
28
|
|
|
29
29
|
// packages/sdk/src/program/engine.ts
|
|
30
30
|
class JournalWriteFailed extends TaggedError("JournalWriteFailed") {
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
Int,
|
|
32
32
|
TaggedError2,
|
|
33
33
|
Json
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-8g2twwm8.js";
|
|
35
35
|
import {
|
|
36
36
|
LoopOutcome,
|
|
37
37
|
defineLoop,
|
|
@@ -67,7 +67,7 @@ import {
|
|
|
67
67
|
mergeFindings,
|
|
68
68
|
settleRound,
|
|
69
69
|
rallyStop
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-0296rete.js";
|
|
71
71
|
|
|
72
72
|
// node_modules/.bun/effect@4.0.4/node_modules/effect/dist/workflow/DurableClock.js
|
|
73
73
|
var TypeId = "~effect/workflow/DurableClock";
|
|
@@ -121,7 +121,7 @@ import {
|
|
|
121
121
|
isStreamSchema,
|
|
122
122
|
getStreamSchemas,
|
|
123
123
|
exitSchema
|
|
124
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-8g2twwm8.js";
|
|
125
125
|
|
|
126
126
|
// node_modules/.bun/effect@4.0.4/node_modules/effect/dist/socket/Socket.js
|
|
127
127
|
var TypeId = "~effect/socket/Socket";
|
|
@@ -11351,7 +11351,7 @@ var Proto6 = /* @__PURE__ */ Object.defineProperties(/* @__PURE__ */ Object.crea
|
|
|
11351
11351
|
},
|
|
11352
11352
|
[symbol2]: {
|
|
11353
11353
|
value(that) {
|
|
11354
|
-
return
|
|
11354
|
+
return Equivalence3(this, that);
|
|
11355
11355
|
}
|
|
11356
11356
|
},
|
|
11357
11357
|
[symbol]: {
|
|
@@ -11367,7 +11367,7 @@ var Proto6 = /* @__PURE__ */ Object.defineProperties(/* @__PURE__ */ Object.crea
|
|
|
11367
11367
|
}
|
|
11368
11368
|
});
|
|
11369
11369
|
var make24 = (input) => Object.assign(Object.create(Proto6), input);
|
|
11370
|
-
var
|
|
11370
|
+
var Equivalence3 = /* @__PURE__ */ makeEquivalence2(/* @__PURE__ */ strictEqual());
|
|
11371
11371
|
var empty3 = /* @__PURE__ */ Object.create(Proto6);
|
|
11372
11372
|
var fromInput = (input) => {
|
|
11373
11373
|
if (input === undefined) {
|
|
@@ -11469,7 +11469,7 @@ var Proto7 = {
|
|
|
11469
11469
|
};
|
|
11470
11470
|
},
|
|
11471
11471
|
[symbol2](that) {
|
|
11472
|
-
return
|
|
11472
|
+
return Equivalence4(this, that);
|
|
11473
11473
|
},
|
|
11474
11474
|
[symbol]() {
|
|
11475
11475
|
return array(this.params.flat());
|
|
@@ -11517,7 +11517,7 @@ var fromInputNested = (input) => {
|
|
|
11517
11517
|
}
|
|
11518
11518
|
return out;
|
|
11519
11519
|
};
|
|
11520
|
-
var
|
|
11520
|
+
var Equivalence4 = /* @__PURE__ */ make((a, b) => arrayEquivalence(a.params, b.params));
|
|
11521
11521
|
var arrayEquivalence = /* @__PURE__ */ makeEquivalence3(/* @__PURE__ */ makeEquivalence([/* @__PURE__ */ strictEqual(), /* @__PURE__ */ strictEqual()]));
|
|
11522
11522
|
var empty6 = /* @__PURE__ */ make25([]);
|
|
11523
11523
|
var setAll2 = /* @__PURE__ */ dual(2, (self, input) => {
|
|
@@ -19841,10 +19841,11 @@ var RunnerReplicaDrainState = Union([
|
|
|
19841
19841
|
Literal("draining"),
|
|
19842
19842
|
Literal("drained")
|
|
19843
19843
|
]);
|
|
19844
|
+
var RunnerProjectAccess = Union([Literal("all"), Literal("selected")]);
|
|
19844
19845
|
var RunnerOwnership = Union([
|
|
19845
19846
|
Struct({
|
|
19846
19847
|
kind: Literal("workspace"),
|
|
19847
|
-
projectAccess:
|
|
19848
|
+
projectAccess: RunnerProjectAccess
|
|
19848
19849
|
}),
|
|
19849
19850
|
Struct({
|
|
19850
19851
|
kind: Literal("project"),
|
|
@@ -19852,7 +19853,8 @@ var RunnerOwnership = Union([
|
|
|
19852
19853
|
}),
|
|
19853
19854
|
Struct({
|
|
19854
19855
|
kind: Literal("personal"),
|
|
19855
|
-
ownerUserId: Id
|
|
19856
|
+
ownerUserId: Id,
|
|
19857
|
+
projectAccess: RunnerProjectAccess.pipe(withDecodingDefaultKey(succeed5("all")))
|
|
19856
19858
|
})
|
|
19857
19859
|
]);
|
|
19858
19860
|
var RunnerSecretProviderType = Union([Literal("env"), Literal("file"), Literal("exec")]);
|
|
@@ -20086,6 +20088,12 @@ var RunnerProjectGrantCreate = Struct({
|
|
|
20086
20088
|
var RunnerRescope = Struct({
|
|
20087
20089
|
ownership: RunnerOwnership
|
|
20088
20090
|
});
|
|
20091
|
+
var RunnerUpdate = Struct({
|
|
20092
|
+
name: String2.check(isMinLength(1), isMaxLength(120))
|
|
20093
|
+
});
|
|
20094
|
+
var RunnerRemoveResult = Struct({
|
|
20095
|
+
removed: Boolean2
|
|
20096
|
+
});
|
|
20089
20097
|
var RunnerDefaultHarnessInput = Struct({
|
|
20090
20098
|
harness: NullOr(Literals(DetectedHarnessIds))
|
|
20091
20099
|
});
|
|
@@ -21708,6 +21716,7 @@ function parseCliConfig(value) {
|
|
|
21708
21716
|
const ids = (field) => Array.isArray(field) && field.every(isString2) ? field : undefined;
|
|
21709
21717
|
const onboarding = isJsonObject(value.onboarding) ? value.onboarding : undefined;
|
|
21710
21718
|
const mcpSkippedProjectIds = ids(onboarding?.mcpSkippedProjectIds);
|
|
21719
|
+
const approvedSkillSources = ids(value.approvedSkillSources);
|
|
21711
21720
|
return {
|
|
21712
21721
|
...text("apiUrl"),
|
|
21713
21722
|
...text("activeWorkspaceId"),
|
|
@@ -21715,6 +21724,7 @@ function parseCliConfig(value) {
|
|
|
21715
21724
|
...text("mcpCredentialName"),
|
|
21716
21725
|
...UserAgentPreferencesValidator(value.userAgentPreferences) ? { userAgentPreferences: value.userAgentPreferences } : undefined,
|
|
21717
21726
|
...AgentSyncProfileValidator(value.agentSyncProfile) ? { agentSyncProfile: value.agentSyncProfile } : undefined,
|
|
21727
|
+
...approvedSkillSources === undefined ? undefined : { approvedSkillSources },
|
|
21718
21728
|
...onboarding === undefined ? undefined : {
|
|
21719
21729
|
onboarding: {
|
|
21720
21730
|
...mcpSkippedProjectIds === undefined ? undefined : { mcpSkippedProjectIds }
|
|
@@ -23193,6 +23203,9 @@ class KitmanEffectClient {
|
|
|
23193
23203
|
const suffix = page === undefined ? "" : `?page=${page}`;
|
|
23194
23204
|
return this.request("listCodeHostRepositories", `/workspaces/${segment(workspaceId)}/code-host-connections/${segment(connectionId)}/repositories${suffix}`, { headers: this.headers() });
|
|
23195
23205
|
}
|
|
23206
|
+
listCodeHostGroups(workspaceId, connectionId) {
|
|
23207
|
+
return this.request("listCodeHostGroups", `/workspaces/${segment(workspaceId)}/code-host-connections/${segment(connectionId)}/groups`, { headers: this.headers() });
|
|
23208
|
+
}
|
|
23196
23209
|
bindCodeHostRepositories(workspaceId, connectionId, input) {
|
|
23197
23210
|
return this.request("bindCodeHostRepositories", `/workspaces/${segment(workspaceId)}/code-host-connections/${segment(connectionId)}/repo-bindings`, { method: "POST", headers: this.headers(true), body: JSON.stringify(input) });
|
|
23198
23211
|
}
|
|
@@ -24164,6 +24177,16 @@ class KitmanEffectClient {
|
|
|
24164
24177
|
body: JSON.stringify(input)
|
|
24165
24178
|
});
|
|
24166
24179
|
}
|
|
24180
|
+
updateRunner(runnerId, input) {
|
|
24181
|
+
return this.request("updateRunner", `/runners/${segment(runnerId)}`, {
|
|
24182
|
+
method: "PATCH",
|
|
24183
|
+
headers: this.headers(true),
|
|
24184
|
+
body: JSON.stringify(input)
|
|
24185
|
+
});
|
|
24186
|
+
}
|
|
24187
|
+
removeRunner(runnerId) {
|
|
24188
|
+
return this.request("removeRunner", `/runners/${segment(runnerId)}`, { method: "DELETE", headers: this.headers() });
|
|
24189
|
+
}
|
|
24167
24190
|
setRunnerDefaultHarness(runnerId, input) {
|
|
24168
24191
|
return this.request("setRunnerDefaultHarness", `/runners/${segment(runnerId)}/default-harness`, {
|
|
24169
24192
|
method: "PUT",
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
RunnerHeaders,
|
|
11
11
|
RunnerRpcProtocolVersion,
|
|
12
12
|
RunnerRpcs
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-8g2twwm8.js";
|
|
14
14
|
import {
|
|
15
15
|
WebSocketConstructor,
|
|
16
16
|
layerWebSocketConstructorGlobal,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
make5,
|
|
20
20
|
withHeaders,
|
|
21
21
|
layerProtocolSocket
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-84t0s0s2.js";
|
|
23
23
|
|
|
24
24
|
// packages/live/src/rpc/runner-client.ts
|
|
25
25
|
var proxiedWebSocket = (proxy) => succeed4(WebSocketConstructor)((target) => {
|
|
@@ -161,7 +161,7 @@ import {
|
|
|
161
161
|
herdrRunnerCapabilitiesForRepoBinding2,
|
|
162
162
|
herdrRunnerCapabilities2,
|
|
163
163
|
assertHerdrRunnerCapability2
|
|
164
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-8g2twwm8.js";
|
|
165
165
|
import {
|
|
166
166
|
make4,
|
|
167
167
|
readerString,
|
|
@@ -172,17 +172,17 @@ import {
|
|
|
172
172
|
SocketUpgradeError,
|
|
173
173
|
SocketCloseError,
|
|
174
174
|
SocketError
|
|
175
|
-
} from "./chunk-
|
|
176
|
-
import"./chunk-
|
|
175
|
+
} from "./chunk-84t0s0s2.js";
|
|
176
|
+
import"./chunk-0296rete.js";
|
|
177
177
|
import {
|
|
178
178
|
programLease,
|
|
179
179
|
programHostsEnv,
|
|
180
180
|
undeclaredHostsEnv
|
|
181
|
-
} from "./chunk-
|
|
182
|
-
import"./chunk-
|
|
181
|
+
} from "./chunk-1n61xbaq.js";
|
|
182
|
+
import"./chunk-c5nwtn11.js";
|
|
183
183
|
import {
|
|
184
184
|
nextInt
|
|
185
|
-
} from "./chunk-
|
|
185
|
+
} from "./chunk-x6j2j12j.js";
|
|
186
186
|
|
|
187
187
|
// packages/core/src/runner-trust.ts
|
|
188
188
|
import { createHash } from "crypto";
|
|
@@ -195,6 +195,129 @@ function sha256(value) {
|
|
|
195
195
|
return createHash("sha256").update(value, "utf8").digest("hex");
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
+
// packages/core/src/engineering-resources.ts
|
|
199
|
+
var marketplace = {
|
|
200
|
+
source: "kitman-engineering-loop",
|
|
201
|
+
publisher: "Kitman Platform",
|
|
202
|
+
visibility: "public",
|
|
203
|
+
trusted: true,
|
|
204
|
+
reviewStatus: "approved",
|
|
205
|
+
installable: true,
|
|
206
|
+
rollout: { channel: "default", installDefault: true, preservesExistingInstallations: true }
|
|
207
|
+
};
|
|
208
|
+
var kit = (input) => ({
|
|
209
|
+
...input,
|
|
210
|
+
metadata: { marketplace }
|
|
211
|
+
});
|
|
212
|
+
var MattPocockProcessKit = kit({
|
|
213
|
+
name: "Matt Pocock Process",
|
|
214
|
+
slug: "matt-pocock-process",
|
|
215
|
+
kind: "process",
|
|
216
|
+
description: "Adversarial, type-safe implementation and review practice for Kitman Engineering.",
|
|
217
|
+
contentMarkdown: [
|
|
218
|
+
"# Matt Pocock Process",
|
|
219
|
+
"",
|
|
220
|
+
"Use fresh-context review, TDD, Effect-native boundaries, and explicit type contracts.",
|
|
221
|
+
"",
|
|
222
|
+
"## Complete skill collection",
|
|
223
|
+
"",
|
|
224
|
+
"diagnosing-bugs, tdd, effect-ts, codebase-design, api-and-interface-design, improve-codebase-architecture, doubt-driven-development, documentation-and-adrs, postgres-drizzle, security-and-hardening, source-driven-development, test-driven-development, research."
|
|
225
|
+
].join(`
|
|
226
|
+
`),
|
|
227
|
+
agentEnvironment: {
|
|
228
|
+
skills: [
|
|
229
|
+
{
|
|
230
|
+
name: "research",
|
|
231
|
+
policy: "required",
|
|
232
|
+
source: {
|
|
233
|
+
kind: "git",
|
|
234
|
+
url: "https://github.com/mattpocock/skills.git",
|
|
235
|
+
ref: "49dd158d1076134a641b33efb035946536778336",
|
|
236
|
+
path: "skills/engineering/research"
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
]
|
|
240
|
+
},
|
|
241
|
+
agentInstructions: "Prefer the smallest correct change, preserve evidence, and stop on ambiguous public-interface decisions.",
|
|
242
|
+
doNotDo: "Do not execute user-controlled code in the API or Workflow worker."
|
|
243
|
+
});
|
|
244
|
+
var AddyOsmaniProcessKit = kit({
|
|
245
|
+
name: "Addy Osmani Process",
|
|
246
|
+
slug: "addy-osmani-process",
|
|
247
|
+
kind: "process",
|
|
248
|
+
description: "Incremental, accessible, observable, and production-focused delivery practice for Kitman Engineering.",
|
|
249
|
+
contentMarkdown: [
|
|
250
|
+
"# Addy Osmani Process",
|
|
251
|
+
"",
|
|
252
|
+
"Use incremental implementation, browser evidence, accessibility checks, CI discipline, and simplification.",
|
|
253
|
+
"",
|
|
254
|
+
"## Complete skill collection",
|
|
255
|
+
"",
|
|
256
|
+
"incremental-implementation, frontend-ui-engineering, browser-testing-with-devtools, web-design-guidelines, ci-cd-and-automation, code-review-and-quality, code-simplification, observability-and-instrumentation, performance-optimization, shipping-and-launch, git-workflow-and-versioning."
|
|
257
|
+
].join(`
|
|
258
|
+
`),
|
|
259
|
+
agentInstructions: "Prefer verifiable slices, accessible interfaces, and evidence that survives handoff.",
|
|
260
|
+
doNotDo: "Do not hide failures behind broad fallbacks or claim production evidence from local fixtures."
|
|
261
|
+
});
|
|
262
|
+
var PonytailProcessKit = kit({
|
|
263
|
+
name: "Ponytail",
|
|
264
|
+
slug: "ponytail",
|
|
265
|
+
kind: "process",
|
|
266
|
+
description: "Removes unnecessary code and complexity before implementation and review complete.",
|
|
267
|
+
contentMarkdown: `# Ponytail
|
|
268
|
+
|
|
269
|
+
Prefer deletion, existing code, and the smallest correct change. Avoid speculative abstractions.`,
|
|
270
|
+
agentEnvironment: {
|
|
271
|
+
plugins: [
|
|
272
|
+
{
|
|
273
|
+
name: "ponytail",
|
|
274
|
+
policy: "required",
|
|
275
|
+
source: {
|
|
276
|
+
kind: "package",
|
|
277
|
+
packageName: "@dietrichgebert/ponytail",
|
|
278
|
+
version: "4.9.0"
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
]
|
|
282
|
+
},
|
|
283
|
+
agentInstructions: "Use the required Ponytail skill before completing implementation or review.",
|
|
284
|
+
doNotDo: "Do not add an abstraction, dependency, or configuration without a present requirement."
|
|
285
|
+
});
|
|
286
|
+
var EngineeringTechnologyKitCatalog = [
|
|
287
|
+
kit({
|
|
288
|
+
name: "Backend",
|
|
289
|
+
slug: "backend",
|
|
290
|
+
kind: "technology",
|
|
291
|
+
description: "Effect, Elysia, PostgreSQL, Drizzle, Better Auth, and backend practices.",
|
|
292
|
+
contentMarkdown: `# Backend
|
|
293
|
+
|
|
294
|
+
Effect, Elysia, PostgreSQL, Drizzle, Better Auth, API contracts, security, and observability.`
|
|
295
|
+
}),
|
|
296
|
+
kit({
|
|
297
|
+
name: "Frontend",
|
|
298
|
+
slug: "frontend",
|
|
299
|
+
kind: "technology",
|
|
300
|
+
description: "Nuxt, Vue, Nuxt UI, TanStack Query, VueUse, accessibility, and browser testing.",
|
|
301
|
+
contentMarkdown: `# Frontend
|
|
302
|
+
|
|
303
|
+
Nuxt, Vue, Nuxt UI, TanStack Query, VueUse, accessibility, responsive UI, and browser testing.`
|
|
304
|
+
}),
|
|
305
|
+
kit({
|
|
306
|
+
name: "DevOps",
|
|
307
|
+
slug: "devops",
|
|
308
|
+
kind: "technology",
|
|
309
|
+
description: "Kubernetes, Kustomize, GitLab CI, and multi-stage container builds.",
|
|
310
|
+
contentMarkdown: `# DevOps
|
|
311
|
+
|
|
312
|
+
Kubernetes, Kustomize, GitLab CI, multi-stage container builds, and operational verification.`
|
|
313
|
+
})
|
|
314
|
+
];
|
|
315
|
+
var EngineeringProcessKitCatalog = [
|
|
316
|
+
MattPocockProcessKit,
|
|
317
|
+
AddyOsmaniProcessKit,
|
|
318
|
+
PonytailProcessKit
|
|
319
|
+
];
|
|
320
|
+
|
|
198
321
|
// packages/agent-runtime/src/agent-environment.ts
|
|
199
322
|
class AgentEnvironmentResolutionError extends TaggedError("AgentEnvironmentResolutionError") {
|
|
200
323
|
get message() {
|
|
@@ -1596,6 +1719,9 @@ function repositoryUrl(repoBinding) {
|
|
|
1596
1719
|
return repoBinding.repositoryUrl ?? `https://${repoBinding.host}/${repoBinding.owner}/${repoBinding.name}.git`;
|
|
1597
1720
|
}
|
|
1598
1721
|
// packages/agent-runtime/src/skill-materializer.ts
|
|
1722
|
+
var gitSourceKey = (source) => `${source.url}#${source.ref}:${source.path ?? ""}`;
|
|
1723
|
+
var reviewedGitSkillSources = new Set([...EngineeringProcessKitCatalog, ...EngineeringTechnologyKitCatalog].flatMap((kit) => kit.agentEnvironment?.skills ?? []).flatMap((skill) => skill.source.kind === "git" ? [gitSourceKey(skill.source)] : []));
|
|
1724
|
+
|
|
1599
1725
|
class AgentEnvironmentMaterializationError extends TaggedError("AgentEnvironmentMaterializationError") {
|
|
1600
1726
|
get message() {
|
|
1601
1727
|
return `AgentEnvironment materialization failed: ${this.issues.map((issue) => issue.message).join("; ")}`;
|
|
@@ -1616,35 +1742,50 @@ var previewAgentEnvironmentMaterialization = fnUntraced(function* (input) {
|
|
|
1616
1742
|
for (const skill of input.environment.skills) {
|
|
1617
1743
|
const skillKey = skillIdentity(skill.item);
|
|
1618
1744
|
const source = skill.item.source;
|
|
1619
|
-
const
|
|
1620
|
-
|
|
1745
|
+
const fromKit = skill.source.label === undefined ? "" : ` (from Kit ${skill.source.label})`;
|
|
1746
|
+
const problem = source.kind === "kitman" ? source.contentMarkdown === undefined ? `Kitman skill ${skill.item.name} has no contentMarkdown to materialize.` : undefined : input.noInstall === true ? `Skipping materialization for ${skill.item.name} because sync was run with noInstall.` : source.kind !== "git" ? `Skill ${skill.item.name}${fromKit} comes from ${source.kind}, which Kitman cannot install yet; only Kitman and git skills are installed. Remove it from the Kit or make it recommended.` : !source.url.startsWith("https://") ? `Git skill ${skill.item.name} must come from an https URL, not ${source.url}.` : !/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/u.test(source.ref) ? `Git skill ${skill.item.name} must be pinned to a commit, not ${source.ref}, so Kitman installs only the reviewed version.` : !reviewedGitSkillSources.has(gitSourceKey(source)) && !(input.approvedSkillSources ?? []).includes(gitSourceKey(source)) ? `Git skill ${skill.item.name}${fromKit} at ${gitSourceKey(source)} is not one Kitman reviewed; approve it by adding that source to approvedSkillSources in your Kitman user config, or remove it from the Kit.` : undefined;
|
|
1747
|
+
if (problem !== undefined) {
|
|
1748
|
+
const issue = { message: problem, skillName: skill.item.name, skillKey };
|
|
1621
1749
|
if (skill.item.policy === "required")
|
|
1622
|
-
return new AgentEnvironmentMaterializationError({ issues: [issue] });
|
|
1750
|
+
return yield* new AgentEnvironmentMaterializationError({ issues: [issue] });
|
|
1623
1751
|
warnings.push(issue);
|
|
1624
|
-
return;
|
|
1625
|
-
};
|
|
1626
|
-
const refusal = source.kind !== "kitman" ? skip(input.noInstall === true ? `Skipping materialization for ${skill.item.name} because sync was run with noInstall.` : `Materializing ${skill.item.name} from ${source.kind} is not supported; only Kitman skills are materialized.`) : source.contentMarkdown === undefined ? skip(`Kitman skill ${skill.item.name} has no contentMarkdown to materialize.`) : undefined;
|
|
1627
|
-
if (refusal !== undefined)
|
|
1628
|
-
return yield* refusal;
|
|
1629
|
-
if (source.kind !== "kitman" || source.contentMarkdown === undefined)
|
|
1630
1752
|
continue;
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1753
|
+
}
|
|
1754
|
+
const expose = (skillPath) => {
|
|
1755
|
+
operations.push({
|
|
1756
|
+
kind: "symlink_skill",
|
|
1757
|
+
skillName: skill.item.name,
|
|
1758
|
+
skillKey,
|
|
1759
|
+
sourcePath: skillPath,
|
|
1760
|
+
targetPath: path.join(targetRoot, `${skillSlug2(skill.item.name)}-${hashSegment(skillKey)}`),
|
|
1761
|
+
sourceRoot,
|
|
1762
|
+
targetRoot
|
|
1763
|
+
});
|
|
1764
|
+
materializedSkills.push({ name: skill.item.name, key: skillKey, harness, source, skillPath, managed: true });
|
|
1765
|
+
};
|
|
1766
|
+
if (source.kind === "git") {
|
|
1767
|
+
const skillPath = path.join(sourceRoot, "git", hashSegment(skillKey), skillSlug2(skill.item.name));
|
|
1768
|
+
operations.push({
|
|
1769
|
+
kind: "fetch_git_skill",
|
|
1770
|
+
skillName: skill.item.name,
|
|
1771
|
+
skillKey,
|
|
1772
|
+
url: source.url,
|
|
1773
|
+
ref: source.ref,
|
|
1774
|
+
...source.path === undefined ? undefined : { repositoryPath: source.path },
|
|
1775
|
+
path: skillPath
|
|
1776
|
+
});
|
|
1777
|
+
expose(skillPath);
|
|
1778
|
+
} else if (source.kind === "kitman" && source.contentMarkdown !== undefined) {
|
|
1779
|
+
const skillPath = path.join(sourceRoot, "kitman", hashSegment(source.skillId ?? source.name ?? skill.item.name), skillSlug2(skill.item.name));
|
|
1780
|
+
operations.push({
|
|
1781
|
+
kind: "write_skill",
|
|
1782
|
+
skillName: skill.item.name,
|
|
1783
|
+
skillKey,
|
|
1784
|
+
path: path.join(skillPath, "SKILL.md"),
|
|
1785
|
+
content: skillMarkdown(skill.item.name, source.contentMarkdown)
|
|
1786
|
+
});
|
|
1787
|
+
expose(skillPath);
|
|
1788
|
+
}
|
|
1648
1789
|
}
|
|
1649
1790
|
return { harness, operations, materializedSkills, warnings };
|
|
1650
1791
|
});
|
|
@@ -1652,28 +1793,74 @@ var applyAgentEnvironmentMaterialization = fnUntraced(function* (plan) {
|
|
|
1652
1793
|
for (const operation of plan.operations) {
|
|
1653
1794
|
if (operation.kind === "write_skill")
|
|
1654
1795
|
yield* writeSkill(plan, operation);
|
|
1796
|
+
else if (operation.kind === "fetch_git_skill")
|
|
1797
|
+
yield* fetchGitSkill(plan, operation);
|
|
1655
1798
|
else
|
|
1656
1799
|
yield* exposeSkill(operation);
|
|
1657
1800
|
}
|
|
1658
1801
|
return plan;
|
|
1659
1802
|
});
|
|
1660
1803
|
var refuse = (message) => fail4(new SkillMaterializationRefused({ message }));
|
|
1661
|
-
var
|
|
1662
|
-
const fs = yield* FileSystem;
|
|
1804
|
+
var managedSkillPath = (plan, skillKey, file) => gen(function* () {
|
|
1663
1805
|
const path = yield* Path;
|
|
1664
|
-
const boundary = plan.operations.find((candidate) => candidate.kind === "symlink_skill" && candidate.skillKey ===
|
|
1806
|
+
const boundary = plan.operations.find((candidate) => candidate.kind === "symlink_skill" && candidate.skillKey === skillKey);
|
|
1665
1807
|
if (boundary === undefined)
|
|
1666
1808
|
return yield* refuse("SKILL_SYMLINK_BOUNDARY_MISSING");
|
|
1667
1809
|
const root = path.resolve(boundary.sourceRoot);
|
|
1668
|
-
const target = path.resolve(
|
|
1810
|
+
const target = path.resolve(file);
|
|
1669
1811
|
if (!isPathWithin(path, root, target) || target === root)
|
|
1670
1812
|
return yield* refuse("SKILL_WRITE_OUTSIDE_ROOT");
|
|
1671
1813
|
yield* assertNoSymlinkComponents(path.dirname(target), "SKILL_WRITE_OUTSIDE_ROOT");
|
|
1814
|
+
return target;
|
|
1815
|
+
});
|
|
1816
|
+
var writeSkill = (plan, operation) => gen(function* () {
|
|
1817
|
+
const fs = yield* FileSystem;
|
|
1818
|
+
const path = yield* Path;
|
|
1819
|
+
const target = yield* managedSkillPath(plan, operation.skillKey, operation.path);
|
|
1672
1820
|
if (yield* isSymbolicLink(target))
|
|
1673
1821
|
return yield* refuse("SKILL_WRITE_SYMLINK");
|
|
1674
1822
|
yield* fs.makeDirectory(path.dirname(target), { recursive: true });
|
|
1675
1823
|
yield* fs.writeFileString(target, operation.content);
|
|
1676
1824
|
});
|
|
1825
|
+
var fetchGitSkill = (plan, operation) => gen(function* () {
|
|
1826
|
+
const fs = yield* FileSystem;
|
|
1827
|
+
const path = yield* Path;
|
|
1828
|
+
const target = yield* managedSkillPath(plan, operation.skillKey, operation.path);
|
|
1829
|
+
const scratch = yield* fs.makeTempDirectoryScoped({ prefix: "kitman-git-skill-" });
|
|
1830
|
+
const repository = path.join(scratch, "repository");
|
|
1831
|
+
const tree = path.join(scratch, "tree");
|
|
1832
|
+
const git = (...args) => runCommand2("git", ["--git-dir", repository, ...args]);
|
|
1833
|
+
yield* fs.makeDirectory(tree);
|
|
1834
|
+
yield* runCommand2("git", ["init", "--quiet", "--bare", repository]);
|
|
1835
|
+
yield* git("fetch", "--quiet", "--depth", "1", "--", operation.url, operation.ref);
|
|
1836
|
+
yield* git("--work-tree", tree, "checkout", "FETCH_HEAD", "--", ".");
|
|
1837
|
+
const skillDirectory = path.resolve(tree, operation.repositoryPath ?? ".");
|
|
1838
|
+
if (!isPathWithin(path, tree, skillDirectory))
|
|
1839
|
+
return yield* refuse("SKILL_SOURCE_OUTSIDE_ROOT");
|
|
1840
|
+
if (yield* containsSymbolicLink(tree, skillDirectory))
|
|
1841
|
+
return yield* refuse(`Git skill ${operation.skillName} links to a file outside itself in ${operation.url}@${operation.ref}; Kitman does not install linked files.`);
|
|
1842
|
+
if (!(yield* fs.exists(path.join(skillDirectory, "SKILL.md"))))
|
|
1843
|
+
return yield* refuse(`Git skill ${operation.skillName} has no SKILL.md at ${operation.repositoryPath ?? "the repository root"} in ${operation.url}@${operation.ref}.`);
|
|
1844
|
+
const staged = `${target}.partial`;
|
|
1845
|
+
yield* fs.remove(staged, { recursive: true, force: true });
|
|
1846
|
+
yield* fs.makeDirectory(path.dirname(target), { recursive: true });
|
|
1847
|
+
yield* fs.copy(skillDirectory, staged);
|
|
1848
|
+
yield* fs.remove(target, { recursive: true, force: true });
|
|
1849
|
+
yield* fs.rename(staged, target);
|
|
1850
|
+
}).pipe(scoped);
|
|
1851
|
+
var containsSymbolicLink = (root, directory) => gen(function* () {
|
|
1852
|
+
const fs = yield* FileSystem;
|
|
1853
|
+
const path = yield* Path;
|
|
1854
|
+
for (let current = directory;current !== root; current = path.dirname(current))
|
|
1855
|
+
if (yield* isSymbolicLink(current))
|
|
1856
|
+
return true;
|
|
1857
|
+
if (!(yield* fs.exists(directory)))
|
|
1858
|
+
return false;
|
|
1859
|
+
for (const entry of yield* fs.readDirectory(directory, { recursive: true }))
|
|
1860
|
+
if (yield* isSymbolicLink(path.join(directory, entry)))
|
|
1861
|
+
return true;
|
|
1862
|
+
return false;
|
|
1863
|
+
});
|
|
1677
1864
|
var exposeSkill = (operation) => gen(function* () {
|
|
1678
1865
|
const fs = yield* FileSystem;
|
|
1679
1866
|
const path = yield* Path;
|
|
@@ -4368,7 +4555,8 @@ var previewAgentEnvironmentPlan = fnUntraced(function* (input) {
|
|
|
4368
4555
|
...input.rootDir === undefined ? undefined : { rootDir: input.rootDir },
|
|
4369
4556
|
...input.scope === undefined ? undefined : { scope: input.scope },
|
|
4370
4557
|
...input.cacheRoot === undefined ? undefined : { cacheRoot: input.cacheRoot },
|
|
4371
|
-
...input.noInstall === undefined ? undefined : { noInstall: input.noInstall }
|
|
4558
|
+
...input.noInstall === undefined ? undefined : { noInstall: input.noInstall },
|
|
4559
|
+
...input.approvedSkillSources === undefined ? undefined : { approvedSkillSources: input.approvedSkillSources }
|
|
4372
4560
|
});
|
|
4373
4561
|
const harnessConfig = yield* previewAgentEnvironmentConfigSync({
|
|
4374
4562
|
environment: input.environment,
|