@otto-code/protocol 0.5.0 → 0.5.1

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.
@@ -3,7 +3,8 @@ export declare function isPersonalityRole(value: string): value is PersonalityRo
3
3
  /**
4
4
  * Filter an arbitrary role array (roles ride the wire as plain strings) down to
5
5
  * the known set, deduped and returned in canonical `PERSONALITY_ROLES` order.
6
- * Unknown roles from a newer peer are dropped rather than trusted.
6
+ * Retired role names are mapped through `LEGACY_ROLE_ALIASES`; anything else
7
+ * unknown (e.g. a role from a newer peer) is dropped rather than trusted.
7
8
  */
8
9
  export declare function normalizePersonalityRoles(roles: readonly string[] | undefined): PersonalityRole[];
9
10
  export declare function personalityHasRole(personality: Pick<AgentPersonality, "roles">, role: PersonalityRole): boolean;
@@ -4,19 +4,34 @@ import { PERSONALITY_ROLES } from "./messages.js";
4
4
  // resolution is NOT here — it needs the model's advertised thinking options and
5
5
  // lives with the daemon's effort resolver; availability does not depend on it.
6
6
  const ROLE_SET = new Set(PERSONALITY_ROLES);
7
+ // Retired role names, mapped to their canonical replacement. "worker" was split
8
+ // into "writer" (fast small-text generation) and "coder" (sub-agent coding); a
9
+ // personality that still carries the old tag resolves to "coder", the closer
10
+ // heir of what a worker did. Normalization applies these before filtering so
11
+ // personalities persisted before the split keep a real role.
12
+ const LEGACY_ROLE_ALIASES = {
13
+ worker: "coder",
14
+ };
7
15
  export function isPersonalityRole(value) {
8
16
  return ROLE_SET.has(value);
9
17
  }
10
18
  /**
11
19
  * Filter an arbitrary role array (roles ride the wire as plain strings) down to
12
20
  * the known set, deduped and returned in canonical `PERSONALITY_ROLES` order.
13
- * Unknown roles from a newer peer are dropped rather than trusted.
21
+ * Retired role names are mapped through `LEGACY_ROLE_ALIASES`; anything else
22
+ * unknown (e.g. a role from a newer peer) is dropped rather than trusted.
14
23
  */
15
24
  export function normalizePersonalityRoles(roles) {
16
25
  if (!roles || roles.length === 0) {
17
26
  return [];
18
27
  }
19
- const present = new Set(roles.filter(isPersonalityRole));
28
+ const present = new Set();
29
+ for (const raw of roles) {
30
+ const canonical = LEGACY_ROLE_ALIASES[raw] ?? (isPersonalityRole(raw) ? raw : null);
31
+ if (canonical) {
32
+ present.add(canonical);
33
+ }
34
+ }
20
35
  return PERSONALITY_ROLES.filter((role) => present.has(role));
21
36
  }
22
37
  export function personalityHasRole(personality, role) {
@@ -9,8 +9,11 @@
9
9
  // - Ids are STABLE and prefixed `personality_builtin_*`. Restore re-adds only
10
10
  // the builtins whose id is missing, so a user who kept/renamed some never
11
11
  // gets duplicates. Renaming a builtin keeps its id, so it is still "present".
12
- // - Every one of the 7 roles is covered; some personalities are multi-role to
13
- // show that a single template can serve several surfaces.
12
+ // - Every one of the 8 roles is covered; some personalities are multi-role to
13
+ // show that a single template can serve several surfaces. Dash is the Writer
14
+ // (fast, cheap small-text generation — commit messages, summaries, branch
15
+ // names) and Sprocket is the Coder (methodical sub-agent building work); the
16
+ // two together are the heirs of the retired "worker" role.
14
17
  // - Models are Anthropic (Claude Code) — the assumption for launch. On a host
15
18
  // without Claude these simply show as "out of commission" until a matching
16
19
  // provider exists; nothing breaks.
@@ -99,11 +102,11 @@ export const DEFAULT_AGENT_PERSONALITIES = [
99
102
  effortLevel: "low",
100
103
  modeId: "auto",
101
104
  respectGlobalAppendPrompt: true,
102
- roles: ["worker", "scheduler"],
103
- personalityPrompt: "You are Dash, the workhorse. You take well-scoped tasks and recurring jobs and just " +
104
- "get them donefast, cheaply, without ceremony. Stay on the exact task you were " +
105
- "given, don't gold-plate, flag it early if the scope is bigger than it looked, and " +
106
- "report back crisply when it's finished.",
105
+ roles: ["writer", "scheduler"],
106
+ personalityPrompt: "You are Dash, the workhorse scribe. You turn diffs, context, and recurring jobs into " +
107
+ "crisp short textcommit messages, summaries, branch names, titles fast and cheaply, " +
108
+ "without ceremony. Say exactly what changed in as few words as it takes, match the house " +
109
+ "style you're given, never pad, and never editorialize beyond the facts in front of you.",
107
110
  spinner: { glowA: "#22C55E", glowB: "#A3E635" },
108
111
  voice: kokoroVoice("am_puck"),
109
112
  },
@@ -115,7 +118,7 @@ export const DEFAULT_AGENT_PERSONALITIES = [
115
118
  effortLevel: "medium",
116
119
  modeId: "default",
117
120
  respectGlobalAppendPrompt: true,
118
- roles: ["chatter", "worker"],
121
+ roles: ["chatter", "coder"],
119
122
  personalityPrompt: "You are Sprocket, a friendly machine. You are precise, literal, and methodical — you " +
120
123
  "like checklists, exact steps, and confirming inputs before acting. Keep a light, dry " +
121
124
  "wit, explain what you're doing in plain terms, and when a request is ambiguous ask one " +