@foxden-app/foxclaw 0.11.1 → 0.13.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.
- package/.env.example +18 -1
- package/CHANGELOG.md +36 -0
- package/README.md +4 -3
- package/README_EN.md +4 -3
- package/dist/antigravity/account_ui.d.ts +34 -0
- package/dist/antigravity/account_ui.js +354 -0
- package/dist/antigravity/adapter.js +1 -1
- package/dist/antigravity/auth.d.ts +4 -1
- package/dist/antigravity/auth.js +17 -5
- package/dist/antigravity/controller.d.ts +3 -106
- package/dist/antigravity/controller.js +2 -2083
- package/dist/antigravity/conversation_ui.d.ts +56 -0
- package/dist/antigravity/conversation_ui.js +509 -0
- package/dist/antigravity/ui_callbacks.d.ts +6 -0
- package/dist/antigravity/ui_callbacks.js +6 -0
- package/dist/bridge/unified_bridge.d.ts +114 -0
- package/dist/bridge/unified_bridge.js +1343 -0
- package/dist/channels/bridge_messaging_router.d.ts +8 -4
- package/dist/channels/bridge_messaging_router.js +15 -4
- package/dist/channels/telegram/telegram_messaging_port.d.ts +16 -0
- package/dist/channels/telegram/telegram_messaging_port.js +22 -2
- package/dist/channels/text_actions.d.ts +14 -0
- package/dist/channels/text_actions.js +48 -0
- package/dist/channels/weixin/weixin_channel_adapter.d.ts +3 -4
- package/dist/channels/weixin/weixin_channel_adapter.js +2 -2
- package/dist/channels/weixin/weixin_messaging_port.d.ts +16 -1
- package/dist/channels/weixin/weixin_messaging_port.js +34 -7
- package/dist/codex_app/activity.d.ts +62 -0
- package/dist/codex_app/activity.js +418 -0
- package/dist/codex_app/adapter.d.ts +2 -2
- package/dist/codex_app/adapter.js +55 -25
- package/dist/codex_app/backend_ui.d.ts +4 -0
- package/dist/codex_app/backend_ui.js +48 -0
- package/dist/codex_app/client.js +0 -12
- package/dist/config.d.ts +4 -0
- package/dist/config.js +41 -5
- package/dist/controller/access.d.ts +1 -11
- package/dist/controller/access.js +1 -33
- package/dist/controller/activity.d.ts +1 -62
- package/dist/controller/activity.js +2 -418
- package/dist/controller/auth_errors.d.ts +11 -0
- package/dist/controller/auth_errors.js +124 -0
- package/dist/controller/auth_files.d.ts +13 -0
- package/dist/controller/auth_files.js +156 -0
- package/dist/controller/auth_presentation.d.ts +77 -0
- package/dist/controller/auth_presentation.js +697 -0
- package/dist/controller/auth_quota_service.d.ts +27 -0
- package/dist/controller/auth_quota_service.js +151 -0
- package/dist/controller/controller.d.ts +30 -56
- package/dist/controller/controller.js +181 -3497
- package/dist/controller/interactions.d.ts +74 -0
- package/dist/controller/interactions.js +560 -0
- package/dist/controller/local_usage_service.d.ts +19 -0
- package/dist/controller/local_usage_service.js +62 -0
- package/dist/controller/native_panel_service.d.ts +55 -0
- package/dist/controller/native_panel_service.js +214 -0
- package/dist/controller/native_panels.d.ts +61 -0
- package/dist/controller/native_panels.js +784 -0
- package/dist/controller/shared_helpers.d.ts +53 -0
- package/dist/controller/shared_helpers.js +399 -0
- package/dist/controller/state_types.d.ts +390 -0
- package/dist/controller/state_types.js +82 -0
- package/dist/controller/turn_rendering.d.ts +22 -0
- package/dist/controller/turn_rendering.js +288 -0
- package/dist/core/access.d.ts +11 -0
- package/dist/core/access.js +33 -0
- package/dist/core/attachment_files.d.ts +13 -0
- package/dist/core/attachment_files.js +180 -0
- package/dist/core/attachment_types.d.ts +22 -0
- package/dist/core/attachment_types.js +1 -0
- package/dist/core/attachments.d.ts +5 -3
- package/dist/core/attachments.js +2 -2
- package/dist/core/backend_registry.d.ts +22 -0
- package/dist/core/backend_registry.js +50 -0
- package/dist/core/backend_ui.d.ts +28 -0
- package/dist/core/backend_ui.js +1 -0
- package/dist/core/channel_events.d.ts +48 -0
- package/dist/core/channel_events.js +1 -0
- package/dist/core/channel_port.d.ts +52 -8
- package/dist/core/engine_spi.d.ts +20 -5
- package/dist/core/listener_scope.d.ts +11 -0
- package/dist/core/listener_scope.js +10 -0
- package/dist/core/message_text.d.ts +2 -0
- package/dist/core/message_text.js +28 -0
- package/dist/core/network_errors.d.ts +1 -0
- package/dist/core/network_errors.js +23 -0
- package/dist/core/orchestrator.d.ts +57 -22
- package/dist/core/orchestrator.js +877 -477
- package/dist/core/queued_engine_input.d.ts +12 -0
- package/dist/core/queued_engine_input.js +16 -0
- package/dist/core/runtime_supervisor.d.ts +19 -0
- package/dist/core/runtime_supervisor.js +45 -0
- package/dist/core/scope_operations.d.ts +7 -0
- package/dist/core/scope_operations.js +19 -0
- package/dist/core/stream_preview.js +21 -9
- package/dist/dsh/adapter.d.ts +48 -0
- package/dist/dsh/adapter.js +205 -0
- package/dist/dsh/backend.d.ts +7 -0
- package/dist/dsh/backend.js +21 -0
- package/dist/dsh/client.d.ts +46 -0
- package/dist/dsh/client.js +184 -0
- package/dist/dsh/permissions_plugin.d.ts +30 -0
- package/dist/dsh/permissions_plugin.js +21 -0
- package/dist/dsh/runtime.d.ts +20 -0
- package/dist/dsh/runtime.js +36 -0
- package/dist/dsh/ui.d.ts +38 -0
- package/dist/dsh/ui.js +342 -0
- package/dist/i18n.d.ts +4 -0
- package/dist/i18n.js +12 -0
- package/dist/main.js +144 -72
- package/dist/opencode/adapter.js +28 -9
- package/dist/opencode/controller.js +1 -1
- package/dist/store/channel_inbox.d.ts +14 -0
- package/dist/store/channel_inbox.js +21 -0
- package/dist/store/database.d.ts +10 -4
- package/dist/store/database.js +13 -3
- package/dist/store/task_journal.d.ts +32 -0
- package/dist/store/task_journal.js +70 -0
- package/dist/telegram/api.d.ts +2 -2
- package/dist/telegram/api.js +10 -28
- package/dist/telegram/gateway.d.ts +13 -27
- package/dist/telegram/gateway.js +86 -43
- package/dist/telegram/media.d.ts +2 -34
- package/dist/telegram/media.js +1 -180
- package/dist/telegram/task_preview.d.ts +13 -0
- package/dist/telegram/task_preview.js +92 -0
- package/dist/telegram/task_result.d.ts +2 -0
- package/dist/telegram/task_result.js +12 -0
- package/dist/telegram/text.d.ts +1 -1
- package/dist/telegram/text.js +2 -27
- package/dist/types.d.ts +2 -2
- package/docs/dsh.md +83 -0
- package/docs/release.md +13 -11
- package/docs/zh/architecture-review.md +106 -0
- package/docs/zh/dsh.md +83 -0
- package/docs/zh/release.md +13 -11
- package/docs/zh/telegram-experience.md +40 -0
- package/package.json +7 -5
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { AppLocale } from '../types.js';
|
|
2
|
+
import type { ChannelTextEvent, ChannelCallbackEvent } from '../core/channel_events.js';
|
|
3
|
+
import type { ChannelInlineKeyboard } from '../core/channel_port.js';
|
|
4
|
+
import type { BackendDescriptor } from './engine_spi.js';
|
|
5
|
+
/** Operations a backend panel can request without depending on the orchestrator implementation. */
|
|
6
|
+
export interface BackendUiHost {
|
|
7
|
+
sendMessage(scopeId: string, text: string, keyboard?: ChannelInlineKeyboard): Promise<number>;
|
|
8
|
+
editMessage(scopeId: string, messageId: number, text: string, keyboard?: ChannelInlineKeyboard): Promise<void>;
|
|
9
|
+
scheduleStalePanelDeletion(scopeId: string, messageId: number): void;
|
|
10
|
+
hasActiveTurn(scopeId: string): boolean;
|
|
11
|
+
syncCurrentBackendSettings(scopeId: string): void;
|
|
12
|
+
getBackendDescriptorForScope(scopeId: string): BackendDescriptor;
|
|
13
|
+
}
|
|
14
|
+
export interface EngineCustomUiHook {
|
|
15
|
+
renderSetupMenu?(scopeId: string, locale: AppLocale, messageId?: number): Promise<boolean>;
|
|
16
|
+
renderModelsMenu?(scopeId: string, locale: AppLocale, messageId?: number): Promise<boolean>;
|
|
17
|
+
renderCustomStatus?(scopeId: string, locale: AppLocale): Promise<string | null>;
|
|
18
|
+
renderCustomSetupRows?(scopeId: string, locale: AppLocale): Promise<ChannelInlineKeyboard>;
|
|
19
|
+
handleCustomCallback?(scopeId: string, data: string, locale: AppLocale, messageId?: number, event?: ChannelCallbackEvent): Promise<boolean>;
|
|
20
|
+
handleCustomCommand?(scopeId: string, command: string, args: string, locale: AppLocale, event?: ChannelTextEvent): Promise<boolean>;
|
|
21
|
+
handleCustomInbound?(event: ChannelTextEvent, locale: AppLocale): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
export interface BackendUi extends EngineCustomUiHook {
|
|
24
|
+
/** Recognize owned buttons even after the user switches to another backend (e.g. pending approvals). */
|
|
25
|
+
ownsCallback?(data: string): boolean;
|
|
26
|
+
getPendingApprovals?(): number;
|
|
27
|
+
stop?(): Promise<void>;
|
|
28
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { InboundAttachment } from './attachment_types.js';
|
|
2
|
+
export interface ChannelMessageEntity {
|
|
3
|
+
type: string;
|
|
4
|
+
offset: number;
|
|
5
|
+
length: number;
|
|
6
|
+
user?: {
|
|
7
|
+
id: number;
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export interface ChannelTextEvent {
|
|
11
|
+
chatId: string;
|
|
12
|
+
topicId: number | null;
|
|
13
|
+
scopeId: string;
|
|
14
|
+
chatType: string;
|
|
15
|
+
userId: string;
|
|
16
|
+
text: string;
|
|
17
|
+
messageId: number;
|
|
18
|
+
mediaGroupId?: string | null;
|
|
19
|
+
attachments: InboundAttachment[];
|
|
20
|
+
entities: ChannelMessageEntity[];
|
|
21
|
+
replyToBot: boolean;
|
|
22
|
+
languageCode?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ChannelCallbackEvent {
|
|
25
|
+
chatId: string;
|
|
26
|
+
topicId: number | null;
|
|
27
|
+
scopeId: string;
|
|
28
|
+
userId: string;
|
|
29
|
+
data: string;
|
|
30
|
+
callbackQueryId: string;
|
|
31
|
+
messageId: number;
|
|
32
|
+
languageCode?: string;
|
|
33
|
+
}
|
|
34
|
+
/** A transport-correlated stop; generation identifiers never select a task in another scope. */
|
|
35
|
+
export interface ChannelStopEvent {
|
|
36
|
+
scopeId: string;
|
|
37
|
+
taskId: string;
|
|
38
|
+
}
|
|
39
|
+
export type ChannelInbound = {
|
|
40
|
+
kind: 'text';
|
|
41
|
+
event: ChannelTextEvent;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'callback';
|
|
44
|
+
event: ChannelCallbackEvent;
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'stop';
|
|
47
|
+
event: ChannelStopEvent;
|
|
48
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,15 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type { AppConfig } from '../config.js';
|
|
2
|
+
import type { AppLocale } from '../types.js';
|
|
3
|
+
import type { ChannelTextEvent, ChannelCallbackEvent, ChannelInbound } from './channel_events.js';
|
|
4
|
+
import type { ParsedCommand } from '../controller/commands.js';
|
|
5
|
+
import type { AttachmentDownloader } from './attachments.js';
|
|
6
|
+
/** Bridge-local handles; a transport maps these to its native message identifiers. */
|
|
7
|
+
export type ChannelMessageRef = number;
|
|
5
8
|
export type ChannelInlineKeyboard = Array<Array<{
|
|
6
9
|
text: string;
|
|
7
10
|
callback_data: string;
|
|
8
11
|
}>>;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
export type InboundAddressing = {
|
|
13
|
+
kind: 'ignore';
|
|
14
|
+
} | {
|
|
15
|
+
kind: 'prompt';
|
|
16
|
+
text: string;
|
|
17
|
+
} | {
|
|
18
|
+
kind: 'command';
|
|
19
|
+
command: ParsedCommand;
|
|
20
|
+
};
|
|
21
|
+
/** Presentation and file transport contract. Native addressing and interaction live in channels. */
|
|
22
|
+
export interface ChannelPort extends AttachmentDownloader {
|
|
23
|
+
readonly capabilities?: {
|
|
24
|
+
editableMessages: boolean;
|
|
25
|
+
inlineActions: boolean;
|
|
26
|
+
maxMessageLength: number;
|
|
27
|
+
};
|
|
28
|
+
resolveIncoming?(event: ChannelTextEvent, config: AppConfig, username?: string | null): InboundAddressing;
|
|
29
|
+
setScopeCommands?(scopeId: string, commands: Array<{
|
|
30
|
+
command: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}>): Promise<void>;
|
|
33
|
+
beginTaskPreview?(scopeId: string, taskId: string, text: string, reuseMessageId?: number): Promise<number>;
|
|
34
|
+
updateTaskPreview?(scopeId: string, taskId: string, messageId: number, html: string): Promise<number>;
|
|
35
|
+
endTaskPreview?(scopeId: string, taskId: string): Promise<void>;
|
|
36
|
+
resolveAction?(event: ChannelTextEvent): ChannelCallbackEvent | null;
|
|
37
|
+
editPlain(scopeId: string, messageId: ChannelMessageRef, text: string, keyboard?: ChannelInlineKeyboard): Promise<void>;
|
|
13
38
|
sendPlain(scopeId: string, text: string, keyboard?: ChannelInlineKeyboard): Promise<ChannelMessageRef>;
|
|
14
39
|
sendHtml(scopeId: string, text: string, keyboard?: ChannelInlineKeyboard): Promise<ChannelMessageRef>;
|
|
40
|
+
sendRichMarkdown(scopeId: string, text: string, keyboard?: ChannelInlineKeyboard): Promise<ChannelMessageRef>;
|
|
41
|
+
editRichMarkdown(scopeId: string, messageId: ChannelMessageRef, text: string, keyboard?: ChannelInlineKeyboard): Promise<void>;
|
|
42
|
+
deleteMessage(scopeId: string, messageId: ChannelMessageRef): Promise<void>;
|
|
43
|
+
sendTypingInScope(scopeId: string): Promise<void>;
|
|
44
|
+
answerCallback(callbackId: string, text: string): Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
export interface ChannelGateway {
|
|
47
|
+
setInboundConsumer?(consumer: (id: string, inbound: ChannelInbound) => Promise<void>): () => void;
|
|
48
|
+
readonly username?: string | null;
|
|
49
|
+
on(event: 'text', listener: (event: ChannelTextEvent) => void): unknown;
|
|
50
|
+
on(event: 'callback', listener: (event: ChannelCallbackEvent) => void): unknown;
|
|
51
|
+
off?(event: 'text' | 'callback', listener: (...args: any[]) => void): unknown;
|
|
52
|
+
start(): Promise<void>;
|
|
53
|
+
stop(): void | Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
export interface ChannelCommand {
|
|
56
|
+
command: string;
|
|
57
|
+
description: string;
|
|
15
58
|
}
|
|
59
|
+
export type ChannelCommandProvider = (locale: AppLocale) => ChannelCommand[];
|
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { AppLocale } from '../types.js';
|
|
1
|
+
import type { StagedAttachment } from './attachment_types.js';
|
|
2
|
+
import type { AppLocale, AccessPresetValue } from '../types.js';
|
|
3
|
+
import type { BackendUi, BackendUiHost } from './backend_ui.js';
|
|
3
4
|
export interface EngineModel {
|
|
4
5
|
id: string;
|
|
5
6
|
name: string;
|
|
6
7
|
description?: string | undefined;
|
|
7
8
|
isDefault?: boolean | undefined;
|
|
9
|
+
supportedReasoningEfforts?: string[] | undefined;
|
|
8
10
|
}
|
|
9
11
|
export interface EngineTurnRequest {
|
|
10
12
|
scopeId: string;
|
|
11
13
|
prompt: string;
|
|
12
|
-
stagedAttachments?:
|
|
14
|
+
stagedAttachments?: StagedAttachment[] | undefined;
|
|
13
15
|
threadId: string | null;
|
|
14
16
|
cwd: string;
|
|
15
17
|
model: string;
|
|
16
18
|
effort?: string | null | undefined;
|
|
17
19
|
serviceTier?: string | null | undefined;
|
|
18
20
|
locale: AppLocale;
|
|
21
|
+
accessPreset?: AccessPresetValue | undefined;
|
|
19
22
|
}
|
|
20
23
|
export interface EngineToolEvent {
|
|
21
24
|
name: string;
|
|
@@ -40,7 +43,8 @@ export interface EngineTurnResult {
|
|
|
40
43
|
}
|
|
41
44
|
export interface EngineTurnExecution {
|
|
42
45
|
turnId?: string | undefined;
|
|
43
|
-
|
|
46
|
+
/** A returned promise resolves after the native backend has released the turn. */
|
|
47
|
+
cancel(): void | Promise<void>;
|
|
44
48
|
waitForResult(): Promise<EngineTurnResult | null>;
|
|
45
49
|
on(event: 'delta', listener: (text: string) => void): void;
|
|
46
50
|
on(event: 'tool', listener: (tool: EngineToolEvent) => void): void;
|
|
@@ -60,7 +64,7 @@ export interface EngineTurnErrorContext {
|
|
|
60
64
|
export interface IEngineAdapter {
|
|
61
65
|
readonly id: string;
|
|
62
66
|
readonly name: string;
|
|
63
|
-
listModels(): Promise<EngineModel[]>;
|
|
67
|
+
listModels(scopeId?: string): Promise<EngineModel[]>;
|
|
64
68
|
executeTurn(request: EngineTurnRequest): EngineTurnExecution;
|
|
65
69
|
preflightTurn?(request: EngineTurnRequest): Promise<void>;
|
|
66
70
|
handleTurnError?(context: EngineTurnErrorContext): Promise<boolean>;
|
|
@@ -74,4 +78,15 @@ export interface BackendDescriptor {
|
|
|
74
78
|
details?: string | undefined;
|
|
75
79
|
isDefault?: boolean | undefined;
|
|
76
80
|
onSelect?: (scopeId: string) => Promise<void>;
|
|
81
|
+
defaults?: {
|
|
82
|
+
reasoningEffort: string | null;
|
|
83
|
+
supportedReasoningEfforts: readonly string[];
|
|
84
|
+
boost: boolean;
|
|
85
|
+
tokenUsage: boolean;
|
|
86
|
+
};
|
|
87
|
+
commands?: (locale: AppLocale) => Array<{
|
|
88
|
+
command: string;
|
|
89
|
+
description: string;
|
|
90
|
+
}>;
|
|
91
|
+
createUi?: (host: BackendUiHost) => BackendUi;
|
|
77
92
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface EventSource {
|
|
2
|
+
on(event: string, listener: (...args: any[]) => void): unknown;
|
|
3
|
+
off?(event: string, listener: (...args: any[]) => void): unknown;
|
|
4
|
+
}
|
|
5
|
+
/** Ownership of subscriptions is separate from ownership of the shared transport. */
|
|
6
|
+
export declare class ListenerScope {
|
|
7
|
+
private readonly cleanup;
|
|
8
|
+
listen(source: EventSource, event: string, listener: (...args: any[]) => void): void;
|
|
9
|
+
clear(): void;
|
|
10
|
+
}
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Ownership of subscriptions is separate from ownership of the shared transport. */
|
|
2
|
+
export class ListenerScope {
|
|
3
|
+
cleanup = [];
|
|
4
|
+
listen(source, event, listener) {
|
|
5
|
+
source.on(event, listener);
|
|
6
|
+
this.cleanup.push(() => source.off?.(event, listener));
|
|
7
|
+
}
|
|
8
|
+
clear() { for (const stop of this.cleanup.splice(0).reverse())
|
|
9
|
+
stop(); }
|
|
10
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function chunkMessage(text, limit = 4000, fallbackText = 'Completed.') {
|
|
2
|
+
const source = text.trim() ? text : fallbackText;
|
|
3
|
+
if (!source) {
|
|
4
|
+
return [];
|
|
5
|
+
}
|
|
6
|
+
if (source.length <= limit) {
|
|
7
|
+
return [source];
|
|
8
|
+
}
|
|
9
|
+
const chunks = [];
|
|
10
|
+
let start = 0;
|
|
11
|
+
while (start < source.length) {
|
|
12
|
+
const remaining = source.length - start;
|
|
13
|
+
if (remaining <= limit) {
|
|
14
|
+
chunks.push(source.slice(start));
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
const tentativeEnd = start + limit;
|
|
18
|
+
const window = source.slice(start, tentativeEnd);
|
|
19
|
+
const splitAt = Math.max(window.lastIndexOf('\n\n'), window.lastIndexOf('\n'));
|
|
20
|
+
const end = splitAt >= Math.floor(limit / 2)
|
|
21
|
+
? start + splitAt + 1
|
|
22
|
+
: tentativeEnd;
|
|
23
|
+
chunks.push(source.slice(start, end));
|
|
24
|
+
start = end;
|
|
25
|
+
}
|
|
26
|
+
return chunks.filter(chunk => chunk.length > 0);
|
|
27
|
+
}
|
|
28
|
+
export function escapeHtml(text) { return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isTransientNetworkError(err: unknown): boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function isTransientNetworkError(err) {
|
|
2
|
+
if (!err)
|
|
3
|
+
return false;
|
|
4
|
+
const msg = String(err.message || err).toLowerCase();
|
|
5
|
+
return (msg.includes('client network socket disconnected') ||
|
|
6
|
+
msg.includes('econnreset') ||
|
|
7
|
+
msg.includes('etimedout') ||
|
|
8
|
+
msg.includes('eai_again') ||
|
|
9
|
+
msg.includes('enotfound') ||
|
|
10
|
+
msg.includes('econnrefused') ||
|
|
11
|
+
msg.includes('socket hang up') ||
|
|
12
|
+
msg.includes('timed out') ||
|
|
13
|
+
msg.includes('timeout') ||
|
|
14
|
+
msg.includes('network socket disconnected') ||
|
|
15
|
+
msg.includes('network error') ||
|
|
16
|
+
msg.includes('fetch failed') ||
|
|
17
|
+
msg.includes('und_err_') ||
|
|
18
|
+
msg.includes('read tcp') ||
|
|
19
|
+
msg.includes('connection timed out') ||
|
|
20
|
+
msg.includes('broken pipe') ||
|
|
21
|
+
msg.includes('ehostunreach') ||
|
|
22
|
+
msg.includes('enetunreach'));
|
|
23
|
+
}
|
|
@@ -2,9 +2,10 @@ import type { AppConfig } from '../config.js';
|
|
|
2
2
|
import type { BridgeStore } from '../store/database.js';
|
|
3
3
|
import type { Logger } from '../logger.js';
|
|
4
4
|
import type { AppLocale } from '../types.js';
|
|
5
|
-
import type {
|
|
6
|
-
import type {
|
|
7
|
-
import {
|
|
5
|
+
import type { ChannelGateway, ChannelPort, ChannelInlineKeyboard } from './channel_port.js';
|
|
6
|
+
import type { ChannelTextEvent, ChannelCallbackEvent } from './channel_events.js';
|
|
7
|
+
import type { EngineCustomUiHook } from './backend_ui.js';
|
|
8
|
+
export type { EngineCustomUiHook } from './backend_ui.js';
|
|
8
9
|
import type { IEngineAdapter, EngineTurnExecution, BackendDescriptor } from './engine_spi.js';
|
|
9
10
|
export declare const STREAM_THROTTLE_MS = 700;
|
|
10
11
|
export declare const TYPING_INTERVAL_MS = 4000;
|
|
@@ -21,41 +22,47 @@ export interface UnifiedActiveTurn {
|
|
|
21
22
|
stepIndex?: number;
|
|
22
23
|
toolCount: number;
|
|
23
24
|
currentTool?: string | null;
|
|
25
|
+
suppressQueueDrain?: boolean;
|
|
24
26
|
startTime: number;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
handleCustomCallback?(scopeId: string, data: string, locale: AppLocale, messageId?: number, event?: TelegramCallbackEvent): Promise<boolean>;
|
|
30
|
-
handleCustomCommand?(scopeId: string, command: string, args: string, locale: AppLocale, event?: TelegramTextEvent): Promise<boolean>;
|
|
31
|
-
handleCustomInbound?(event: TelegramTextEvent, locale: AppLocale): Promise<boolean>;
|
|
27
|
+
previewKey: string;
|
|
28
|
+
queueId?: string | undefined;
|
|
29
|
+
taskId: string;
|
|
30
|
+
settling?: boolean;
|
|
32
31
|
}
|
|
33
32
|
export declare class UnifiedChannelOrchestrator {
|
|
34
33
|
readonly config: AppConfig;
|
|
35
34
|
readonly store: BridgeStore;
|
|
36
35
|
readonly logger: Logger;
|
|
37
|
-
readonly bot:
|
|
38
|
-
readonly messaging:
|
|
39
|
-
readonly queueManager: TurnQueueManager;
|
|
36
|
+
readonly bot: ChannelGateway;
|
|
37
|
+
readonly messaging: ChannelPort;
|
|
40
38
|
readonly customUi?: EngineCustomUiHook | undefined;
|
|
41
39
|
private readonly backends;
|
|
40
|
+
private readonly scopeOperations;
|
|
41
|
+
private readonly messageOperations;
|
|
42
|
+
private readonly settlements;
|
|
43
|
+
private stopped;
|
|
44
|
+
private readonly serviceUi?;
|
|
42
45
|
private readonly defaultBackendId;
|
|
43
46
|
private readonly activeTurns;
|
|
44
47
|
private readonly stalePanelDeleteTimers;
|
|
48
|
+
private readonly recoveryTimers;
|
|
49
|
+
private readonly ownsScope;
|
|
45
50
|
private readonly backendProvider?;
|
|
46
51
|
get adapter(): IEngineAdapter;
|
|
47
52
|
constructor(options: {
|
|
48
53
|
config: AppConfig;
|
|
49
54
|
store: BridgeStore;
|
|
50
55
|
logger: Logger;
|
|
51
|
-
bot:
|
|
56
|
+
bot: ChannelGateway;
|
|
52
57
|
adapter?: IEngineAdapter;
|
|
53
58
|
adapters?: Map<string, IEngineAdapter> | IEngineAdapter[];
|
|
54
59
|
backends?: BackendDescriptor[];
|
|
55
60
|
backendProvider?: (() => Promise<BackendDescriptor[]> | BackendDescriptor[]) | undefined;
|
|
56
61
|
defaultBackendId?: string;
|
|
57
|
-
|
|
62
|
+
ownsScope?: (scopeId: string) => boolean;
|
|
63
|
+
messaging: ChannelPort;
|
|
58
64
|
customUi?: EngineCustomUiHook | undefined;
|
|
65
|
+
serviceUi?: EngineCustomUiHook | undefined;
|
|
59
66
|
});
|
|
60
67
|
getAdapterForScope(scopeId: string): IEngineAdapter;
|
|
61
68
|
getBackendDescriptorForScope(scopeId: string): BackendDescriptor;
|
|
@@ -71,32 +78,60 @@ export declare class UnifiedChannelOrchestrator {
|
|
|
71
78
|
restoredThreadId: string | null;
|
|
72
79
|
cwd: string | null;
|
|
73
80
|
}>;
|
|
81
|
+
private switchBackendNow;
|
|
82
|
+
private removeInboundConsumer;
|
|
83
|
+
private readonly intakeOperations;
|
|
84
|
+
private receiveInbound;
|
|
85
|
+
private readonly inboundListeners;
|
|
74
86
|
registerInboundHandlers(): void;
|
|
75
|
-
dispatchInboundLikeTelegramText(event:
|
|
87
|
+
dispatchInboundLikeTelegramText(event: ChannelTextEvent): void;
|
|
76
88
|
start(): Promise<void>;
|
|
89
|
+
private recoveryEvent;
|
|
90
|
+
private showRecovery;
|
|
91
|
+
private restoreDurableTasks;
|
|
92
|
+
private resolveDeliveredTask;
|
|
93
|
+
private handleRecovery;
|
|
94
|
+
stopTask(scopeId: string, taskId: string): Promise<boolean>;
|
|
95
|
+
private cancelActiveTurn;
|
|
77
96
|
stop(): Promise<void>;
|
|
97
|
+
isIdleForServiceUpdate(): boolean;
|
|
98
|
+
getPendingApprovals(): number;
|
|
78
99
|
getActiveTurnsCount(): number;
|
|
100
|
+
ownsScopeId(scopeId: string): boolean;
|
|
101
|
+
hasExecutingTasks(): boolean;
|
|
79
102
|
hasActiveTurn(scopeId: string): boolean;
|
|
80
|
-
sendMessage(scopeId: string, text: string, keyboard?:
|
|
81
|
-
editMessage(scopeId: string, messageId: number, text: string, keyboard?:
|
|
103
|
+
sendMessage(scopeId: string, text: string, keyboard?: ChannelInlineKeyboard): Promise<number>;
|
|
104
|
+
editMessage(scopeId: string, messageId: number, text: string, keyboard?: ChannelInlineKeyboard): Promise<void>;
|
|
105
|
+
private trackSettlement;
|
|
106
|
+
private deliverTaskChunks;
|
|
82
107
|
private safeDeliverChunks;
|
|
83
108
|
private safeDeliverMessage;
|
|
84
|
-
handleText(event:
|
|
85
|
-
handleCallback(event:
|
|
86
|
-
|
|
109
|
+
handleText(event: ChannelTextEvent): Promise<void>;
|
|
110
|
+
handleCallback(event: ChannelCallbackEvent): Promise<void>;
|
|
111
|
+
private captureTask;
|
|
112
|
+
private recoveryBlocksScope;
|
|
113
|
+
startPromptTurn(event: ChannelTextEvent, prompt: string, locale: AppLocale, options?: {
|
|
87
114
|
reuseMessageId?: number | undefined;
|
|
88
115
|
forcedThreadId?: string | undefined;
|
|
116
|
+
taskId?: string | undefined;
|
|
89
117
|
}): Promise<void>;
|
|
118
|
+
private startPromptTurnNow;
|
|
119
|
+
private cancelQueuedWork;
|
|
90
120
|
private enqueuePromptTurn;
|
|
91
121
|
private drainNextQueuedTurn;
|
|
92
122
|
private executeTurn;
|
|
123
|
+
private supportedEfforts;
|
|
93
124
|
private handleEffortCommand;
|
|
94
125
|
private handleBoostCommand;
|
|
95
126
|
private handleActiveCommand;
|
|
96
127
|
private handleQueueCommand;
|
|
128
|
+
private handleQueueCommandNow;
|
|
97
129
|
private handleSteerCommand;
|
|
130
|
+
private handleSteerCommandNow;
|
|
98
131
|
handleInterrupt(scopeId: string, locale: AppLocale): Promise<void>;
|
|
99
|
-
|
|
132
|
+
private handleInterruptNow;
|
|
133
|
+
handleNewSession(scopeId: string, locale: AppLocale, cwdArg?: string): Promise<void>;
|
|
134
|
+
private handleNewSessionNow;
|
|
100
135
|
sendStatus(scopeId: string, locale: AppLocale): Promise<void>;
|
|
101
136
|
sendSetupMenu(scopeId: string, locale: AppLocale, editMessageId?: number): Promise<void>;
|
|
102
137
|
sendModelsMenu(scopeId: string, locale: AppLocale, editMessageId?: number): Promise<void>;
|