@otto-code/protocol 0.8.13 → 0.8.14

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,8 +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 (for example, a role from a newer peer) are dropped rather
7
- * 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.
8
8
  */
9
9
  export declare function normalizePersonalityRoles(roles: readonly string[] | undefined): PersonalityRole[];
10
10
  export declare function personalityHasRole(personality: Pick<AgentPersonality, "roles">, role: PersonalityRole): boolean;
@@ -64,7 +64,16 @@ export type PersonalityAvailability = {
64
64
  * A personality is out of commission the moment any bound setting can't resolve:
65
65
  * provider absent/disabled/not-ready, model gone, or an explicit mode missing.
66
66
  * The caller grays it out in pickers and hard-fails it in automation.
67
+ *
68
+ * `model` is optional because the stored template is an `AgentProfile`, which
69
+ * may name no model at all ("use whatever this provider defaults to"). Absent
70
+ * means the provider only has to advertise SOME model; the concrete id is
71
+ * chosen at resolution time, not here.
67
72
  */
68
- export declare function checkPersonalityAvailability(personality: Pick<AgentPersonality, "provider" | "model" | "modeId">, input: PersonalityAvailabilityInput): PersonalityAvailability;
73
+ export declare function checkPersonalityAvailability(personality: {
74
+ provider: string;
75
+ model?: string | undefined;
76
+ modeId?: string | undefined;
77
+ }, input: PersonalityAvailabilityInput): PersonalityAvailability;
69
78
  export {};
70
- //# sourceMappingURL=agent-personalities.d.ts.map
79
+ //# sourceMappingURL=agent-profiles.d.ts.map
@@ -4,14 +4,22 @@ 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 (for example, a role from a newer peer) are dropped rather
14
- * 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.
15
23
  */
16
24
  export function normalizePersonalityRoles(roles) {
17
25
  if (!roles || roles.length === 0) {
@@ -19,7 +27,7 @@ export function normalizePersonalityRoles(roles) {
19
27
  }
20
28
  const present = new Set();
21
29
  for (const raw of roles) {
22
- const canonical = isPersonalityRole(raw) ? raw : null;
30
+ const canonical = LEGACY_ROLE_ALIASES[raw] ?? (isPersonalityRole(raw) ? raw : null);
23
31
  if (canonical) {
24
32
  present.add(canonical);
25
33
  }
@@ -139,6 +147,11 @@ export function composeRoleFocusDirective(roles) {
139
147
  * A personality is out of commission the moment any bound setting can't resolve:
140
148
  * provider absent/disabled/not-ready, model gone, or an explicit mode missing.
141
149
  * The caller grays it out in pickers and hard-fails it in automation.
150
+ *
151
+ * `model` is optional because the stored template is an `AgentProfile`, which
152
+ * may name no model at all ("use whatever this provider defaults to"). Absent
153
+ * means the provider only has to advertise SOME model; the concrete id is
154
+ * chosen at resolution time, not here.
142
155
  */
143
156
  export function checkPersonalityAvailability(personality, input) {
144
157
  if (input.providerStatus === undefined) {
@@ -162,7 +175,17 @@ export function checkPersonalityAvailability(personality, input) {
162
175
  reason: `Provider "${personality.provider}" is not ready (${input.providerStatus}).`,
163
176
  };
164
177
  }
165
- if (!(input.modelIds ?? []).includes(personality.model)) {
178
+ const modelIds = input.modelIds ?? [];
179
+ if (personality.model === undefined) {
180
+ if (modelIds.length === 0) {
181
+ return {
182
+ available: false,
183
+ code: "model-missing",
184
+ reason: `Provider "${personality.provider}" advertises no models.`,
185
+ };
186
+ }
187
+ }
188
+ else if (!modelIds.includes(personality.model)) {
166
189
  return {
167
190
  available: false,
168
191
  code: "model-missing",
@@ -178,4 +201,4 @@ export function checkPersonalityAvailability(personality, input) {
178
201
  }
179
202
  return { available: true };
180
203
  }
181
- //# sourceMappingURL=agent-personalities.js.map
204
+ //# sourceMappingURL=agent-profiles.js.map
@@ -1,4 +1,4 @@
1
- import type { AgentPersonality, AgentTeam, PersonalityRole } from "./messages.js";
1
+ import type { AgentProfile, AgentTeam, PersonalityRole } from "./messages.js";
2
2
  /**
3
3
  * The dynamic "Team's Scheduler" schedule binding. Stored in the schedule's
4
4
  * `personality` field in place of a personality name; resolved at RUN time to
@@ -29,13 +29,13 @@ export declare function isTeamMember(team: Pick<AgentTeam, "memberIds"> | null |
29
29
  * and ignored (it is pruned opportunistically on the next save of the team,
30
30
  * never eagerly cascaded on delete).
31
31
  */
32
- export declare function resolveTeamMembers(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentPersonality[] | undefined): AgentPersonality[];
32
+ export declare function resolveTeamMembers(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentProfile[] | undefined): AgentProfile[];
33
33
  /**
34
34
  * The save-time prune: drop member ids that no longer resolve to a personality
35
35
  * (and dedupe), preserving order. Editors call this when persisting a team so
36
36
  * dangling ids don't accumulate; readers never require it.
37
37
  */
38
- export declare function pruneTeamMemberIds(memberIds: readonly string[] | undefined, personalities: readonly AgentPersonality[] | undefined): string[];
38
+ export declare function pruneTeamMemberIds(memberIds: readonly string[] | undefined, personalities: readonly AgentProfile[] | undefined): string[];
39
39
  /**
40
40
  * The members a team owns exclusively: personalities on `team` that no team in
41
41
  * `otherTeams` also lists. These are the ones deleting `team` would leave on no
@@ -45,12 +45,12 @@ export declare function pruneTeamMemberIds(memberIds: readonly string[] | undefi
45
45
  * Pass the teams that will REMAIN after the delete - the caller owns the filter,
46
46
  * so this stays a pure set operation with no notion of "the team being deleted".
47
47
  */
48
- export declare function resolveExclusiveTeamMembers(team: Pick<AgentTeam, "memberIds"> | null | undefined, otherTeams: readonly Pick<AgentTeam, "memberIds">[] | undefined, personalities: readonly AgentPersonality[] | undefined): AgentPersonality[];
48
+ export declare function resolveExclusiveTeamMembers(team: Pick<AgentTeam, "memberIds"> | null | undefined, otherTeams: readonly Pick<AgentTeam, "memberIds">[] | undefined, personalities: readonly AgentProfile[] | undefined): AgentProfile[];
49
49
  /**
50
50
  * The union of all members' roles, normalized and returned in canonical
51
51
  * `PERSONALITY_ROLES` order - the team card's role-pill strip.
52
52
  */
53
- export declare function teamRoleUnion(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentPersonality[] | undefined): PersonalityRole[];
53
+ export declare function teamRoleUnion(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentProfile[] | undefined): PersonalityRole[];
54
54
  /**
55
55
  * A team prompt only stacks when it has content; a team with an empty or
56
56
  * whitespace prompt is purely organizational (picker scoping, no prompt layer).
@@ -1,4 +1,4 @@
1
- import { normalizePersonalityRoles } from "./agent-personalities.js";
1
+ import { normalizePersonalityRoles } from "./agent-profiles.js";
2
2
  // Pure, dependency-free team helpers shared by the daemon (spawn-time active
3
3
  // team resolution, list_personalities scoping) and the app (team cards,
4
4
  // pickers, the Active Team switcher). Availability is deliberately NOT here -
@@ -103,6 +103,8 @@ export declare const MutableAgentPersonalitiesConfigSchema: z.ZodObject<{
103
103
  personalities: z.ZodDefault<z.ZodArray<z.ZodObject<{
104
104
  id: z.ZodString;
105
105
  name: z.ZodString;
106
+ icon: z.ZodOptional<z.ZodString>;
107
+ color: z.ZodOptional<z.ZodString>;
106
108
  provider: z.ZodString;
107
109
  model: z.ZodString;
108
110
  effortLevel: z.ZodOptional<z.ZodString>;
@@ -132,6 +134,8 @@ export declare const MutableAgentPersonalitiesConfigPatchSchema: z.ZodObject<{
132
134
  personalities: z.ZodOptional<z.ZodArray<z.ZodObject<{
133
135
  id: z.ZodString;
134
136
  name: z.ZodString;
137
+ icon: z.ZodOptional<z.ZodString>;
138
+ color: z.ZodOptional<z.ZodString>;
135
139
  provider: z.ZodString;
136
140
  model: z.ZodString;
137
141
  effortLevel: z.ZodOptional<z.ZodString>;
@@ -1,4 +1,4 @@
1
- import type { AgentPersonality, AgentTeam } from "./messages.js";
2
- export declare const DEFAULT_AGENT_PERSONALITIES: readonly AgentPersonality[];
1
+ import type { AgentProfile, AgentTeam } from "./messages.js";
2
+ export declare const DEFAULT_AGENT_PROFILES: readonly AgentProfile[];
3
3
  export declare const DEFAULT_AGENT_TEAMS: readonly AgentTeam[];
4
4
  //# sourceMappingURL=default-personalities.d.ts.map
@@ -31,7 +31,7 @@ const KOKORO_V1_MODEL = "kokoro-multi-lang-v1_0";
31
31
  function kokoroVoice(name) {
32
32
  return { provider: "local", model: KOKORO_V1_MODEL, name };
33
33
  }
34
- export const DEFAULT_AGENT_PERSONALITIES = [
34
+ export const DEFAULT_AGENT_PROFILES = [
35
35
  {
36
36
  id: "personality_builtin_atlas",
37
37
  name: "Atlas",
@@ -148,7 +148,7 @@ export const DEFAULT_AGENT_TEAMS = [
148
148
  "together under Atlas's lead. Stay in your lane and trust your teammates' lanes: do your " +
149
149
  "own role's work well, hand off cleanly with the context the next specialist needs, and " +
150
150
  "flag anything you notice outside your remit instead of fixing it yourself.",
151
- memberIds: DEFAULT_AGENT_PERSONALITIES.map((personality) => personality.id),
151
+ memberIds: DEFAULT_AGENT_PROFILES.map((profile) => profile.id),
152
152
  },
153
153
  ];
154
154
  //# sourceMappingURL=default-personalities.js.map