@fonz/tgcc 0.6.17 → 0.6.18
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/README.md +74 -50
- package/dist/bridge.d.ts +19 -7
- package/dist/bridge.js +882 -646
- package/dist/bridge.js.map +1 -1
- package/dist/cc-process.js +7 -0
- package/dist/cc-process.js.map +1 -1
- package/dist/ctl-server.d.ts +4 -0
- package/dist/ctl-server.js +30 -4
- package/dist/ctl-server.js.map +1 -1
- package/dist/event-buffer.d.ts +27 -0
- package/dist/event-buffer.js +50 -0
- package/dist/event-buffer.js.map +1 -0
- package/dist/high-signal.d.ts +53 -0
- package/dist/high-signal.js +391 -0
- package/dist/high-signal.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-bridge.d.ts +3 -5
- package/dist/mcp-server.js +80 -0
- package/dist/mcp-server.js.map +1 -1
- package/dist/session.d.ts +13 -8
- package/dist/session.js +61 -37
- package/dist/session.js.map +1 -1
- package/dist/streaming.d.ts +20 -7
- package/dist/streaming.js +232 -112
- package/dist/streaming.js.map +1 -1
- package/dist/telegram.d.ts +3 -1
- package/dist/telegram.js +18 -1
- package/dist/telegram.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// ── Event Ring Buffer for CC process observability ──
|
|
2
|
+
export class EventBuffer {
|
|
3
|
+
buffer = [];
|
|
4
|
+
maxSize;
|
|
5
|
+
constructor(maxSize = 1000) {
|
|
6
|
+
this.maxSize = maxSize;
|
|
7
|
+
}
|
|
8
|
+
push(line) {
|
|
9
|
+
this.buffer.push(line);
|
|
10
|
+
if (this.buffer.length > this.maxSize) {
|
|
11
|
+
this.buffer = this.buffer.slice(this.buffer.length - this.maxSize);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
query(opts = {}) {
|
|
15
|
+
let lines = this.buffer;
|
|
16
|
+
if (opts.type) {
|
|
17
|
+
lines = lines.filter(l => l.type === opts.type);
|
|
18
|
+
}
|
|
19
|
+
if (opts.since) {
|
|
20
|
+
const cutoff = Date.now() - opts.since;
|
|
21
|
+
lines = lines.filter(l => l.ts >= cutoff);
|
|
22
|
+
}
|
|
23
|
+
if (opts.grep) {
|
|
24
|
+
try {
|
|
25
|
+
const re = new RegExp(opts.grep, 'i');
|
|
26
|
+
lines = lines.filter(l => re.test(l.text));
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// Invalid regex — skip filter
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
const totalLines = lines.length;
|
|
33
|
+
const offset = opts.offset ?? 0;
|
|
34
|
+
const limit = opts.limit ?? 50;
|
|
35
|
+
const sliced = lines.slice(offset, offset + limit);
|
|
36
|
+
return {
|
|
37
|
+
totalLines,
|
|
38
|
+
returnedLines: sliced.length,
|
|
39
|
+
offset,
|
|
40
|
+
lines: sliced,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
get totalLines() {
|
|
44
|
+
return this.buffer.length;
|
|
45
|
+
}
|
|
46
|
+
clear() {
|
|
47
|
+
this.buffer = [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=event-buffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-buffer.js","sourceRoot":"","sources":["../src/event-buffer.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAuBvD,MAAM,OAAO,WAAW;IACd,MAAM,GAAc,EAAE,CAAC;IACvB,OAAO,CAAS;IAExB,YAAY,OAAO,GAAG,IAAI;QACxB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,IAAI,CAAC,IAAa;QAChB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;YACtC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QACrE,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAqB,EAAE;QAC3B,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAExB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;YACvC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,MAAM,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,CAAC;gBACH,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBACtC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7C,CAAC;YAAC,MAAM,CAAC;gBACP,8BAA8B;YAChC,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC;QAEnD,OAAO;YACL,UAAU;YACV,aAAa,EAAE,MAAM,CAAC,MAAM;YAC5B,MAAM;YACN,KAAK,EAAE,MAAM;SACd,CAAC;IACJ,CAAC;IAED,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { LogLine } from './event-buffer.js';
|
|
2
|
+
import type { StreamInnerEvent } from './cc-protocol.js';
|
|
3
|
+
export interface HighSignalEvent {
|
|
4
|
+
type: 'event';
|
|
5
|
+
event: string;
|
|
6
|
+
agentId: string;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface HighSignalCallbacks {
|
|
10
|
+
emitSupervisorEvent: (event: HighSignalEvent) => void;
|
|
11
|
+
pushEventBuffer: (agentId: string, line: LogLine) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare class HighSignalDetector {
|
|
14
|
+
private callbacks;
|
|
15
|
+
private agentStates;
|
|
16
|
+
private stuckTimeoutMs;
|
|
17
|
+
constructor(callbacks: HighSignalCallbacks, stuckTimeoutMs?: number);
|
|
18
|
+
/**
|
|
19
|
+
* Handle a stream event from CC (content_block_start, message_start, etc.)
|
|
20
|
+
*/
|
|
21
|
+
handleStreamEvent(agentId: string, event: StreamInnerEvent): void;
|
|
22
|
+
/**
|
|
23
|
+
* Handle a tool_result event from CC
|
|
24
|
+
*/
|
|
25
|
+
handleToolResult(agentId: string, toolUseId: string, content: string, isError: boolean, toolName?: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Handle an assistant message (for TodoWrite/Read tool_use blocks with full input)
|
|
28
|
+
*/
|
|
29
|
+
handleAssistantToolUse(agentId: string, toolName: string, toolUseId: string, input: Record<string, unknown>): void;
|
|
30
|
+
/**
|
|
31
|
+
* Clean up state for an agent (on process exit)
|
|
32
|
+
*/
|
|
33
|
+
cleanup(agentId: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Destroy all state
|
|
36
|
+
*/
|
|
37
|
+
destroy(): void;
|
|
38
|
+
private getState;
|
|
39
|
+
private checkContextPressure;
|
|
40
|
+
private detectBuildResult;
|
|
41
|
+
private detectGitCommit;
|
|
42
|
+
private detectTaskMilestone;
|
|
43
|
+
private touchActivity;
|
|
44
|
+
private resetStuckTimer;
|
|
45
|
+
private checkStuck;
|
|
46
|
+
private emit;
|
|
47
|
+
private eventEmoji;
|
|
48
|
+
private eventSummary;
|
|
49
|
+
private extractCommand;
|
|
50
|
+
private extractExitCode;
|
|
51
|
+
private hasNonZeroExit;
|
|
52
|
+
private extractFirstMeaningfulLine;
|
|
53
|
+
}
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
// ── High-Signal Event Detection for CC process observability ──
|
|
2
|
+
//
|
|
3
|
+
// Watches CC stream events for patterns that indicate meaningful progress,
|
|
4
|
+
// failures, or pressure. Emits supervisor events and pushes to EventBuffer.
|
|
5
|
+
// ── Constants ──
|
|
6
|
+
const BUILD_TEST_PATTERNS = /\b(npm run build|npm run test|npx tsc|tsc\b|jest\b|vitest\b|pytest\b|cargo test|go test|make\b|npm test|yarn build|yarn test|pnpm build|pnpm test)\b/i;
|
|
7
|
+
const GIT_COMMIT_PATTERN = /\bgit commit\b/i;
|
|
8
|
+
const SUBAGENT_TOOLS = new Set(['Task', 'dispatch_agent', 'create_agent', 'AgentRunner']);
|
|
9
|
+
const TODO_TOOLS = new Set(['TodoWrite', 'TodoRead']);
|
|
10
|
+
const BASH_TOOLS = new Set(['Bash', 'shell']);
|
|
11
|
+
const CONTEXT_THRESHOLDS = [50, 75, 90];
|
|
12
|
+
const CONTEXT_WINDOW_TOKENS = 200_000;
|
|
13
|
+
const FAILURE_LOOP_THRESHOLD = 3;
|
|
14
|
+
const DEFAULT_STUCK_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes
|
|
15
|
+
export class HighSignalDetector {
|
|
16
|
+
callbacks;
|
|
17
|
+
agentStates = new Map();
|
|
18
|
+
stuckTimeoutMs;
|
|
19
|
+
constructor(callbacks, stuckTimeoutMs = DEFAULT_STUCK_TIMEOUT_MS) {
|
|
20
|
+
this.callbacks = callbacks;
|
|
21
|
+
this.stuckTimeoutMs = stuckTimeoutMs;
|
|
22
|
+
}
|
|
23
|
+
// ── Public API ──
|
|
24
|
+
/**
|
|
25
|
+
* Handle a stream event from CC (content_block_start, message_start, etc.)
|
|
26
|
+
*/
|
|
27
|
+
handleStreamEvent(agentId, event) {
|
|
28
|
+
const state = this.getState(agentId);
|
|
29
|
+
// Track output activity for stuck detection
|
|
30
|
+
this.touchActivity(agentId, state);
|
|
31
|
+
if (event.type === 'message_start') {
|
|
32
|
+
// Reset per-turn state
|
|
33
|
+
state.spawnCountThisTurn = 0;
|
|
34
|
+
// Context pressure tracking
|
|
35
|
+
this.checkContextPressure(agentId, state, event);
|
|
36
|
+
}
|
|
37
|
+
if (event.type === 'content_block_start') {
|
|
38
|
+
const block = event.content_block;
|
|
39
|
+
if (block.type === 'tool_use' && block.id && block.name) {
|
|
40
|
+
// Track active tool use
|
|
41
|
+
state.activeToolUses.set(block.id, { id: block.id, name: block.name, inputJson: '' });
|
|
42
|
+
state.currentToolBlockId = block.id;
|
|
43
|
+
state.isExecutingTool = true;
|
|
44
|
+
// Sub-agent spawn detection
|
|
45
|
+
if (SUBAGENT_TOOLS.has(block.name)) {
|
|
46
|
+
state.spawnCountThisTurn++;
|
|
47
|
+
this.emit(agentId, {
|
|
48
|
+
type: 'event',
|
|
49
|
+
event: 'subagent_spawn',
|
|
50
|
+
agentId,
|
|
51
|
+
count: state.spawnCountThisTurn,
|
|
52
|
+
toolName: block.name,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Accumulate tool input JSON for the current tool block
|
|
58
|
+
if (event.type === 'content_block_delta') {
|
|
59
|
+
const delta = event.delta;
|
|
60
|
+
if (delta?.type === 'input_json_delta' && delta.partial_json && state.currentToolBlockId) {
|
|
61
|
+
const info = state.activeToolUses.get(state.currentToolBlockId);
|
|
62
|
+
if (info) {
|
|
63
|
+
info.inputJson += delta.partial_json;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (event.type === 'content_block_stop') {
|
|
68
|
+
state.currentToolBlockId = null;
|
|
69
|
+
// isExecutingTool stays true until tool_result comes back
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Handle a tool_result event from CC
|
|
74
|
+
*/
|
|
75
|
+
handleToolResult(agentId, toolUseId, content, isError, toolName) {
|
|
76
|
+
const state = this.getState(agentId);
|
|
77
|
+
// Resolve tool name from tracked tool uses
|
|
78
|
+
const toolInfo = state.activeToolUses.get(toolUseId);
|
|
79
|
+
const resolvedToolName = toolName || toolInfo?.name || 'unknown';
|
|
80
|
+
const toolInput = toolInfo?.inputJson || '';
|
|
81
|
+
// Clean up tracked tool use
|
|
82
|
+
state.activeToolUses.delete(toolUseId);
|
|
83
|
+
state.isExecutingTool = state.activeToolUses.size > 0;
|
|
84
|
+
// Track output activity
|
|
85
|
+
this.touchActivity(agentId, state);
|
|
86
|
+
// ── Failure loop detection ──
|
|
87
|
+
if (isError || this.hasNonZeroExit(content)) {
|
|
88
|
+
state.consecutiveFailures++;
|
|
89
|
+
state.lastFailedTool = resolvedToolName;
|
|
90
|
+
state.lastFailedError = content.length > 200 ? content.slice(0, 200) + '…' : content;
|
|
91
|
+
if (state.consecutiveFailures >= FAILURE_LOOP_THRESHOLD && !state.failureLoopEmitted) {
|
|
92
|
+
state.failureLoopEmitted = true;
|
|
93
|
+
this.emit(agentId, {
|
|
94
|
+
type: 'event',
|
|
95
|
+
event: 'failure_loop',
|
|
96
|
+
agentId,
|
|
97
|
+
consecutiveFailures: state.consecutiveFailures,
|
|
98
|
+
lastTool: state.lastFailedTool,
|
|
99
|
+
lastError: state.lastFailedError,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
// Success resets counter
|
|
105
|
+
if (state.failureLoopEmitted && state.consecutiveFailures >= FAILURE_LOOP_THRESHOLD) {
|
|
106
|
+
// Was in a failure loop, now recovered — reset emit flag for next potential loop
|
|
107
|
+
state.failureLoopEmitted = false;
|
|
108
|
+
}
|
|
109
|
+
state.consecutiveFailures = 0;
|
|
110
|
+
state.failureLoopEmitted = false;
|
|
111
|
+
}
|
|
112
|
+
// ── Build/test result detection (Bash tools only) ──
|
|
113
|
+
if (BASH_TOOLS.has(resolvedToolName)) {
|
|
114
|
+
const command = this.extractCommand(toolInput);
|
|
115
|
+
if (command && BUILD_TEST_PATTERNS.test(command)) {
|
|
116
|
+
this.detectBuildResult(agentId, command, content);
|
|
117
|
+
}
|
|
118
|
+
if (command && GIT_COMMIT_PATTERN.test(command)) {
|
|
119
|
+
this.detectGitCommit(agentId, content);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// ── Task milestone detection (TodoWrite) ──
|
|
123
|
+
if (TODO_TOOLS.has(resolvedToolName)) {
|
|
124
|
+
this.detectTaskMilestone(agentId, resolvedToolName, toolInput);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Handle an assistant message (for TodoWrite/Read tool_use blocks with full input)
|
|
129
|
+
*/
|
|
130
|
+
handleAssistantToolUse(agentId, toolName, toolUseId, input) {
|
|
131
|
+
const state = this.getState(agentId);
|
|
132
|
+
// Update tracked tool with parsed input
|
|
133
|
+
const existing = state.activeToolUses.get(toolUseId);
|
|
134
|
+
if (existing) {
|
|
135
|
+
existing.inputJson = JSON.stringify(input);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Clean up state for an agent (on process exit)
|
|
140
|
+
*/
|
|
141
|
+
cleanup(agentId) {
|
|
142
|
+
const state = this.agentStates.get(agentId);
|
|
143
|
+
if (state?.stuckTimer) {
|
|
144
|
+
clearTimeout(state.stuckTimer);
|
|
145
|
+
}
|
|
146
|
+
this.agentStates.delete(agentId);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Destroy all state
|
|
150
|
+
*/
|
|
151
|
+
destroy() {
|
|
152
|
+
for (const [agentId] of this.agentStates) {
|
|
153
|
+
this.cleanup(agentId);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// ── Private: State management ──
|
|
157
|
+
getState(agentId) {
|
|
158
|
+
let state = this.agentStates.get(agentId);
|
|
159
|
+
if (!state) {
|
|
160
|
+
state = {
|
|
161
|
+
consecutiveFailures: 0,
|
|
162
|
+
failureLoopEmitted: false,
|
|
163
|
+
lastFailedTool: '',
|
|
164
|
+
lastFailedError: '',
|
|
165
|
+
contextThresholdsHit: new Set(),
|
|
166
|
+
spawnCountThisTurn: 0,
|
|
167
|
+
lastOutputTs: Date.now(),
|
|
168
|
+
stuckTimer: null,
|
|
169
|
+
isExecutingTool: false,
|
|
170
|
+
activeToolUses: new Map(),
|
|
171
|
+
currentToolBlockId: null,
|
|
172
|
+
};
|
|
173
|
+
this.agentStates.set(agentId, state);
|
|
174
|
+
}
|
|
175
|
+
return state;
|
|
176
|
+
}
|
|
177
|
+
// ── Private: Detection logic ──
|
|
178
|
+
checkContextPressure(agentId, state, event) {
|
|
179
|
+
const usage = event.message?.usage;
|
|
180
|
+
if (!usage)
|
|
181
|
+
return;
|
|
182
|
+
const inputTokens = usage.input_tokens ?? 0;
|
|
183
|
+
const cacheRead = usage.cache_read_input_tokens ?? 0;
|
|
184
|
+
const cacheCreation = usage.cache_creation_input_tokens ?? 0;
|
|
185
|
+
const totalTokens = inputTokens + cacheRead + cacheCreation;
|
|
186
|
+
const percent = Math.round((totalTokens / CONTEXT_WINDOW_TOKENS) * 100);
|
|
187
|
+
for (const threshold of CONTEXT_THRESHOLDS) {
|
|
188
|
+
if (percent >= threshold && !state.contextThresholdsHit.has(threshold)) {
|
|
189
|
+
state.contextThresholdsHit.add(threshold);
|
|
190
|
+
this.emit(agentId, {
|
|
191
|
+
type: 'event',
|
|
192
|
+
event: 'context_pressure',
|
|
193
|
+
agentId,
|
|
194
|
+
percent: threshold,
|
|
195
|
+
tokens: totalTokens,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
detectBuildResult(agentId, command, output) {
|
|
201
|
+
const exitCode = this.extractExitCode(output);
|
|
202
|
+
const passed = exitCode === 0;
|
|
203
|
+
const errorCount = (output.match(/\berror\b/gi) || []).length;
|
|
204
|
+
const summary = passed
|
|
205
|
+
? `Build/test passed${errorCount > 0 ? ` (${errorCount} error mentions)` : ''}`
|
|
206
|
+
: `Build/test failed: ${errorCount} error${errorCount !== 1 ? 's' : ''}`;
|
|
207
|
+
this.emit(agentId, {
|
|
208
|
+
type: 'event',
|
|
209
|
+
event: 'build_result',
|
|
210
|
+
agentId,
|
|
211
|
+
command: command.length > 100 ? command.slice(0, 100) + '…' : command,
|
|
212
|
+
passed,
|
|
213
|
+
errors: errorCount,
|
|
214
|
+
summary,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
detectGitCommit(agentId, output) {
|
|
218
|
+
// Extract commit message from git output
|
|
219
|
+
// Typical: [branch abc1234] commit message here
|
|
220
|
+
const match = output.match(/\[[\w/.-]+\s+[a-f0-9]+\]\s+(.+)/);
|
|
221
|
+
const message = match?.[1]?.trim() || this.extractFirstMeaningfulLine(output);
|
|
222
|
+
if (message) {
|
|
223
|
+
this.emit(agentId, {
|
|
224
|
+
type: 'event',
|
|
225
|
+
event: 'git_commit',
|
|
226
|
+
agentId,
|
|
227
|
+
message,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
detectTaskMilestone(agentId, toolName, inputJson) {
|
|
232
|
+
if (toolName !== 'TodoWrite')
|
|
233
|
+
return;
|
|
234
|
+
try {
|
|
235
|
+
const input = JSON.parse(inputJson);
|
|
236
|
+
const todos = input.todos;
|
|
237
|
+
if (!Array.isArray(todos))
|
|
238
|
+
return;
|
|
239
|
+
// Count completed vs total
|
|
240
|
+
let completed = 0;
|
|
241
|
+
let total = todos.length;
|
|
242
|
+
let currentTask = '';
|
|
243
|
+
let currentStatus = '';
|
|
244
|
+
for (const todo of todos) {
|
|
245
|
+
if (todo.status === 'completed')
|
|
246
|
+
completed++;
|
|
247
|
+
// Find the most recently changed task (last in-progress or completed)
|
|
248
|
+
if (todo.status === 'in_progress' || todo.status === 'completed') {
|
|
249
|
+
currentTask = todo.content || todo.task || todo.description || '';
|
|
250
|
+
currentStatus = todo.status;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (!currentTask && todos.length > 0) {
|
|
254
|
+
// Fallback: use first todo
|
|
255
|
+
const first = todos[0];
|
|
256
|
+
currentTask = first.content || first.task || first.description || '';
|
|
257
|
+
currentStatus = first.status || 'unknown';
|
|
258
|
+
}
|
|
259
|
+
const progress = `${completed}/${total}`;
|
|
260
|
+
this.emit(agentId, {
|
|
261
|
+
type: 'event',
|
|
262
|
+
event: 'task_milestone',
|
|
263
|
+
agentId,
|
|
264
|
+
task: currentTask.length > 100 ? currentTask.slice(0, 100) + '…' : currentTask,
|
|
265
|
+
status: currentStatus,
|
|
266
|
+
progress,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
// Invalid JSON — skip
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// ── Private: Stuck detection ──
|
|
274
|
+
touchActivity(agentId, state) {
|
|
275
|
+
state.lastOutputTs = Date.now();
|
|
276
|
+
this.resetStuckTimer(agentId, state);
|
|
277
|
+
}
|
|
278
|
+
resetStuckTimer(agentId, state) {
|
|
279
|
+
if (state.stuckTimer) {
|
|
280
|
+
clearTimeout(state.stuckTimer);
|
|
281
|
+
}
|
|
282
|
+
state.stuckTimer = setTimeout(() => {
|
|
283
|
+
this.checkStuck(agentId);
|
|
284
|
+
}, this.stuckTimeoutMs);
|
|
285
|
+
}
|
|
286
|
+
checkStuck(agentId) {
|
|
287
|
+
const state = this.agentStates.get(agentId);
|
|
288
|
+
if (!state)
|
|
289
|
+
return;
|
|
290
|
+
// Don't fire during tool execution
|
|
291
|
+
if (state.isExecutingTool) {
|
|
292
|
+
// Re-schedule — check again after timeout
|
|
293
|
+
this.resetStuckTimer(agentId, state);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const silentMs = Date.now() - state.lastOutputTs;
|
|
297
|
+
if (silentMs >= this.stuckTimeoutMs) {
|
|
298
|
+
this.emit(agentId, {
|
|
299
|
+
type: 'event',
|
|
300
|
+
event: 'stuck',
|
|
301
|
+
agentId,
|
|
302
|
+
silentMs,
|
|
303
|
+
lastActivity: new Date(state.lastOutputTs).toISOString(),
|
|
304
|
+
});
|
|
305
|
+
// Don't re-emit continuously — one stuck event per silence period
|
|
306
|
+
// Timer will re-arm on next activity
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// ── Private: Helpers ──
|
|
310
|
+
emit(agentId, event) {
|
|
311
|
+
// Push to event buffer
|
|
312
|
+
const emoji = this.eventEmoji(event.event);
|
|
313
|
+
const summary = this.eventSummary(event);
|
|
314
|
+
this.callbacks.pushEventBuffer(agentId, {
|
|
315
|
+
ts: Date.now(),
|
|
316
|
+
type: 'system',
|
|
317
|
+
text: `${emoji} ${summary}`,
|
|
318
|
+
});
|
|
319
|
+
// Emit to supervisor
|
|
320
|
+
this.callbacks.emitSupervisorEvent(event);
|
|
321
|
+
}
|
|
322
|
+
eventEmoji(event) {
|
|
323
|
+
switch (event) {
|
|
324
|
+
case 'build_result': return '🔨';
|
|
325
|
+
case 'git_commit': return '📝';
|
|
326
|
+
case 'context_pressure': return '🧠';
|
|
327
|
+
case 'subagent_spawn': return '🔄';
|
|
328
|
+
case 'failure_loop': return '🔁';
|
|
329
|
+
case 'task_milestone': return '📋';
|
|
330
|
+
case 'stuck': return '⚠️';
|
|
331
|
+
default: return '📡';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
eventSummary(event) {
|
|
335
|
+
switch (event.event) {
|
|
336
|
+
case 'build_result':
|
|
337
|
+
return event.passed ? `Build passed ✅` : `Build failed: ${event.errors} errors`;
|
|
338
|
+
case 'git_commit':
|
|
339
|
+
return `Committed: "${event.message}"`;
|
|
340
|
+
case 'context_pressure':
|
|
341
|
+
return `Context at ${event.percent}%`;
|
|
342
|
+
case 'subagent_spawn':
|
|
343
|
+
return `Spawned sub-agent (${event.toolName}, total: ${event.count})`;
|
|
344
|
+
case 'failure_loop':
|
|
345
|
+
return `${event.consecutiveFailures} consecutive failures — possibly stuck`;
|
|
346
|
+
case 'task_milestone':
|
|
347
|
+
return `[${event.progress}] ${event.task} (${event.status})`;
|
|
348
|
+
case 'stuck':
|
|
349
|
+
return `No output for ${Math.round(event.silentMs / 60000)}min`;
|
|
350
|
+
default:
|
|
351
|
+
return event.event;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
extractCommand(inputJson) {
|
|
355
|
+
try {
|
|
356
|
+
const input = JSON.parse(inputJson);
|
|
357
|
+
return input.command || input.cmd || null;
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
extractExitCode(output) {
|
|
364
|
+
// CC tool results for Bash typically end with exit code info
|
|
365
|
+
// or the output itself indicates success/failure
|
|
366
|
+
if (/exit code[:\s]+0\b/i.test(output))
|
|
367
|
+
return 0;
|
|
368
|
+
if (/exit code[:\s]+(\d+)/i.test(output)) {
|
|
369
|
+
const match = output.match(/exit code[:\s]+(\d+)/i);
|
|
370
|
+
return match ? parseInt(match[1], 10) : 1;
|
|
371
|
+
}
|
|
372
|
+
// If no explicit exit code, check for common failure patterns
|
|
373
|
+
if (/\berror\b.*\bfailed\b/i.test(output) || /\bfailed\b/i.test(output.slice(-200))) {
|
|
374
|
+
return 1;
|
|
375
|
+
}
|
|
376
|
+
// Default: assume success if no obvious failure indicators
|
|
377
|
+
return 0;
|
|
378
|
+
}
|
|
379
|
+
hasNonZeroExit(content) {
|
|
380
|
+
// Check for explicit non-zero exit codes in Bash output
|
|
381
|
+
const match = content.match(/exit code[:\s]+(\d+)/i);
|
|
382
|
+
if (match)
|
|
383
|
+
return parseInt(match[1], 10) !== 0;
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
extractFirstMeaningfulLine(output) {
|
|
387
|
+
const lines = output.split('\n').filter(l => l.trim().length > 0);
|
|
388
|
+
return lines[0]?.trim() || '';
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
//# sourceMappingURL=high-signal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"high-signal.js","sourceRoot":"","sources":["../src/high-signal.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { CCProcess, type CCProcessOptions, type CCUserConfig, type ProcessState, type CCActivityState, hasActiveChildren, generateMcpConfig, } from './cc-process.js';
|
|
2
2
|
export { parseCCOutputLine, createInitializeRequest, createPermissionResponse, createTextMessage, createImageMessage, createDocumentMessage, serializeMessage, extractAssistantText, extractToolUses, isStreamTextDelta, isStreamThinkingDelta, getStreamBlockType, type TextContent, type ImageContent, type ContentBlock, type UserMessage, type ControlRequestInitialize, type PermissionRequest, type ControlRequest, type ControlResponse, type InitEvent, type AssistantTextBlock, type AssistantToolUseBlock, type AssistantThinkingBlock, type AssistantContentBlock, type AssistantMessage, type ToolResultEvent, type UserOutputMessage, type ResultEvent, type ApiErrorEvent, type CCOutputEvent, type StreamMessageStart, type StreamContentBlockStart, type StreamContentBlockStartText, type StreamContentBlockStartThinking, type StreamContentBlockStartToolUse, type StreamTextDelta, type StreamThinkingDelta, type StreamInputJsonDelta, type StreamContentBlockDelta, type StreamContentBlockStop, type StreamMessageStop, type StreamInnerEvent, type StreamEvent, } from './cc-protocol.js';
|
|
3
|
-
export { SessionStore, getSessionJsonlPath, computeProjectSlug, discoverCCSessions, type
|
|
3
|
+
export { SessionStore, getSessionJsonlPath, computeProjectSlug, discoverCCSessions, type AgentState, type StateStore, type DiscoveredSession, } from './session.js';
|
|
4
4
|
export { StreamAccumulator, SubAgentTracker, markdownToHtml, makeHtmlSafe, escapeHtml, formatUsageFooter, splitText, isSubAgentTool, type TelegramSender, type TurnUsage, type StreamAccumulatorOptions, type SubAgentInfo, type SubAgentSender, type SubAgentTrackerOptions, } from './streaming.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,6DAA6D;AAC7D,2EAA2E;AAE3E,uBAAuB;AACvB,OAAO,EACL,SAAS,EAKT,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,6BAA6B;AAC7B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GAqCnB,MAAM,kBAAkB,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,6DAA6D;AAC7D,2EAA2E;AAE3E,uBAAuB;AACvB,OAAO,EACL,SAAS,EAKT,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AAEzB,6BAA6B;AAC7B,OAAO,EACL,iBAAiB,EACjB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,kBAAkB,GAqCnB,MAAM,kBAAkB,CAAC;AAE1B,gBAAgB;AAChB,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GAKnB,MAAM,cAAc,CAAC;AAEtB,sBAAsB;AACtB,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,cAAc,GAOf,MAAM,gBAAgB,CAAC"}
|
package/dist/mcp-bridge.d.ts
CHANGED
|
@@ -2,18 +2,16 @@ import { EventEmitter } from 'node:events';
|
|
|
2
2
|
import type pino from 'pino';
|
|
3
3
|
export interface McpToolRequest {
|
|
4
4
|
id: string;
|
|
5
|
-
tool:
|
|
5
|
+
tool: string;
|
|
6
6
|
agentId: string;
|
|
7
7
|
userId: string;
|
|
8
|
-
params:
|
|
9
|
-
path: string;
|
|
10
|
-
caption?: string;
|
|
11
|
-
};
|
|
8
|
+
params: Record<string, any>;
|
|
12
9
|
}
|
|
13
10
|
export interface McpToolResponse {
|
|
14
11
|
id: string;
|
|
15
12
|
success: boolean;
|
|
16
13
|
error?: string;
|
|
14
|
+
result?: any;
|
|
17
15
|
}
|
|
18
16
|
export type McpToolHandler = (request: McpToolRequest) => Promise<McpToolResponse>;
|
|
19
17
|
export declare class McpBridgeServer extends EventEmitter {
|
package/dist/mcp-server.js
CHANGED
|
@@ -98,6 +98,86 @@ async function main() {
|
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
|
+
// ── notify_parent tool ──
|
|
102
|
+
server.tool('notify_parent', 'Send a message to the orchestrator/parent that spawned this task. Use for asking questions, reporting blockers, or progress updates.', {
|
|
103
|
+
message: z.string().describe('Message to send to the parent'),
|
|
104
|
+
priority: z.enum(['info', 'question', 'blocker']).default('info').describe('Message priority'),
|
|
105
|
+
}, async ({ message, priority }) => {
|
|
106
|
+
const request = {
|
|
107
|
+
id: uuidv4(),
|
|
108
|
+
tool: 'notify_parent',
|
|
109
|
+
agentId: AGENT_ID,
|
|
110
|
+
userId: USER_ID,
|
|
111
|
+
params: { message, priority },
|
|
112
|
+
};
|
|
113
|
+
try {
|
|
114
|
+
const response = await client.sendRequest(request);
|
|
115
|
+
if (response.success) {
|
|
116
|
+
return { content: [{ type: 'text', text: 'Message sent to parent.' }] };
|
|
117
|
+
}
|
|
118
|
+
return { content: [{ type: 'text', text: `Failed: ${response.error}` }], isError: true };
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
return {
|
|
122
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
123
|
+
isError: true,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
// ── supervisor_exec tool ──
|
|
128
|
+
server.tool('supervisor_exec', 'Request the supervisor to execute a shell command. The supervisor may reject unsafe commands.', {
|
|
129
|
+
command: z.string().describe('Shell command to execute'),
|
|
130
|
+
timeoutMs: z.number().default(60000).describe('Timeout in milliseconds'),
|
|
131
|
+
}, async ({ command, timeoutMs }) => {
|
|
132
|
+
const request = {
|
|
133
|
+
id: uuidv4(),
|
|
134
|
+
tool: 'supervisor_exec',
|
|
135
|
+
agentId: AGENT_ID,
|
|
136
|
+
userId: USER_ID,
|
|
137
|
+
params: { command, timeoutMs },
|
|
138
|
+
};
|
|
139
|
+
try {
|
|
140
|
+
const response = await client.sendRequest(request, timeoutMs + 5000);
|
|
141
|
+
if (response.success) {
|
|
142
|
+
const resultStr = response.result ? JSON.stringify(response.result) : 'Command executed.';
|
|
143
|
+
return { content: [{ type: 'text', text: resultStr }] };
|
|
144
|
+
}
|
|
145
|
+
return { content: [{ type: 'text', text: `Failed: ${response.error}` }], isError: true };
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
return {
|
|
149
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
150
|
+
isError: true,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
// ── supervisor_notify tool ──
|
|
155
|
+
server.tool('supervisor_notify', 'Send a notification through the supervisor to the user.', {
|
|
156
|
+
title: z.string().describe('Notification title'),
|
|
157
|
+
body: z.string().describe('Notification body'),
|
|
158
|
+
priority: z.enum(['passive', 'active', 'timeSensitive']).default('active').describe('Notification priority'),
|
|
159
|
+
}, async ({ title, body, priority }) => {
|
|
160
|
+
const request = {
|
|
161
|
+
id: uuidv4(),
|
|
162
|
+
tool: 'supervisor_notify',
|
|
163
|
+
agentId: AGENT_ID,
|
|
164
|
+
userId: USER_ID,
|
|
165
|
+
params: { title, body, priority },
|
|
166
|
+
};
|
|
167
|
+
try {
|
|
168
|
+
const response = await client.sendRequest(request);
|
|
169
|
+
if (response.success) {
|
|
170
|
+
return { content: [{ type: 'text', text: 'Notification sent.' }] };
|
|
171
|
+
}
|
|
172
|
+
return { content: [{ type: 'text', text: `Failed: ${response.error}` }], isError: true };
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
return {
|
|
176
|
+
content: [{ type: 'text', text: `Bridge unavailable: ${err instanceof Error ? err.message : 'unknown error'}` }],
|
|
177
|
+
isError: true,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
});
|
|
101
181
|
// Start the MCP server on stdio
|
|
102
182
|
const transport = new StdioServerTransport();
|
|
103
183
|
await server.connect(transport);
|