pi-harness-runtime 1.1.194 → 1.1.196
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/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/package.json +1 -1
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/e2e-tester/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/dist/conversation-bridge.d.ts +1 -19
- package/packages/notification/dist/conversation-bridge.d.ts.map +1 -1
- package/packages/notification/dist/conversation-bridge.js +6 -94
- package/packages/notification/dist/conversation-bridge.js.map +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/conversation-bridge.ts +6 -122
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/telegram/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Telegram Conversation Bridge
|
|
3
3
|
*
|
|
4
|
-
* Sends assistant responses
|
|
4
|
+
* Sends assistant responses to Telegram.
|
|
5
5
|
* Hooks into Pi lifecycle events to capture:
|
|
6
6
|
* - message_end: Final assistant responses
|
|
7
|
-
* - agent_end: When agent finishes a turn
|
|
8
7
|
* - agent_settled: When agent fully settles
|
|
9
8
|
*
|
|
10
9
|
* Features:
|
|
@@ -24,15 +23,12 @@ export class ConversationBridge {
|
|
|
24
23
|
pendingMessages = new Map();
|
|
25
24
|
deliveredMessageIds = new Set();
|
|
26
25
|
sessionStartTime = Date.now();
|
|
27
|
-
lastMessageId = null;
|
|
28
26
|
constructor(pi, center, config = {}) {
|
|
29
27
|
this.pi = pi;
|
|
30
28
|
this.center = center;
|
|
31
29
|
this.config = {
|
|
32
30
|
sendAssistantResponses: true,
|
|
33
|
-
sendToolSummaries: true,
|
|
34
31
|
maxMessageLength: 4000,
|
|
35
|
-
minConfidence: 0.5,
|
|
36
32
|
...config,
|
|
37
33
|
};
|
|
38
34
|
}
|
|
@@ -40,30 +36,19 @@ export class ConversationBridge {
|
|
|
40
36
|
* Register all lifecycle hooks
|
|
41
37
|
*/
|
|
42
38
|
register() {
|
|
43
|
-
console.log("[ConversationBridge] Registering lifecycle hooks...");
|
|
44
39
|
// Session start - reset state
|
|
45
40
|
this.pi.on("session_start", () => {
|
|
46
41
|
this.reset();
|
|
47
|
-
console.log("[ConversationBridge] Session started");
|
|
48
42
|
});
|
|
49
43
|
// Session compact - flush pending messages
|
|
50
|
-
this.pi.on("session_compact", (
|
|
51
|
-
console.log(`[ConversationBridge] Compaction: ${event.reason} (willRetry=${event.willRetry})`);
|
|
44
|
+
this.pi.on("session_compact", (_event) => {
|
|
52
45
|
this.flushPendingMessages();
|
|
53
46
|
});
|
|
54
47
|
// Session shutdown - cleanup
|
|
55
48
|
this.pi.on("session_shutdown", () => {
|
|
56
|
-
console.log("[ConversationBridge] Session shutting down");
|
|
57
49
|
this.flushPendingMessages();
|
|
58
50
|
this.stop();
|
|
59
51
|
});
|
|
60
|
-
// Message start - track new message
|
|
61
|
-
this.pi.on("message_start", (event) => {
|
|
62
|
-
const msg = event.message;
|
|
63
|
-
if (msg?.role === "assistant" && msg?.id) {
|
|
64
|
-
this.lastMessageId = msg.id;
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
52
|
// Message end - capture final assistant response
|
|
68
53
|
this.pi.on("message_end", (event) => {
|
|
69
54
|
const msg = event.message;
|
|
@@ -72,10 +57,9 @@ export class ConversationBridge {
|
|
|
72
57
|
const content = this.extractMessageContent(msg);
|
|
73
58
|
if (!content || content.length < 10)
|
|
74
59
|
return; // Skip empty/too short
|
|
75
|
-
const messageId = msg.id ?? `msg-${
|
|
60
|
+
const messageId = msg.id ?? `msg-${this.sessionStartTime}`;
|
|
76
61
|
// Deduplicate
|
|
77
62
|
if (this.deliveredMessageIds.has(messageId)) {
|
|
78
|
-
console.log(`[ConversationBridge] Skipping duplicate: ${messageId}`);
|
|
79
63
|
return;
|
|
80
64
|
}
|
|
81
65
|
// Check if already pending
|
|
@@ -90,23 +74,11 @@ export class ConversationBridge {
|
|
|
90
74
|
this.pendingMessages.set(messageId, pending);
|
|
91
75
|
}
|
|
92
76
|
pending.events.add("message_end");
|
|
93
|
-
console.log(`[ConversationBridge] Assistant message captured: ${messageId.substring(0, 20)}...`);
|
|
94
77
|
});
|
|
95
|
-
// Tool execution end - capture tool summaries
|
|
96
|
-
if (this.config.sendToolSummaries) {
|
|
97
|
-
this.pi.on("tool_execution_end", (event) => {
|
|
98
|
-
const summary = this.formatToolSummary(event);
|
|
99
|
-
if (summary) {
|
|
100
|
-
this.sendToolSummary(summary);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
78
|
// Agent settled - finalize and send pending messages
|
|
105
79
|
this.pi.on("agent_settled", () => {
|
|
106
|
-
console.log("[ConversationBridge] Agent settled, finalizing messages...");
|
|
107
80
|
this.finalizePendingMessages();
|
|
108
81
|
});
|
|
109
|
-
console.log("[ConversationBridge] Lifecycle hooks registered");
|
|
110
82
|
}
|
|
111
83
|
/**
|
|
112
84
|
* Extract text content from a message
|
|
@@ -134,45 +106,6 @@ export class ConversationBridge {
|
|
|
134
106
|
}
|
|
135
107
|
return null;
|
|
136
108
|
}
|
|
137
|
-
/**
|
|
138
|
-
* Format a tool execution summary
|
|
139
|
-
*/
|
|
140
|
-
formatToolSummary(event) {
|
|
141
|
-
const status = event.isError ? "FAILED" : "DONE";
|
|
142
|
-
const resultPreview = this.truncate(JSON.stringify(event.result ?? ""), 100);
|
|
143
|
-
return `[Tool] ${event.toolName}: ${status}${resultPreview ? ` - ${resultPreview}` : ""}`;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Send a tool summary to Telegram
|
|
147
|
-
*/
|
|
148
|
-
async sendToolSummary(summary) {
|
|
149
|
-
if (!this.center.hasHealthyChannels())
|
|
150
|
-
return;
|
|
151
|
-
const payload = {
|
|
152
|
-
event: "CodexSessionStarted", // Reusing existing event
|
|
153
|
-
jobId: `tool-${Date.now()}`,
|
|
154
|
-
timestamp: new Date().toISOString(),
|
|
155
|
-
title: "Tool Executed",
|
|
156
|
-
message: summary,
|
|
157
|
-
};
|
|
158
|
-
try {
|
|
159
|
-
const results = await this.center.notify("CodexSessionStarted", {
|
|
160
|
-
jobId: payload.jobId,
|
|
161
|
-
requirement: payload.message,
|
|
162
|
-
});
|
|
163
|
-
for (const result of results) {
|
|
164
|
-
if (result.success) {
|
|
165
|
-
console.log(`[ConversationBridge] Tool summary sent`);
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
console.warn(`[ConversationBridge] Tool summary failed: ${result.error}`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
console.error("[ConversationBridge] Failed to send tool summary:", err);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
109
|
/**
|
|
177
110
|
* Finalize and send pending messages (called on agent_settled)
|
|
178
111
|
*/
|
|
@@ -186,16 +119,12 @@ export class ConversationBridge {
|
|
|
186
119
|
this.deliveredMessageIds.add(messageId);
|
|
187
120
|
this.pendingMessages.delete(messageId);
|
|
188
121
|
}
|
|
189
|
-
else {
|
|
190
|
-
console.log(`[ConversationBridge] Failed to send ${messageId}, will retry`);
|
|
191
|
-
}
|
|
192
122
|
}
|
|
193
123
|
}
|
|
194
124
|
/**
|
|
195
125
|
* Flush pending messages (on compaction) - send before clearing
|
|
196
126
|
*/
|
|
197
127
|
async flushPendingMessages() {
|
|
198
|
-
console.log(`[ConversationBridge] Flushing ${this.pendingMessages.size} pending messages`);
|
|
199
128
|
// Send all pending messages before clearing
|
|
200
129
|
await this.finalizePendingMessages();
|
|
201
130
|
}
|
|
@@ -204,7 +133,6 @@ export class ConversationBridge {
|
|
|
204
133
|
*/
|
|
205
134
|
async sendAssistantResponse(content, messageId) {
|
|
206
135
|
if (!this.center.hasHealthyChannels()) {
|
|
207
|
-
console.log("[ConversationBridge] No healthy channels, skipping");
|
|
208
136
|
return false;
|
|
209
137
|
}
|
|
210
138
|
// Chunk if too long
|
|
@@ -219,17 +147,12 @@ export class ConversationBridge {
|
|
|
219
147
|
requirement: chunk + chunkSuffix,
|
|
220
148
|
});
|
|
221
149
|
for (const result of results) {
|
|
222
|
-
if (result.success) {
|
|
223
|
-
console.log(`[ConversationBridge] Response chunk ${i + 1}/${chunks.length} sent`);
|
|
224
|
-
}
|
|
225
|
-
else {
|
|
226
|
-
console.warn(`[ConversationBridge] Response chunk failed: ${result.error}`);
|
|
150
|
+
if (!result.success) {
|
|
227
151
|
allSent = false;
|
|
228
152
|
}
|
|
229
153
|
}
|
|
230
154
|
}
|
|
231
|
-
catch
|
|
232
|
-
console.error("[ConversationBridge] Failed to send response:", err);
|
|
155
|
+
catch {
|
|
233
156
|
allSent = false;
|
|
234
157
|
}
|
|
235
158
|
}
|
|
@@ -245,7 +168,6 @@ export class ConversationBridge {
|
|
|
245
168
|
const chunks = [];
|
|
246
169
|
const maxLen = this.config.maxMessageLength;
|
|
247
170
|
// Split by sentence boundaries, keeping the punctuation
|
|
248
|
-
// Also split on newlines and other natural breaks
|
|
249
171
|
const parts = message.split(/(?<=[.!?])\s+|(?<=\n)\s*|(?<=[,;:])\s+/);
|
|
250
172
|
let currentChunk = "";
|
|
251
173
|
for (const part of parts) {
|
|
@@ -295,29 +217,19 @@ export class ConversationBridge {
|
|
|
295
217
|
}
|
|
296
218
|
return chunks;
|
|
297
219
|
}
|
|
298
|
-
/**
|
|
299
|
-
* Truncate a string
|
|
300
|
-
*/
|
|
301
|
-
truncate(str, maxLen) {
|
|
302
|
-
if (str.length <= maxLen)
|
|
303
|
-
return str;
|
|
304
|
-
return str.substring(0, maxLen - 3) + "...";
|
|
305
|
-
}
|
|
306
220
|
/**
|
|
307
221
|
* Reset state for new session
|
|
308
222
|
*/
|
|
309
223
|
reset() {
|
|
310
224
|
this.pendingMessages.clear();
|
|
311
225
|
this.deliveredMessageIds.clear();
|
|
312
|
-
this.lastMessageId = null;
|
|
313
226
|
this.sessionStartTime = Date.now();
|
|
314
227
|
}
|
|
315
228
|
/**
|
|
316
229
|
* Stop the bridge (cleanup)
|
|
317
230
|
*/
|
|
318
231
|
stop() {
|
|
319
|
-
|
|
320
|
-
// Cleanup will happen on shutdown
|
|
232
|
+
// Cleanup happens on shutdown
|
|
321
233
|
}
|
|
322
234
|
}
|
|
323
235
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-bridge.js","sourceRoot":"","sources":["../src/conversation-bridge.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"conversation-bridge.js","sourceRoot":"","sources":["../src/conversation-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Telegram Conversation Bridge
|
|
3
3
|
*
|
|
4
|
-
* Sends assistant responses
|
|
4
|
+
* Sends assistant responses to Telegram.
|
|
5
5
|
* Hooks into Pi lifecycle events to capture:
|
|
6
6
|
* - message_end: Final assistant responses
|
|
7
|
-
* - agent_end: When agent finishes a turn
|
|
8
7
|
* - agent_settled: When agent fully settles
|
|
9
8
|
*
|
|
10
9
|
* Features:
|
|
@@ -15,7 +14,6 @@
|
|
|
15
14
|
|
|
16
15
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
17
16
|
import type { NotificationCenter } from "./notification-center.js";
|
|
18
|
-
import type { NotificationPayload } from "./types.js";
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
19
|
* Configuration for the conversation bridge
|
|
@@ -23,12 +21,8 @@ import type { NotificationPayload } from "./types.js";
|
|
|
23
21
|
export interface ConversationBridgeConfig {
|
|
24
22
|
/** Whether to send assistant final responses */
|
|
25
23
|
sendAssistantResponses: boolean;
|
|
26
|
-
/** Whether to send tool summaries */
|
|
27
|
-
sendToolSummaries: boolean;
|
|
28
24
|
/** Max message length before chunking */
|
|
29
25
|
maxMessageLength: number;
|
|
30
|
-
/** Minimum confidence to send a message */
|
|
31
|
-
minConfidence: number;
|
|
32
26
|
}
|
|
33
27
|
|
|
34
28
|
/**
|
|
@@ -53,7 +47,6 @@ export class ConversationBridge {
|
|
|
53
47
|
private pendingMessages: Map<string, PendingMessage> = new Map();
|
|
54
48
|
private deliveredMessageIds: Set<string> = new Set();
|
|
55
49
|
private sessionStartTime: number = Date.now();
|
|
56
|
-
private lastMessageId: string | null = null;
|
|
57
50
|
|
|
58
51
|
constructor(
|
|
59
52
|
pi: ExtensionAPI,
|
|
@@ -64,9 +57,7 @@ export class ConversationBridge {
|
|
|
64
57
|
this.center = center;
|
|
65
58
|
this.config = {
|
|
66
59
|
sendAssistantResponses: true,
|
|
67
|
-
sendToolSummaries: true,
|
|
68
60
|
maxMessageLength: 4000,
|
|
69
|
-
minConfidence: 0.5,
|
|
70
61
|
...config,
|
|
71
62
|
};
|
|
72
63
|
}
|
|
@@ -75,37 +66,22 @@ export class ConversationBridge {
|
|
|
75
66
|
* Register all lifecycle hooks
|
|
76
67
|
*/
|
|
77
68
|
register(): void {
|
|
78
|
-
console.log("[ConversationBridge] Registering lifecycle hooks...");
|
|
79
|
-
|
|
80
69
|
// Session start - reset state
|
|
81
70
|
this.pi.on("session_start", () => {
|
|
82
71
|
this.reset();
|
|
83
|
-
console.log("[ConversationBridge] Session started");
|
|
84
72
|
});
|
|
85
73
|
|
|
86
74
|
// Session compact - flush pending messages
|
|
87
|
-
this.pi.on("session_compact", (
|
|
88
|
-
console.log(
|
|
89
|
-
`[ConversationBridge] Compaction: ${event.reason} (willRetry=${event.willRetry})`,
|
|
90
|
-
);
|
|
75
|
+
this.pi.on("session_compact", (_event) => {
|
|
91
76
|
this.flushPendingMessages();
|
|
92
77
|
});
|
|
93
78
|
|
|
94
79
|
// Session shutdown - cleanup
|
|
95
80
|
this.pi.on("session_shutdown", () => {
|
|
96
|
-
console.log("[ConversationBridge] Session shutting down");
|
|
97
81
|
this.flushPendingMessages();
|
|
98
82
|
this.stop();
|
|
99
83
|
});
|
|
100
84
|
|
|
101
|
-
// Message start - track new message
|
|
102
|
-
this.pi.on("message_start", (event) => {
|
|
103
|
-
const msg = event.message as { id?: string; role?: string };
|
|
104
|
-
if (msg?.role === "assistant" && msg?.id) {
|
|
105
|
-
this.lastMessageId = msg.id;
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
85
|
// Message end - capture final assistant response
|
|
110
86
|
this.pi.on("message_end", (event) => {
|
|
111
87
|
const msg = event.message as { id?: string; role?: string; content?: unknown };
|
|
@@ -114,11 +90,10 @@ export class ConversationBridge {
|
|
|
114
90
|
const content = this.extractMessageContent(msg);
|
|
115
91
|
if (!content || content.length < 10) return; // Skip empty/too short
|
|
116
92
|
|
|
117
|
-
const messageId = msg.id ?? `msg-${
|
|
93
|
+
const messageId = msg.id ?? `msg-${this.sessionStartTime}`;
|
|
118
94
|
|
|
119
95
|
// Deduplicate
|
|
120
96
|
if (this.deliveredMessageIds.has(messageId)) {
|
|
121
|
-
console.log(`[ConversationBridge] Skipping duplicate: ${messageId}`);
|
|
122
97
|
return;
|
|
123
98
|
}
|
|
124
99
|
|
|
@@ -134,29 +109,12 @@ export class ConversationBridge {
|
|
|
134
109
|
this.pendingMessages.set(messageId, pending);
|
|
135
110
|
}
|
|
136
111
|
pending.events.add("message_end");
|
|
137
|
-
|
|
138
|
-
console.log(
|
|
139
|
-
`[ConversationBridge] Assistant message captured: ${messageId.substring(0, 20)}...`,
|
|
140
|
-
);
|
|
141
112
|
});
|
|
142
113
|
|
|
143
|
-
// Tool execution end - capture tool summaries
|
|
144
|
-
if (this.config.sendToolSummaries) {
|
|
145
|
-
this.pi.on("tool_execution_end", (event) => {
|
|
146
|
-
const summary = this.formatToolSummary(event);
|
|
147
|
-
if (summary) {
|
|
148
|
-
this.sendToolSummary(summary);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
114
|
// Agent settled - finalize and send pending messages
|
|
154
115
|
this.pi.on("agent_settled", () => {
|
|
155
|
-
console.log("[ConversationBridge] Agent settled, finalizing messages...");
|
|
156
116
|
this.finalizePendingMessages();
|
|
157
117
|
});
|
|
158
|
-
|
|
159
|
-
console.log("[ConversationBridge] Lifecycle hooks registered");
|
|
160
118
|
}
|
|
161
119
|
|
|
162
120
|
/**
|
|
@@ -192,54 +150,6 @@ export class ConversationBridge {
|
|
|
192
150
|
return null;
|
|
193
151
|
}
|
|
194
152
|
|
|
195
|
-
/**
|
|
196
|
-
* Format a tool execution summary
|
|
197
|
-
*/
|
|
198
|
-
private formatToolSummary(event: {
|
|
199
|
-
toolName: string;
|
|
200
|
-
result?: unknown;
|
|
201
|
-
isError: boolean;
|
|
202
|
-
}): string {
|
|
203
|
-
const status = event.isError ? "FAILED" : "DONE";
|
|
204
|
-
const resultPreview = this.truncate(
|
|
205
|
-
JSON.stringify(event.result ?? ""),
|
|
206
|
-
100,
|
|
207
|
-
);
|
|
208
|
-
return `[Tool] ${event.toolName}: ${status}${resultPreview ? ` - ${resultPreview}` : ""}`;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/**
|
|
212
|
-
* Send a tool summary to Telegram
|
|
213
|
-
*/
|
|
214
|
-
private async sendToolSummary(summary: string): Promise<void> {
|
|
215
|
-
if (!this.center.hasHealthyChannels()) return;
|
|
216
|
-
|
|
217
|
-
const payload: NotificationPayload = {
|
|
218
|
-
event: "CodexSessionStarted", // Reusing existing event
|
|
219
|
-
jobId: `tool-${Date.now()}`,
|
|
220
|
-
timestamp: new Date().toISOString(),
|
|
221
|
-
title: "Tool Executed",
|
|
222
|
-
message: summary,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
try {
|
|
226
|
-
const results = await this.center.notify("CodexSessionStarted", {
|
|
227
|
-
jobId: payload.jobId,
|
|
228
|
-
requirement: payload.message,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
for (const result of results) {
|
|
232
|
-
if (result.success) {
|
|
233
|
-
console.log(`[ConversationBridge] Tool summary sent`);
|
|
234
|
-
} else {
|
|
235
|
-
console.warn(`[ConversationBridge] Tool summary failed: ${result.error}`);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
} catch (err) {
|
|
239
|
-
console.error("[ConversationBridge] Failed to send tool summary:", err);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
153
|
/**
|
|
244
154
|
* Finalize and send pending messages (called on agent_settled)
|
|
245
155
|
*/
|
|
@@ -252,8 +162,6 @@ export class ConversationBridge {
|
|
|
252
162
|
if (success) {
|
|
253
163
|
this.deliveredMessageIds.add(messageId);
|
|
254
164
|
this.pendingMessages.delete(messageId);
|
|
255
|
-
} else {
|
|
256
|
-
console.log(`[ConversationBridge] Failed to send ${messageId}, will retry`);
|
|
257
165
|
}
|
|
258
166
|
}
|
|
259
167
|
}
|
|
@@ -262,9 +170,6 @@ export class ConversationBridge {
|
|
|
262
170
|
* Flush pending messages (on compaction) - send before clearing
|
|
263
171
|
*/
|
|
264
172
|
private async flushPendingMessages(): Promise<void> {
|
|
265
|
-
console.log(
|
|
266
|
-
`[ConversationBridge] Flushing ${this.pendingMessages.size} pending messages`,
|
|
267
|
-
);
|
|
268
173
|
// Send all pending messages before clearing
|
|
269
174
|
await this.finalizePendingMessages();
|
|
270
175
|
}
|
|
@@ -277,7 +182,6 @@ export class ConversationBridge {
|
|
|
277
182
|
messageId: string,
|
|
278
183
|
): Promise<boolean> {
|
|
279
184
|
if (!this.center.hasHealthyChannels()) {
|
|
280
|
-
console.log("[ConversationBridge] No healthy channels, skipping");
|
|
281
185
|
return false;
|
|
282
186
|
}
|
|
283
187
|
|
|
@@ -289,7 +193,6 @@ export class ConversationBridge {
|
|
|
289
193
|
const chunk = chunks[i];
|
|
290
194
|
const chunkSuffix = chunks.length > 1 ? ` [${i + 1}/${chunks.length}]` : "";
|
|
291
195
|
|
|
292
|
-
|
|
293
196
|
try {
|
|
294
197
|
const results = await this.center.notify("AssistantResponse", {
|
|
295
198
|
jobId: `msg-${messageId}`,
|
|
@@ -297,19 +200,11 @@ export class ConversationBridge {
|
|
|
297
200
|
});
|
|
298
201
|
|
|
299
202
|
for (const result of results) {
|
|
300
|
-
if (result.success) {
|
|
301
|
-
console.log(
|
|
302
|
-
`[ConversationBridge] Response chunk ${i + 1}/${chunks.length} sent`,
|
|
303
|
-
);
|
|
304
|
-
} else {
|
|
305
|
-
console.warn(
|
|
306
|
-
`[ConversationBridge] Response chunk failed: ${result.error}`,
|
|
307
|
-
);
|
|
203
|
+
if (!result.success) {
|
|
308
204
|
allSent = false;
|
|
309
205
|
}
|
|
310
206
|
}
|
|
311
|
-
} catch
|
|
312
|
-
console.error("[ConversationBridge] Failed to send response:", err);
|
|
207
|
+
} catch {
|
|
313
208
|
allSent = false;
|
|
314
209
|
}
|
|
315
210
|
}
|
|
@@ -329,7 +224,6 @@ export class ConversationBridge {
|
|
|
329
224
|
const maxLen = this.config.maxMessageLength;
|
|
330
225
|
|
|
331
226
|
// Split by sentence boundaries, keeping the punctuation
|
|
332
|
-
// Also split on newlines and other natural breaks
|
|
333
227
|
const parts = message.split(/(?<=[.!?])\s+|(?<=\n)\s*|(?<=[,;:])\s+/);
|
|
334
228
|
let currentChunk = "";
|
|
335
229
|
|
|
@@ -382,21 +276,12 @@ export class ConversationBridge {
|
|
|
382
276
|
return chunks;
|
|
383
277
|
}
|
|
384
278
|
|
|
385
|
-
/**
|
|
386
|
-
* Truncate a string
|
|
387
|
-
*/
|
|
388
|
-
private truncate(str: string, maxLen: number): string {
|
|
389
|
-
if (str.length <= maxLen) return str;
|
|
390
|
-
return str.substring(0, maxLen - 3) + "...";
|
|
391
|
-
}
|
|
392
|
-
|
|
393
279
|
/**
|
|
394
280
|
* Reset state for new session
|
|
395
281
|
*/
|
|
396
282
|
private reset(): void {
|
|
397
283
|
this.pendingMessages.clear();
|
|
398
284
|
this.deliveredMessageIds.clear();
|
|
399
|
-
this.lastMessageId = null;
|
|
400
285
|
this.sessionStartTime = Date.now();
|
|
401
286
|
}
|
|
402
287
|
|
|
@@ -404,8 +289,7 @@ export class ConversationBridge {
|
|
|
404
289
|
* Stop the bridge (cleanup)
|
|
405
290
|
*/
|
|
406
291
|
stop(): void {
|
|
407
|
-
|
|
408
|
-
// Cleanup will happen on shutdown
|
|
292
|
+
// Cleanup happens on shutdown
|
|
409
293
|
}
|
|
410
294
|
}
|
|
411
295
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/provider-router",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.196",
|
|
4
4
|
"description": "Enhanced Provider Router for pi-harness-runtime — intelligent routing with capabilities, costs, and quotas",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/provider-router.js",
|