pi-harness-runtime 1.1.346 → 1.1.349
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/index.ts +83 -75
- 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/connection-runtime/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/contracts/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/durable-review/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-sink/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/index.d.ts +1 -0
- package/packages/notification/dist/index.d.ts.map +1 -1
- package/packages/notification/dist/index.js +1 -0
- package/packages/notification/dist/index.js.map +1 -1
- package/packages/notification/dist/notification-center.d.ts +13 -0
- package/packages/notification/dist/notification-center.d.ts.map +1 -1
- package/packages/notification/dist/notification-center.js +91 -1
- package/packages/notification/dist/notification-center.js.map +1 -1
- package/packages/notification/dist/pending-question.d.ts +198 -0
- package/packages/notification/dist/pending-question.d.ts.map +1 -0
- package/packages/notification/dist/pending-question.js +410 -0
- package/packages/notification/dist/pending-question.js.map +1 -0
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/index.ts +1 -0
- package/packages/notification/src/notification-center.ts +92 -1
- package/packages/notification/src/pending-question.ts +594 -0
- package/packages/notification/test/pending-question.test.ts +331 -0
- 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/permission-mode/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/relay/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/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/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
package/index.ts
CHANGED
|
@@ -134,6 +134,8 @@ const sharedState = {
|
|
|
134
134
|
todoContinuationController: null as unknown,
|
|
135
135
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
136
|
updateAutoContinueStatus: null as any,
|
|
137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
138
|
+
pqController: null as any,
|
|
137
139
|
};
|
|
138
140
|
|
|
139
141
|
async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
@@ -168,6 +170,9 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
168
170
|
readFileSync(`${keysDir}/jev-api-key.txt`, "utf8").trim();
|
|
169
171
|
|
|
170
172
|
const mod = await import("./packages/jev-judge/src/auto-continue.js");
|
|
173
|
+
const { createPendingQuestionController } = await import("./packages/notification/dist/index.js");
|
|
174
|
+
const pqController = createPendingQuestionController();
|
|
175
|
+
sharedState.pqController = pqController;
|
|
171
176
|
|
|
172
177
|
// Track waiting state
|
|
173
178
|
let waitingForUserSince: Date | null = null;
|
|
@@ -176,6 +181,7 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
176
181
|
let _inferenceInProgress = false; // Track for overlap prevention
|
|
177
182
|
let _sessionId = Date.now().toString(36); // Track session for cancellation
|
|
178
183
|
let _lastNotifiedQuestion = ""; // Track last question to prevent repeat notifications
|
|
184
|
+
let _completedNotifiedFor: string | null = null; // Track completion notification deduplication
|
|
179
185
|
|
|
180
186
|
// UI status for auto-continue (captured from session_start ctx)
|
|
181
187
|
let _setAutoContinueStatus: ((text: string | undefined) => void) | null = null;
|
|
@@ -271,50 +277,20 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
271
277
|
}
|
|
272
278
|
|
|
273
279
|
// Detect actual confirmation requests (questions, not progress statements)
|
|
274
|
-
//
|
|
280
|
+
// Uses the pending question controller for detection with expanded patterns
|
|
275
281
|
function detectConfirmationRequest(text: string): string | null {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
const matches = text.matchAll(questionPattern);
|
|
280
|
-
|
|
281
|
-
for (const match of matches) {
|
|
282
|
-
const sentence = match[1].trim();
|
|
283
|
-
const lower = sentence.toLowerCase();
|
|
284
|
-
|
|
285
|
-
// Must contain request words AND user intent words
|
|
286
|
-
const hasRequest = /\b(continue|proceed|next|wait|pause|stop|hold|resume|repeat|rephrase|clarify|explain)\b/i.test(lower);
|
|
287
|
-
const hasUserIntent = /\b(should|would|could|shall|may i|do you|would you|should i|could we|can i|can we|would like)\b/i.test(lower);
|
|
288
|
-
|
|
289
|
-
if (hasRequest && hasUserIntent) {
|
|
290
|
-
// Return the question for deduplication (with the ? preserved)
|
|
291
|
-
return sentence;
|
|
292
|
-
}
|
|
282
|
+
const result = pqController.detectQuestion(text);
|
|
283
|
+
if (result.detected && result.questionText) {
|
|
284
|
+
return result.questionText;
|
|
293
285
|
}
|
|
294
|
-
|
|
295
286
|
return null;
|
|
296
287
|
}
|
|
297
288
|
|
|
298
289
|
// Detect routine continuation questions ("Should I continue?")
|
|
299
290
|
// These should NOT block immediate continuation - let Jev/todo controller decide
|
|
300
291
|
function isRoutineContinuation(question: string): boolean {
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
const routinePatterns = [
|
|
304
|
-
/\b(should i|should we|should the|can i continue|can we continue)\b/,
|
|
305
|
-
/\b(would you like me to continue|shall i proceed)\b/,
|
|
306
|
-
/\b(can i proceed|may i continue)\b/,
|
|
307
|
-
/\b(continue|proceed)\s*(with|to|on|with the next|to the next)\b/,
|
|
308
|
-
/\bshall\s+(i|we)\s+(proceed|continue)\b/,
|
|
309
|
-
/\bshould\s+(i|we)\s+(continue|proceed|move on)\b/,
|
|
310
|
-
/\b(continue|proceed)\s+\?/,
|
|
311
|
-
];
|
|
312
|
-
for (const pattern of routinePatterns) {
|
|
313
|
-
if (pattern.test(lower)) {
|
|
314
|
-
return true;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
return false;
|
|
292
|
+
const result = pqController.detectQuestion(question);
|
|
293
|
+
return result.isRoutine ?? false;
|
|
318
294
|
}
|
|
319
295
|
|
|
320
296
|
// Detect when agent asks for continuation
|
|
@@ -488,6 +464,9 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
488
464
|
waitingForUserSince = null;
|
|
489
465
|
_lastNotifiedQuestion = "";
|
|
490
466
|
updateAutoContinueStatus("IDLE");
|
|
467
|
+
// Cancel pending question on user response
|
|
468
|
+
// (User answered via Pi instead of button)
|
|
469
|
+
sharedState.pqController?.cancel("User responded via Pi");
|
|
491
470
|
}
|
|
492
471
|
}
|
|
493
472
|
});
|
|
@@ -550,6 +529,8 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
550
529
|
|
|
551
530
|
// Check session validity and user response before applying
|
|
552
531
|
if (checkSessionId !== _sessionId) {
|
|
532
|
+
// Session changed - cancel pending question
|
|
533
|
+
sharedState.pqController?.cancel("Session switched");
|
|
553
534
|
_inferenceInProgress = false;
|
|
554
535
|
updateAutoContinueStatus("IDLE");
|
|
555
536
|
return;
|
|
@@ -792,26 +773,50 @@ async function initAutoContinue(pi: ExtensionAPI): Promise<void> {
|
|
|
792
773
|
if (result.action === "blocked") {
|
|
793
774
|
updateAutoContinueStatus("ERROR", "blocked");
|
|
794
775
|
logToFile("[auto-continue]", "Tasks blocked:", result.question ?? "unknown");
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
776
|
+
} else if (result.action === "stop") {
|
|
777
|
+
const reason = result.reason ?? "unknown";
|
|
778
|
+
logToFile("[auto-continue]", "decide returned stop:", reason);
|
|
779
|
+
|
|
780
|
+
// Only send completion notification for "No pending tasks"
|
|
781
|
+
// Other stop reasons (paused, unavailable, max attempts) are not completion
|
|
782
|
+
const isNoPendingTasks = reason === "No pending tasks";
|
|
783
|
+
|
|
784
|
+
if (isNoPendingTasks) {
|
|
785
|
+
// Check if there's a pending question - suppress completion if so
|
|
786
|
+
if (pqController.hasPendingQuestion()) {
|
|
787
|
+
logToFile("[auto-continue]", "Suppressing completion - pending question exists");
|
|
788
|
+
updateAutoContinueStatus("WAITING", "pending");
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Deduplication: only notify once per work generation
|
|
793
|
+
// Use a static flag for this session's settled cycle
|
|
794
|
+
const completionKey = `done-${reason}`;
|
|
795
|
+
if (_completedNotifiedFor === completionKey) {
|
|
796
|
+
logToFile("[auto-continue]", "Completion already notified for:", reason);
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
799
|
+
_completedNotifiedFor = completionKey;
|
|
800
|
+
|
|
801
|
+
// Get full todo list for notification
|
|
802
|
+
const snapshot = await todoContinuationController.getSnapshot();
|
|
803
|
+
const todoList = snapshot.items
|
|
804
|
+
.map((item) => {
|
|
805
|
+
const status = item.status === "completed" ? "[DONE]" : "[PENDING]";
|
|
806
|
+
const subject = item.subject.length > 50 ? item.subject.slice(0, 47) + "..." : item.subject;
|
|
807
|
+
return `${status} ${subject}`;
|
|
808
|
+
})
|
|
809
|
+
.join("\n");
|
|
810
|
+
const message = todoList || "All tasks completed";
|
|
811
|
+
// Notify user that all work is complete with todo list
|
|
812
|
+
_nc?.notify("ReadyForClient", {
|
|
813
|
+
jobId: `done-${reason.replace(/\s+/g, "-")}`,
|
|
814
|
+
requirement: message,
|
|
815
|
+
}).catch((e) => logToFile("[Notification]", "ReadyForClient failed:", String(e)));
|
|
812
816
|
}
|
|
813
|
-
|
|
814
|
-
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
} catch (err) {
|
|
815
820
|
logToFile("[auto-continue]", "agent_settled handler error:", String(err));
|
|
816
821
|
todoContinuationController?.clearQueue();
|
|
817
822
|
}
|
|
@@ -1202,12 +1207,16 @@ async function initTelegram(pi: ExtensionAPI): Promise<void> {
|
|
|
1202
1207
|
logToFile("[TelegramCallback] Approved - user clicked Continue, resuming work");
|
|
1203
1208
|
sharedState.waitingForUserSince = null;
|
|
1204
1209
|
sharedState.updateAutoContinueStatus?.("IDLE");
|
|
1210
|
+
// Resolve pending question with yes
|
|
1211
|
+
sharedState.pqController?.resolve({ resolution: "yes", by: "user" });
|
|
1205
1212
|
// Also resume continuation controller
|
|
1206
1213
|
(sharedState.todoContinuationController as any)?.resume?.();
|
|
1207
1214
|
break;
|
|
1208
1215
|
case CallbackActions.REJECT:
|
|
1209
1216
|
// User clicked Not yet - just dismiss, don't resume
|
|
1210
1217
|
logToFile("[TelegramCallback] Rejected - user clicked Not yet, pausing");
|
|
1218
|
+
// Resolve pending question with no
|
|
1219
|
+
sharedState.pqController?.resolve({ resolution: "no", by: "user" });
|
|
1211
1220
|
// Explicitly pause the continuation
|
|
1212
1221
|
(sharedState.todoContinuationController as any)?.explicitPause?.();
|
|
1213
1222
|
break;
|
|
@@ -1231,30 +1240,29 @@ async function initTelegram(pi: ExtensionAPI): Promise<void> {
|
|
|
1231
1240
|
|
|
1232
1241
|
// Register message handler to forward Telegram messages to Pi
|
|
1233
1242
|
center.setMessageHandler(async (text: string, _chatId: string) => {
|
|
1234
|
-
// Parse /notify command for channel management
|
|
1235
|
-
// Usage: /notify
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1243
|
+
// Parse /notify-settings command for channel management
|
|
1244
|
+
// Usage: /notify-settings - show current status
|
|
1245
|
+
// /notify-settings telegram on - enable Telegram
|
|
1246
|
+
// /notify-settings line off - disable LINE
|
|
1247
|
+
// /notify-settings all on - enable all channels
|
|
1248
|
+
const settingsMatch = text.match(/^\/notify-settings(?:\s+(\w+)\s+(on|off))?/i);
|
|
1249
|
+
if (settingsMatch || text === "/notify-settings") {
|
|
1250
|
+
const [, channel, action] = settingsMatch || [];
|
|
1251
|
+
|
|
1252
|
+
if (action && channel) {
|
|
1253
|
+
const isEnabled = action === "on";
|
|
1254
|
+
const targetChannels = channel === "all" ? ["telegram", "line"] : [channel];
|
|
1255
|
+
for (const ch of targetChannels) {
|
|
1256
|
+
(center as any).setChannelEnabled?.(ch, isEnabled);
|
|
1257
|
+
logToFile("[NotifySettings]", `Set ${ch} to ${isEnabled ? "enabled" : "disabled"}`);
|
|
1258
|
+
}
|
|
1246
1259
|
}
|
|
1247
|
-
const telegramStatus = (center as any).isChannelEnabled?.("telegram") ? "ON" : "OFF";
|
|
1248
|
-
const lineStatus = (center as any).isChannelEnabled?.("line") ? "ON" : "OFF";
|
|
1249
|
-
logToFile("[NotifyCommand]", `Current: Telegram=${telegramStatus}, LINE=${lineStatus}`);
|
|
1250
|
-
return;
|
|
1251
|
-
}
|
|
1252
1260
|
|
|
1253
|
-
|
|
1254
|
-
if (text === "/notify") {
|
|
1261
|
+
// Show current status
|
|
1255
1262
|
const telegramStatus = (center as any).isChannelEnabled?.("telegram") ? "ON" : "OFF";
|
|
1256
1263
|
const lineStatus = (center as any).isChannelEnabled?.("line") ? "ON" : "OFF";
|
|
1257
|
-
logToFile("[
|
|
1264
|
+
logToFile("[NotifySettings]", `Current: Telegram=${telegramStatus}, LINE=${lineStatus}`);
|
|
1265
|
+
logToFile("[NotifySettings]", `Commands: /notify-settings telegram on|off, /notify-settings line on|off, /notify-settings all on|off`);
|
|
1258
1266
|
return;
|
|
1259
1267
|
}
|
|
1260
1268
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-harness/capability-registry",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.349",
|
|
4
4
|
"description": "Capability Registry for pi-harness-runtime — tracks model capabilities and enables capability-based routing",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|