@adhdev/daemon-core 0.5.3
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/index.d.ts +2662 -0
- package/dist/index.js +11341 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
- package/providers/_builtin/.github/workflows/generate-registry.yml +57 -0
- package/providers/_builtin/COMPATIBILITY.md +217 -0
- package/providers/_builtin/CONTRIBUTING.md +200 -0
- package/providers/_builtin/README.md +119 -0
- package/providers/_builtin/_helpers/index.js +188 -0
- package/providers/_builtin/acp/agentpool/provider.json +54 -0
- package/providers/_builtin/acp/amp/provider.json +52 -0
- package/providers/_builtin/acp/auggie/provider.json +57 -0
- package/providers/_builtin/acp/autodev/provider.json +54 -0
- package/providers/_builtin/acp/autohand/provider.json +52 -0
- package/providers/_builtin/acp/blackbox-ai/provider.json +54 -0
- package/providers/_builtin/acp/claude-agent/provider.json +57 -0
- package/providers/_builtin/acp/cline-acp/provider.json +54 -0
- package/providers/_builtin/acp/codebuddy/provider.json +54 -0
- package/providers/_builtin/acp/codex-cli/provider.json +57 -0
- package/providers/_builtin/acp/corust-agent/provider.json +52 -0
- package/providers/_builtin/acp/crow-cli/provider.json +54 -0
- package/providers/_builtin/acp/cursor-acp/provider.json +54 -0
- package/providers/_builtin/acp/deepagents/provider.json +52 -0
- package/providers/_builtin/acp/dimcode/provider.json +54 -0
- package/providers/_builtin/acp/docker-cagent/provider.json +57 -0
- package/providers/_builtin/acp/factory-droid/provider.json +60 -0
- package/providers/_builtin/acp/fast-agent/provider.json +52 -0
- package/providers/_builtin/acp/gemini-cli/provider.json +114 -0
- package/providers/_builtin/acp/github-copilot/provider.json +54 -0
- package/providers/_builtin/acp/goose/provider.json +57 -0
- package/providers/_builtin/acp/junie/provider.json +52 -0
- package/providers/_builtin/acp/kilo/provider.json +54 -0
- package/providers/_builtin/acp/kimi-cli/provider.json +57 -0
- package/providers/_builtin/acp/minion-code/provider.json +52 -0
- package/providers/_builtin/acp/mistral-vibe/provider.json +57 -0
- package/providers/_builtin/acp/nova/provider.json +54 -0
- package/providers/_builtin/acp/openclaw/provider.json +54 -0
- package/providers/_builtin/acp/opencode/provider.json +52 -0
- package/providers/_builtin/acp/openhands/provider.json +54 -0
- package/providers/_builtin/acp/pi-acp/provider.json +52 -0
- package/providers/_builtin/acp/qoder/provider.json +54 -0
- package/providers/_builtin/acp/qwen-code/provider.json +60 -0
- package/providers/_builtin/acp/stakpak/provider.json +54 -0
- package/providers/_builtin/acp/vtcode/provider.json +54 -0
- package/providers/_builtin/cli/claude-cli/provider.json +100 -0
- package/providers/_builtin/cli/codex-cli/provider.json +89 -0
- package/providers/_builtin/cli/gemini-cli/provider.json +93 -0
- package/providers/_builtin/docs/CDP_SELECTOR_GUIDE.md +370 -0
- package/providers/_builtin/docs/PROVIDER_GUIDE.md +916 -0
- package/providers/_builtin/extension/cline/provider.json +35 -0
- package/providers/_builtin/extension/cline/scripts/focus_editor.js +48 -0
- package/providers/_builtin/extension/cline/scripts/list_chats.js +100 -0
- package/providers/_builtin/extension/cline/scripts/list_models.js +43 -0
- package/providers/_builtin/extension/cline/scripts/list_modes.js +35 -0
- package/providers/_builtin/extension/cline/scripts/new_session.js +85 -0
- package/providers/_builtin/extension/cline/scripts/open_panel.js +25 -0
- package/providers/_builtin/extension/cline/scripts/read_chat.js +257 -0
- package/providers/_builtin/extension/cline/scripts/resolve_action.js +83 -0
- package/providers/_builtin/extension/cline/scripts/send_message.js +95 -0
- package/providers/_builtin/extension/cline/scripts/set_mode.js +36 -0
- package/providers/_builtin/extension/cline/scripts/set_model.js +36 -0
- package/providers/_builtin/extension/cline/scripts/switch_session.js +206 -0
- package/providers/_builtin/extension/cline/scripts.js +73 -0
- package/providers/_builtin/extension/roo-code/provider.json +35 -0
- package/providers/_builtin/extension/roo-code/scripts.js +659 -0
- package/providers/_builtin/ide/antigravity/provider.json +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_models.js +38 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/list_modes.js +48 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/scripts.js +57 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_mode.js +34 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/set_model.js +47 -0
- package/providers/_builtin/ide/antigravity/scripts/1.106/switch_session.js +114 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/focus_editor.js +20 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_chats.js +137 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_models.js +61 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/list_modes.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/new_session.js +75 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/read_chat.js +262 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/resolve_action.js +68 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/scripts.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/send_message.js +56 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_mode.js +67 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/set_model.js +72 -0
- package/providers/_builtin/ide/antigravity/scripts/1.107/switch_session.js +114 -0
- package/providers/_builtin/ide/cursor/provider.json +70 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/dismiss_notification.js +30 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/focus_editor.js +13 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_models.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_modes.js +40 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_notifications.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/list_sessions.js +42 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/new_session.js +20 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/open_panel.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/read_chat.js +75 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/resolve_action.js +19 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/scripts.js +78 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/send_message.js +23 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_mode.js +38 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/set_model.js +81 -0
- package/providers/_builtin/ide/cursor/scripts/0.49/switch_session.js +28 -0
- package/providers/_builtin/ide/kiro/provider.json +67 -0
- package/providers/_builtin/ide/kiro/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/kiro/scripts/open_panel.js +47 -0
- package/providers/_builtin/ide/kiro/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/kiro/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_models.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_modes.js +39 -0
- package/providers/_builtin/ide/kiro/scripts/webview_list_sessions.js +21 -0
- package/providers/_builtin/ide/kiro/scripts/webview_new_session.js +34 -0
- package/providers/_builtin/ide/kiro/scripts/webview_read_chat.js +68 -0
- package/providers/_builtin/ide/kiro/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_mode.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_set_model.js +15 -0
- package/providers/_builtin/ide/kiro/scripts/webview_switch_session.js +26 -0
- package/providers/_builtin/ide/kiro/scripts.js +62 -0
- package/providers/_builtin/ide/pearai/provider.json +67 -0
- package/providers/_builtin/ide/pearai/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/pearai/scripts/list_sessions.js +38 -0
- package/providers/_builtin/ide/pearai/scripts/new_session.js +55 -0
- package/providers/_builtin/ide/pearai/scripts/open_panel.js +46 -0
- package/providers/_builtin/ide/pearai/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/pearai/scripts/send_message.js +29 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_models.js +43 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_modes.js +35 -0
- package/providers/_builtin/ide/pearai/scripts/webview_list_sessions.js +62 -0
- package/providers/_builtin/ide/pearai/scripts/webview_new_session.js +49 -0
- package/providers/_builtin/ide/pearai/scripts/webview_read_chat.js +92 -0
- package/providers/_builtin/ide/pearai/scripts/webview_resolve_action.js +59 -0
- package/providers/_builtin/ide/pearai/scripts/webview_send_message.js +72 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_mode.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_set_model.js +36 -0
- package/providers/_builtin/ide/pearai/scripts/webview_switch_session.js +34 -0
- package/providers/_builtin/ide/pearai/scripts.js +74 -0
- package/providers/_builtin/ide/trae/provider.json +66 -0
- package/providers/_builtin/ide/trae/scripts/focus_editor.js +20 -0
- package/providers/_builtin/ide/trae/scripts/list_chats.js +24 -0
- package/providers/_builtin/ide/trae/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/trae/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/trae/scripts/new_session.js +30 -0
- package/providers/_builtin/ide/trae/scripts/open_panel.js +44 -0
- package/providers/_builtin/ide/trae/scripts/read_chat.js +113 -0
- package/providers/_builtin/ide/trae/scripts/resolve_action.js +54 -0
- package/providers/_builtin/ide/trae/scripts/send_message.js +69 -0
- package/providers/_builtin/ide/trae/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/trae/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/trae/scripts/switch_session.js +23 -0
- package/providers/_builtin/ide/trae/scripts.js +57 -0
- package/providers/_builtin/ide/vscode/provider.json +64 -0
- package/providers/_builtin/ide/vscode-insiders/provider.json +62 -0
- package/providers/_builtin/ide/vscodium/provider.json +63 -0
- package/providers/_builtin/ide/windsurf/provider.json +53 -0
- package/providers/_builtin/ide/windsurf/scripts/focus_editor.js +30 -0
- package/providers/_builtin/ide/windsurf/scripts/list_chats.js +117 -0
- package/providers/_builtin/ide/windsurf/scripts/list_models.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/list_modes.js +39 -0
- package/providers/_builtin/ide/windsurf/scripts/new_session.js +69 -0
- package/providers/_builtin/ide/windsurf/scripts/open_panel.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts/read_chat.js +297 -0
- package/providers/_builtin/ide/windsurf/scripts/resolve_action.js +68 -0
- package/providers/_builtin/ide/windsurf/scripts/send_message.js +87 -0
- package/providers/_builtin/ide/windsurf/scripts/set_mode.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/set_model.js +15 -0
- package/providers/_builtin/ide/windsurf/scripts/switch_session.js +58 -0
- package/providers/_builtin/ide/windsurf/scripts.js +57 -0
- package/providers/_builtin/registry.json +266 -0
- package/providers/_builtin/validate.js +156 -0
- package/src/agent-stream/index.ts +6 -0
- package/src/agent-stream/manager.ts +286 -0
- package/src/agent-stream/poller.ts +154 -0
- package/src/agent-stream/provider-adapter.ts +138 -0
- package/src/agent-stream/types.ts +61 -0
- package/src/boot/daemon-lifecycle.ts +252 -0
- package/src/cdp/devtools.ts +335 -0
- package/src/cdp/initializer.ts +191 -0
- package/src/cdp/manager.ts +897 -0
- package/src/cdp/scanner.ts +185 -0
- package/src/cdp/setup.ts +150 -0
- package/src/cli-adapter-types.ts +25 -0
- package/src/cli-adapters/provider-cli-adapter.ts +448 -0
- package/src/commands/cdp-commands.ts +208 -0
- package/src/commands/chat-commands.ts +675 -0
- package/src/commands/cli-manager.ts +353 -0
- package/src/commands/handler.ts +328 -0
- package/src/commands/router.ts +258 -0
- package/src/commands/stream-commands.ts +325 -0
- package/src/config/chat-history.ts +211 -0
- package/src/config/config.ts +219 -0
- package/src/daemon/dev-server.ts +2378 -0
- package/src/daemon/scaffold-template.ts +394 -0
- package/src/daemon-core.ts +50 -0
- package/src/detection/cli-detector.ts +89 -0
- package/src/detection/ide-detector.ts +157 -0
- package/src/index.ts +103 -0
- package/src/installer.ts +263 -0
- package/src/ipc-protocol.ts +133 -0
- package/src/launch.ts +433 -0
- package/src/logging/command-log.ts +180 -0
- package/src/logging/logger.ts +316 -0
- package/src/providers/acp-provider-instance.ts +1140 -0
- package/src/providers/cli-provider-instance.ts +207 -0
- package/src/providers/contracts.ts +524 -0
- package/src/providers/extension-provider-instance.ts +156 -0
- package/src/providers/ide-provider-instance.ts +377 -0
- package/src/providers/index.ts +18 -0
- package/src/providers/provider-instance-manager.ts +182 -0
- package/src/providers/provider-instance.ts +112 -0
- package/src/providers/provider-loader.ts +1031 -0
- package/src/providers/status-monitor.ts +125 -0
- package/src/providers/version-archive.ts +266 -0
- package/src/status/reporter.ts +294 -0
- package/src/types.ts +206 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Output Contracts — Output contracts all providers must conform to
|
|
3
|
+
*
|
|
4
|
+
* Design principles:
|
|
5
|
+
* - Only output format is standardized; implementation is free
|
|
6
|
+
* - Common across all categories (cli, ide, extension)
|
|
7
|
+
* - User custom providers use the same contracts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ─── readChat() return value ───────────────────────────
|
|
11
|
+
|
|
12
|
+
export interface ReadChatResult {
|
|
13
|
+
messages: ChatMessage[];
|
|
14
|
+
status: AgentStatus;
|
|
15
|
+
activeModal?: ModalInfo | null;
|
|
16
|
+
/** IDE/Extension only: session info */
|
|
17
|
+
id?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
/** Extension only: additional metadata */
|
|
20
|
+
agentType?: string;
|
|
21
|
+
agentName?: string;
|
|
22
|
+
extensionId?: string;
|
|
23
|
+
/** Status metadata */
|
|
24
|
+
isVisible?: boolean;
|
|
25
|
+
isWelcomeScreen?: boolean;
|
|
26
|
+
inputContent?: string;
|
|
27
|
+
model?: string;
|
|
28
|
+
mode?: string;
|
|
29
|
+
autoApprove?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ChatMessage {
|
|
33
|
+
role: 'user' | 'assistant' | 'system';
|
|
34
|
+
/** Plain text (legacy) or rich content blocks (ACP standard) */
|
|
35
|
+
content: string | ContentBlock[];
|
|
36
|
+
/** Optional: unique message ID */
|
|
37
|
+
id?: string;
|
|
38
|
+
/** Optional: order index */
|
|
39
|
+
index?: number;
|
|
40
|
+
/** Optional: timestamp */
|
|
41
|
+
timestamp?: number;
|
|
42
|
+
/** Optional: receivedAt (assigned by daemon) */
|
|
43
|
+
receivedAt?: number;
|
|
44
|
+
/** Optional: tool calls associated with this message */
|
|
45
|
+
toolCalls?: ToolCallInfo[];
|
|
46
|
+
/** Optional: fiber metadata */
|
|
47
|
+
_type?: string;
|
|
48
|
+
_sub?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type AgentStatus =
|
|
52
|
+
| 'idle'
|
|
53
|
+
| 'generating'
|
|
54
|
+
| 'waiting_approval'
|
|
55
|
+
| 'error'
|
|
56
|
+
| 'panel_hidden'
|
|
57
|
+
| 'streaming';
|
|
58
|
+
|
|
59
|
+
export interface ModalInfo {
|
|
60
|
+
message: string;
|
|
61
|
+
buttons: string[];
|
|
62
|
+
width?: number;
|
|
63
|
+
height?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ─── Rich Content Types (ACP Standard) ─────────────────
|
|
67
|
+
// Based on ACP SDK v0.16.1 schema types.
|
|
68
|
+
// All provider categories (ACP, IDE, Extension, CLI) use these as output standard.
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* ContentBlock — ACP ContentBlock union type
|
|
72
|
+
* Represents displayable content in messages, tool call results, etc.
|
|
73
|
+
*/
|
|
74
|
+
export type ContentBlock =
|
|
75
|
+
| TextBlock
|
|
76
|
+
| ImageBlock
|
|
77
|
+
| AudioBlock
|
|
78
|
+
| ResourceLinkBlock
|
|
79
|
+
| ResourceBlock;
|
|
80
|
+
|
|
81
|
+
/** Text content — ACP TextContent */
|
|
82
|
+
export interface TextBlock {
|
|
83
|
+
type: 'text';
|
|
84
|
+
text: string;
|
|
85
|
+
annotations?: ContentAnnotations;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Image content — ACP ImageContent */
|
|
89
|
+
export interface ImageBlock {
|
|
90
|
+
type: 'image';
|
|
91
|
+
data: string; // base64-encoded
|
|
92
|
+
mimeType: string; // 'image/png', 'image/jpeg', etc.
|
|
93
|
+
uri?: string; // optional URL reference
|
|
94
|
+
annotations?: ContentAnnotations;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Audio content — ACP AudioContent */
|
|
98
|
+
export interface AudioBlock {
|
|
99
|
+
type: 'audio';
|
|
100
|
+
data: string; // base64-encoded
|
|
101
|
+
mimeType: string;
|
|
102
|
+
annotations?: ContentAnnotations;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Resource link (file reference) — ACP ResourceLink */
|
|
106
|
+
export interface ResourceLinkBlock {
|
|
107
|
+
type: 'resource_link';
|
|
108
|
+
uri: string;
|
|
109
|
+
name: string;
|
|
110
|
+
title?: string;
|
|
111
|
+
description?: string;
|
|
112
|
+
mimeType?: string;
|
|
113
|
+
size?: number;
|
|
114
|
+
annotations?: ContentAnnotations;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Embedded resource (inline file) — ACP EmbeddedResource */
|
|
118
|
+
export interface ResourceBlock {
|
|
119
|
+
type: 'resource';
|
|
120
|
+
resource: TextResourceContents | BlobResourceContents;
|
|
121
|
+
annotations?: ContentAnnotations;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface TextResourceContents {
|
|
125
|
+
uri: string;
|
|
126
|
+
text: string;
|
|
127
|
+
mimeType?: string;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface BlobResourceContents {
|
|
131
|
+
uri: string;
|
|
132
|
+
blob: string; // base64-encoded
|
|
133
|
+
mimeType?: string;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export interface ContentAnnotations {
|
|
137
|
+
audience?: ('user' | 'assistant')[];
|
|
138
|
+
priority?: number; // 0.0 ~ 1.0
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ─── Tool Call Types (ACP Standard) ─────────────────────
|
|
142
|
+
|
|
143
|
+
/** Tool call info — ACP ToolCall */
|
|
144
|
+
export interface ToolCallInfo {
|
|
145
|
+
toolCallId: string;
|
|
146
|
+
title: string;
|
|
147
|
+
kind?: ToolKind;
|
|
148
|
+
status?: ToolCallStatus;
|
|
149
|
+
rawInput?: unknown;
|
|
150
|
+
rawOutput?: unknown;
|
|
151
|
+
content?: ToolCallContent[];
|
|
152
|
+
locations?: ToolCallLocation[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export type ToolKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'switch_mode' | 'other';
|
|
156
|
+
export type ToolCallStatus = 'pending' | 'in_progress' | 'completed' | 'failed';
|
|
157
|
+
|
|
158
|
+
/** Content produced by a tool call — ACP ToolCallContent */
|
|
159
|
+
export type ToolCallContent =
|
|
160
|
+
| { type: 'content'; content: ContentBlock }
|
|
161
|
+
| { type: 'diff'; path: string; oldText?: string; newText: string }
|
|
162
|
+
| { type: 'terminal'; terminalId: string };
|
|
163
|
+
|
|
164
|
+
export interface ToolCallLocation {
|
|
165
|
+
path: string;
|
|
166
|
+
line?: number;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ─── Content Helpers ────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
/** Normalize content: string → ContentBlock[] */
|
|
172
|
+
export function normalizeContent(content: string | ContentBlock[]): ContentBlock[] {
|
|
173
|
+
if (typeof content === 'string') {
|
|
174
|
+
return [{ type: 'text', text: content }];
|
|
175
|
+
}
|
|
176
|
+
return content;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Flatten ContentBlock[] → string (backward compat / plain-text extraction) */
|
|
180
|
+
export function flattenContent(content: string | ContentBlock[]): string {
|
|
181
|
+
if (typeof content === 'string') return content;
|
|
182
|
+
return content
|
|
183
|
+
.filter((b): b is TextBlock => b.type === 'text')
|
|
184
|
+
.map(b => b.text)
|
|
185
|
+
.join('\n');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/** SendMessage params — supports rich content (ACP PromptRequest compatible) */
|
|
189
|
+
export interface SendMessageParams {
|
|
190
|
+
/** Shortcut: text-only message */
|
|
191
|
+
text?: string;
|
|
192
|
+
/** Rich content blocks (ACP ContentBlock[]) */
|
|
193
|
+
prompt?: ContentBlock[];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ─── sendMessage() return value ────────────────────────
|
|
197
|
+
|
|
198
|
+
export interface SendMessageResult {
|
|
199
|
+
sent: boolean;
|
|
200
|
+
error?: string;
|
|
201
|
+
/** When CDP Input API is needed (Lexical editor etc) */
|
|
202
|
+
needsTypeAndSend?: boolean;
|
|
203
|
+
selector?: string;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ─── listSessions() return value ───────────────────────
|
|
207
|
+
|
|
208
|
+
export interface ListSessionsResult {
|
|
209
|
+
sessions: SessionInfo[];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export interface SessionInfo {
|
|
213
|
+
id: string;
|
|
214
|
+
title: string;
|
|
215
|
+
time?: string;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// ─── switchSession() return value ──────────────────────
|
|
219
|
+
|
|
220
|
+
export interface SwitchSessionResult {
|
|
221
|
+
switched: boolean;
|
|
222
|
+
/** When CDP click coordinates are needed (Antigravity QuickInput etc) */
|
|
223
|
+
action?: 'click';
|
|
224
|
+
clickX?: number;
|
|
225
|
+
clickY?: number;
|
|
226
|
+
error?: string;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ─── resolveAction() return value ──────────────────────
|
|
230
|
+
// Two methods supported:
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Method 1: Script-Click — script calls el.click() directly
|
|
234
|
+
* Cursor Suitable for IDEs using div.cursor-pointer elements.
|
|
235
|
+
*/
|
|
236
|
+
export interface ResolveActionScriptClick {
|
|
237
|
+
resolved: boolean; // true = click succeeded
|
|
238
|
+
clicked?: string; // clicked button text
|
|
239
|
+
available?: string[]; // available buttons when resolved=false
|
|
240
|
+
error?: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Method 2: Coordinate-Click — returns coordinates, daemon performs CDP mouse click
|
|
245
|
+
* Antigravity Suitable for IDEs where el.click() does not work.
|
|
246
|
+
*/
|
|
247
|
+
export interface ResolveActionCoordinateClick {
|
|
248
|
+
found: boolean; // true = button found
|
|
249
|
+
text?: string; // button text
|
|
250
|
+
x?: number; // click X coordinate
|
|
251
|
+
y?: number; // click Y coordinate
|
|
252
|
+
w?: number; // button width
|
|
253
|
+
h?: number; // button height
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export type ResolveActionResult = ResolveActionScriptClick | ResolveActionCoordinateClick;
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
// ─── Provider Module type ────────────────────────
|
|
260
|
+
|
|
261
|
+
export type ProviderCategory = 'cli' | 'ide' | 'extension' | 'acp';
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Type of object exported by module.exports in provider.js.
|
|
265
|
+
*
|
|
266
|
+
* Each provider.js is fully independent and does not import other providers.
|
|
267
|
+
* Helpers (_helpers/) can be optionally used.
|
|
268
|
+
*/
|
|
269
|
+
/**
|
|
270
|
+
* Provider-configurable CDP target filter.
|
|
271
|
+
* Used by DaemonCdpManager to select the correct page/tab to connect to.
|
|
272
|
+
* Without this, the manager uses a hardcoded default filter.
|
|
273
|
+
*/
|
|
274
|
+
export interface CdpTargetFilter {
|
|
275
|
+
/** URL must include this string (e.g. 'workbench.html') */
|
|
276
|
+
urlIncludes?: string;
|
|
277
|
+
/** URL must NOT include any of these strings */
|
|
278
|
+
urlExcludes?: string[];
|
|
279
|
+
/** Page title regex pattern for titles to EXCLUDE (e.g. 'Debug Console|Output') */
|
|
280
|
+
titleExcludes?: string;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export interface ProviderModule {
|
|
284
|
+
/** Unique identifier (e.g. 'cline', 'cursor', 'gemini-cli') */
|
|
285
|
+
type: string;
|
|
286
|
+
/** Display name (e.g. 'Cline', 'Cursor') */
|
|
287
|
+
name: string;
|
|
288
|
+
/** Category: determines execution method */
|
|
289
|
+
category: ProviderCategory;
|
|
290
|
+
/** Alias list — allows users to invoke by alternate names (e.g. ['claude', 'claude-code']) */
|
|
291
|
+
aliases?: string[];
|
|
292
|
+
|
|
293
|
+
// ─── IDE infrastructure (used by launch/daemon) ───
|
|
294
|
+
/** CDP ports [primary, secondary] (IDE category only) */
|
|
295
|
+
cdpPorts?: [number, number];
|
|
296
|
+
/** CDP target filter — controls which page/tab to connect to (IDE category only) */
|
|
297
|
+
targetFilter?: CdpTargetFilter;
|
|
298
|
+
/** CLI command (e.g. 'cursor', 'code') */
|
|
299
|
+
cli?: string;
|
|
300
|
+
/** Display icon */
|
|
301
|
+
icon?: string;
|
|
302
|
+
/** Display name (short name) */
|
|
303
|
+
displayName?: string;
|
|
304
|
+
/** Install instructions (shown when command is missing) */
|
|
305
|
+
install?: string;
|
|
306
|
+
/** Custom version detection command (e.g. 'cursor --version', 'claude -v') */
|
|
307
|
+
versionCommand?: string;
|
|
308
|
+
/** Versions tested by provider maintainer (informational) */
|
|
309
|
+
testedVersions?: string[];
|
|
310
|
+
/** Per-OS process names — used by launch.ts to detect/kill IDE processes */
|
|
311
|
+
processNames?: {
|
|
312
|
+
darwin?: string;
|
|
313
|
+
win32?: string[];
|
|
314
|
+
linux?: string[];
|
|
315
|
+
[key: string]: string | string[] | undefined;
|
|
316
|
+
};
|
|
317
|
+
/** Per-OS install paths — used by detector.ts to detect IDE installation */
|
|
318
|
+
paths?: {
|
|
319
|
+
darwin?: string[];
|
|
320
|
+
win32?: string[];
|
|
321
|
+
linux?: string[];
|
|
322
|
+
[key: string]: string[] | undefined;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
// ─── Extension category only ───
|
|
326
|
+
extensionId?: string;
|
|
327
|
+
extensionIdPattern?: RegExp;
|
|
328
|
+
|
|
329
|
+
// ─── CLI category only ───
|
|
330
|
+
binary?: string;
|
|
331
|
+
spawn?: {
|
|
332
|
+
command: string;
|
|
333
|
+
args?: string[];
|
|
334
|
+
shell?: boolean;
|
|
335
|
+
env?: Record<string, string>;
|
|
336
|
+
};
|
|
337
|
+
patterns?: {
|
|
338
|
+
prompt?: RegExp[];
|
|
339
|
+
generating?: RegExp[];
|
|
340
|
+
approval?: RegExp[];
|
|
341
|
+
ready?: RegExp[];
|
|
342
|
+
};
|
|
343
|
+
cleanOutput?: (raw: string, lastUserInput?: string) => string;
|
|
344
|
+
|
|
345
|
+
// ─── CDP scripts (ide/extension category) ───
|
|
346
|
+
scripts?: ProviderScripts;
|
|
347
|
+
|
|
348
|
+
// ─── VS Code Commands (Extension IPC via) ───
|
|
349
|
+
vscodeCommands?: {
|
|
350
|
+
focusPanel?: string;
|
|
351
|
+
openPanel?: string;
|
|
352
|
+
[key: string]: string | undefined;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// ─── Input method (IDE category — Lexical editor etc) ───
|
|
356
|
+
inputMethod?: 'cdp-type-and-send' | 'script';
|
|
357
|
+
inputSelector?: string;
|
|
358
|
+
|
|
359
|
+
// ─── Webview chat (IDE category — chat UI is in webview iframe) ───
|
|
360
|
+
/** webview iframe match text (must be contained in body) */
|
|
361
|
+
webviewMatchText?: string;
|
|
362
|
+
|
|
363
|
+
// ─── Per-OS overrides ───
|
|
364
|
+
os?: {
|
|
365
|
+
[platform: string]: Partial<Pick<ProviderModule, 'scripts' | 'inputMethod' | 'inputSelector'>>;
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// ─── Per-version overrides ───
|
|
369
|
+
/** Key: semver range string (e.g. '< 1.107.0', '>= 2.0.0') */
|
|
370
|
+
versions?: {
|
|
371
|
+
[versionRange: string]: Partial<Pick<ProviderModule, 'scripts'>> & {
|
|
372
|
+
/**
|
|
373
|
+
* Load scripts from a subdirectory instead of scripts.js root.
|
|
374
|
+
* Path is relative to the provider directory (e.g. 'scripts/legacy').
|
|
375
|
+
* The subdirectory should contain its own scripts.js or individual .js files.
|
|
376
|
+
*/
|
|
377
|
+
__dir?: string;
|
|
378
|
+
};
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// ─── Composite override (OS + version) ───
|
|
382
|
+
overrides?: Array<{
|
|
383
|
+
when: { os?: string; version?: string };
|
|
384
|
+
scripts?: Partial<ProviderScripts>;
|
|
385
|
+
/** Load scripts from a subdirectory for this OS+version combination */
|
|
386
|
+
__dir?: string;
|
|
387
|
+
}>;
|
|
388
|
+
|
|
389
|
+
// ─── Provider Settings (variables controllable from dashboard) ───
|
|
390
|
+
settings?: Record<string, ProviderSettingDef>;
|
|
391
|
+
|
|
392
|
+
// ─── ACP Static Config (for agents without config/* support) ───
|
|
393
|
+
/** Static options used when agent does not provide configOptions */
|
|
394
|
+
staticConfigOptions?: Array<{
|
|
395
|
+
category: 'model' | 'mode' | 'thought_level' | 'other';
|
|
396
|
+
configId: string;
|
|
397
|
+
defaultValue?: string;
|
|
398
|
+
options: Array<{ value: string; name: string; description?: string; group?: string }>;
|
|
399
|
+
}>;
|
|
400
|
+
/** Function to convert selected config values to spawn args (applied via process restart when config/* not supported) */
|
|
401
|
+
spawnArgBuilder?: (config: Record<string, string>) => string[];
|
|
402
|
+
|
|
403
|
+
// ─── ACP Authentication (auth method definitions) ───
|
|
404
|
+
/** ACP agent auth methods (multiple supported — in priority order) */
|
|
405
|
+
auth?: AcpAuthMethod[];
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// ─── ACP Auth Types ─────────────────────────────────
|
|
409
|
+
|
|
410
|
+
/** ACP auth method — based on ACP official spec */
|
|
411
|
+
export type AcpAuthMethod = AcpAuthEnvVar | AcpAuthAgent | AcpAuthTerminal;
|
|
412
|
+
|
|
413
|
+
/** Environment variable-based auth (API keys etc) */
|
|
414
|
+
export interface AcpAuthEnvVar {
|
|
415
|
+
type: 'env_var';
|
|
416
|
+
id: string;
|
|
417
|
+
name: string;
|
|
418
|
+
vars: Array<{
|
|
419
|
+
name: string;
|
|
420
|
+
label?: string;
|
|
421
|
+
secret?: boolean; // default true
|
|
422
|
+
optional?: boolean; // default false
|
|
423
|
+
}>;
|
|
424
|
+
link?: string; // Key issuance URL
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Agent self-auth (OAuth, browser-based etc) */
|
|
428
|
+
export interface AcpAuthAgent {
|
|
429
|
+
type: 'agent';
|
|
430
|
+
id: string;
|
|
431
|
+
name: string;
|
|
432
|
+
description?: string;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/** Terminal command-based auth (runs setup command) */
|
|
436
|
+
export interface AcpAuthTerminal {
|
|
437
|
+
type: 'terminal';
|
|
438
|
+
id: string;
|
|
439
|
+
name: string;
|
|
440
|
+
description?: string;
|
|
441
|
+
args?: string[];
|
|
442
|
+
env?: Record<string, string>;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* CDP script functions.
|
|
447
|
+
* Each function takes a params object and returns a JS code string for CDP evaluate.
|
|
448
|
+
* The JS execution result must conform to the Output Contract.
|
|
449
|
+
*
|
|
450
|
+
* Custom scripts can be added via index signature in addition to built-in scripts.
|
|
451
|
+
* All scripts can receive params: Record<string, any>,
|
|
452
|
+
* backward compatible with legacy single-argument style (e.g. sendMessage(text)).
|
|
453
|
+
*/
|
|
454
|
+
export interface ProviderScripts {
|
|
455
|
+
// ─── Core ───
|
|
456
|
+
readChat?: (params?: Record<string, any>) => string;
|
|
457
|
+
sendMessage?: (params?: Record<string, any>) => string;
|
|
458
|
+
listSessions?: (params?: Record<string, any>) => string;
|
|
459
|
+
switchSession?: (params?: Record<string, any>) => string;
|
|
460
|
+
newSession?: (params?: Record<string, any>) => string;
|
|
461
|
+
|
|
462
|
+
// ─── UI Control ───
|
|
463
|
+
focusEditor?: (params?: Record<string, any>) => string;
|
|
464
|
+
openPanel?: (params?: Record<string, any>) => string;
|
|
465
|
+
|
|
466
|
+
// ─── Model / Mode Control ───
|
|
467
|
+
/** List available models → { models: string[], current: string } */
|
|
468
|
+
listModels?: (params?: Record<string, any>) => string;
|
|
469
|
+
/** Change model → { success: boolean } */
|
|
470
|
+
setModel?: (params?: Record<string, any>) => string;
|
|
471
|
+
/** List available modes → { modes: string[], current: string } */
|
|
472
|
+
listModes?: (params?: Record<string, any>) => string;
|
|
473
|
+
/** Change mode → { success: boolean } */
|
|
474
|
+
setMode?: (params?: Record<string, any>) => string;
|
|
475
|
+
|
|
476
|
+
// ─── Modal/Approval ───
|
|
477
|
+
/** params: { action: 'approve'|'reject'|'custom', button?: string } */
|
|
478
|
+
resolveAction?: (params?: Record<string, any>) => string;
|
|
479
|
+
|
|
480
|
+
// ─── Notifications ───
|
|
481
|
+
listNotifications?: (params?: Record<string, any>) => string;
|
|
482
|
+
dismissNotification?: (params?: Record<string, any>) => string;
|
|
483
|
+
|
|
484
|
+
// ─── Custom Scripts (user-defined) ───
|
|
485
|
+
[scriptName: string]: ((params?: Record<string, any>) => string) | undefined;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* ProviderLoader.resolve() result: Final provider with OS/version overrides applied
|
|
491
|
+
*/
|
|
492
|
+
export interface ResolvedProvider extends ProviderModule {
|
|
493
|
+
/** OS applied during resolve */
|
|
494
|
+
_resolvedOs?: string;
|
|
495
|
+
/** Version applied during resolve */
|
|
496
|
+
_resolvedVersion?: string;
|
|
497
|
+
/** Warning when detected version is not in compatibility matrix */
|
|
498
|
+
_versionWarning?: string;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// ─── Provider Settings ─────────────────────────────────
|
|
502
|
+
|
|
503
|
+
/** Setting variable definition declared by provider */
|
|
504
|
+
export interface ProviderSettingDef {
|
|
505
|
+
type: 'boolean' | 'number' | 'string' | 'select';
|
|
506
|
+
default: any;
|
|
507
|
+
/** true = controllable from dashboard UI */
|
|
508
|
+
public: boolean;
|
|
509
|
+
/** UI label */
|
|
510
|
+
label?: string;
|
|
511
|
+
/** UI description */
|
|
512
|
+
description?: string;
|
|
513
|
+
/** Minimum value for number type */
|
|
514
|
+
min?: number;
|
|
515
|
+
/** Maximum value for number type */
|
|
516
|
+
max?: number;
|
|
517
|
+
/** Options for select type */
|
|
518
|
+
options?: string[];
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/** Public settings schema (for dashboard transmission) */
|
|
522
|
+
export interface ProviderSettingSchema extends ProviderSettingDef {
|
|
523
|
+
key: string;
|
|
524
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExtensionProviderInstance — Runtime instance for Extension Provider
|
|
3
|
+
*
|
|
4
|
+
* Manages IDE extensions (Cline, Roo Code, etc).
|
|
5
|
+
* CDP webview discovery + agent stream collection moved here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ProviderModule } from './contracts.js';
|
|
9
|
+
import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext } from './provider-instance.js';
|
|
10
|
+
import { StatusMonitor } from './status-monitor.js';
|
|
11
|
+
|
|
12
|
+
export class ExtensionProviderInstance implements ProviderInstance {
|
|
13
|
+
readonly type: string;
|
|
14
|
+
readonly category = 'extension' as const;
|
|
15
|
+
|
|
16
|
+
private provider: ProviderModule;
|
|
17
|
+
private context: InstanceContext | null = null;
|
|
18
|
+
private settings: Record<string, any> = {};
|
|
19
|
+
private events: ProviderEvent[] = [];
|
|
20
|
+
|
|
21
|
+
// status
|
|
22
|
+
private currentStatus: string = 'idle';
|
|
23
|
+
private agentStreams: any[] = [];
|
|
24
|
+
private messages: any[] = [];
|
|
25
|
+
private activeModal: any = null;
|
|
26
|
+
private lastAgentStatus: string = 'idle';
|
|
27
|
+
private generatingStartedAt: number = 0;
|
|
28
|
+
private monitor: StatusMonitor;
|
|
29
|
+
|
|
30
|
+
// meta
|
|
31
|
+
private instanceId: string;
|
|
32
|
+
private ideType: string = '';
|
|
33
|
+
|
|
34
|
+
constructor(provider: ProviderModule) {
|
|
35
|
+
this.type = provider.type;
|
|
36
|
+
this.provider = provider;
|
|
37
|
+
this.instanceId = crypto.randomUUID();
|
|
38
|
+
this.monitor = new StatusMonitor();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ─── Lifecycle ──────────────────────────────────
|
|
42
|
+
|
|
43
|
+
async init(context: InstanceContext): Promise<void> {
|
|
44
|
+
this.context = context;
|
|
45
|
+
this.settings = context.settings || {};
|
|
46
|
+
this.monitor.updateConfig({
|
|
47
|
+
approvalAlert: this.settings.approvalAlert !== false,
|
|
48
|
+
longGeneratingAlert: this.settings.longGeneratingAlert !== false,
|
|
49
|
+
longGeneratingThresholdSec: this.settings.longGeneratingThresholdSec || 180,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async onTick(): Promise<void> {
|
|
54
|
+
// Extension gets data pushed from IDE's CDP agent stream
|
|
55
|
+
// Needed when direct stream collection via CDP is possible
|
|
56
|
+
if (!this.context?.cdp?.isConnected) return;
|
|
57
|
+
|
|
58
|
+
// Agent stream collect (CDP discoverAgentWebviews etc)
|
|
59
|
+
// Currently handled separately by agent-stream-manager only
|
|
60
|
+
// Can be moved here in the future
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getState(): ProviderState {
|
|
64
|
+
return {
|
|
65
|
+
type: this.type,
|
|
66
|
+
name: this.provider.name,
|
|
67
|
+
category: 'extension',
|
|
68
|
+
status: this.currentStatus as ProviderState['status'],
|
|
69
|
+
activeChat: this.messages.length > 0 ? {
|
|
70
|
+
id: `${this.type}_session`,
|
|
71
|
+
title: this.provider.name,
|
|
72
|
+
status: this.currentStatus,
|
|
73
|
+
messages: this.messages,
|
|
74
|
+
activeModal: this.activeModal,
|
|
75
|
+
inputContent: '',
|
|
76
|
+
} : null,
|
|
77
|
+
agentStreams: this.agentStreams,
|
|
78
|
+
instanceId: this.instanceId,
|
|
79
|
+
lastUpdated: Date.now(),
|
|
80
|
+
settings: this.settings,
|
|
81
|
+
pendingEvents: this.flushEvents(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
onEvent(event: string, data?: any): void {
|
|
86
|
+
if (event === 'stream_update') {
|
|
87
|
+
// Reflect data collected from agent-stream-manager
|
|
88
|
+
if (data?.streams) this.agentStreams = data.streams;
|
|
89
|
+
if (data?.messages) this.messages = data.messages;
|
|
90
|
+
if (data?.status) {
|
|
91
|
+
const newStatus = data.status;
|
|
92
|
+
this.detectTransition(newStatus, data);
|
|
93
|
+
this.currentStatus = newStatus;
|
|
94
|
+
}
|
|
95
|
+
} else if (event === 'extension_connected') {
|
|
96
|
+
this.ideType = data?.ideType || '';
|
|
97
|
+
// Maintain instanceId UUID — do not overwrite
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
dispose(): void {
|
|
102
|
+
this.agentStreams = [];
|
|
103
|
+
this.messages = [];
|
|
104
|
+
this.monitor.reset();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Query UUID instanceId */
|
|
108
|
+
getInstanceId(): string {
|
|
109
|
+
return this.instanceId;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ─── status transition detect ──────────────────────────────
|
|
113
|
+
|
|
114
|
+
private detectTransition(newStatus: string, data: any): void {
|
|
115
|
+
const now = Date.now();
|
|
116
|
+
const agentStatus = (newStatus === 'streaming' || newStatus === 'generating') ? 'generating'
|
|
117
|
+
: newStatus === 'waiting_approval' ? 'waiting_approval'
|
|
118
|
+
: 'idle';
|
|
119
|
+
|
|
120
|
+
if (agentStatus !== this.lastAgentStatus) {
|
|
121
|
+
const chatTitle = this.provider.name;
|
|
122
|
+
|
|
123
|
+
if (this.lastAgentStatus === 'idle' && agentStatus === 'generating') {
|
|
124
|
+
this.generatingStartedAt = now;
|
|
125
|
+
this.pushEvent({ event: 'agent:generating_started', chatTitle, timestamp: now });
|
|
126
|
+
} else if (agentStatus === 'waiting_approval') {
|
|
127
|
+
if (!this.generatingStartedAt) this.generatingStartedAt = now;
|
|
128
|
+
this.pushEvent({ event: 'agent:waiting_approval', chatTitle, timestamp: now });
|
|
129
|
+
} else if (agentStatus === 'idle' && (this.lastAgentStatus === 'generating' || this.lastAgentStatus === 'waiting_approval')) {
|
|
130
|
+
const duration = this.generatingStartedAt ? Math.round((now - this.generatingStartedAt) / 1000) : 0;
|
|
131
|
+
this.pushEvent({ event: 'agent:generating_completed', chatTitle, duration, timestamp: now });
|
|
132
|
+
this.generatingStartedAt = 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
this.lastAgentStatus = agentStatus;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Monitor check (cooldown based notification)
|
|
139
|
+
const agentKey = `${this.type}:ext`;
|
|
140
|
+
const monitorEvents = this.monitor.check(agentKey, agentStatus, now);
|
|
141
|
+
for (const me of monitorEvents) {
|
|
142
|
+
this.pushEvent({ event: me.type, agentKey: me.agentKey, message: me.message, elapsedSec: me.elapsedSec, timestamp: me.timestamp });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
private pushEvent(event: ProviderEvent): void {
|
|
147
|
+
this.events.push(event);
|
|
148
|
+
if (this.events.length > 50) this.events = this.events.slice(-50);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private flushEvents(): ProviderEvent[] {
|
|
152
|
+
const events = [...this.events];
|
|
153
|
+
this.events = [];
|
|
154
|
+
return events;
|
|
155
|
+
}
|
|
156
|
+
}
|