bloby-bot 0.32.0 → 0.32.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.
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex (OpenAI app-server) harness — STUB for Phase 1.
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 introduces the harness split with zero behavior change for Claude
|
|
5
|
+
* users. Codex routing is wired up but every method emits a clear "not
|
|
6
|
+
* implemented yet" error so we can spot any accidental route during testing.
|
|
7
|
+
*
|
|
8
|
+
* Phase 2 will spawn `codex app-server` over stdio JSON-RPC, manage threads,
|
|
9
|
+
* and translate item/turn notifications into the shared `bot:*` event vocab.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { log } from '../../shared/logger.js';
|
|
13
|
+
import type { OnAgentMessage, RecentMessage, AgentAttachment } from './types.js';
|
|
14
|
+
import type { SavedFile } from '../file-saver.js';
|
|
15
|
+
|
|
16
|
+
const NOT_READY = 'OpenAI/Codex harness is not implemented yet. Switch the provider back to Anthropic, or wait for Phase 2 of the harness work.';
|
|
17
|
+
|
|
18
|
+
function emitNotReady(conversationId: string, onMessage: OnAgentMessage): void {
|
|
19
|
+
log.warn(`[codex-harness] ${NOT_READY}`);
|
|
20
|
+
onMessage('bot:error', { conversationId, error: NOT_READY });
|
|
21
|
+
onMessage('bot:done', { conversationId, usedFileTools: false });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function startConversation(
|
|
25
|
+
conversationId: string,
|
|
26
|
+
_model: string,
|
|
27
|
+
onMessage: OnAgentMessage,
|
|
28
|
+
_names?: { botName: string; humanName: string },
|
|
29
|
+
_recentMessages?: RecentMessage[],
|
|
30
|
+
): Promise<boolean> {
|
|
31
|
+
emitNotReady(conversationId, onMessage);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function pushMessage(
|
|
36
|
+
conversationId: string,
|
|
37
|
+
_content: string,
|
|
38
|
+
_attachments?: AgentAttachment[],
|
|
39
|
+
_savedFiles?: SavedFile[],
|
|
40
|
+
): boolean {
|
|
41
|
+
log.warn(`[codex-harness] pushMessage(${conversationId}) — ${NOT_READY}`);
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function hasConversation(_conversationId: string): boolean {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function endConversation(_conversationId: string): void { /* no-op */ }
|
|
50
|
+
export function endAllConversations(): void { /* no-op */ }
|
|
51
|
+
export function isConversationBusy(_conversationId: string): boolean { return false; }
|
|
52
|
+
export async function stopSubAgentTask(_conversationId: string, _taskId: string): Promise<void> { /* no-op */ }
|
|
53
|
+
export async function warmUpForLiveConversation(
|
|
54
|
+
_model: string,
|
|
55
|
+
_names?: { botName: string; humanName: string },
|
|
56
|
+
): Promise<void> { /* no-op */ }
|
|
57
|
+
|
|
58
|
+
export async function startBlobyAgentQuery(
|
|
59
|
+
conversationId: string,
|
|
60
|
+
_prompt: string,
|
|
61
|
+
_model: string,
|
|
62
|
+
onMessage: OnAgentMessage,
|
|
63
|
+
_attachments?: AgentAttachment[],
|
|
64
|
+
_savedFiles?: SavedFile[],
|
|
65
|
+
_names?: { botName: string; humanName: string },
|
|
66
|
+
_recentMessages?: RecentMessage[],
|
|
67
|
+
_supportPrompt?: string,
|
|
68
|
+
_maxTurns?: number,
|
|
69
|
+
): Promise<void> {
|
|
70
|
+
emitNotReady(conversationId, onMessage);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function stopBlobyAgentQuery(_conversationId: string): void { /* no-op */ }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness — provider-agnostic agent runtime contract.
|
|
3
|
+
*
|
|
4
|
+
* Each AI provider that ships an "agent" experience (Claude Agent SDK,
|
|
5
|
+
* Codex app-server, …) implements this interface. The dispatcher in
|
|
6
|
+
* `supervisor/bloby-agent.ts` selects which one to use based on
|
|
7
|
+
* `cfg.ai.provider` so the rest of the supervisor never needs to care.
|
|
8
|
+
*
|
|
9
|
+
* The two execution shapes mirror what the supervisor already needs:
|
|
10
|
+
* • startConversation / pushMessage / endConversation — long-lived chat
|
|
11
|
+
* with streaming events. Used by the dashboard and admin WhatsApp.
|
|
12
|
+
* • startBlobyAgentQuery / stopBlobyAgentQuery — one-shot request/response
|
|
13
|
+
* used by customer WhatsApp and the scheduler.
|
|
14
|
+
*
|
|
15
|
+
* Event names emitted via the `onMessage` callback are the same vocabulary
|
|
16
|
+
* `supervisor/index.ts` and `channels/manager.ts` already consume — every
|
|
17
|
+
* harness translates its native events into this set:
|
|
18
|
+
* bot:typing, bot:token, bot:tool, bot:response, bot:turn-complete,
|
|
19
|
+
* bot:done, bot:error, bot:task-created, bot:task-progress, bot:task-done,
|
|
20
|
+
* bot:conversation-ended.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import type { SavedFile } from '../file-saver.js';
|
|
24
|
+
|
|
25
|
+
export interface RecentMessage {
|
|
26
|
+
role: 'user' | 'assistant';
|
|
27
|
+
content: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface AgentAttachment {
|
|
31
|
+
type: 'image' | 'file';
|
|
32
|
+
name: string;
|
|
33
|
+
mediaType: string;
|
|
34
|
+
data: string; // base64
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type OnAgentMessage = (type: string, data: any) => void;
|
|
38
|
+
|
|
39
|
+
export interface Harness {
|
|
40
|
+
/* ── Live conversation API ── */
|
|
41
|
+
startConversation(
|
|
42
|
+
conversationId: string,
|
|
43
|
+
model: string,
|
|
44
|
+
onMessage: OnAgentMessage,
|
|
45
|
+
names?: { botName: string; humanName: string },
|
|
46
|
+
recentMessages?: RecentMessage[],
|
|
47
|
+
): Promise<boolean>;
|
|
48
|
+
|
|
49
|
+
pushMessage(
|
|
50
|
+
conversationId: string,
|
|
51
|
+
content: string,
|
|
52
|
+
attachments?: AgentAttachment[],
|
|
53
|
+
savedFiles?: SavedFile[],
|
|
54
|
+
): boolean;
|
|
55
|
+
|
|
56
|
+
hasConversation(conversationId: string): boolean;
|
|
57
|
+
endConversation(conversationId: string): void;
|
|
58
|
+
endAllConversations(): void;
|
|
59
|
+
isConversationBusy(conversationId: string): boolean;
|
|
60
|
+
stopSubAgentTask(conversationId: string, taskId: string): Promise<void>;
|
|
61
|
+
warmUpForLiveConversation(
|
|
62
|
+
model: string,
|
|
63
|
+
names?: { botName: string; humanName: string },
|
|
64
|
+
): Promise<void>;
|
|
65
|
+
|
|
66
|
+
/* ── One-shot API (request/response) ── */
|
|
67
|
+
startBlobyAgentQuery(
|
|
68
|
+
conversationId: string,
|
|
69
|
+
prompt: string,
|
|
70
|
+
model: string,
|
|
71
|
+
onMessage: OnAgentMessage,
|
|
72
|
+
attachments?: AgentAttachment[],
|
|
73
|
+
savedFiles?: SavedFile[],
|
|
74
|
+
names?: { botName: string; humanName: string },
|
|
75
|
+
recentMessages?: RecentMessage[],
|
|
76
|
+
supportPrompt?: string,
|
|
77
|
+
maxTurns?: number,
|
|
78
|
+
): Promise<void>;
|
|
79
|
+
|
|
80
|
+
stopBlobyAgentQuery(conversationId: string): void;
|
|
81
|
+
}
|