@divaltor/academy 0.1.5 → 0.1.7
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/README.md +5 -1
- package/package.json +1 -1
- package/src/index.ts +32 -31
package/README.md
CHANGED
|
@@ -36,7 +36,11 @@ Add Academy to `opencode.jsonc`. Each agent can override its display name and co
|
|
|
36
36
|
}
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Colors accept six-digit hex values or OpenCode theme colors: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, and `info`. You can alternatively set a color with OpenCode's native `agents.<id>.color` configuration. Custom names also update persona references.
|
|
39
|
+
Colors accept six-digit hex values or OpenCode theme colors: `primary`, `secondary`, `accent`, `success`, `warning`, `error`, and `info`. You can alternatively set a color with OpenCode's native `agents.<id>.color` configuration. Custom names also become the agents' IDs and update persona and permission references. Without custom names, agent IDs are `rudolf`, `bourbon`, `agnes`, `cafe`, `dantsu`, and `bellno`.
|
|
40
|
+
|
|
41
|
+
> [!WARNING] Choose custom names when first setting up Academy and avoid changing them later. OpenCode stores the selected agent ID in each session, so renaming an agent removes the ID referenced by existing sessions and can prevent those sessions from continuing.
|
|
42
|
+
|
|
43
|
+
See the [plugin docs](https://opencode.ai/v2/docs/build/plugins) to learn more.
|
|
40
44
|
|
|
41
45
|
### Private GitHub repositories
|
|
42
46
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@divaltor/academy",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "An OpenCode plugin that trains a Tracen Academy roster of specialist coding agents to research, build, and review.",
|
|
5
5
|
"homepage": "https://github.com/divaltor/academy#readme",
|
|
6
6
|
"bugs": {
|
package/src/index.ts
CHANGED
|
@@ -9,23 +9,11 @@ const AgentOptions = Schema.Struct({
|
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
const AcademyOptions = Schema.Struct({
|
|
12
|
-
agentNames: Schema.optionalKey(
|
|
13
|
-
Schema.Struct({
|
|
14
|
-
agnes: Schema.optionalKey(Schema.NonEmptyString),
|
|
15
|
-
bellno: Schema.optionalKey(Schema.NonEmptyString),
|
|
16
|
-
bourbon: Schema.optionalKey(Schema.NonEmptyString),
|
|
17
|
-
cafe: Schema.optionalKey(Schema.NonEmptyString),
|
|
18
|
-
dantsu: Schema.optionalKey(Schema.NonEmptyString),
|
|
19
|
-
diana: Schema.optionalKey(Schema.NonEmptyString),
|
|
20
|
-
rudolf: Schema.optionalKey(Schema.NonEmptyString),
|
|
21
|
-
})
|
|
22
|
-
),
|
|
23
12
|
agnes: Schema.optionalKey(AgentOptions),
|
|
24
13
|
bellno: Schema.optionalKey(AgentOptions),
|
|
25
14
|
bourbon: Schema.optionalKey(AgentOptions),
|
|
26
15
|
cafe: Schema.optionalKey(AgentOptions),
|
|
27
16
|
dantsu: Schema.optionalKey(AgentOptions),
|
|
28
|
-
diana: Schema.optionalKey(AgentOptions),
|
|
29
17
|
rudolf: Schema.optionalKey(AgentOptions),
|
|
30
18
|
});
|
|
31
19
|
|
|
@@ -36,17 +24,18 @@ const setup = Effect.fn("Academy.setup")(function* setup(ctx: Plugin.Context) {
|
|
|
36
24
|
const options = yield* Schema.decodeUnknownEffect(AcademyOptions, {
|
|
37
25
|
onExcessProperty: "error",
|
|
38
26
|
})(ctx.options).pipe(Effect.orDie);
|
|
39
|
-
const legacyNames = options.agentNames ?? {};
|
|
40
27
|
const agentNames = new Map(
|
|
41
|
-
agents.map((agent) => [
|
|
42
|
-
agent.name,
|
|
43
|
-
options[agent.id]?.name ??
|
|
44
|
-
(agent.id === "rudolf" ? options.diana?.name : undefined) ??
|
|
45
|
-
legacyNames[agent.id] ??
|
|
46
|
-
(agent.id === "rudolf" ? legacyNames.diana : undefined) ??
|
|
47
|
-
agent.name,
|
|
48
|
-
])
|
|
28
|
+
agents.map((agent) => [agent.name, options[agent.id]?.name ?? agent.name])
|
|
49
29
|
);
|
|
30
|
+
const agentID = (id: (typeof agents)[number]["id"]) =>
|
|
31
|
+
Agent.ID.make(options[id]?.name ?? id);
|
|
32
|
+
const configuredAgentIDs = agents.map((agent) => agentID(agent.id));
|
|
33
|
+
|
|
34
|
+
if (new Set(configuredAgentIDs).size !== configuredAgentIDs.length) {
|
|
35
|
+
return yield* Effect.die(
|
|
36
|
+
new Error("Academy agent names must produce unique agent IDs")
|
|
37
|
+
);
|
|
38
|
+
}
|
|
50
39
|
|
|
51
40
|
yield* ctx.mcp.transform((editor) => {
|
|
52
41
|
if (Option.isNone(githubToken)) {
|
|
@@ -65,29 +54,41 @@ const setup = Effect.fn("Academy.setup")(function* setup(ctx: Plugin.Context) {
|
|
|
65
54
|
});
|
|
66
55
|
|
|
67
56
|
yield* ctx.agent.transform((editor) => {
|
|
68
|
-
for (const id of ["build", "plan", "explore", "general"
|
|
57
|
+
for (const id of ["build", "plan", "explore", "general"]) {
|
|
69
58
|
editor.remove(id);
|
|
70
59
|
}
|
|
71
60
|
|
|
72
61
|
for (const definition of agents) {
|
|
73
|
-
|
|
62
|
+
if (agentID(definition.id) !== definition.id) {
|
|
63
|
+
editor.remove(definition.id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for (const definition of agents) {
|
|
68
|
+
editor.update(agentID(definition.id), (agent) => {
|
|
74
69
|
agent.name = Agent.Name.make(
|
|
75
70
|
agentNames.get(definition.name) ?? definition.name
|
|
76
71
|
);
|
|
77
72
|
agent.description = definition.description;
|
|
78
73
|
agent.mode = definition.mode;
|
|
79
74
|
agent.color =
|
|
80
|
-
options[definition.id]?.color ??
|
|
81
|
-
(definition.id === "rudolf" ? options.diana?.color : undefined) ??
|
|
82
|
-
agent.color ??
|
|
83
|
-
definition.color;
|
|
75
|
+
options[definition.id]?.color ?? agent.color ?? definition.color;
|
|
84
76
|
agent.system = definition.system.replaceAll(
|
|
85
77
|
/\b(?:Rudolf|Agnes|Bourbon|Cafe|Dantsu|Bellno)\b/gu,
|
|
86
78
|
(name) => agentNames.get(name) ?? name
|
|
87
79
|
);
|
|
88
|
-
agent.permissions = definition.permissions.map((permission) =>
|
|
89
|
-
|
|
90
|
-
|
|
80
|
+
agent.permissions = definition.permissions.map((permission) => {
|
|
81
|
+
const referencedAgent = agents.find(
|
|
82
|
+
(candidate) => candidate.id === permission.resource
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
...permission,
|
|
87
|
+
resource: referencedAgent
|
|
88
|
+
? agentID(referencedAgent.id)
|
|
89
|
+
: permission.resource,
|
|
90
|
+
};
|
|
91
|
+
});
|
|
91
92
|
agent.model = definition.model
|
|
92
93
|
? {
|
|
93
94
|
id: Model.ID.make(definition.model.id),
|
|
@@ -98,7 +99,7 @@ const setup = Effect.fn("Academy.setup")(function* setup(ctx: Plugin.Context) {
|
|
|
98
99
|
});
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
editor.default("rudolf");
|
|
102
|
+
editor.default(agentID("rudolf"));
|
|
102
103
|
});
|
|
103
104
|
});
|
|
104
105
|
|