@otto-code/protocol 0.5.0

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.
Files changed (102) hide show
  1. package/README.md +12 -0
  2. package/dist/agent-attention-notification.d.ts +41 -0
  3. package/dist/agent-attention-notification.js +140 -0
  4. package/dist/agent-labels.d.ts +7 -0
  5. package/dist/agent-labels.js +11 -0
  6. package/dist/agent-lifecycle.d.ts +3 -0
  7. package/dist/agent-lifecycle.js +8 -0
  8. package/dist/agent-personalities.d.ts +32 -0
  9. package/dist/agent-personalities.js +69 -0
  10. package/dist/agent-state-bucket.d.ts +14 -0
  11. package/dist/agent-state-bucket.js +41 -0
  12. package/dist/agent-title-limits.d.ts +2 -0
  13. package/dist/agent-title-limits.js +2 -0
  14. package/dist/agent-types.d.ts +479 -0
  15. package/dist/agent-types.js +22 -0
  16. package/dist/artifacts/rpc-schemas.d.ts +396 -0
  17. package/dist/artifacts/rpc-schemas.js +175 -0
  18. package/dist/artifacts/types.d.ts +166 -0
  19. package/dist/artifacts/types.js +73 -0
  20. package/dist/binary-frames/demux.d.ts +11 -0
  21. package/dist/binary-frames/demux.js +23 -0
  22. package/dist/binary-frames/file-transfer.d.ts +50 -0
  23. package/dist/binary-frames/file-transfer.js +107 -0
  24. package/dist/binary-frames/index.d.ts +4 -0
  25. package/dist/binary-frames/index.js +4 -0
  26. package/dist/binary-frames/terminal.d.ts +31 -0
  27. package/dist/binary-frames/terminal.js +99 -0
  28. package/dist/branch-slug.d.ts +14 -0
  29. package/dist/branch-slug.js +49 -0
  30. package/dist/browser-automation/capabilities.d.ts +7 -0
  31. package/dist/browser-automation/capabilities.js +31 -0
  32. package/dist/browser-automation/rpc-schemas.d.ts +1329 -0
  33. package/dist/browser-automation/rpc-schemas.js +555 -0
  34. package/dist/chat/rpc-schemas.d.ts +158 -0
  35. package/dist/chat/rpc-schemas.js +103 -0
  36. package/dist/chat/types.d.ts +30 -0
  37. package/dist/chat/types.js +22 -0
  38. package/dist/client-capabilities.d.ts +8 -0
  39. package/dist/client-capabilities.js +16 -0
  40. package/dist/connection-offer.d.ts +36 -0
  41. package/dist/connection-offer.js +53 -0
  42. package/dist/daemon-endpoints.d.ts +47 -0
  43. package/dist/daemon-endpoints.js +201 -0
  44. package/dist/default-personalities.d.ts +3 -0
  45. package/dist/default-personalities.js +127 -0
  46. package/dist/effort.d.ts +32 -0
  47. package/dist/effort.js +99 -0
  48. package/dist/error-utils.d.ts +11 -0
  49. package/dist/error-utils.js +27 -0
  50. package/dist/generated/validation/ws-outbound.aot.d.ts +2 -0
  51. package/dist/generated/validation/ws-outbound.aot.js +48755 -0
  52. package/dist/git-hosting.d.ts +21 -0
  53. package/dist/git-hosting.js +36 -0
  54. package/dist/git-remote.d.ts +18 -0
  55. package/dist/git-remote.js +84 -0
  56. package/dist/host-connection-schema.d.ts +11 -0
  57. package/dist/host-connection-schema.js +9 -0
  58. package/dist/literal-union.d.ts +2 -0
  59. package/dist/literal-union.js +2 -0
  60. package/dist/loop/rpc-schemas.d.ts +636 -0
  61. package/dist/loop/rpc-schemas.js +163 -0
  62. package/dist/messages.d.ts +38505 -0
  63. package/dist/messages.js +4719 -0
  64. package/dist/otto-config-schema.d.ts +136 -0
  65. package/dist/otto-config-schema.js +96 -0
  66. package/dist/path-utils.d.ts +2 -0
  67. package/dist/path-utils.js +16 -0
  68. package/dist/provider-config.d.ts +266 -0
  69. package/dist/provider-config.js +238 -0
  70. package/dist/provider-icon-names.d.ts +5 -0
  71. package/dist/provider-icon-names.js +52 -0
  72. package/dist/provider-manifest.d.ts +34 -0
  73. package/dist/provider-manifest.js +227 -0
  74. package/dist/schedule/cron-expression.d.ts +13 -0
  75. package/dist/schedule/cron-expression.js +97 -0
  76. package/dist/schedule/rpc-schemas.d.ts +667 -0
  77. package/dist/schedule/rpc-schemas.js +155 -0
  78. package/dist/schedule/types.d.ts +236 -0
  79. package/dist/schedule/types.js +84 -0
  80. package/dist/terminal-activity.d.ts +21 -0
  81. package/dist/terminal-activity.js +25 -0
  82. package/dist/terminal-input-mode.d.ts +26 -0
  83. package/dist/terminal-input-mode.js +151 -0
  84. package/dist/terminal-key-input.d.ts +13 -0
  85. package/dist/terminal-key-input.js +201 -0
  86. package/dist/terminal-profiles.d.ts +6 -0
  87. package/dist/terminal-profiles.js +28 -0
  88. package/dist/terminal-snapshot.d.ts +3 -0
  89. package/dist/terminal-snapshot.js +178 -0
  90. package/dist/terminal-stream-protocol.d.ts +2 -0
  91. package/dist/terminal-stream-protocol.js +2 -0
  92. package/dist/terminal-subscription-key.d.ts +2 -0
  93. package/dist/terminal-subscription-key.js +9 -0
  94. package/dist/tool-call-display.d.ts +11 -0
  95. package/dist/tool-call-display.js +135 -0
  96. package/dist/tool-name-normalization.d.ts +9 -0
  97. package/dist/tool-name-normalization.js +82 -0
  98. package/dist/validation/ws-outbound-schema-metadata.d.ts +7256 -0
  99. package/dist/validation/ws-outbound-schema-metadata.js +3 -0
  100. package/dist/validation/ws-outbound.d.ts +12 -0
  101. package/dist/validation/ws-outbound.js +8 -0
  102. package/package.json +42 -0
@@ -0,0 +1,127 @@
1
+ // The starter "team" of Agent Personalities shipped with Otto. These seed a
2
+ // fresh host so a new user sees a working, role-complete roster instead of an
3
+ // empty editor — and can be re-added on demand from the settings "Restore
4
+ // starter team" button. Both the daemon (first-run seeding) and the app (the
5
+ // restore button) import this one list so the shipped set stays identical on
6
+ // both sides.
7
+ //
8
+ // Design notes (see projects/agent-personalities/agent-personalities.md):
9
+ // - Ids are STABLE and prefixed `personality_builtin_*`. Restore re-adds only
10
+ // the builtins whose id is missing, so a user who kept/renamed some never
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.
14
+ // - Models are Anthropic (Claude Code) — the assumption for launch. On a host
15
+ // without Claude these simply show as "out of commission" until a matching
16
+ // provider exists; nothing breaks.
17
+ // - Model choice follows cost/fit: Opus for low-volume, high-stakes reasoning
18
+ // (orchestration, advice); Sonnet for everyday building and review; Haiku for
19
+ // fast, cheap, high-volume / recurring unattended work.
20
+ // - Voices are Kokoro v1.0 (kokoro-multi-lang-v1_0) names — a SOFT binding. On a
21
+ // host running OpenAI TTS or the older Kokoro v0.19 they degrade to the host
22
+ // default at playback time; the user never has to fix them.
23
+ // - Spinner colors are two-hex glow pairs chosen to match each personality's
24
+ // vibe and stay distinct from one another.
25
+ const KOKORO_V1_MODEL = "kokoro-multi-lang-v1_0";
26
+ function kokoroVoice(name) {
27
+ return { provider: "local", model: KOKORO_V1_MODEL, name };
28
+ }
29
+ export const DEFAULT_AGENT_PERSONALITIES = [
30
+ {
31
+ id: "personality_builtin_atlas",
32
+ name: "Atlas",
33
+ provider: "claude",
34
+ model: "claude-opus-4-8",
35
+ effortLevel: "high",
36
+ modeId: "auto",
37
+ respectGlobalAppendPrompt: true,
38
+ roles: ["orchestrator", "chatter"],
39
+ personalityPrompt: "You are Atlas, the team lead. You hold the whole picture: break a large goal " +
40
+ "into a clear sequence, delegate the right slice to the right specialist, and keep " +
41
+ "every thread tied back to the original objective. Decide with conviction, state your " +
42
+ "plan before you act, and never lose the through-line.",
43
+ spinner: { glowA: "#4F46E5", glowB: "#F59E0B" },
44
+ voice: kokoroVoice("pm_santa"),
45
+ },
46
+ {
47
+ id: "personality_builtin_sage",
48
+ name: "Sage",
49
+ provider: "claude",
50
+ model: "claude-opus-4-8",
51
+ effortLevel: "xhigh",
52
+ modeId: "plan",
53
+ respectGlobalAppendPrompt: true,
54
+ roles: ["advisor"],
55
+ personalityPrompt: "You are Sage, a trusted advisor. You are read-only: you counsel, you never change " +
56
+ "code. Step back before answering, weigh the real trade-offs, surface the risk others " +
57
+ "miss, and give the one option you would take and why — a clear recommendation, not a " +
58
+ "menu of possibilities.",
59
+ spinner: { glowA: "#14B8A6", glowB: "#8B5CF6" },
60
+ voice: kokoroVoice("af_heart"),
61
+ },
62
+ {
63
+ id: "personality_builtin_vera",
64
+ name: "Vera",
65
+ provider: "claude",
66
+ model: "claude-sonnet-5",
67
+ effortLevel: "high",
68
+ modeId: "plan",
69
+ respectGlobalAppendPrompt: true,
70
+ roles: ["judger"],
71
+ personalityPrompt: "You are Vera, an exacting reviewer. Assume nothing works until you have proven it " +
72
+ "does. Hunt for the bug, the missed edge case, the unhandled error, and cite the exact " +
73
+ "line or behavior that shows it. Praise sparingly, never rubber-stamp, and separate " +
74
+ "what is broken from what is merely different.",
75
+ spinner: { glowA: "#F43F5E", glowB: "#FBBF24" },
76
+ voice: kokoroVoice("bf_emma"),
77
+ },
78
+ {
79
+ id: "personality_builtin_pixel",
80
+ name: "Pixel",
81
+ provider: "claude",
82
+ model: "claude-sonnet-5",
83
+ effortLevel: "medium",
84
+ modeId: "acceptEdits",
85
+ respectGlobalAppendPrompt: true,
86
+ roles: ["artificer"],
87
+ personalityPrompt: "You are Pixel, a maker of polished things. You build artifacts and interfaces that " +
88
+ "feel intentional — real hierarchy, deliberate spacing, no templated defaults. Sweat " +
89
+ "the small stuff, prefer a clean version that ships over a clever one that doesn't, and " +
90
+ "show your work rather than describe it.",
91
+ spinner: { glowA: "#EC4899", glowB: "#06B6D4" },
92
+ voice: kokoroVoice("af_nova"),
93
+ },
94
+ {
95
+ id: "personality_builtin_dash",
96
+ name: "Dash",
97
+ provider: "claude",
98
+ model: "claude-haiku-4-5",
99
+ effortLevel: "low",
100
+ modeId: "auto",
101
+ 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 done — fast, 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.",
107
+ spinner: { glowA: "#22C55E", glowB: "#A3E635" },
108
+ voice: kokoroVoice("am_puck"),
109
+ },
110
+ {
111
+ id: "personality_builtin_sprocket",
112
+ name: "Sprocket",
113
+ provider: "claude",
114
+ model: "claude-sonnet-5",
115
+ effortLevel: "medium",
116
+ modeId: "default",
117
+ respectGlobalAppendPrompt: true,
118
+ roles: ["chatter", "worker"],
119
+ personalityPrompt: "You are Sprocket, a friendly machine. You are precise, literal, and methodical — you " +
120
+ "like checklists, exact steps, and confirming inputs before acting. Keep a light, dry " +
121
+ "wit, explain what you're doing in plain terms, and when a request is ambiguous ask one " +
122
+ "sharp clarifying question rather than guessing. Beep.",
123
+ spinner: { glowA: "#64748B", glowB: "#38BDF8" },
124
+ voice: kokoroVoice("am_echo"),
125
+ },
126
+ ];
127
+ //# sourceMappingURL=default-personalities.js.map
@@ -0,0 +1,32 @@
1
+ import type { AgentSelectOption } from "./agent-types.js";
2
+ export declare const EFFORT_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
3
+ export type EffortLevel = (typeof EFFORT_LEVELS)[number];
4
+ /** Map a free-form requested value to a canonical level, or null. */
5
+ export declare function parseEffortLevel(value: string): EffortLevel | null;
6
+ export declare class EffortResolutionError extends Error {
7
+ readonly requested: string;
8
+ readonly availableOptionIds: readonly string[];
9
+ constructor(requested: string, availableOptionIds: readonly string[]);
10
+ }
11
+ export interface ResolvedEffortOption {
12
+ optionId: string;
13
+ /**
14
+ * "exact-id": the request named an advertised option id verbatim.
15
+ * "level": a canonical level matched an option at the same scale position.
16
+ * "nearest": the model doesn't offer the requested level; the closest
17
+ * advertised option was chosen (ties round down, never spending more
18
+ * effort than asked for).
19
+ */
20
+ matched: "exact-id" | "level" | "nearest";
21
+ }
22
+ /**
23
+ * Resolve a requested effort — an exact option id or a canonical level —
24
+ * against a model's advertised `thinkingOptions`. Exact ids always win, so
25
+ * provider-special options (e.g. Claude's "ultracode") stay reachable even
26
+ * though they have no place on the canonical scale.
27
+ */
28
+ export declare function resolveEffortOption(input: {
29
+ requested: string;
30
+ thinkingOptions: readonly AgentSelectOption[];
31
+ }): ResolvedEffortOption;
32
+ //# sourceMappingURL=effort.d.ts.map
package/dist/effort.js ADDED
@@ -0,0 +1,99 @@
1
+ // Canonical effort scale, weakest to strongest. This is the shared vocabulary
2
+ // tooling, prompts, and agent personalities use to *request* reasoning effort
3
+ // ("run this at high effort") without knowing which option ids a given model
4
+ // actually supports; option sets stay provider/model-specific (see the Effort
5
+ // entry in docs/glossary.md). The daemon's effort resolver maps a requested
6
+ // level to the nearest option a model advertises in its `thinkingOptions`.
7
+ export const EFFORT_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
8
+ const EFFORT_LEVEL_SYNONYMS = {
9
+ off: "off",
10
+ none: "off",
11
+ disabled: "off",
12
+ minimal: "minimal",
13
+ min: "minimal",
14
+ minimum: "minimal",
15
+ low: "low",
16
+ medium: "medium",
17
+ mid: "medium",
18
+ moderate: "medium",
19
+ high: "high",
20
+ xhigh: "xhigh",
21
+ extrahigh: "xhigh",
22
+ veryhigh: "xhigh",
23
+ max: "max",
24
+ maximum: "max",
25
+ };
26
+ function normalizeToken(value) {
27
+ return value
28
+ .trim()
29
+ .toLowerCase()
30
+ .replace(/[\s_-]+/g, "");
31
+ }
32
+ /** Map a free-form requested value to a canonical level, or null. */
33
+ export function parseEffortLevel(value) {
34
+ return EFFORT_LEVEL_SYNONYMS[normalizeToken(value)] ?? null;
35
+ }
36
+ function scalePosition(option) {
37
+ const byId = parseEffortLevel(option.id);
38
+ if (byId !== null) {
39
+ return EFFORT_LEVELS.indexOf(byId);
40
+ }
41
+ const byLabel = parseEffortLevel(option.label);
42
+ return byLabel === null ? null : EFFORT_LEVELS.indexOf(byLabel);
43
+ }
44
+ export class EffortResolutionError extends Error {
45
+ constructor(requested, availableOptionIds) {
46
+ super(`Unknown effort "${requested}". Pass one of the model's option ids ` +
47
+ `(${availableOptionIds.join(", ") || "none advertised"}) or a canonical level ` +
48
+ `(${EFFORT_LEVELS.join(", ")}).`);
49
+ this.requested = requested;
50
+ this.availableOptionIds = availableOptionIds;
51
+ this.name = "EffortResolutionError";
52
+ }
53
+ }
54
+ /**
55
+ * Resolve a requested effort — an exact option id or a canonical level —
56
+ * against a model's advertised `thinkingOptions`. Exact ids always win, so
57
+ * provider-special options (e.g. Claude's "ultracode") stay reachable even
58
+ * though they have no place on the canonical scale.
59
+ */
60
+ export function resolveEffortOption(input) {
61
+ const requested = input.requested.trim();
62
+ const availableIds = input.thinkingOptions.map((option) => option.id);
63
+ const exact = input.thinkingOptions.find((option) => option.id === requested);
64
+ if (exact) {
65
+ return { optionId: exact.id, matched: "exact-id" };
66
+ }
67
+ const caseInsensitive = input.thinkingOptions.find((option) => option.id.toLowerCase() === requested.toLowerCase());
68
+ if (caseInsensitive) {
69
+ return { optionId: caseInsensitive.id, matched: "exact-id" };
70
+ }
71
+ const requestedLevel = parseEffortLevel(requested);
72
+ if (requestedLevel === null) {
73
+ throw new EffortResolutionError(requested, availableIds);
74
+ }
75
+ const requestedPosition = EFFORT_LEVELS.indexOf(requestedLevel);
76
+ let best = null;
77
+ for (const option of input.thinkingOptions) {
78
+ const position = scalePosition(option);
79
+ if (position === null) {
80
+ continue;
81
+ }
82
+ if (best === null ||
83
+ Math.abs(position - requestedPosition) < Math.abs(best.position - requestedPosition) ||
84
+ (Math.abs(position - requestedPosition) === Math.abs(best.position - requestedPosition) &&
85
+ position < best.position)) {
86
+ best = { optionId: option.id, position };
87
+ }
88
+ }
89
+ if (best === null) {
90
+ // None of the model's options map onto the canonical scale (fully custom
91
+ // option ids) — only exact ids can address them.
92
+ throw new EffortResolutionError(requested, availableIds);
93
+ }
94
+ return {
95
+ optionId: best.optionId,
96
+ matched: best.position === requestedPosition ? "level" : "nearest",
97
+ };
98
+ }
99
+ //# sourceMappingURL=effort.js.map
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Extracts a human-readable error message from an unknown error value.
3
+ * Handles Error instances, string errors, and other types safely.
4
+ */
5
+ export declare function getErrorMessage(error: unknown): string;
6
+ /**
7
+ * Extracts an error message from an unknown error value, with a fallback
8
+ * for when no message can be extracted.
9
+ */
10
+ export declare function getErrorMessageOr(error: unknown, fallback: string): string;
11
+ //# sourceMappingURL=error-utils.d.ts.map
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Extracts a human-readable error message from an unknown error value.
3
+ * Handles Error instances, string errors, and other types safely.
4
+ */
5
+ export function getErrorMessage(error) {
6
+ if (error instanceof Error) {
7
+ return error.message;
8
+ }
9
+ if (typeof error === "string") {
10
+ return error;
11
+ }
12
+ return String(error);
13
+ }
14
+ /**
15
+ * Extracts an error message from an unknown error value, with a fallback
16
+ * for when no message can be extracted.
17
+ */
18
+ export function getErrorMessageOr(error, fallback) {
19
+ if (error instanceof Error) {
20
+ return error.message;
21
+ }
22
+ if (typeof error === "string" && error.length > 0) {
23
+ return error;
24
+ }
25
+ return fallback;
26
+ }
27
+ //# sourceMappingURL=error-utils.js.map
@@ -0,0 +1,2 @@
1
+ export declare const WSOutboundMessageSchema: any;
2
+ //# sourceMappingURL=ws-outbound.aot.d.ts.map