osborn 0.9.31 → 0.9.32

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.
@@ -17,12 +17,17 @@ Do not batch — capture as they happen.
17
17
  </what-to-do>
18
18
 
19
19
  <trigger-phrases>
20
- - "grill me"
20
+ This skill is a META operation — about building a model of the USER THEMSELVES,
21
+ not about any subject matter in the current conversation. The trigger phrases below
22
+ are intentionally specific so they cannot be confused with domain requests in any session.
23
+
24
+ - "update user context"
21
25
  - "learn my language"
22
- - "update my context"
26
+ - "start context interview"
27
+ - "grill me on my language"
23
28
  - "learn how I talk"
24
29
  - "standardise my language"
25
- - "update user context"
30
+ - "update my context"
26
31
  </trigger-phrases>
27
32
 
28
33
  <supporting-info>
@@ -4,18 +4,33 @@ export interface RecallBot {
4
4
  meeting_url: string;
5
5
  status: string;
6
6
  }
7
- export interface TranscriptWord {
8
- text: string;
9
- start_time: number;
10
- end_time: number;
11
- }
12
7
  export interface TranscriptPayload {
13
- bot_id: string;
14
- transcript: {
15
- speaker: string;
16
- words: TranscriptWord[];
17
- is_final: boolean;
18
- language?: string;
8
+ event: string;
9
+ data: {
10
+ data: {
11
+ words: Array<{
12
+ text: string;
13
+ start_timestamp?: {
14
+ relative?: number;
15
+ };
16
+ end_timestamp?: {
17
+ relative?: number;
18
+ };
19
+ }>;
20
+ language_code?: string;
21
+ participant?: {
22
+ id: number;
23
+ name: string;
24
+ is_host?: boolean;
25
+ platform?: string;
26
+ };
27
+ };
28
+ bot?: {
29
+ id: string;
30
+ };
31
+ recording?: {
32
+ id: string;
33
+ };
19
34
  };
20
35
  }
21
36
  export declare class RecallClient extends EventEmitter {
@@ -9,6 +9,17 @@ export class RecallClient extends EventEmitter {
9
9
  this.#apiKey = apiKey;
10
10
  }
11
11
  async joinMeeting(meetingUrl, webhookBaseUrl, botName = 'Osborn') {
12
+ // Authoritative structure per https://docs.recall.ai/reference/bot_create
13
+ // and https://docs.recall.ai/docs/real-time-transcription:
14
+ //
15
+ // recording_config.transcript.provider — transcription provider config
16
+ // recording_config.realtime_endpoints — webhook/websocket delivery
17
+ //
18
+ // IMPORTANT:
19
+ // - Field is `realtime_endpoints` (NOT `real_time_endpoints`)
20
+ // - `url` and `events` are flat on the endpoint object (NOT nested under `config`)
21
+ // - `transcription_options` does NOT exist — use `transcript.provider`
22
+ // - Both transcript.provider AND realtime_endpoints must be set, or no events delivered
12
23
  const res = await fetch(`${RECALL_BASE_URL}/bot`, {
13
24
  method: 'POST',
14
25
  headers: {
@@ -19,24 +30,26 @@ export class RecallClient extends EventEmitter {
19
30
  meeting_url: meetingUrl,
20
31
  bot_name: botName,
21
32
  recording_config: {
22
- // Field names must match Recall API exactly (no underscore in realtime_endpoints).
23
- // real_time_endpoints was silently ignored — API uses realtime_endpoints.
33
+ transcript: {
34
+ provider: {
35
+ // recallai_streaming is built-in — no external API key needed,
36
+ // low-latency, works across all meeting platforms.
37
+ recallai_streaming: {
38
+ mode: 'prioritize_low_latency',
39
+ language_code: 'en',
40
+ },
41
+ },
42
+ },
24
43
  realtime_endpoints: [{
25
44
  type: 'webhook',
26
- config: {
27
- url: `${webhookBaseUrl}/webhook/recall`,
28
- events: ['transcript.data'],
29
- },
45
+ url: `${webhookBaseUrl}/webhook/recall`,
46
+ events: ['transcript.data'],
30
47
  }],
31
- transcription_options: {
32
- provider: 'assembly_ai',
33
- mode: 'prioritize_low_latency',
34
- },
35
48
  },
36
49
  output_media: {
37
50
  camera: {
38
- // Recall API expects `kind` (not `type`); the wrong key arrives as null and
39
- // gets rejected as "Invalid choice null. Expected 'webpage' or 'default'."
51
+ // `kind` (not `type`) confirmed from prior debugging.
52
+ // Output webpage plays TTS audio so meeting participants can hear the agent.
40
53
  kind: 'webpage',
41
54
  config: {
42
55
  url: `${webhookBaseUrl}/meeting-output`,
@@ -69,16 +82,16 @@ export class RecallClient extends EventEmitter {
69
82
  return bot.status_changes?.at(-1)?.code ?? 'unknown';
70
83
  }
71
84
  handleWebhook(payload) {
72
- if (!payload.transcript?.is_final)
85
+ // Only process final transcripts (transcript.data), skip partials
86
+ if (payload.event !== 'transcript.data')
73
87
  return;
74
- const text = payload.transcript.words.map(w => w.text).join(' ').trim();
88
+ const words = payload.data?.data?.words ?? [];
89
+ const text = words.map(w => w.text).join(' ').trim();
75
90
  if (!text)
76
91
  return;
77
- this.emit('transcript', {
78
- botId: payload.bot_id,
79
- speaker: payload.transcript.speaker,
80
- text,
81
- });
92
+ const speaker = payload.data?.data?.participant?.name ?? 'Unknown';
93
+ const botId = payload.data?.bot?.id ?? 'unknown';
94
+ this.emit('transcript', { botId, speaker, text });
82
95
  }
83
96
  registerBot(botId, sessionId) {
84
97
  this.#activeBots.set(botId, sessionId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "osborn",
3
- "version": "0.9.31",
3
+ "version": "0.9.32",
4
4
  "description": "Voice AI coding assistant - local agent that connects to Osborn frontend",
5
5
  "type": "module",
6
6
  "bin": {