@kitman-sh/cli 0.9.0 → 0.10.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-11p4wf6n.js +3551 -0
- package/dist/chunk-1mc9vgcr.js +39 -0
- package/dist/chunk-30397r95.js +30 -0
- package/dist/chunk-3bj7sc3v.js +389 -0
- package/dist/chunk-6vns3ej0.js +23 -0
- package/dist/chunk-7thnf14y.js +936 -0
- package/dist/chunk-arvwar2c.js +141 -0
- package/dist/chunk-b6thzgc9.js +32 -0
- package/dist/{chunk-8bvf4fh4.js → chunk-ctasxxz5.js} +26 -11
- package/dist/{chunk-5gjpv3ax.js → chunk-dzh9e6n2.js} +824 -651
- package/dist/{chunk-snn0e1qb.js → chunk-eg8f5ncv.js} +7 -3
- package/dist/chunk-g5bs3f6z.js +173 -0
- package/dist/chunk-jafetf7z.js +109 -0
- package/dist/chunk-jagzz148.js +527 -0
- package/dist/{chunk-1d4316hp.js → chunk-jfvq7s24.js} +38 -25
- package/dist/chunk-mbctzx7e.js +11436 -0
- package/dist/chunk-mej2bx5n.js +100 -0
- package/dist/chunk-p6spvbwq.js +6305 -0
- package/dist/chunk-pp1p3g6e.js +133 -0
- package/dist/chunk-r8p3nxcp.js +231 -0
- package/dist/chunk-txwt6r25.js +1731 -0
- package/dist/chunk-v290mf51.js +5242 -0
- package/dist/chunk-vjmz23rs.js +13 -0
- package/dist/chunk-vyv0p5eq.js +3183 -0
- package/dist/chunk-wh1pa2aa.js +15322 -0
- package/dist/chunk-x0b92bjb.js +222 -0
- package/dist/{chunk-8z5b6fpd.js → chunk-x9dhxfts.js} +216 -152
- package/dist/chunk-z821b2gp.js +164 -0
- package/dist/index.js +13 -5738
- package/dist/opencode-reader.main.ts +4 -0
- package/package.json +6 -5
- package/dist/chunk-3gxahgnq.js +0 -28495
- package/dist/chunk-ehzbtavj.js +0 -247
- package/dist/chunk-f5z8tgss.js +0 -1214
- package/dist/chunk-kdb1cbnx.js +0 -1273
- package/dist/chunk-ke1w0hx7.js +0 -5771
- package/dist/chunk-z6hc4ew9.js +0 -13
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
isObject2,
|
|
4
|
+
isSuccess2,
|
|
5
|
+
decodeUnknownExit,
|
|
6
|
+
optionalKey,
|
|
7
|
+
toType,
|
|
8
|
+
Literal,
|
|
9
|
+
Unknown,
|
|
10
|
+
String4,
|
|
11
|
+
Struct,
|
|
12
|
+
Record,
|
|
13
|
+
ArraySchema,
|
|
14
|
+
Union,
|
|
15
|
+
makeFilter,
|
|
16
|
+
isPattern,
|
|
17
|
+
Finite,
|
|
18
|
+
isMinLength,
|
|
19
|
+
isMaxLength,
|
|
20
|
+
FiniteFromString
|
|
21
|
+
} from "./chunk-mbctzx7e.js";
|
|
22
|
+
|
|
23
|
+
// packages/core/src/schema.ts
|
|
24
|
+
var Days = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
25
|
+
var DatePattern = /^(\d\d\d\d)-(\d\d)-(\d\d)$/;
|
|
26
|
+
var TimePattern = /^(\d\d):(\d\d):(\d\d)(?:\.\d+)?(?:([Zz])|([+-])(\d\d):(\d\d))$/;
|
|
27
|
+
function isRfc3339Date(value) {
|
|
28
|
+
const match = DatePattern.exec(value);
|
|
29
|
+
if (match === null)
|
|
30
|
+
return false;
|
|
31
|
+
const year = Number(match[1]);
|
|
32
|
+
const month = Number(match[2]);
|
|
33
|
+
const day = Number(match[3]);
|
|
34
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
35
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= (month === 2 && leap ? 29 : Days[month] ?? 0);
|
|
36
|
+
}
|
|
37
|
+
function isRfc3339Time(value) {
|
|
38
|
+
const match = TimePattern.exec(value);
|
|
39
|
+
if (match === null)
|
|
40
|
+
return false;
|
|
41
|
+
const hour = Number(match[1]);
|
|
42
|
+
const minute = Number(match[2]);
|
|
43
|
+
const second = Number(match[3]);
|
|
44
|
+
if (hour > 23 || minute > 59 || second > 60)
|
|
45
|
+
return false;
|
|
46
|
+
if (match[5] !== undefined && (Number(match[6]) > 23 || Number(match[7]) > 59))
|
|
47
|
+
return false;
|
|
48
|
+
if (second < 60)
|
|
49
|
+
return true;
|
|
50
|
+
const sign = match[5] === "-" ? -1 : 1;
|
|
51
|
+
const utcMinutes = hour * 60 + minute - sign * (Number(match[6] ?? 0) * 60 + Number(match[7] ?? 0));
|
|
52
|
+
return (utcMinutes % 1440 + 1440) % 1440 === 1439;
|
|
53
|
+
}
|
|
54
|
+
var isDateTime = makeFilter((value) => {
|
|
55
|
+
const parts = value.split(/T/i);
|
|
56
|
+
return parts.length === 2 && isRfc3339Date(parts[0] ?? "") && isRfc3339Time(parts[1] ?? "");
|
|
57
|
+
}, { expected: "an RFC 3339 date-time", toJsonSchema: () => ({ format: "date-time" }) });
|
|
58
|
+
var Numeric = Union([Finite, FiniteFromString]);
|
|
59
|
+
var isWholeNumber = makeFilter(Number.isInteger, {
|
|
60
|
+
expected: "an integer",
|
|
61
|
+
toJsonSchema: () => ({ multipleOf: 1 })
|
|
62
|
+
});
|
|
63
|
+
function guard(schema) {
|
|
64
|
+
const cached = guards.get(schema);
|
|
65
|
+
if (cached !== undefined) {
|
|
66
|
+
return cached;
|
|
67
|
+
}
|
|
68
|
+
const decode = decodeUnknownExit(toType(schema));
|
|
69
|
+
const created = (input) => isSuccess2(decode(input, { onExcessProperty: "error" })) || hasUndefinedProperty(input) && isSuccess2(decode(withoutUndefined(input), { onExcessProperty: "error" }));
|
|
70
|
+
guards.set(schema, created);
|
|
71
|
+
return created;
|
|
72
|
+
}
|
|
73
|
+
var guards = new WeakMap;
|
|
74
|
+
function hasUndefinedProperty(value) {
|
|
75
|
+
if (Array.isArray(value))
|
|
76
|
+
return value.some(hasUndefinedProperty);
|
|
77
|
+
if (!isObject2(value))
|
|
78
|
+
return false;
|
|
79
|
+
return Object.values(value).some((entry) => entry === undefined || hasUndefinedProperty(entry));
|
|
80
|
+
}
|
|
81
|
+
function withoutUndefined(value) {
|
|
82
|
+
if (Array.isArray(value)) {
|
|
83
|
+
return value.map(withoutUndefined);
|
|
84
|
+
}
|
|
85
|
+
if (!isObject2(value) || Object.getPrototypeOf(value) !== Object.prototype)
|
|
86
|
+
return value;
|
|
87
|
+
return Object.fromEntries(Object.entries(value).flatMap(([key, entry]) => entry === undefined ? [] : [[key, withoutUndefined(entry)]]));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// packages/core/src/common.ts
|
|
91
|
+
var Id = String4.check(isMinLength(1));
|
|
92
|
+
var Slug = String4.check(isMinLength(1), isPattern(new RegExp("^[a-z0-9]+(?:-[a-z0-9]+)*$", "u")));
|
|
93
|
+
var Timestamp = String4.check(isDateTime);
|
|
94
|
+
var ApiError = Struct({
|
|
95
|
+
error: Struct({
|
|
96
|
+
code: String4,
|
|
97
|
+
message: String4,
|
|
98
|
+
details: optionalKey(Record(String4, Unknown))
|
|
99
|
+
})
|
|
100
|
+
});
|
|
101
|
+
var ActorType = Union([
|
|
102
|
+
Literal("human"),
|
|
103
|
+
Literal("delegated_agent"),
|
|
104
|
+
Literal("agent")
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
// packages/core/src/secret.ts
|
|
108
|
+
var SecretName = String4.check(isPattern(new RegExp("^[A-Za-z_][A-Za-z0-9_]*$", "u")), isMinLength(1), isMaxLength(128));
|
|
109
|
+
var SecretScope = Union([Literal("workspace"), Literal("team")]);
|
|
110
|
+
var SecretHost = String4.check(isPattern(new RegExp("^(\\*\\.)?[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*(?::[0-9]{1,5})?$", "u")), isMaxLength(260));
|
|
111
|
+
var SecretHosts = ArraySchema(SecretHost).check(isMaxLength(32));
|
|
112
|
+
var secretReference = (owner, name) => `secret://${owner}/${name}`;
|
|
113
|
+
var referencePattern = /secret:\/\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+/g;
|
|
114
|
+
var replaceSecretReferences = (text, swap) => text.replace(referencePattern, swap);
|
|
115
|
+
var secretReferencesIn = (text) => [...new Set(text.match(referencePattern) ?? [])];
|
|
116
|
+
var SecretSummary = Struct({
|
|
117
|
+
name: SecretName,
|
|
118
|
+
scope: SecretScope,
|
|
119
|
+
teamId: optionalKey(Id),
|
|
120
|
+
hosts: SecretHosts,
|
|
121
|
+
setByActorType: ActorType,
|
|
122
|
+
setByActorId: String4,
|
|
123
|
+
setAt: Timestamp
|
|
124
|
+
});
|
|
125
|
+
var SecretList = Struct({ items: ArraySchema(SecretSummary) });
|
|
126
|
+
var SecretSet = Struct({
|
|
127
|
+
value: String4.check(isMinLength(1), isMaxLength(65536)),
|
|
128
|
+
teamId: optionalKey(String4.check(isMinLength(1))),
|
|
129
|
+
hosts: optionalKey(SecretHosts)
|
|
130
|
+
});
|
|
131
|
+
var SecretScopeQuery = Struct({ teamId: optionalKey(Id) });
|
|
132
|
+
|
|
133
|
+
export { isDateTime, Numeric, isWholeNumber, guard, Id, Timestamp, ActorType, SecretName, SecretScope, SecretHosts, secretReference, replaceSecretReferences, secretReferencesIn };
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
isObject2,
|
|
4
|
+
isUint8Array,
|
|
5
|
+
isSuccess,
|
|
6
|
+
TaggedError,
|
|
7
|
+
succeed6,
|
|
8
|
+
gen,
|
|
9
|
+
flatMap3,
|
|
10
|
+
andThen2,
|
|
11
|
+
catchReason,
|
|
12
|
+
orElseSucceed,
|
|
13
|
+
decodeJsonString,
|
|
14
|
+
encodePrettyJsonString
|
|
15
|
+
} from "./chunk-mbctzx7e.js";
|
|
16
|
+
import {
|
|
17
|
+
isJsonObject
|
|
18
|
+
} from "./chunk-arvwar2c.js";
|
|
19
|
+
import {
|
|
20
|
+
FileSystem,
|
|
21
|
+
Path
|
|
22
|
+
} from "./chunk-11p4wf6n.js";
|
|
23
|
+
import {
|
|
24
|
+
tomlTableHeader2,
|
|
25
|
+
tomlKeyPath2,
|
|
26
|
+
isPathWithin2
|
|
27
|
+
} from "./chunk-7thnf14y.js";
|
|
28
|
+
import {
|
|
29
|
+
instructionsStart,
|
|
30
|
+
instructionsEnd,
|
|
31
|
+
renderMcpServer,
|
|
32
|
+
materializeKitSetup,
|
|
33
|
+
tomlInline
|
|
34
|
+
} from "./chunk-wh1pa2aa.js";
|
|
35
|
+
import"./chunk-pp1p3g6e.js";
|
|
36
|
+
import"./chunk-g5bs3f6z.js";
|
|
37
|
+
import"./chunk-3bj7sc3v.js";
|
|
38
|
+
import"./chunk-z821b2gp.js";
|
|
39
|
+
|
|
40
|
+
// packages/agent-runtime/src/kit-setup-sync.ts
|
|
41
|
+
class KitSyncError extends TaggedError("KitSyncError") {
|
|
42
|
+
}
|
|
43
|
+
var layoutOf = (path, harness, home) => {
|
|
44
|
+
switch (harness) {
|
|
45
|
+
case "claude":
|
|
46
|
+
return {
|
|
47
|
+
root: home,
|
|
48
|
+
instructions: path.join(home, ".claude/CLAUDE.md"),
|
|
49
|
+
marketplace: path.join(home, ".claude/kitman-marketplace"),
|
|
50
|
+
mcp: { file: path.join(home, ".claude.json"), key: "mcpServers" }
|
|
51
|
+
};
|
|
52
|
+
case "codex":
|
|
53
|
+
return {
|
|
54
|
+
root: path.join(home, ".codex"),
|
|
55
|
+
instructions: path.join(home, ".codex/AGENTS.md"),
|
|
56
|
+
marketplace: path.join(home, ".codex/codex-marketplace")
|
|
57
|
+
};
|
|
58
|
+
case "pi":
|
|
59
|
+
return {
|
|
60
|
+
root: path.join(home, ".pi/agent"),
|
|
61
|
+
instructions: path.join(home, ".pi/agent/AGENTS.md"),
|
|
62
|
+
mcp: { file: path.join(home, ".pi/agent/mcp.json"), key: "mcpServers" }
|
|
63
|
+
};
|
|
64
|
+
case "opencode":
|
|
65
|
+
return {
|
|
66
|
+
root: path.join(home, ".config/opencode"),
|
|
67
|
+
instructions: path.join(home, ".config/opencode/AGENTS.md"),
|
|
68
|
+
mcp: { file: path.join(home, ".config/opencode/opencode.json"), key: "mcp" }
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var codexBlockStart = "# >>> kitman sync: replaced on every sync";
|
|
73
|
+
var codexBlockEnd = "# <<< kitman sync";
|
|
74
|
+
var retiredInstructions = [
|
|
75
|
+
"<!-- KITMAN_AGENT_ENVIRONMENT_START -->",
|
|
76
|
+
"<!-- KITMAN_AGENT_ENVIRONMENT_END -->"
|
|
77
|
+
];
|
|
78
|
+
var withoutBlock = (text, start, end) => {
|
|
79
|
+
const from = text.indexOf(start);
|
|
80
|
+
const to = text.indexOf(end, from);
|
|
81
|
+
return from === -1 || to === -1 ? text : `${text.slice(0, from).trimEnd()}
|
|
82
|
+
|
|
83
|
+
${text.slice(to + end.length).trimStart()}`;
|
|
84
|
+
};
|
|
85
|
+
var objectAt = (value, key) => {
|
|
86
|
+
const entry = value[key];
|
|
87
|
+
return isJsonObject(entry) ? entry : {};
|
|
88
|
+
};
|
|
89
|
+
var withEntries = (value, key, entries) => {
|
|
90
|
+
const { [key]: _replaced, ...rest } = value;
|
|
91
|
+
return Object.keys(entries).length === 0 ? rest : { ...rest, [key]: entries };
|
|
92
|
+
};
|
|
93
|
+
var tomlKey = (key) => /^[A-Za-z0-9_-]+$/u.test(key) ? key : JSON.stringify(key);
|
|
94
|
+
var tomlTable = (header, value) => [
|
|
95
|
+
header,
|
|
96
|
+
...isObject2(value) && !Array.isArray(value) ? Object.entries(value).map(([key, entry]) => `${tomlKey(key)} = ${tomlInline(entry)}`) : [],
|
|
97
|
+
""
|
|
98
|
+
];
|
|
99
|
+
var codexConfigKept = (text, servers) => {
|
|
100
|
+
const kept = [];
|
|
101
|
+
let inBlock = false;
|
|
102
|
+
let dropping = false;
|
|
103
|
+
for (const line of text.split(`
|
|
104
|
+
`)) {
|
|
105
|
+
if (line === codexBlockStart)
|
|
106
|
+
inBlock = true;
|
|
107
|
+
if (inBlock) {
|
|
108
|
+
inBlock = line !== codexBlockEnd;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
const header = tomlTableHeader2(line);
|
|
112
|
+
if (header !== undefined) {
|
|
113
|
+
const [table, name] = tomlKeyPath2(header);
|
|
114
|
+
dropping = table === "mcp_servers" && name !== undefined && servers.has(name) || table === "marketplaces" && name === "kitman" || table === "plugins" && name?.endsWith("@kitman") === true;
|
|
115
|
+
}
|
|
116
|
+
if (!dropping)
|
|
117
|
+
kept.push(line);
|
|
118
|
+
}
|
|
119
|
+
return kept.join(`
|
|
120
|
+
`).trim();
|
|
121
|
+
};
|
|
122
|
+
var syncKitSetup = (input) => gen(function* () {
|
|
123
|
+
const fs = yield* FileSystem;
|
|
124
|
+
const path = yield* Path;
|
|
125
|
+
const setup = materializeKitSetup(input.harness, input.kits);
|
|
126
|
+
const layout = layoutOf(path, input.harness, input.home);
|
|
127
|
+
const skillsDir = path.join(layout.root, setup.skillsRoot);
|
|
128
|
+
const write = (file, content) => andThen2(fs.makeDirectory(path.dirname(file), { recursive: true }), isUint8Array(content) ? fs.writeFile(file, content) : fs.writeFileString(file, content));
|
|
129
|
+
const readText = (file) => fs.readFileString(file).pipe(catchReason("PlatformError", "NotFound", () => succeed6("")));
|
|
130
|
+
const readJson = (file) => gen(function* () {
|
|
131
|
+
const text = yield* readText(file);
|
|
132
|
+
const value = yield* decodeJsonString(text.trim() === "" ? "{}" : text).pipe(orElseSucceed(() => {
|
|
133
|
+
return;
|
|
134
|
+
}));
|
|
135
|
+
if (!isJsonObject(value))
|
|
136
|
+
return yield* new KitSyncError({ message: `${file} is not a JSON object; fix or move it, then sync again` });
|
|
137
|
+
return value;
|
|
138
|
+
});
|
|
139
|
+
const writeJson = (file, value) => flatMap3(encodePrettyJsonString(value), (json) => write(file, `${json}
|
|
140
|
+
`));
|
|
141
|
+
const targets = Object.entries(setup.files).flatMap(([file, content]) => {
|
|
142
|
+
if (file === setup.instructions?.path || file === ".mcp.json")
|
|
143
|
+
return [];
|
|
144
|
+
const target = input.harness === "claude" && file.startsWith("plugins/") && layout.marketplace !== undefined ? path.join(layout.marketplace, file) : path.join(layout.root, file);
|
|
145
|
+
return [{ file, target, content }];
|
|
146
|
+
});
|
|
147
|
+
const astray = targets.find(({ target }) => !isPathWithin2(path, skillsDir, target) && (layout.marketplace === undefined || !isPathWithin2(path, layout.marketplace, target)));
|
|
148
|
+
if (astray !== undefined)
|
|
149
|
+
return yield* new KitSyncError({ message: `A Kit's file ${astray.file} would land outside its directory` });
|
|
150
|
+
const skills = [...new Set([...input.previous?.skills ?? [], ...setup.skills])];
|
|
151
|
+
const outside = skills.find((skill) => path.dirname(path.join(skillsDir, skill)) !== skillsDir);
|
|
152
|
+
if (outside !== undefined)
|
|
153
|
+
return yield* new KitSyncError({ message: `A Kit's skill name ${outside} would land outside its directory` });
|
|
154
|
+
for (const skill of skills)
|
|
155
|
+
yield* fs.remove(path.join(skillsDir, skill), { recursive: true, force: true });
|
|
156
|
+
if (layout.marketplace !== undefined)
|
|
157
|
+
yield* fs.remove(layout.marketplace, { recursive: true, force: true });
|
|
158
|
+
for (const { target, content } of targets)
|
|
159
|
+
yield* write(target, content);
|
|
160
|
+
if (input.harness === "claude" && layout.marketplace !== undefined && setup.plugins.length > 0)
|
|
161
|
+
yield* writeJson(path.join(layout.marketplace, ".claude-plugin/marketplace.json"), {
|
|
162
|
+
name: "kitman",
|
|
163
|
+
owner: { name: "Kitman" },
|
|
164
|
+
plugins: setup.plugins.map((name) => ({ name, source: `./plugins/${name}` }))
|
|
165
|
+
});
|
|
166
|
+
const instructions = withoutBlock(withoutBlock(yield* readText(layout.instructions), instructionsStart, instructionsEnd), ...retiredInstructions).trim();
|
|
167
|
+
if (setup.instructions !== undefined)
|
|
168
|
+
yield* write(layout.instructions, instructions === "" ? setup.instructions.content : `${instructions}
|
|
169
|
+
|
|
170
|
+
${setup.instructions.content}`);
|
|
171
|
+
else if (instructions === "")
|
|
172
|
+
yield* fs.remove(layout.instructions, { force: true });
|
|
173
|
+
else
|
|
174
|
+
yield* write(layout.instructions, `${instructions}
|
|
175
|
+
`);
|
|
176
|
+
const kitman = renderMcpServer(input.harness, {
|
|
177
|
+
kind: "stdio",
|
|
178
|
+
command: input.kitman.command,
|
|
179
|
+
args: [...input.kitman.args]
|
|
180
|
+
});
|
|
181
|
+
const servers = {
|
|
182
|
+
...isSuccess(kitman) ? { kitman: kitman.success } : undefined,
|
|
183
|
+
...setup.mcpConfig
|
|
184
|
+
};
|
|
185
|
+
const replaced = new Set(["kitman", ...input.previous?.mcpServers ?? [], ...Object.keys(servers)]);
|
|
186
|
+
if (layout.mcp !== undefined) {
|
|
187
|
+
const { file, key } = layout.mcp;
|
|
188
|
+
const config = yield* readJson(file);
|
|
189
|
+
const kept = Object.fromEntries(Object.entries(objectAt(config, key)).filter(([name]) => !replaced.has(name)));
|
|
190
|
+
yield* writeJson(file, withEntries(config, key, Object.fromEntries([...Object.entries(kept), ...Object.entries(servers)])));
|
|
191
|
+
}
|
|
192
|
+
if (input.harness === "codex") {
|
|
193
|
+
const file = path.join(layout.root, "config.toml");
|
|
194
|
+
const kept = codexConfigKept(yield* readText(file), replaced);
|
|
195
|
+
const block = [
|
|
196
|
+
codexBlockStart,
|
|
197
|
+
...Object.entries(servers).flatMap(([name, server]) => tomlTable(`[mcp_servers.${tomlKey(name)}]`, server)),
|
|
198
|
+
...setup.plugins.length === 0 || layout.marketplace === undefined ? [] : [
|
|
199
|
+
...tomlTable("[marketplaces.kitman]", { source_type: "local", source: layout.marketplace }),
|
|
200
|
+
...setup.plugins.flatMap((plugin) => tomlTable(`[plugins.${tomlKey(`${plugin}@kitman`)}]`, { enabled: true }))
|
|
201
|
+
],
|
|
202
|
+
...setup.skills.flatMap((skill) => tomlTable("[[skills.config]]", { path: path.join(skillsDir, skill, "SKILL.md"), enabled: true })),
|
|
203
|
+
codexBlockEnd,
|
|
204
|
+
""
|
|
205
|
+
].join(`
|
|
206
|
+
`);
|
|
207
|
+
yield* write(file, kept === "" ? block : `${kept}
|
|
208
|
+
|
|
209
|
+
${block}`);
|
|
210
|
+
}
|
|
211
|
+
if (input.harness === "claude" && layout.marketplace !== undefined) {
|
|
212
|
+
const file = path.join(input.home, ".claude/settings.json");
|
|
213
|
+
const settings = yield* readJson(file);
|
|
214
|
+
const { kitman: _kitman, ...marketplaces } = objectAt(settings, "extraKnownMarketplaces");
|
|
215
|
+
const enabled = Object.fromEntries(Object.entries(objectAt(settings, "enabledPlugins")).filter(([plugin]) => !plugin.endsWith("@kitman")));
|
|
216
|
+
const next = withEntries(withEntries(settings, "extraKnownMarketplaces", {
|
|
217
|
+
...marketplaces,
|
|
218
|
+
...setup.plugins.length === 0 ? undefined : { kitman: { source: { source: "directory", path: layout.marketplace } } }
|
|
219
|
+
}), "enabledPlugins", { ...enabled, ...Object.fromEntries(setup.plugins.map((plugin) => [`${plugin}@kitman`, true])) });
|
|
220
|
+
if (Object.keys(next).length > 0 || Object.keys(settings).length > 0)
|
|
221
|
+
yield* writeJson(file, next);
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
synced: { skills: setup.skills, mcpServers: Object.keys(setup.mcpConfig) },
|
|
225
|
+
unsupported: setup.unsupported
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
export {
|
|
229
|
+
KitSyncError,
|
|
230
|
+
syncKitSetup
|
|
231
|
+
};
|