@babyclaw/gateway 0.0.0 → 0.2.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/index.d.ts +91 -1
- package/dist/index.js +308 -79
- package/dist/index.js.map +1 -1
- package/dist/main.js +255 -71
- package/dist/main.js.map +1 -1
- package/package.json +8 -2
package/dist/index.js
CHANGED
|
@@ -5,7 +5,8 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/runtime.ts
|
|
8
|
-
import {
|
|
8
|
+
import { mkdirSync as mkdirSync3 } from "fs";
|
|
9
|
+
import { getBundledSkillsDir } from "@babyclaw/skills";
|
|
9
10
|
|
|
10
11
|
// src/ai/agent.ts
|
|
11
12
|
import {
|
|
@@ -280,37 +281,84 @@ var SUPPORTED_PROVIDERS = [
|
|
|
280
281
|
{
|
|
281
282
|
id: "anthropic",
|
|
282
283
|
displayName: "Anthropic",
|
|
283
|
-
exampleModels: [
|
|
284
|
+
exampleModels: [
|
|
285
|
+
"claude-sonnet-4-20250514",
|
|
286
|
+
"claude-opus-4-6",
|
|
287
|
+
"claude-haiku-4-5",
|
|
288
|
+
"claude-4.5-sonnet",
|
|
289
|
+
"claude-3.5-sonnet-20241022",
|
|
290
|
+
"claude-3.5-haiku-20241022"
|
|
291
|
+
]
|
|
284
292
|
},
|
|
285
293
|
{
|
|
286
294
|
id: "openai",
|
|
287
295
|
displayName: "OpenAI",
|
|
288
|
-
exampleModels: [
|
|
296
|
+
exampleModels: [
|
|
297
|
+
"gpt-4o",
|
|
298
|
+
"gpt-4o-mini",
|
|
299
|
+
"gpt-4.1",
|
|
300
|
+
"gpt-4.1-mini",
|
|
301
|
+
"gpt-4.1-nano",
|
|
302
|
+
"o3",
|
|
303
|
+
"o3-mini",
|
|
304
|
+
"o4-mini"
|
|
305
|
+
]
|
|
289
306
|
},
|
|
290
307
|
{
|
|
291
308
|
id: "google",
|
|
292
309
|
displayName: "Google Generative AI",
|
|
293
|
-
exampleModels: [
|
|
310
|
+
exampleModels: [
|
|
311
|
+
"gemini-2.5-pro",
|
|
312
|
+
"gemini-2.5-flash",
|
|
313
|
+
"gemini-2.0-flash",
|
|
314
|
+
"gemini-2.0-flash-lite"
|
|
315
|
+
]
|
|
294
316
|
},
|
|
295
317
|
{
|
|
296
318
|
id: "mistral",
|
|
297
319
|
displayName: "Mistral",
|
|
298
|
-
exampleModels: [
|
|
320
|
+
exampleModels: [
|
|
321
|
+
"mistral-large-latest",
|
|
322
|
+
"mistral-medium-latest",
|
|
323
|
+
"mistral-small-latest",
|
|
324
|
+
"codestral-latest",
|
|
325
|
+
"pixtral-large-latest"
|
|
326
|
+
]
|
|
299
327
|
},
|
|
300
328
|
{
|
|
301
329
|
id: "xai",
|
|
302
330
|
displayName: "xAI",
|
|
303
|
-
exampleModels: ["grok-3", "grok-3-mini"]
|
|
331
|
+
exampleModels: ["grok-3", "grok-3-fast", "grok-3-mini", "grok-3-mini-fast"]
|
|
304
332
|
},
|
|
305
333
|
{
|
|
306
334
|
id: "openrouter",
|
|
307
335
|
displayName: "OpenRouter",
|
|
308
|
-
exampleModels: [
|
|
336
|
+
exampleModels: [
|
|
337
|
+
"anthropic/claude-sonnet-4",
|
|
338
|
+
"anthropic/claude-opus-4",
|
|
339
|
+
"anthropic/claude-4.5-sonnet",
|
|
340
|
+
"openai/gpt-4o",
|
|
341
|
+
"openai/gpt-4.1",
|
|
342
|
+
"openai/o3",
|
|
343
|
+
"openai/o4-mini",
|
|
344
|
+
"google/gemini-2.5-pro",
|
|
345
|
+
"google/gemini-2.5-flash",
|
|
346
|
+
"deepseek/deepseek-r1",
|
|
347
|
+
"deepseek/deepseek-chat-v3",
|
|
348
|
+
"meta-llama/llama-4-maverick",
|
|
349
|
+
"meta-llama/llama-4-scout"
|
|
350
|
+
]
|
|
309
351
|
},
|
|
310
352
|
{
|
|
311
353
|
id: "gateway",
|
|
312
354
|
displayName: "Vercel AI Gateway",
|
|
313
|
-
exampleModels: [
|
|
355
|
+
exampleModels: [
|
|
356
|
+
"anthropic/claude-sonnet-4-20250514",
|
|
357
|
+
"anthropic/claude-opus-4-6",
|
|
358
|
+
"openai/gpt-4o",
|
|
359
|
+
"openai/gpt-4.1",
|
|
360
|
+
"google/gemini-2.5-pro"
|
|
361
|
+
]
|
|
314
362
|
}
|
|
315
363
|
];
|
|
316
364
|
var PROVIDER_FACTORY_MAP = {
|
|
@@ -1995,9 +2043,26 @@ import { z } from "zod";
|
|
|
1995
2043
|
// src/utils/path.ts
|
|
1996
2044
|
import { resolve, sep } from "path";
|
|
1997
2045
|
import { stat } from "fs/promises";
|
|
2046
|
+
var BUNDLED_SKILLS_PREFIX = "bundled-skills/";
|
|
1998
2047
|
function normalizeSeparators({ path }) {
|
|
1999
2048
|
return path.replaceAll("\\", "/");
|
|
2000
2049
|
}
|
|
2050
|
+
function resolveBundledSkillPath({
|
|
2051
|
+
bundledSkillsDir,
|
|
2052
|
+
requestedPath
|
|
2053
|
+
}) {
|
|
2054
|
+
const relative3 = requestedPath.slice(BUNDLED_SKILLS_PREFIX.length);
|
|
2055
|
+
const normalized = normalizeSeparators({ path: relative3 }).trim();
|
|
2056
|
+
if (normalized.length === 0) {
|
|
2057
|
+
throw new Error("Path is required");
|
|
2058
|
+
}
|
|
2059
|
+
const absoluteRoot = resolve(bundledSkillsDir);
|
|
2060
|
+
const absoluteTarget = resolve(absoluteRoot, normalized);
|
|
2061
|
+
if (!isSubPath({ parent: absoluteRoot, child: absoluteTarget })) {
|
|
2062
|
+
throw new Error("Path escapes bundled skills root");
|
|
2063
|
+
}
|
|
2064
|
+
return absoluteTarget;
|
|
2065
|
+
}
|
|
2001
2066
|
function resolveWorkspacePath({
|
|
2002
2067
|
workspaceRoot,
|
|
2003
2068
|
requestedPath
|
|
@@ -3754,10 +3819,25 @@ function createWorkspaceTools({ context }) {
|
|
|
3754
3819
|
defaultCode: "WORKSPACE_READ_FAILED",
|
|
3755
3820
|
input: { path, format },
|
|
3756
3821
|
action: async () => {
|
|
3757
|
-
const
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3822
|
+
const isBundled = path.startsWith(BUNDLED_SKILLS_PREFIX);
|
|
3823
|
+
let absolutePath;
|
|
3824
|
+
if (isBundled) {
|
|
3825
|
+
if (!context.bundledSkillsDir) {
|
|
3826
|
+
throw new ToolExecutionError({
|
|
3827
|
+
code: "BUNDLED_SKILLS_UNAVAILABLE",
|
|
3828
|
+
message: "Bundled skills directory is not configured"
|
|
3829
|
+
});
|
|
3830
|
+
}
|
|
3831
|
+
absolutePath = resolveBundledSkillPath({
|
|
3832
|
+
bundledSkillsDir: context.bundledSkillsDir,
|
|
3833
|
+
requestedPath: path
|
|
3834
|
+
});
|
|
3835
|
+
} else {
|
|
3836
|
+
absolutePath = resolveWorkspacePath({
|
|
3837
|
+
workspaceRoot: context.workspaceRoot,
|
|
3838
|
+
requestedPath: path
|
|
3839
|
+
});
|
|
3840
|
+
}
|
|
3761
3841
|
const raw = await readFile6(absolutePath, "utf8");
|
|
3762
3842
|
ensurePayloadWithinLimit({
|
|
3763
3843
|
value: raw,
|
|
@@ -3815,6 +3895,12 @@ function createWorkspaceTools({ context }) {
|
|
|
3815
3895
|
hasValue: value !== void 0
|
|
3816
3896
|
},
|
|
3817
3897
|
action: async () => {
|
|
3898
|
+
if (path.startsWith(BUNDLED_SKILLS_PREFIX)) {
|
|
3899
|
+
throw new ToolExecutionError({
|
|
3900
|
+
code: "BUNDLED_SKILLS_READONLY",
|
|
3901
|
+
message: "Bundled skills are read-only and cannot be written to"
|
|
3902
|
+
});
|
|
3903
|
+
}
|
|
3818
3904
|
const absolutePath = resolveWorkspacePath({
|
|
3819
3905
|
workspaceRoot: context.workspaceRoot,
|
|
3820
3906
|
requestedPath: path
|
|
@@ -3954,6 +4040,12 @@ function createWorkspaceTools({ context }) {
|
|
|
3954
4040
|
defaultCode: "WORKSPACE_DELETE_FAILED",
|
|
3955
4041
|
input: { path, recursive },
|
|
3956
4042
|
action: async () => {
|
|
4043
|
+
if (path.startsWith(BUNDLED_SKILLS_PREFIX)) {
|
|
4044
|
+
throw new ToolExecutionError({
|
|
4045
|
+
code: "BUNDLED_SKILLS_READONLY",
|
|
4046
|
+
message: "Bundled skills are read-only and cannot be deleted"
|
|
4047
|
+
});
|
|
4048
|
+
}
|
|
3957
4049
|
const absolutePath = resolveWorkspacePath({
|
|
3958
4050
|
workspaceRoot: context.workspaceRoot,
|
|
3959
4051
|
requestedPath: path
|
|
@@ -3990,6 +4082,12 @@ function createWorkspaceTools({ context }) {
|
|
|
3990
4082
|
defaultCode: "WORKSPACE_MOVE_FAILED",
|
|
3991
4083
|
input: { from_path, to_path, overwrite },
|
|
3992
4084
|
action: async () => {
|
|
4085
|
+
if (from_path.startsWith(BUNDLED_SKILLS_PREFIX) || to_path.startsWith(BUNDLED_SKILLS_PREFIX)) {
|
|
4086
|
+
throw new ToolExecutionError({
|
|
4087
|
+
code: "BUNDLED_SKILLS_READONLY",
|
|
4088
|
+
message: "Bundled skills are read-only and cannot be moved"
|
|
4089
|
+
});
|
|
4090
|
+
}
|
|
3993
4091
|
const fromAbsolute = resolveWorkspacePath({
|
|
3994
4092
|
workspaceRoot: context.workspaceRoot,
|
|
3995
4093
|
requestedPath: from_path
|
|
@@ -4170,44 +4268,15 @@ function createUnifiedTools({
|
|
|
4170
4268
|
};
|
|
4171
4269
|
}
|
|
4172
4270
|
|
|
4173
|
-
// src/
|
|
4174
|
-
import {
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
userPath: join9(workspacePath, "USER.md")
|
|
4181
|
-
};
|
|
4182
|
-
}
|
|
4183
|
-
async function readPersonalityFiles({
|
|
4184
|
-
workspacePath
|
|
4271
|
+
// src/bundled-skills/index.ts
|
|
4272
|
+
import { listBundledSlugs, readBundledSkillContent, getBundledSkillInfo } from "@babyclaw/skills";
|
|
4273
|
+
|
|
4274
|
+
// src/workspace/skills/types.ts
|
|
4275
|
+
function getSkillKey({
|
|
4276
|
+
frontmatter,
|
|
4277
|
+
slug
|
|
4185
4278
|
}) {
|
|
4186
|
-
|
|
4187
|
-
const [identity, soul, user] = await Promise.all([
|
|
4188
|
-
readOptionalFile2({ path: identityPath }),
|
|
4189
|
-
readOptionalFile2({ path: soulPath }),
|
|
4190
|
-
readOptionalFile2({ path: userPath })
|
|
4191
|
-
]);
|
|
4192
|
-
return {
|
|
4193
|
-
identity,
|
|
4194
|
-
soul,
|
|
4195
|
-
user
|
|
4196
|
-
};
|
|
4197
|
-
}
|
|
4198
|
-
function hasCompletePersonalityFiles(files) {
|
|
4199
|
-
return typeof files.identity === "string" && files.identity.trim().length > 0 && typeof files.soul === "string" && files.soul.trim().length > 0 && typeof files.user === "string" && files.user.trim().length > 0;
|
|
4200
|
-
}
|
|
4201
|
-
async function readOptionalFile2({ path }) {
|
|
4202
|
-
try {
|
|
4203
|
-
return await readFile7(path, "utf8");
|
|
4204
|
-
} catch (error) {
|
|
4205
|
-
const maybeErrno = error;
|
|
4206
|
-
if (maybeErrno.code === "ENOENT") {
|
|
4207
|
-
return null;
|
|
4208
|
-
}
|
|
4209
|
-
throw error;
|
|
4210
|
-
}
|
|
4279
|
+
return frontmatter?.openclaw?.skillKey ?? frontmatter?.name ?? slug;
|
|
4211
4280
|
}
|
|
4212
4281
|
|
|
4213
4282
|
// src/workspace/skills/eligibility.ts
|
|
@@ -4217,54 +4286,84 @@ function getEligibleSkills({
|
|
|
4217
4286
|
skillsConfig,
|
|
4218
4287
|
fullConfig
|
|
4219
4288
|
}) {
|
|
4220
|
-
return skills.filter((skill) =>
|
|
4289
|
+
return skills.filter((skill) => {
|
|
4290
|
+
const { frontmatter, slug } = skill;
|
|
4291
|
+
const entry = skillsConfig.entries[getSkillKey({ frontmatter, slug })];
|
|
4292
|
+
if (entry?.enabled === false) return false;
|
|
4293
|
+
return checkSkillEligibility({ frontmatter, skillsConfig, fullConfig }).eligible;
|
|
4294
|
+
});
|
|
4221
4295
|
}
|
|
4222
|
-
function
|
|
4223
|
-
|
|
4296
|
+
function checkSkillEligibility({
|
|
4297
|
+
frontmatter,
|
|
4224
4298
|
skillsConfig,
|
|
4225
4299
|
fullConfig
|
|
4226
4300
|
}) {
|
|
4227
|
-
|
|
4301
|
+
if (frontmatter.disableModelInvocation) {
|
|
4302
|
+
return { eligible: false, reason: "Model invocation disabled" };
|
|
4303
|
+
}
|
|
4228
4304
|
const openclaw = frontmatter.openclaw;
|
|
4229
|
-
const skillKey = openclaw?.skillKey ?? frontmatter.name;
|
|
4230
|
-
const entry = skillsConfig.entries[skillKey];
|
|
4231
|
-
if (entry?.enabled === false) return false;
|
|
4232
|
-
if (frontmatter.disableModelInvocation) return false;
|
|
4233
4305
|
if (openclaw?.os && openclaw.os.length > 0) {
|
|
4234
|
-
if (!openclaw.os.includes(process.platform))
|
|
4306
|
+
if (!openclaw.os.includes(process.platform)) {
|
|
4307
|
+
return {
|
|
4308
|
+
eligible: false,
|
|
4309
|
+
reason: `Requires OS: ${openclaw.os.join(", ")} (current: ${process.platform})`
|
|
4310
|
+
};
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
if (openclaw?.always) {
|
|
4314
|
+
return { eligible: true, reason: null };
|
|
4235
4315
|
}
|
|
4236
|
-
if (openclaw?.always) return true;
|
|
4237
4316
|
const requires = openclaw?.requires;
|
|
4238
|
-
if (!requires)
|
|
4317
|
+
if (!requires) {
|
|
4318
|
+
return { eligible: true, reason: null };
|
|
4319
|
+
}
|
|
4239
4320
|
if (requires.bins && requires.bins.length > 0) {
|
|
4240
|
-
|
|
4321
|
+
const missing = requires.bins.filter((bin) => !binaryExists({ name: bin }));
|
|
4322
|
+
if (missing.length > 0) {
|
|
4323
|
+
return { eligible: false, reason: `Missing binaries: ${missing.join(", ")}` };
|
|
4324
|
+
}
|
|
4241
4325
|
}
|
|
4242
4326
|
if (requires.anyBins && requires.anyBins.length > 0) {
|
|
4243
|
-
if (!requires.anyBins.some((bin) => binaryExists({ name: bin })))
|
|
4327
|
+
if (!requires.anyBins.some((bin) => binaryExists({ name: bin }))) {
|
|
4328
|
+
return {
|
|
4329
|
+
eligible: false,
|
|
4330
|
+
reason: `Requires at least one of: ${requires.anyBins.join(", ")}`
|
|
4331
|
+
};
|
|
4332
|
+
}
|
|
4244
4333
|
}
|
|
4245
4334
|
if (requires.env && requires.env.length > 0) {
|
|
4335
|
+
const skillKey = openclaw?.skillKey ?? frontmatter.name;
|
|
4336
|
+
const entry = skillsConfig.entries[skillKey];
|
|
4246
4337
|
const primaryEnv = openclaw?.primaryEnv;
|
|
4247
4338
|
const hasApiKeyInConfig = Boolean(entry?.apiKey);
|
|
4248
4339
|
for (const envVar of requires.env) {
|
|
4249
4340
|
if (process.env[envVar]) continue;
|
|
4250
4341
|
if (primaryEnv === envVar && hasApiKeyInConfig) continue;
|
|
4251
|
-
return false;
|
|
4342
|
+
return { eligible: false, reason: `Missing environment variable: ${envVar}` };
|
|
4252
4343
|
}
|
|
4253
4344
|
}
|
|
4254
4345
|
if (requires.config && requires.config.length > 0) {
|
|
4255
4346
|
for (const configPath of requires.config) {
|
|
4256
|
-
if (!getConfigValue({ config: fullConfig, path: configPath }))
|
|
4347
|
+
if (!getConfigValue({ config: fullConfig, path: configPath })) {
|
|
4348
|
+
return { eligible: false, reason: `Missing config value: ${configPath}` };
|
|
4349
|
+
}
|
|
4257
4350
|
}
|
|
4258
4351
|
}
|
|
4259
|
-
return true;
|
|
4352
|
+
return { eligible: true, reason: null };
|
|
4260
4353
|
}
|
|
4354
|
+
var binaryExistsCache = /* @__PURE__ */ new Map();
|
|
4261
4355
|
function binaryExists({ name }) {
|
|
4356
|
+
const cached = binaryExistsCache.get(name);
|
|
4357
|
+
if (cached !== void 0) return cached;
|
|
4358
|
+
let exists;
|
|
4262
4359
|
try {
|
|
4263
4360
|
execFileSync("which", [name], { stdio: "ignore" });
|
|
4264
|
-
|
|
4361
|
+
exists = true;
|
|
4265
4362
|
} catch {
|
|
4266
|
-
|
|
4363
|
+
exists = false;
|
|
4267
4364
|
}
|
|
4365
|
+
binaryExistsCache.set(name, exists);
|
|
4366
|
+
return exists;
|
|
4268
4367
|
}
|
|
4269
4368
|
function getConfigValue({
|
|
4270
4369
|
config,
|
|
@@ -4279,6 +4378,94 @@ function getConfigValue({
|
|
|
4279
4378
|
return current;
|
|
4280
4379
|
}
|
|
4281
4380
|
|
|
4381
|
+
// src/bundled-skills/index.ts
|
|
4382
|
+
function listBundledSkills({
|
|
4383
|
+
skillsConfig,
|
|
4384
|
+
fullConfig
|
|
4385
|
+
}) {
|
|
4386
|
+
const slugs = listBundledSlugs();
|
|
4387
|
+
return slugs.map((slug) => {
|
|
4388
|
+
const content = readBundledSkillContent({ slug });
|
|
4389
|
+
if (!content) {
|
|
4390
|
+
return {
|
|
4391
|
+
slug,
|
|
4392
|
+
frontmatter: null,
|
|
4393
|
+
enabled: false,
|
|
4394
|
+
eligible: false,
|
|
4395
|
+
ineligibilityReason: "Could not read SKILL.md"
|
|
4396
|
+
};
|
|
4397
|
+
}
|
|
4398
|
+
const raw = parseFrontmatter({ content });
|
|
4399
|
+
const frontmatter = raw ? buildFrontmatter({ raw }) : null;
|
|
4400
|
+
const skillKey = getSkillKey({ frontmatter, slug });
|
|
4401
|
+
const entry = skillsConfig.entries[skillKey];
|
|
4402
|
+
const enabled = entry?.enabled === true;
|
|
4403
|
+
const { eligible, reason } = frontmatter ? checkSkillEligibility({ frontmatter, skillsConfig, fullConfig }) : { eligible: false, reason: "Invalid frontmatter" };
|
|
4404
|
+
return {
|
|
4405
|
+
slug,
|
|
4406
|
+
frontmatter,
|
|
4407
|
+
enabled,
|
|
4408
|
+
eligible,
|
|
4409
|
+
ineligibilityReason: reason
|
|
4410
|
+
};
|
|
4411
|
+
});
|
|
4412
|
+
}
|
|
4413
|
+
function getEnabledBundledSkills({
|
|
4414
|
+
skillsConfig,
|
|
4415
|
+
fullConfig
|
|
4416
|
+
}) {
|
|
4417
|
+
const all = listBundledSkills({ skillsConfig, fullConfig });
|
|
4418
|
+
return all.filter((s) => s.enabled && s.eligible && s.frontmatter).map((s) => ({
|
|
4419
|
+
frontmatter: s.frontmatter,
|
|
4420
|
+
slug: s.slug,
|
|
4421
|
+
relativePath: `bundled-skills/${s.slug}/SKILL.md`
|
|
4422
|
+
}));
|
|
4423
|
+
}
|
|
4424
|
+
function getBundledSkillPath({ slug }) {
|
|
4425
|
+
const info = getBundledSkillInfo({ slug });
|
|
4426
|
+
return info?.skillDir ?? null;
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
// src/onboarding/personality.ts
|
|
4430
|
+
import { readFile as readFile7 } from "fs/promises";
|
|
4431
|
+
import { join as join9 } from "path";
|
|
4432
|
+
function getPersonalityFilePaths({ workspacePath }) {
|
|
4433
|
+
return {
|
|
4434
|
+
identityPath: join9(workspacePath, "IDENTITY.md"),
|
|
4435
|
+
soulPath: join9(workspacePath, "SOUL.md"),
|
|
4436
|
+
userPath: join9(workspacePath, "USER.md")
|
|
4437
|
+
};
|
|
4438
|
+
}
|
|
4439
|
+
async function readPersonalityFiles({
|
|
4440
|
+
workspacePath
|
|
4441
|
+
}) {
|
|
4442
|
+
const { identityPath, soulPath, userPath } = getPersonalityFilePaths({ workspacePath });
|
|
4443
|
+
const [identity, soul, user] = await Promise.all([
|
|
4444
|
+
readOptionalFile2({ path: identityPath }),
|
|
4445
|
+
readOptionalFile2({ path: soulPath }),
|
|
4446
|
+
readOptionalFile2({ path: userPath })
|
|
4447
|
+
]);
|
|
4448
|
+
return {
|
|
4449
|
+
identity,
|
|
4450
|
+
soul,
|
|
4451
|
+
user
|
|
4452
|
+
};
|
|
4453
|
+
}
|
|
4454
|
+
function hasCompletePersonalityFiles(files) {
|
|
4455
|
+
return typeof files.identity === "string" && files.identity.trim().length > 0 && typeof files.soul === "string" && files.soul.trim().length > 0 && typeof files.user === "string" && files.user.trim().length > 0;
|
|
4456
|
+
}
|
|
4457
|
+
async function readOptionalFile2({ path }) {
|
|
4458
|
+
try {
|
|
4459
|
+
return await readFile7(path, "utf8");
|
|
4460
|
+
} catch (error) {
|
|
4461
|
+
const maybeErrno = error;
|
|
4462
|
+
if (maybeErrno.code === "ENOENT") {
|
|
4463
|
+
return null;
|
|
4464
|
+
}
|
|
4465
|
+
throw error;
|
|
4466
|
+
}
|
|
4467
|
+
}
|
|
4468
|
+
|
|
4282
4469
|
// src/agent/context.ts
|
|
4283
4470
|
async function loadAgentContext({
|
|
4284
4471
|
workspacePath,
|
|
@@ -4291,7 +4478,11 @@ async function loadAgentContext({
|
|
|
4291
4478
|
readWorkspaceGuide({ workspacePath }),
|
|
4292
4479
|
scanWorkspaceSkills({ workspacePath })
|
|
4293
4480
|
]);
|
|
4294
|
-
const
|
|
4481
|
+
const workspaceSkills = getEligibleSkills({ skills: allSkills, skillsConfig, fullConfig });
|
|
4482
|
+
const bundledSkills = getEnabledBundledSkills({ skillsConfig, fullConfig });
|
|
4483
|
+
const workspaceSlugs = new Set(workspaceSkills.map((s) => s.slug));
|
|
4484
|
+
const dedupedBundled = bundledSkills.filter((s) => !workspaceSlugs.has(s.slug));
|
|
4485
|
+
const skills = [...workspaceSkills, ...dedupedBundled];
|
|
4295
4486
|
const personalityFiles = hasCompletePersonalityFiles(rawPersonalityFiles) ? rawPersonalityFiles : void 0;
|
|
4296
4487
|
return { personalityFiles, toolNotesContent, agentsContent, skills };
|
|
4297
4488
|
}
|
|
@@ -4472,6 +4663,7 @@ var AgentTurnOrchestrator = class {
|
|
|
4472
4663
|
if (abortSignal.aborted) return;
|
|
4473
4664
|
const {
|
|
4474
4665
|
workspacePath,
|
|
4666
|
+
bundledSkillsDir,
|
|
4475
4667
|
aiAgent,
|
|
4476
4668
|
sessionManager,
|
|
4477
4669
|
schedulerService,
|
|
@@ -4571,6 +4763,7 @@ ${description}`;
|
|
|
4571
4763
|
toolDeps: this.toolDeps,
|
|
4572
4764
|
executionContext: {
|
|
4573
4765
|
workspaceRoot: workspacePath,
|
|
4766
|
+
bundledSkillsDir,
|
|
4574
4767
|
botTimezone: schedulerService.getTimezone(),
|
|
4575
4768
|
platform: event.platform,
|
|
4576
4769
|
chatId: event.chatId,
|
|
@@ -5885,11 +6078,11 @@ var ChatRegistry = class {
|
|
|
5885
6078
|
|
|
5886
6079
|
// src/config/loader.ts
|
|
5887
6080
|
import { access, mkdir as mkdir5, readFile as readFile8, writeFile as writeFile5 } from "fs/promises";
|
|
5888
|
-
import { dirname as
|
|
6081
|
+
import { dirname as dirname6 } from "path";
|
|
5889
6082
|
|
|
5890
6083
|
// src/config/paths.ts
|
|
5891
6084
|
import { homedir as homedir2 } from "os";
|
|
5892
|
-
import { join as join11 } from "path";
|
|
6085
|
+
import { dirname as dirname5, join as join11, resolve as resolve4, isAbsolute } from "path";
|
|
5893
6086
|
var CONFIG_PATH_ENV_VAR = "BABYCLAW_CONFIG_PATH";
|
|
5894
6087
|
function getDefaultConfigPath() {
|
|
5895
6088
|
return join11(homedir2(), ".babyclaw", "babyclaw.json");
|
|
@@ -5901,6 +6094,19 @@ function getConfigPath() {
|
|
|
5901
6094
|
}
|
|
5902
6095
|
return getDefaultConfigPath();
|
|
5903
6096
|
}
|
|
6097
|
+
function getConfigDir() {
|
|
6098
|
+
return dirname5(getConfigPath());
|
|
6099
|
+
}
|
|
6100
|
+
var DEFAULT_WORKSPACE_ROOT = "~/babyclaw";
|
|
6101
|
+
function resolveWorkspaceRoot({ configRoot }) {
|
|
6102
|
+
if (configRoot === "~" || configRoot.startsWith("~/")) {
|
|
6103
|
+
return join11(homedir2(), configRoot.slice(2));
|
|
6104
|
+
}
|
|
6105
|
+
if (isAbsolute(configRoot)) {
|
|
6106
|
+
return configRoot;
|
|
6107
|
+
}
|
|
6108
|
+
return resolve4(getConfigDir(), configRoot);
|
|
6109
|
+
}
|
|
5904
6110
|
|
|
5905
6111
|
// src/config/schema.ts
|
|
5906
6112
|
import { z as z11 } from "zod";
|
|
@@ -6054,9 +6260,9 @@ var babyclawConfigSchema = z11.object({
|
|
|
6054
6260
|
timezone: "UTC"
|
|
6055
6261
|
}),
|
|
6056
6262
|
workspace: z11.object({
|
|
6057
|
-
root: z11.string().min(1).default("
|
|
6263
|
+
root: z11.string().min(1).default("~/babyclaw")
|
|
6058
6264
|
}).strict().default({
|
|
6059
|
-
root: "
|
|
6265
|
+
root: "~/babyclaw"
|
|
6060
6266
|
}),
|
|
6061
6267
|
session: z11.object({
|
|
6062
6268
|
maxMessagesPerSession: z11.number().int().positive().default(120),
|
|
@@ -6116,7 +6322,7 @@ var DEFAULT_CONFIG_TEMPLATE = {
|
|
|
6116
6322
|
timezone: "UTC"
|
|
6117
6323
|
},
|
|
6118
6324
|
workspace: {
|
|
6119
|
-
root: "
|
|
6325
|
+
root: "~/babyclaw"
|
|
6120
6326
|
},
|
|
6121
6327
|
session: {
|
|
6122
6328
|
maxMessagesPerSession: 120,
|
|
@@ -6191,7 +6397,7 @@ async function loadConfigRaw() {
|
|
|
6191
6397
|
}
|
|
6192
6398
|
async function writeConfig({ config }) {
|
|
6193
6399
|
const configPath = getConfigPath();
|
|
6194
|
-
await mkdir5(
|
|
6400
|
+
await mkdir5(dirname6(configPath), { recursive: true });
|
|
6195
6401
|
await writeFile5(configPath, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
6196
6402
|
}
|
|
6197
6403
|
async function ensureConfigFileExists({ configPath }) {
|
|
@@ -6202,7 +6408,7 @@ async function ensureConfigFileExists({ configPath }) {
|
|
|
6202
6408
|
if (error.code !== "ENOENT") {
|
|
6203
6409
|
throw error;
|
|
6204
6410
|
}
|
|
6205
|
-
await mkdir5(
|
|
6411
|
+
await mkdir5(dirname6(configPath), { recursive: true });
|
|
6206
6412
|
await writeFile5(configPath, getDefaultConfigTemplate(), "utf8");
|
|
6207
6413
|
getLogger().warn({ configPath }, "Created config file. Fill required secrets and restart.");
|
|
6208
6414
|
}
|
|
@@ -6374,6 +6580,7 @@ var HeartbeatExecutor = class {
|
|
|
6374
6580
|
toolDeps: this.toolDeps,
|
|
6375
6581
|
executionContext: {
|
|
6376
6582
|
workspaceRoot: workspacePath,
|
|
6583
|
+
bundledSkillsDir: this.toolDeps.bundledSkillsDir,
|
|
6377
6584
|
botTimezone: schedulerService.getTimezone(),
|
|
6378
6585
|
platform: mainChat.platform,
|
|
6379
6586
|
chatId: platformChatId,
|
|
@@ -6830,6 +7037,7 @@ var SchedulerExecutor = class {
|
|
|
6830
7037
|
toolDeps: this.toolDeps,
|
|
6831
7038
|
executionContext: {
|
|
6832
7039
|
workspaceRoot: workspacePath,
|
|
7040
|
+
bundledSkillsDir: this.toolDeps.bundledSkillsDir,
|
|
6833
7041
|
botTimezone: schedulerService.getTimezone(),
|
|
6834
7042
|
platform: this.channelSender.platform,
|
|
6835
7043
|
chatId: chatIdStr,
|
|
@@ -7576,13 +7784,13 @@ function createDatabase({ workspacePath }) {
|
|
|
7576
7784
|
}
|
|
7577
7785
|
|
|
7578
7786
|
// src/database/migrate.ts
|
|
7579
|
-
import { dirname as
|
|
7787
|
+
import { dirname as dirname7, resolve as resolve5 } from "path";
|
|
7580
7788
|
import { fileURLToPath } from "url";
|
|
7581
7789
|
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
|
7582
|
-
var __dirname =
|
|
7790
|
+
var __dirname = dirname7(fileURLToPath(import.meta.url));
|
|
7583
7791
|
function applyMigrations({ workspacePath }) {
|
|
7584
7792
|
const db = createDatabase({ workspacePath });
|
|
7585
|
-
const migrationsFolder =
|
|
7793
|
+
const migrationsFolder = resolve5(__dirname, "..", "drizzle");
|
|
7586
7794
|
migrate(db, { migrationsFolder });
|
|
7587
7795
|
}
|
|
7588
7796
|
|
|
@@ -7620,7 +7828,8 @@ var GatewayRuntime = class {
|
|
|
7620
7828
|
},
|
|
7621
7829
|
"Gateway configuration summary"
|
|
7622
7830
|
);
|
|
7623
|
-
const workspacePath =
|
|
7831
|
+
const workspacePath = resolveWorkspaceRoot({ configRoot: config.workspace.root });
|
|
7832
|
+
mkdirSync3(workspacePath, { recursive: true });
|
|
7624
7833
|
log.info("Applying database migrations...");
|
|
7625
7834
|
applyMigrations({ workspacePath });
|
|
7626
7835
|
log.info("Database migrations applied");
|
|
@@ -7704,6 +7913,7 @@ var GatewayRuntime = class {
|
|
|
7704
7913
|
const adminSocketPath = getAdminSocketPath();
|
|
7705
7914
|
const toolDeps = {
|
|
7706
7915
|
workspacePath,
|
|
7916
|
+
bundledSkillsDir: getBundledSkillsDir(),
|
|
7707
7917
|
aiAgent,
|
|
7708
7918
|
sessionManager,
|
|
7709
7919
|
schedulerService,
|
|
@@ -7809,6 +8019,16 @@ var GatewayRuntime = class {
|
|
|
7809
8019
|
void this.stop().then(() => process.exit(0));
|
|
7810
8020
|
});
|
|
7811
8021
|
return { ok: true };
|
|
8022
|
+
},
|
|
8023
|
+
"/reload-skills": async () => {
|
|
8024
|
+
const freshConfig = await loadConfigRaw();
|
|
8025
|
+
if (!freshConfig) {
|
|
8026
|
+
return { ok: false, error: "config_not_found" };
|
|
8027
|
+
}
|
|
8028
|
+
toolDeps.skillsConfig = freshConfig.skills;
|
|
8029
|
+
toolDeps.fullConfig = freshConfig;
|
|
8030
|
+
log.info("Skills configuration reloaded via admin socket");
|
|
8031
|
+
return { ok: true };
|
|
7812
8032
|
}
|
|
7813
8033
|
}
|
|
7814
8034
|
});
|
|
@@ -7909,6 +8129,9 @@ var AdminClient = class {
|
|
|
7909
8129
|
async shutdown() {
|
|
7910
8130
|
return this.get({ path: "/shutdown" });
|
|
7911
8131
|
}
|
|
8132
|
+
async reloadSkills() {
|
|
8133
|
+
return this.get({ path: "/reload-skills" });
|
|
8134
|
+
}
|
|
7912
8135
|
get({ path }) {
|
|
7913
8136
|
return new Promise((resolve6, reject) => {
|
|
7914
8137
|
const req = request(
|
|
@@ -7950,6 +8173,7 @@ export {
|
|
|
7950
8173
|
AdminClient,
|
|
7951
8174
|
CONFIG_PATH_ENV_VAR,
|
|
7952
8175
|
ClawHubError,
|
|
8176
|
+
DEFAULT_WORKSPACE_ROOT,
|
|
7953
8177
|
GatewayRuntime,
|
|
7954
8178
|
SUPPORTED_PROVIDERS,
|
|
7955
8179
|
SkillAlreadyInstalledError,
|
|
@@ -7957,14 +8181,19 @@ export {
|
|
|
7957
8181
|
createChildLogger,
|
|
7958
8182
|
createLogger,
|
|
7959
8183
|
getAdminSocketPath,
|
|
8184
|
+
getBundledSkillPath,
|
|
7960
8185
|
getConfigPath,
|
|
7961
8186
|
getDefaultConfigPath,
|
|
7962
8187
|
getDefaultConfigTemplate,
|
|
8188
|
+
getEnabledBundledSkills,
|
|
7963
8189
|
getLogger,
|
|
8190
|
+
getSkillKey,
|
|
7964
8191
|
installSkillFromClawHub,
|
|
8192
|
+
listBundledSkills,
|
|
7965
8193
|
loadConfig,
|
|
7966
8194
|
loadConfigRaw,
|
|
7967
8195
|
resolveLanguageModel,
|
|
8196
|
+
resolveWorkspaceRoot,
|
|
7968
8197
|
runSkillSetup,
|
|
7969
8198
|
writeConfig
|
|
7970
8199
|
};
|