@otto-code/protocol 0.8.14 → 0.8.16
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/agent-profiles.d.ts +37 -19
- package/dist/agent-profiles.js +46 -23
- package/dist/agent-teams.d.ts +3 -3
- package/dist/agent-teams.js +5 -5
- package/dist/artifacts/types.js +2 -2
- package/dist/daemon-config.js +1 -1
- package/dist/default-personalities.js +1 -1
- package/dist/generated/validation/ws-outbound.aot.js +60353 -59899
- package/dist/git-hosting.js +1 -1
- package/dist/messages.d.ts +356 -0
- package/dist/messages.js +41 -23
- package/dist/personality-schemas.d.ts +4 -4
- package/dist/personality-schemas.js +6 -6
- package/dist/schedule/rpc-schemas.d.ts +8 -0
- package/dist/schedule/types.d.ts +5 -0
- package/dist/schedule/types.js +9 -3
- package/dist/validation/ws-outbound-schema-metadata.d.ts +75 -0
- package/package.json +1 -1
package/dist/agent-profiles.d.ts
CHANGED
|
@@ -1,28 +1,46 @@
|
|
|
1
|
-
import { type AgentPersonality, type
|
|
2
|
-
export declare function
|
|
1
|
+
import { type AgentPersonality, type ProfileRole } from "./messages.js";
|
|
2
|
+
export declare function isProfileRole(value: string): value is ProfileRole;
|
|
3
3
|
/**
|
|
4
4
|
* Filter an arbitrary role array (roles ride the wire as plain strings) down to
|
|
5
|
-
* the known set, deduped and returned in canonical `
|
|
5
|
+
* the known set, deduped and returned in canonical `PROFILE_ROLES` order.
|
|
6
6
|
* Retired role names are mapped through `LEGACY_ROLE_ALIASES`; anything else
|
|
7
7
|
* unknown (e.g. a role from a newer peer) is dropped rather than trusted.
|
|
8
8
|
*/
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
export declare function normalizeProfileRoles(roles: readonly string[] | undefined): ProfileRole[];
|
|
10
|
+
export declare function profileHasRole(personality: Pick<AgentPersonality, "roles">, role: ProfileRole): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve one roster entry from either identifier a caller might hold.
|
|
13
|
+
*
|
|
14
|
+
* Two kinds of caller reach the roster and they hold different things. A model
|
|
15
|
+
* reads `list_agent_profiles` and passes the display name it saw. Daemon-internal
|
|
16
|
+
* callers (orchestration role resolution, a stored schedule binding) already
|
|
17
|
+
* hold the stable id and must not round-trip through a name: names carry no
|
|
18
|
+
* uniqueness constraint, so a name lookup can land on a different entry than the
|
|
19
|
+
* one the caller meant.
|
|
20
|
+
*
|
|
21
|
+
* Id is checked first because ids are opaque and unique, so an id match is never
|
|
22
|
+
* ambiguous. The exact-name pass comes before the case-insensitive one so an
|
|
23
|
+
* exact match always wins over a differently-cased near-miss.
|
|
24
|
+
*/
|
|
25
|
+
export declare function findProfileByRef<T extends {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
}>(roster: readonly T[], ref: string): T | undefined;
|
|
29
|
+
export type ProfileRoleTier = "coordinator" | "focused";
|
|
30
|
+
interface ProfileRoleInfo {
|
|
31
|
+
tier: ProfileRoleTier;
|
|
14
32
|
guidance: string;
|
|
15
33
|
}
|
|
16
|
-
export declare const
|
|
34
|
+
export declare const PROFILE_ROLE_INFO: Readonly<Record<ProfileRole, ProfileRoleInfo>>;
|
|
17
35
|
/**
|
|
18
36
|
* A personality may launch/coordinate when it carries at least one coordinator
|
|
19
37
|
* role. A personality whose roles are entirely focused (researcher, planner,
|
|
20
38
|
* judger, advisor, coder, designer, writer), or that has no roles at all, is a
|
|
21
39
|
* "lifter": it should finish its task, not fan out.
|
|
22
40
|
*/
|
|
23
|
-
export declare function
|
|
24
|
-
export interface
|
|
25
|
-
tier:
|
|
41
|
+
export declare function profileCanLaunch(personality: Pick<AgentPersonality, "roles">): boolean;
|
|
42
|
+
export interface ProfileSelectionSummary {
|
|
43
|
+
tier: ProfileRoleTier;
|
|
26
44
|
canLaunch: boolean;
|
|
27
45
|
/** The "why you'd choose me" blurb - each of the personality's roles, joined. */
|
|
28
46
|
guidance: string;
|
|
@@ -30,11 +48,11 @@ export interface PersonalitySelectionSummary {
|
|
|
30
48
|
/**
|
|
31
49
|
* Build the selection decision-aid for a personality from its roles: the tier
|
|
32
50
|
* (coordinator if any role coordinates), whether it may launch, and a short
|
|
33
|
-
* multi-role "why choose me" blurb. Surfaced by
|
|
51
|
+
* multi-role "why choose me" blurb. Surfaced by list_agent_profiles so a
|
|
34
52
|
* deciding agent can pick the right teammate from the list alone.
|
|
35
53
|
*/
|
|
36
|
-
export declare function
|
|
37
|
-
export declare const OTTO_WORK_VOCABULARY_DIRECTIVE = "Otto work vocabulary: a suggested task is deferred work for the user and does not start work; a chat is an active Otto chat session; a child chat is created by another chat; a
|
|
54
|
+
export declare function summarizeProfileForSelection(personality: Pick<AgentPersonality, "roles">): ProfileSelectionSummary;
|
|
55
|
+
export declare const OTTO_WORK_VOCABULARY_DIRECTIVE = "Otto work vocabulary: a suggested task is deferred work for the user and does not start work; a chat is an active Otto chat session; a child chat is created by another chat; a Personality is a reusable provider, model, mode, effort, and behavior template; an orchestration coordinates multiple chats; a schedule starts a background chat when due; a heartbeat sends a reminder or prompt and does not start a chat. Use suggest_task for concrete work to preserve for later, create_chat to start one chat now, and start_orchestration only for managed multi-chat coordination. Use list_agent_profiles, optionally filtered by roles, before choosing a Personality. Never substitute a harness-native agent-spawn tool for suggest_task, and when a user names an Otto tool exactly, use that exact Otto tool.";
|
|
38
56
|
export declare const ORCHESTRATOR_METHOD_DIRECTIVE: string;
|
|
39
57
|
/**
|
|
40
58
|
* The in-context "role directive" injected into a personality's system prompt at
|
|
@@ -45,14 +63,14 @@ export declare const ORCHESTRATOR_METHOD_DIRECTIVE: string;
|
|
|
45
63
|
*/
|
|
46
64
|
export declare function composeRoleFocusDirective(roles: readonly string[] | undefined): string | undefined;
|
|
47
65
|
export type PersonalityUnavailableCode = "provider-missing" | "provider-disabled" | "provider-not-ready" | "model-missing" | "mode-missing";
|
|
48
|
-
export interface
|
|
66
|
+
export interface ProfileAvailabilityInput {
|
|
49
67
|
/** Provider snapshot status, or undefined when the provider is absent entirely. */
|
|
50
68
|
providerStatus: "ready" | "loading" | "error" | "unavailable" | undefined;
|
|
51
69
|
providerEnabled: boolean | undefined;
|
|
52
70
|
modelIds: readonly string[] | undefined;
|
|
53
71
|
modeIds: readonly string[] | undefined;
|
|
54
72
|
}
|
|
55
|
-
export type
|
|
73
|
+
export type ProfileAvailability = {
|
|
56
74
|
available: true;
|
|
57
75
|
} | {
|
|
58
76
|
available: false;
|
|
@@ -70,10 +88,10 @@ export type PersonalityAvailability = {
|
|
|
70
88
|
* means the provider only has to advertise SOME model; the concrete id is
|
|
71
89
|
* chosen at resolution time, not here.
|
|
72
90
|
*/
|
|
73
|
-
export declare function
|
|
91
|
+
export declare function checkProfileAvailability(personality: {
|
|
74
92
|
provider: string;
|
|
75
93
|
model?: string | undefined;
|
|
76
94
|
modeId?: string | undefined;
|
|
77
|
-
}, input:
|
|
95
|
+
}, input: ProfileAvailabilityInput): ProfileAvailability;
|
|
78
96
|
export {};
|
|
79
97
|
//# sourceMappingURL=agent-profiles.d.ts.map
|
package/dist/agent-profiles.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PROFILE_ROLES } from "./messages.js";
|
|
2
2
|
// Pure, dependency-free personality helpers shared by the daemon (spawn-time
|
|
3
3
|
// resolution) and the app (picker availability + role filtering). Effort
|
|
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
|
-
const ROLE_SET = new Set(
|
|
6
|
+
const ROLE_SET = new Set(PROFILE_ROLES);
|
|
7
7
|
// Retired role names, mapped to their canonical replacement. "worker" was split
|
|
8
8
|
// into "writer" (fast small-text generation) and "coder" (sub-agent coding); a
|
|
9
9
|
// personality that still carries the old tag resolves to "coder", the closer
|
|
@@ -12,32 +12,55 @@ const ROLE_SET = new Set(PERSONALITY_ROLES);
|
|
|
12
12
|
const LEGACY_ROLE_ALIASES = {
|
|
13
13
|
worker: "coder",
|
|
14
14
|
};
|
|
15
|
-
export function
|
|
15
|
+
export function isProfileRole(value) {
|
|
16
16
|
return ROLE_SET.has(value);
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Filter an arbitrary role array (roles ride the wire as plain strings) down to
|
|
20
|
-
* the known set, deduped and returned in canonical `
|
|
20
|
+
* the known set, deduped and returned in canonical `PROFILE_ROLES` order.
|
|
21
21
|
* Retired role names are mapped through `LEGACY_ROLE_ALIASES`; anything else
|
|
22
22
|
* unknown (e.g. a role from a newer peer) is dropped rather than trusted.
|
|
23
23
|
*/
|
|
24
|
-
export function
|
|
24
|
+
export function normalizeProfileRoles(roles) {
|
|
25
25
|
if (!roles || roles.length === 0) {
|
|
26
26
|
return [];
|
|
27
27
|
}
|
|
28
28
|
const present = new Set();
|
|
29
29
|
for (const raw of roles) {
|
|
30
|
-
const canonical = LEGACY_ROLE_ALIASES[raw] ?? (
|
|
30
|
+
const canonical = LEGACY_ROLE_ALIASES[raw] ?? (isProfileRole(raw) ? raw : null);
|
|
31
31
|
if (canonical) {
|
|
32
32
|
present.add(canonical);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
return
|
|
35
|
+
return PROFILE_ROLES.filter((role) => present.has(role));
|
|
36
36
|
}
|
|
37
|
-
export function
|
|
38
|
-
return
|
|
37
|
+
export function profileHasRole(personality, role) {
|
|
38
|
+
return normalizeProfileRoles(personality.roles).includes(role);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Resolve one roster entry from either identifier a caller might hold.
|
|
42
|
+
*
|
|
43
|
+
* Two kinds of caller reach the roster and they hold different things. A model
|
|
44
|
+
* reads `list_agent_profiles` and passes the display name it saw. Daemon-internal
|
|
45
|
+
* callers (orchestration role resolution, a stored schedule binding) already
|
|
46
|
+
* hold the stable id and must not round-trip through a name: names carry no
|
|
47
|
+
* uniqueness constraint, so a name lookup can land on a different entry than the
|
|
48
|
+
* one the caller meant.
|
|
49
|
+
*
|
|
50
|
+
* Id is checked first because ids are opaque and unique, so an id match is never
|
|
51
|
+
* ambiguous. The exact-name pass comes before the case-insensitive one so an
|
|
52
|
+
* exact match always wins over a differently-cased near-miss.
|
|
53
|
+
*/
|
|
54
|
+
export function findProfileByRef(roster, ref) {
|
|
55
|
+
const trimmed = ref.trim();
|
|
56
|
+
if (!trimmed) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
return (roster.find((entry) => entry.id === trimmed) ??
|
|
60
|
+
roster.find((entry) => entry.name === trimmed) ??
|
|
61
|
+
roster.find((entry) => entry.name.toLowerCase() === trimmed.toLowerCase()));
|
|
62
|
+
}
|
|
63
|
+
export const PROFILE_ROLE_INFO = {
|
|
41
64
|
// ── Surfaces ──────────────────────────────────────────────────────────────
|
|
42
65
|
chatter: {
|
|
43
66
|
tier: "coordinator",
|
|
@@ -93,22 +116,22 @@ export const PERSONALITY_ROLE_INFO = {
|
|
|
93
116
|
* judger, advisor, coder, designer, writer), or that has no roles at all, is a
|
|
94
117
|
* "lifter": it should finish its task, not fan out.
|
|
95
118
|
*/
|
|
96
|
-
export function
|
|
97
|
-
return
|
|
119
|
+
export function profileCanLaunch(personality) {
|
|
120
|
+
return normalizeProfileRoles(personality.roles).some((role) => PROFILE_ROLE_INFO[role].tier === "coordinator");
|
|
98
121
|
}
|
|
99
122
|
/**
|
|
100
123
|
* Build the selection decision-aid for a personality from its roles: the tier
|
|
101
124
|
* (coordinator if any role coordinates), whether it may launch, and a short
|
|
102
|
-
* multi-role "why choose me" blurb. Surfaced by
|
|
125
|
+
* multi-role "why choose me" blurb. Surfaced by list_agent_profiles so a
|
|
103
126
|
* deciding agent can pick the right teammate from the list alone.
|
|
104
127
|
*/
|
|
105
|
-
export function
|
|
106
|
-
const roles =
|
|
107
|
-
const canLaunch = roles.some((role) =>
|
|
128
|
+
export function summarizeProfileForSelection(personality) {
|
|
129
|
+
const roles = normalizeProfileRoles(personality.roles);
|
|
130
|
+
const canLaunch = roles.some((role) => PROFILE_ROLE_INFO[role].tier === "coordinator");
|
|
108
131
|
return {
|
|
109
132
|
tier: canLaunch ? "coordinator" : "focused",
|
|
110
133
|
canLaunch,
|
|
111
|
-
guidance: roles.map((role) =>
|
|
134
|
+
guidance: roles.map((role) => PROFILE_ROLE_INFO[role].guidance).join(" "),
|
|
112
135
|
};
|
|
113
136
|
}
|
|
114
137
|
// The conductor's standing directive - the distilled `/epic` method taught to
|
|
@@ -116,7 +139,7 @@ export function summarizePersonalityForSelection(personality) {
|
|
|
116
139
|
// chat, a suggested task, or an orchestration by the task's actual needs rather than
|
|
117
140
|
// treating orchestration as the default. Kept here as one exported constant so
|
|
118
141
|
// the wording is testable and shared. See projects/agent-orchestration/agent-orchestration.md.
|
|
119
|
-
export const OTTO_WORK_VOCABULARY_DIRECTIVE = "Otto work vocabulary: a suggested task is deferred work for the user and does not start work; a chat is an active Otto chat session; a child chat is created by another chat; a
|
|
142
|
+
export const OTTO_WORK_VOCABULARY_DIRECTIVE = "Otto work vocabulary: a suggested task is deferred work for the user and does not start work; a chat is an active Otto chat session; a child chat is created by another chat; a Personality is a reusable provider, model, mode, effort, and behavior template; an orchestration coordinates multiple chats; a schedule starts a background chat when due; a heartbeat sends a reminder or prompt and does not start a chat. Use suggest_task for concrete work to preserve for later, create_chat to start one chat now, and start_orchestration only for managed multi-chat coordination. Use list_agent_profiles, optionally filtered by roles, before choosing a Personality. Never substitute a harness-native agent-spawn tool for suggest_task, and when a user names an Otto tool exactly, use that exact Otto tool.";
|
|
120
143
|
export const ORCHESTRATOR_METHOD_DIRECTIVE = "You are the orchestrator - the team's sole conductor. Choose tools because the task needs their specific capability, never because a tool is available or named. " +
|
|
121
144
|
"Do a small, self-contained task directly. Use create_chat only for an independently executable piece of active work that benefits from its own chat. Use suggest_task only to preserve a concrete, out-of-scope follow-up for later. Use start_orchestration only when the active work needs a declared multi-chat plan with daemon-managed fan-out, gathering, judging, loops, or approval gates. " +
|
|
122
145
|
"For work that genuinely needs orchestration: (1) if the shape is unclear, dispatch research and planning chats; (2) declare the plan with start_orchestration - phases typed research/plan/implement/design/verify/gate/deliver, fanning out where several angles help and attaching a judger to grade them, looping until enough pass; (3) put a gate before irreversible or costly steps so the user approves; (4) synthesize the passing results into the deliverable. " +
|
|
@@ -129,7 +152,7 @@ export const ORCHESTRATOR_METHOD_DIRECTIVE = "You are the orchestrator - the tea
|
|
|
129
152
|
* nothing. This is guidance, not a gate - the tools stay available either way.
|
|
130
153
|
*/
|
|
131
154
|
export function composeRoleFocusDirective(roles) {
|
|
132
|
-
const normalized =
|
|
155
|
+
const normalized = normalizeProfileRoles(roles);
|
|
133
156
|
if (normalized.length === 0) {
|
|
134
157
|
return undefined;
|
|
135
158
|
}
|
|
@@ -137,10 +160,10 @@ export function composeRoleFocusDirective(roles) {
|
|
|
137
160
|
if (normalized.includes("orchestrator")) {
|
|
138
161
|
return `${ORCHESTRATOR_METHOD_DIRECTIVE} (Your roles: ${roleList}.)`;
|
|
139
162
|
}
|
|
140
|
-
if (normalized.some((role) =>
|
|
141
|
-
return `You are a coordinator personality (roles: ${roleList}). You front interactive work and may delegate when the task benefits from it: use
|
|
163
|
+
if (normalized.some((role) => PROFILE_ROLE_INFO[role].tier === "coordinator")) {
|
|
164
|
+
return `You are a coordinator personality (roles: ${roleList}). You front interactive work and may delegate when the task benefits from it: use list_agent_profiles to see who else is available, then either do the work directly, create a child chat for an independent active piece, or hand off genuinely multi-chat work to the team's orchestrator.`;
|
|
142
165
|
}
|
|
143
|
-
return `You are a focused personality (roles: ${roleList}). Someone is waiting on this specific task - stay on it and finish it. You can still call
|
|
166
|
+
return `You are a focused personality (roles: ${roleList}). Someone is waiting on this specific task - stay on it and finish it. You can still call list_agent_profiles to see the roster, but don't create child chats or start side workflows unless it is genuinely essential to completing this job.`;
|
|
144
167
|
}
|
|
145
168
|
/**
|
|
146
169
|
* Decide whether a personality is usable against a provider's current snapshot.
|
|
@@ -153,7 +176,7 @@ export function composeRoleFocusDirective(roles) {
|
|
|
153
176
|
* means the provider only has to advertise SOME model; the concrete id is
|
|
154
177
|
* chosen at resolution time, not here.
|
|
155
178
|
*/
|
|
156
|
-
export function
|
|
179
|
+
export function checkProfileAvailability(personality, input) {
|
|
157
180
|
if (input.providerStatus === undefined) {
|
|
158
181
|
return {
|
|
159
182
|
available: false,
|
package/dist/agent-teams.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentProfile, AgentTeam,
|
|
1
|
+
import type { AgentProfile, AgentTeam, ProfileRole } 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
|
|
@@ -48,9 +48,9 @@ export declare function pruneTeamMemberIds(memberIds: readonly string[] | undefi
|
|
|
48
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
|
+
* `PROFILE_ROLES` order - the team card's role-pill strip.
|
|
52
52
|
*/
|
|
53
|
-
export declare function teamRoleUnion(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentProfile[] | undefined):
|
|
53
|
+
export declare function teamRoleUnion(team: Pick<AgentTeam, "memberIds"> | null | undefined, personalities: readonly AgentProfile[] | undefined): ProfileRole[];
|
|
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).
|
package/dist/agent-teams.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizeProfileRoles } from "./agent-profiles.js";
|
|
2
2
|
// Pure, dependency-free team helpers shared by the daemon (spawn-time active
|
|
3
|
-
// team resolution,
|
|
3
|
+
// team resolution, list_agent_profiles scoping) and the app (team cards,
|
|
4
4
|
// pickers, the Active Team switcher). Availability is deliberately NOT here -
|
|
5
5
|
// a team is never "out of commission"; its members are individually available
|
|
6
|
-
// or not, judged by
|
|
6
|
+
// or not, judged by checkProfileAvailability per member.
|
|
7
7
|
/**
|
|
8
8
|
* The dynamic "Team's Scheduler" schedule binding. Stored in the schedule's
|
|
9
9
|
* `personality` field in place of a personality name; resolved at RUN time to
|
|
@@ -100,11 +100,11 @@ export function resolveExclusiveTeamMembers(team, otherTeams, personalities) {
|
|
|
100
100
|
}
|
|
101
101
|
/**
|
|
102
102
|
* The union of all members' roles, normalized and returned in canonical
|
|
103
|
-
* `
|
|
103
|
+
* `PROFILE_ROLES` order - the team card's role-pill strip.
|
|
104
104
|
*/
|
|
105
105
|
export function teamRoleUnion(team, personalities) {
|
|
106
106
|
const roles = resolveTeamMembers(team, personalities).flatMap((personality) => personality.roles ?? []);
|
|
107
|
-
return
|
|
107
|
+
return normalizeProfileRoles(roles);
|
|
108
108
|
}
|
|
109
109
|
/**
|
|
110
110
|
* A team prompt only stacks when it has content; a team with an empty or
|
package/dist/artifacts/types.js
CHANGED
|
@@ -4,7 +4,7 @@ export const ArtifactStatusSchema = z.enum(["generating", "ready", "error"]);
|
|
|
4
4
|
// Two glow colors for the generating spinner, snapshotted from the Agent
|
|
5
5
|
// Personality the artifact was generated under (BlobLoader glowA/glowB), so its
|
|
6
6
|
// card spinner renders in the personality's identity. Passthrough for
|
|
7
|
-
// forward-compat, mirroring
|
|
7
|
+
// forward-compat, mirroring AgentProfileSpinnerSchema in messages.ts.
|
|
8
8
|
export const ArtifactSpinnerSchema = z
|
|
9
9
|
.object({
|
|
10
10
|
glowA: z.string().min(1),
|
|
@@ -35,7 +35,7 @@ export const ArtifactMetadataSchema = z.object({
|
|
|
35
35
|
// Spinner glow colors of the Agent Personality this artifact was generated
|
|
36
36
|
// under, snapshotted at create time like the provider/model above. Absent ⇒
|
|
37
37
|
// the card falls back to the theme's default spinner colors. Purely additive
|
|
38
|
-
// (no daemon floor needed). See docs/agent-
|
|
38
|
+
// (no daemon floor needed). See docs/agent-profiles.md.
|
|
39
39
|
generationSpinner: ArtifactSpinnerSchema.nullable().optional(),
|
|
40
40
|
// Human name of the Agent Personality that generated (last generated) this
|
|
41
41
|
// artifact, snapshotted at create/regenerate time like the provider/model
|
package/dist/daemon-config.js
CHANGED
|
@@ -191,7 +191,7 @@ export const MutableAgentTeamsConfigSchema = z
|
|
|
191
191
|
// The host's active team id; null/absent = no team active (exactly legacy
|
|
192
192
|
// behavior). Host-scoped daemon config rather than device-local: the team
|
|
193
193
|
// prompt is applied daemon-side at spawn, so headless spawns (MCP
|
|
194
|
-
//
|
|
194
|
+
// create_chat, schedule runs) must see it, and a patch from any client
|
|
195
195
|
// hot-reloads the switch to every connected client.
|
|
196
196
|
activeTeamId: z.string().nullable().optional(),
|
|
197
197
|
})
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// restore button) import this one list so the shipped set stays identical on
|
|
6
6
|
// both sides.
|
|
7
7
|
//
|
|
8
|
-
// Design notes (see docs/agent-
|
|
8
|
+
// Design notes (see docs/agent-profiles.md):
|
|
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".
|