char-slop/berry

multipurpose self-modifiable agentic harness

git clone https://git.t4t.associates/char-slop/berry

Charlotte Somadd skills extension for loading skillsa4e772a

main
1.9 KiB56 linesraw
1import { BACKGROUND_CONTEXT } from "@earendil-works/chord/context";
2import { getOrThrow } from "@earendil-works/pi-durable/env";
3import type { Environment } from "@berry/api";
4import { localEnvironment } from "@berry/api/environment.ts";
5import { rootedEnvironment } from "@berry/api/testing.ts";
6
7export function targetEnvironment(
8  root: string,
9  options: Parameters<typeof rootedEnvironment>[1] = {},
10): Environment {
11  const env = rootedEnvironment(root, options);
12  const exec = env.exec;
13  env.exec = (command, options, context) =>
14    exec(
15      typeof command === "string"
16        ? command
17        : command.map((arg) => arg.startsWith("/") ? root + arg : arg),
18      options,
19      context,
20    );
21  return env;
22}
23
24export function hostEnvironment(home: string, variables: Record<string, string> = {}): Environment {
25  const env = localEnvironment(home);
26  Object.defineProperties(env, { home: { value: home }, variables: { value: variables } });
27  return env;
28}
29
30export async function activeDirectory(env: Environment, prompt: string): Promise<string> {
31  for (const match of prompt.matchAll(/"(?:[^"\\]|\\.)*"/g)) {
32    const directory: string = JSON.parse(match[0]);
33    const file = getOrThrow(await env.joinPath([directory, "SKILL.md"], BACKGROUND_CONTEXT));
34    const info = await env.fileInfo(file, BACKGROUND_CONTEXT);
35    if (info.ok && info.value.kind === "file") return directory;
36  }
37  throw new Error("The prompt has no readable skill directory");
38}
39
40export async function writeSkill(
41  env: Environment,
42  collection: string,
43  name: string,
44  body: string,
45  description = `Use ${name} for its workflow.`,
46): Promise<string> {
47  const path = getOrThrow(await env.joinPath([collection, name, "SKILL.md"], BACKGROUND_CONTEXT));
48  getOrThrow(
49    await env.writeFile(
50      path,
51      `---\nname: ${name}\ndescription: ${JSON.stringify(description)}\n---\n${body}`,
52      BACKGROUND_CONTEXT,
53    ),
54  );
55  return path;
56}