pi-harness-runtime 1.1.429 → 1.1.431

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.
Files changed (139) hide show
  1. package/package.json +1 -1
  2. package/packages/a2a-adapter/package.json +1 -1
  3. package/packages/agent-policy/package.json +1 -1
  4. package/packages/architecture-generator/package.json +1 -1
  5. package/packages/auth/package.json +1 -1
  6. package/packages/autonomous-refactor/package.json +1 -1
  7. package/packages/autonomous-runtime/package.json +1 -1
  8. package/packages/cache-strategy/package.json +1 -1
  9. package/packages/capability-registry/package.json +1 -1
  10. package/packages/checkpoint/package.json +1 -1
  11. package/packages/cli-plugin-sdk/package.json +1 -1
  12. package/packages/clipboard/package.json +1 -1
  13. package/packages/clipboard-plugin/package.json +1 -1
  14. package/packages/code-generation/package.json +1 -1
  15. package/packages/code-review/package.json +1 -1
  16. package/packages/codex-adapter/package.json +1 -1
  17. package/packages/codex-watcher/package.json +1 -1
  18. package/packages/config-capture/package.json +1 -1
  19. package/packages/connection-runtime/package.json +1 -1
  20. package/packages/context-compiler/package.json +1 -1
  21. package/packages/context-discovery/package.json +1 -1
  22. package/packages/context-manager/package.json +1 -1
  23. package/packages/contracts/package.json +1 -1
  24. package/packages/cookie-sanitizer/package.json +1 -1
  25. package/packages/cost-optimizer/package.json +1 -1
  26. package/packages/dependency-analyzer/package.json +1 -1
  27. package/packages/django-plugin/package.json +1 -1
  28. package/packages/doc-generator/package.json +1 -1
  29. package/packages/durable-review/package.json +1 -1
  30. package/packages/e2e-tester/package.json +1 -1
  31. package/packages/evaluation-engine/package.json +1 -1
  32. package/packages/evaluation-runner/package.json +1 -1
  33. package/packages/event-bus/package.json +1 -1
  34. package/packages/event-sink/package.json +1 -1
  35. package/packages/event-store/package.json +1 -1
  36. package/packages/experience-replay/package.json +1 -1
  37. package/packages/feedback-collector/package.json +1 -1
  38. package/packages/file-copy-helper/package.json +1 -1
  39. package/packages/framework-detector/package.json +1 -1
  40. package/packages/framework-plugin-sdk/package.json +1 -1
  41. package/packages/frappe-plugin/package.json +1 -1
  42. package/packages/generic-web-plugin/package.json +1 -1
  43. package/packages/health-monitor/package.json +1 -1
  44. package/packages/intent-analyzer/package.json +1 -1
  45. package/packages/jev-judge/package.json +1 -1
  46. package/packages/knowledge-graph/package.json +1 -1
  47. package/packages/knowledge-retrieval/package.json +1 -1
  48. package/packages/laravel-plugin/package.json +1 -1
  49. package/packages/learning-engine/package.json +1 -1
  50. package/packages/logging/package.json +1 -1
  51. package/packages/mcp-adapter/package.json +1 -1
  52. package/packages/memory-engine/package.json +1 -1
  53. package/packages/milestone-manager/package.json +1 -1
  54. package/packages/model-registry/package.json +1 -1
  55. package/packages/nextjs-plugin/package.json +1 -1
  56. package/packages/notification/package.json +1 -1
  57. package/packages/observability/package.json +1 -1
  58. package/packages/okf-indexer/package.json +1 -1
  59. package/packages/paperclip-integration/package.json +1 -1
  60. package/packages/performance-optimizer/package.json +1 -1
  61. package/packages/permission-mode/package.json +1 -1
  62. package/packages/privilege-broker/package.json +1 -1
  63. package/packages/project-analyzer/package.json +1 -1
  64. package/packages/project-bootstrap/package.json +1 -1
  65. package/packages/projection-engine/package.json +1 -1
  66. package/packages/prompt-compiler/package.json +1 -1
  67. package/packages/prompt-versioning/package.json +1 -1
  68. package/packages/provider-adapter-sdk/package.json +1 -1
  69. package/packages/provider-router/package.json +1 -1
  70. package/packages/provider-selector/package.json +1 -1
  71. package/packages/providers/package.json +1 -1
  72. package/packages/qdrant-skills/package.json +1 -1
  73. package/packages/quota-manager/package.json +1 -1
  74. package/packages/rate-limiter/package.json +1 -1
  75. package/packages/react-vite-plugin/package.json +1 -1
  76. package/packages/relay/package.json +1 -1
  77. package/packages/release-manager/package.json +1 -1
  78. package/packages/requirement-compiler/package.json +1 -1
  79. package/packages/runtime/dist/runtime-api.d.ts +61 -6
  80. package/packages/runtime/dist/runtime-api.d.ts.map +1 -1
  81. package/packages/runtime/dist/runtime-api.js +83 -30
  82. package/packages/runtime/dist/runtime-api.js.map +1 -1
  83. package/packages/runtime/package.json +1 -1
  84. package/packages/runtime/src/runtime-api.ts +168 -52
  85. package/packages/runtime/test/runtime-api.test.ts +169 -0
  86. package/packages/scheduler/package.json +1 -1
  87. package/packages/scheduler-adapter/package.json +1 -1
  88. package/packages/session/package.json +1 -1
  89. package/packages/session-api/package.json +1 -1
  90. package/packages/session-export/package.json +1 -1
  91. package/packages/shared-context/package.json +1 -1
  92. package/packages/skill-mcp-client/package.json +1 -1
  93. package/packages/skill-registry/package.json +1 -1
  94. package/packages/skills/package.json +1 -1
  95. package/packages/sprint-planner/package.json +1 -1
  96. package/packages/subscription-engine/package.json +1 -1
  97. package/packages/task-compiler/package.json +1 -1
  98. package/packages/tencentdb-memory/package.json +1 -1
  99. package/packages/tencentdb-sync/package.json +1 -1
  100. package/packages/test-data-generator/package.json +1 -1
  101. package/packages/test-generator/package.json +1 -1
  102. package/packages/todo-bd-sync/package.json +1 -1
  103. package/packages/token-estimation/package.json +1 -1
  104. package/packages/token-optimizer/package.json +1 -1
  105. package/packages/tooling-preference/package.json +1 -1
  106. package/packages/trajectory/package.json +1 -1
  107. package/packages/tui/package.json +1 -1
  108. package/packages/two-phase-review/package.json +1 -1
  109. package/packages/types/package.json +1 -1
  110. package/packages/voice-api/package.json +1 -1
  111. package/packages/webmcp-tester/package.json +1 -1
  112. package/packages/wiki/package.json +1 -1
  113. package/packages/workflow-events/package.json +1 -1
  114. package/packages/workspace-scanner/package.json +1 -1
  115. package/packages/worktree/package.json +1 -1
  116. package/packages/write-review/package.json +1 -1
  117. package/scripts/typecheck-packages.mjs +1 -1
  118. package/harness/task-graph.d.ts +0 -51
  119. package/packages/notification/adapters/email-adapter.ts +0 -126
  120. package/packages/notification/adapters/ntfy-adapter.ts +0 -100
  121. package/packages/notification/adapters/telegram-adapter.ts +0 -107
  122. package/packages/notification/adapters/webhook-adapter.ts +0 -75
  123. package/packages/notification/base-adapter.ts +0 -75
  124. package/packages/notification/index.ts +0 -51
  125. package/packages/notification/notification-center.ts +0 -286
  126. package/packages/notification/types.ts +0 -89
  127. package/packages/quota-manager/index.ts +0 -28
  128. package/packages/quota-manager/quota-manager.ts +0 -339
  129. package/packages/quota-manager/tui-usage-monitor.ts +0 -355
  130. package/packages/runtime/command-executor.ts +0 -523
  131. package/packages/runtime/index.ts +0 -50
  132. package/packages/runtime/local-runtime-agent.ts +0 -480
  133. package/packages/runtime/policy-engine.ts +0 -813
  134. package/packages/runtime/runtime-api.ts +0 -665
  135. package/packages/runtime/workspace-manager.ts +0 -591
  136. package/packages/types/src/ai-providers.d.ts +0 -36
  137. package/packages/types/src/ai-providers.js +0 -66
  138. package/packages/types/src/runtime-types.d.ts +0 -418
  139. package/packages/types/src/runtime-types.js +0 -3
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/two-phase-review",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "pi-harness-runtime — two-phase implementation and review workflow (queue review signals, gate the phase, scope the diff)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/types",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "Shared TypeScript types for pi-harness-runtime packages",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/voice-api",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "type": "module",
5
5
  "description": "Voice-to-text API using Whisper for Telegram and LINE integration",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/webmcp-tester",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "WebMCP-powered E2E testing for pi-harness - natural language test scenarios",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/wiki",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "LLM Wiki integration for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/workflow-events",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/workspace-scanner",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/worktree",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "pi-harness-runtime — worktree",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moocoding/write-review",
3
- "version": "1.1.429",
3
+ "version": "1.1.431",
4
4
  "description": "Two-agent write-review loop with blackboard coordination",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -32,7 +32,7 @@ const BASELINES = new Map([
32
32
  ["provider-router", 0],
33
33
  ["providers", 0],
34
34
  ["quota-manager", 0],
35
- ["runtime", 5],
35
+ ["runtime", 0],
36
36
  ["voice-api", 16],
37
37
  ["worktree", 0],
38
38
  ["harness", 20],
@@ -1,51 +0,0 @@
1
- /**
2
- * Task Graph Manager — RFC-0028 Phase 3
3
- *
4
- * Manages task dependency graph for compact-aware scheduling.
5
- * Currently a stub — integrates with CompactOrchestrator for
6
- * dependency-aware compaction prioritization.
7
- *
8
- * Future work:
9
- * - Track task dependencies (blocking/ready tasks)
10
- * - Prioritize compaction to keep blocking path messages
11
- * - Track which tasks depend on which checkpoint artifacts
12
- */
13
- import type { RuntimeTask } from "../packages/types/src/runtime-types.js";
14
- export interface TaskNode {
15
- task: RuntimeTask;
16
- dependencies: Set<string>;
17
- dependents: Set<string>;
18
- status: "pending" | "ready" | "running" | "done" | "blocked";
19
- }
20
- export interface TaskGraphManager {
21
- /** Add a task to the graph */
22
- addTask(task: RuntimeTask): void;
23
- /** Mark a task as done and update dependents */
24
- completeTask(taskId: string): void;
25
- /** Get tasks ready for execution */
26
- getReadyTasks(): RuntimeTask[];
27
- /** Get tasks blocked by a given task */
28
- getBlockedTasks(taskId: string): RuntimeTask[];
29
- /** Get all pending tasks */
30
- getPendingTasks(): RuntimeTask[];
31
- /** Get all tasks */
32
- getAllTasks(): RuntimeTask[];
33
- /** Get current progress summary */
34
- getProgressSummary(): {
35
- total: number;
36
- done: number;
37
- running: number;
38
- failed: number;
39
- };
40
- /** Get compact priority: tasks to keep in context vs prune */
41
- getCompactPriority(): {
42
- keep: string[];
43
- prune: string[];
44
- };
45
- }
46
- /**
47
- * Creates a new TaskGraphManager instance.
48
- * Stub implementation — returns minimal working graph.
49
- */
50
- export declare function createTaskGraphManager(): TaskGraphManager;
51
- //# sourceMappingURL=task-graph.d.ts.map
@@ -1,126 +0,0 @@
1
- /**
2
- * Email Adapter — RFC-0022
3
- *
4
- * Sends notifications via SMTP.
5
- */
6
-
7
- import type {
8
- NotificationPayload,
9
- NotificationResult,
10
- EmailConfig,
11
- } from "../types.js";
12
- import { BaseChannelAdapter } from "../base-adapter.js";
13
-
14
- // Simple SMTP client using built-in net module
15
- async function sendSmtpEmail(
16
- host: string,
17
- port: number,
18
- user: string,
19
- password: string,
20
- from: string,
21
- to: string[],
22
- subject: string,
23
- body: string,
24
- tls: boolean = false,
25
- ): Promise<void> {
26
- // For a production implementation, you'd use a proper SMTP library
27
- // This is a placeholder that logs the email
28
- console.log(`[Email] Would send to ${to.join(", ")}`);
29
- console.log(`[Email] Subject: ${subject}`);
30
- console.log(`[Email] Body: ${body}`);
31
-
32
- // In practice, you'd use something like:
33
- // import { createClient } from "nodemailer";
34
- // const transporter = nodemailer.createTransport({ ... });
35
- // await transporter.sendMail({ ... });
36
- }
37
-
38
- export class EmailAdapter extends BaseChannelAdapter {
39
- readonly id = "email";
40
- readonly type = "email";
41
-
42
- constructor(config: EmailConfig) {
43
- super({ id: "email", type: "email", enabled: true, config });
44
- }
45
-
46
- async initialize(): Promise<boolean> {
47
- // Verify SMTP connection
48
- try {
49
- const cfg = this.config.config as EmailConfig;
50
- // In production, verify SMTP credentials
51
- return Boolean(
52
- cfg.smtpHost && cfg.smtpUser && cfg.from && cfg.to.length > 0,
53
- );
54
- } catch {
55
- return false;
56
- }
57
- }
58
-
59
- async send(payload: NotificationPayload): Promise<NotificationResult> {
60
- try {
61
- const cfg = this.config.config as EmailConfig;
62
- const subject = `${this.getEmoji(payload.event)} ${payload.title}`;
63
- const body = this.formatBody(payload);
64
-
65
- await sendSmtpEmail(
66
- cfg.smtpHost,
67
- cfg.smtpPort,
68
- cfg.smtpUser,
69
- cfg.smtpPassword,
70
- cfg.from,
71
- cfg.to,
72
- subject,
73
- body,
74
- cfg.tls,
75
- );
76
-
77
- return { success: true, channel: this.id };
78
- } catch (error) {
79
- return {
80
- success: false,
81
- channel: this.id,
82
- error: String(error),
83
- };
84
- }
85
- }
86
-
87
- private formatBody(payload: NotificationPayload): string {
88
- const lines = [
89
- payload.message,
90
- "",
91
- "---",
92
- `Event: ${payload.event}`,
93
- `Time: ${payload.timestamp}`,
94
- ];
95
-
96
- if (payload.details?.taskTitle) {
97
- lines.push(`Task: ${payload.details.taskTitle}`);
98
- }
99
- if (payload.details?.jobId) {
100
- lines.push(`Job ID: ${payload.details.jobId}`);
101
- }
102
- if (payload.details?.error) {
103
- lines.push("", `Error: ${payload.details.error}`);
104
- }
105
-
106
- return lines.join("\n");
107
- }
108
-
109
- private getEmoji(event: NotificationPayload["event"]): string {
110
- const map: Record<string, string> = {
111
- JobStarted: "[🚀]",
112
- TaskCompleted: "[✅]",
113
- TaskFailed: "[❌]",
114
- QuotaPaused: "[⏸]",
115
- ResumeScheduled: "[▶]",
116
- ContextCompacted: "[📦]",
117
- OutputLimitContinued: "[🔄]",
118
- E2EFailed: "[🧪]",
119
- HumanReviewNeeded: "[👤]",
120
- ReadyForClient: "[🎉]",
121
- JobCancelled: "[🚫]",
122
- Error: "[⚠]",
123
- };
124
- return map[event] ?? "[📢]";
125
- }
126
- }
@@ -1,100 +0,0 @@
1
- /**
2
- * Ntfy Adapter — RFC-0022
3
- *
4
- * Sends notifications via ntfy.sh (or self-hosted ntfy server).
5
- */
6
-
7
- import type {
8
- NotificationPayload,
9
- NotificationResult,
10
- NtfyConfig,
11
- } from "../types.js";
12
- import { BaseChannelAdapter } from "../base-adapter.js";
13
-
14
- export class NtfyAdapter extends BaseChannelAdapter {
15
- readonly id = "ntfy";
16
- readonly type = "ntfy";
17
-
18
- constructor(config: NtfyConfig) {
19
- super({ id: "ntfy", type: "ntfy", enabled: true, config });
20
- }
21
-
22
- async initialize(): Promise<boolean> {
23
- // Ntfy doesn't require initialization; it's fire-and-forget
24
- return true;
25
- }
26
-
27
- async send(payload: NotificationPayload): Promise<NotificationResult> {
28
- try {
29
- const cfg = this.config.config as NtfyConfig;
30
- const message = this.formatMessage(payload);
31
- const headers: Record<string, string> = {
32
- "Content-Type": "text/plain",
33
- Title: payload.title,
34
- Tags: this.getTags(payload.event),
35
- };
36
-
37
- // Add auth if configured
38
- if (cfg.authToken) {
39
- headers["Authorization"] = `Bearer ${cfg.authToken}`;
40
- }
41
-
42
- const response = await fetch(`${cfg.server}/${cfg.topic}`, {
43
- method: "POST",
44
- headers,
45
- body: message,
46
- });
47
-
48
- if (!response.ok) {
49
- const error = await response.text();
50
- return {
51
- success: false,
52
- channel: this.id,
53
- error: `Ntfy error: ${error}`,
54
- };
55
- }
56
-
57
- return { success: true, channel: this.id };
58
- } catch (error) {
59
- return {
60
- success: false,
61
- channel: this.id,
62
- error: String(error),
63
- };
64
- }
65
- }
66
-
67
- private formatMessage(payload: NotificationPayload): string {
68
- const lines = [payload.message];
69
-
70
- if (payload.details?.taskTitle) {
71
- lines.push(`\nTask: ${payload.details.taskTitle}`);
72
- }
73
- if (payload.details?.jobId) {
74
- lines.push(`Job: ${payload.details.jobId}`);
75
- }
76
- if (payload.details?.error) {
77
- lines.push(`\nError: ${payload.details.error}`);
78
- }
79
-
80
- return lines.join("");
81
- }
82
-
83
- private getTags(event: NotificationPayload["event"]): string {
84
- const map: Record<string, string> = {
85
- JobStarted: "rocket",
86
- TaskCompleted: "white_check_mark",
87
- TaskFailed: "x",
88
- QuotaPaused: "pause_button",
89
- ResumeScheduled: "play_button",
90
- ContextCompacted: "package",
91
- OutputLimitContinued: "repeat",
92
- E2EFailed: "test_tube",
93
- HumanReviewNeeded: "bust_in_silhouette",
94
- ReadyForClient: "tada",
95
- JobCancelled: "no_entry",
96
- Error: "warning",
97
- };
98
- return map[event] ?? "bell";
99
- }
100
- }
@@ -1,107 +0,0 @@
1
- /**
2
- * Telegram Adapter — RFC-0022
3
- *
4
- * Sends notifications via Telegram Bot API.
5
- */
6
-
7
- import type {
8
- NotificationPayload,
9
- NotificationResult,
10
- TelegramConfig,
11
- } from "../types.js";
12
- import { BaseChannelAdapter } from "../base-adapter.js";
13
-
14
- export class TelegramAdapter extends BaseChannelAdapter {
15
- readonly id = "telegram";
16
- readonly type = "telegram";
17
-
18
- constructor(config: TelegramConfig) {
19
- super({ id: "telegram", type: "telegram", enabled: true, config });
20
- }
21
-
22
- async initialize(): Promise<boolean> {
23
- try {
24
- const cfg = this.config.config as TelegramConfig;
25
- // Verify bot token by calling getMe
26
- const response = await fetch(
27
- `https://api.telegram.org/bot${cfg.botToken}/getMe`,
28
- );
29
- return response.ok;
30
- } catch {
31
- return false;
32
- }
33
- }
34
-
35
- async send(payload: NotificationPayload): Promise<NotificationResult> {
36
- try {
37
- const cfg = this.config.config as TelegramConfig;
38
- const message = this.formatMessage(payload);
39
-
40
- const response = await fetch(
41
- `https://api.telegram.org/bot${cfg.botToken}/sendMessage`,
42
- {
43
- method: "POST",
44
- headers: { "Content-Type": "application/json" },
45
- body: JSON.stringify({
46
- chat_id: cfg.chatId,
47
- text: message,
48
- parse_mode: cfg.parseMode ?? "MarkdownV2",
49
- }),
50
- },
51
- );
52
-
53
- if (!response.ok) {
54
- const error = await response.text();
55
- return {
56
- success: false,
57
- channel: this.id,
58
- error: `Telegram API error: ${error}`,
59
- };
60
- }
61
-
62
- return { success: true, channel: this.id };
63
- } catch (error) {
64
- return {
65
- success: false,
66
- channel: this.id,
67
- error: String(error),
68
- };
69
- }
70
- }
71
-
72
- private formatMessage(payload: NotificationPayload): string {
73
- const emoji = this.getEmoji(payload.event);
74
- const title = `${emoji} ${payload.title}`;
75
- const lines = [title, "", payload.message];
76
-
77
- if (payload.details?.taskTitle) {
78
- lines.push("", `Task: ${payload.details.taskTitle}`);
79
- }
80
- if (payload.details?.jobId) {
81
- lines.push(`Job: ${payload.details.jobId}`);
82
- }
83
- if (payload.details?.error) {
84
- lines.push("", `Error: ${payload.details.error}`);
85
- }
86
-
87
- return lines.filter(Boolean).join("\n");
88
- }
89
-
90
- private getEmoji(event: NotificationPayload["event"]): string {
91
- const map: Record<string, string> = {
92
- JobStarted: "🚀",
93
- TaskCompleted: "✅",
94
- TaskFailed: "❌",
95
- QuotaPaused: "⏸️",
96
- ResumeScheduled: "▶️",
97
- ContextCompacted: "📦",
98
- OutputLimitContinued: "🔄",
99
- E2EFailed: "🧪",
100
- HumanReviewNeeded: "👤",
101
- ReadyForClient: "🎉",
102
- JobCancelled: "🚫",
103
- Error: "⚠️",
104
- };
105
- return map[event] ?? "📢";
106
- }
107
- }
@@ -1,75 +0,0 @@
1
- /**
2
- * Webhook Adapter — RFC-0022
3
- *
4
- * Sends notifications to a generic webhook endpoint.
5
- */
6
-
7
- import type {
8
- NotificationPayload,
9
- NotificationResult,
10
- WebhookConfig,
11
- } from "../types.js";
12
- import { BaseChannelAdapter } from "../base-adapter.js";
13
-
14
- export class WebhookAdapter extends BaseChannelAdapter {
15
- readonly id = "webhook";
16
- readonly type = "webhook";
17
-
18
- constructor(config: WebhookConfig) {
19
- super({ id: "webhook", type: "webhook", enabled: true, config });
20
- }
21
-
22
- async initialize(): Promise<boolean> {
23
- try {
24
- const cfg = this.config.config as WebhookConfig;
25
- return Boolean(cfg.url && cfg.url.startsWith("http"));
26
- } catch {
27
- return false;
28
- }
29
- }
30
-
31
- async send(payload: NotificationPayload): Promise<NotificationResult> {
32
- try {
33
- const cfg = this.config.config as WebhookConfig;
34
- const headers: Record<string, string> = {
35
- "Content-Type": "application/json",
36
- ...(cfg.headers ?? {}),
37
- };
38
-
39
- // Add auth token if configured
40
- if (cfg.authToken) {
41
- headers["Authorization"] = `Bearer ${cfg.authToken}`;
42
- }
43
-
44
- const response = await fetch(cfg.url, {
45
- method: cfg.method ?? "POST",
46
- headers,
47
- body: JSON.stringify({
48
- event: payload.event,
49
- jobId: payload.jobId,
50
- timestamp: payload.timestamp,
51
- title: payload.title,
52
- message: payload.message,
53
- details: payload.details,
54
- }),
55
- });
56
-
57
- if (!response.ok) {
58
- const error = await response.text();
59
- return {
60
- success: false,
61
- channel: this.id,
62
- error: `Webhook error ${response.status}: ${error}`,
63
- };
64
- }
65
-
66
- return { success: true, channel: this.id };
67
- } catch (error) {
68
- return {
69
- success: false,
70
- channel: this.id,
71
- error: String(error),
72
- };
73
- }
74
- }
75
- }
@@ -1,75 +0,0 @@
1
- /**
2
- * Notification Base Adapter — RFC-0022
3
- *
4
- * Abstract base class for all notification channel adapters.
5
- */
6
-
7
- import type {
8
- NotificationPayload,
9
- NotificationChannelConfig,
10
- NotificationResult,
11
- } from "./types.js";
12
-
13
- export interface ChannelAdapter {
14
- readonly id: string;
15
- readonly type: string;
16
-
17
- /**
18
- * Initialize the adapter (e.g., verify credentials)
19
- */
20
- initialize(): Promise<boolean>;
21
-
22
- /**
23
- * Send a notification
24
- */
25
- send(payload: NotificationPayload): Promise<NotificationResult>;
26
-
27
- /**
28
- * Check if the adapter is properly configured
29
- */
30
- isConfigured(): boolean;
31
- }
32
-
33
- export abstract class BaseChannelAdapter implements ChannelAdapter {
34
- abstract readonly id: string;
35
- abstract readonly type: string;
36
-
37
- constructor(protected config: NotificationChannelConfig) {}
38
-
39
- abstract initialize(): Promise<boolean>;
40
- abstract send(payload: NotificationPayload): Promise<NotificationResult>;
41
-
42
- isConfigured(): boolean {
43
- return this.config.enabled;
44
- }
45
-
46
- /**
47
- * Redact sensitive data from payload before sending
48
- */
49
- protected redact(
50
- payload: NotificationPayload,
51
- patterns: RegExp[],
52
- ): NotificationPayload {
53
- if (patterns.length === 0) return payload;
54
-
55
- const redacted: string[] = [];
56
- const details = payload.details ? { ...payload.details } : {};
57
-
58
- for (const [key, value] of Object.entries(details)) {
59
- const valStr = String(value);
60
- for (const pattern of patterns) {
61
- if (pattern.test(valStr)) {
62
- redacted.push(key);
63
- (details as Record<string, unknown>)[key] = "[REDACTED]";
64
- break;
65
- }
66
- }
67
- }
68
-
69
- return {
70
- ...payload,
71
- details,
72
- redacted: redacted.length > 0 ? redacted : undefined,
73
- };
74
- }
75
- }
@@ -1,51 +0,0 @@
1
- /**
2
- * Notification Center — RFC-0022
3
- *
4
- * Mobile notification system for harness runtime events.
5
- *
6
- * @example
7
- * ```typescript
8
- * import { NotificationCenter } from "./notification/index.js";
9
- *
10
- * const center = new NotificationCenter({
11
- * channels: [
12
- * {
13
- * id: "my-telegram",
14
- * type: "telegram",
15
- * enabled: true,
16
- * config: {
17
- * botToken: process.env.TELEGRAM_BOT_TOKEN,
18
- * chatId: "YOUR_CHAT_ID",
19
- * },
20
- * },
21
- * ],
22
- * });
23
- *
24
- * await center.initialize();
25
- *
26
- * await center.notify("JobStarted", {
27
- * jobId: "job-123",
28
- * requirement: "Build a REST API",
29
- * });
30
- * ```
31
- */
32
-
33
- export { NotificationCenter } from "./notification-center.js";
34
- export { TelegramAdapter } from "./adapters/telegram-adapter.js";
35
- export { NtfyAdapter } from "./adapters/ntfy-adapter.js";
36
- export { EmailAdapter } from "./adapters/email-adapter.js";
37
- export { WebhookAdapter } from "./adapters/webhook-adapter.js";
38
-
39
- export type {
40
- NotificationEvent,
41
- NotificationPayload,
42
- NotificationConfig,
43
- NotificationChannelConfig,
44
- NotificationChannelType,
45
- NotificationResult,
46
- NotificationContext,
47
- TelegramConfig,
48
- NtfyConfig,
49
- EmailConfig,
50
- WebhookConfig,
51
- } from "./types.js";