@teamvibe/poller 0.1.52 → 0.1.53

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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Scan for JSON maintenance reports in the brain's reports/ directory
3
+ * and POST each to the /events endpoint. Fire-and-forget — never throws.
4
+ */
5
+ export declare function postMaintenanceReports(brainPath: string, channelId: string): Promise<void>;
@@ -0,0 +1,68 @@
1
+ import { readdir, readFile, unlink } from 'fs/promises';
2
+ import { join } from 'path';
3
+ import { config } from './config.js';
4
+ import { logger } from './logger.js';
5
+ const OPERATION_TO_EVENT_TYPE = {
6
+ consolidation: 'maintenance.consolidation',
7
+ reflection: 'maintenance.reflection',
8
+ };
9
+ /**
10
+ * Scan for JSON maintenance reports in the brain's reports/ directory
11
+ * and POST each to the /events endpoint. Fire-and-forget — never throws.
12
+ */
13
+ export async function postMaintenanceReports(brainPath, channelId) {
14
+ if (!config.TEAMVIBE_API_URL || !config.TEAMVIBE_POLLER_TOKEN) {
15
+ return;
16
+ }
17
+ const reportsDir = join(brainPath, 'reports');
18
+ try {
19
+ const files = await readdir(reportsDir).catch(() => []);
20
+ const jsonFiles = files.filter((f) => f.endsWith('.json'));
21
+ if (jsonFiles.length === 0)
22
+ return;
23
+ logger.info(`[MaintenanceReporter] Found ${jsonFiles.length} JSON report(s) in ${reportsDir}`);
24
+ for (const file of jsonFiles) {
25
+ const filePath = join(reportsDir, file);
26
+ try {
27
+ const content = await readFile(filePath, 'utf-8');
28
+ const report = JSON.parse(content);
29
+ if (!report.operationType) {
30
+ logger.warn(`[MaintenanceReporter] Skipping ${file}: missing operationType`);
31
+ continue;
32
+ }
33
+ const eventType = OPERATION_TO_EVENT_TYPE[report.operationType];
34
+ if (!eventType) {
35
+ logger.warn(`[MaintenanceReporter] Skipping ${file}: unknown operationType "${report.operationType}"`);
36
+ continue;
37
+ }
38
+ const payload = {
39
+ eventType,
40
+ channelId,
41
+ metadata: report,
42
+ };
43
+ const response = await fetch(`${config.TEAMVIBE_API_URL}/events`, {
44
+ method: 'POST',
45
+ headers: {
46
+ 'Content-Type': 'application/json',
47
+ Authorization: `Bearer ${config.TEAMVIBE_POLLER_TOKEN}`,
48
+ },
49
+ body: JSON.stringify(payload),
50
+ });
51
+ if (response.ok) {
52
+ logger.info(`[MaintenanceReporter] Posted ${file} as ${eventType}`);
53
+ await unlink(filePath).catch(() => { });
54
+ }
55
+ else {
56
+ const errorBody = await response.text().catch(() => 'unknown');
57
+ logger.warn(`[MaintenanceReporter] Failed to POST ${file}: ${response.status} ${errorBody}`);
58
+ }
59
+ }
60
+ catch (err) {
61
+ logger.warn(`[MaintenanceReporter] Error processing ${file}: ${err instanceof Error ? err.message : err}`);
62
+ }
63
+ }
64
+ }
65
+ catch (err) {
66
+ logger.warn(`[MaintenanceReporter] Error scanning reports: ${err instanceof Error ? err.message : err}`);
67
+ }
68
+ }
package/dist/poller.js CHANGED
@@ -5,6 +5,7 @@ import { spawnClaudeCode, isAtCapacity, getActiveProcessCount, killAllActiveProc
5
5
  import { sendSlackError, addReaction, getUserInfo, startTypingIndicator } from './slack-client.js';
6
6
  import { acquireSessionLock, releaseSessionLock, updateSessionId } from './session-store.js';
7
7
  import { getBrainPath, ensureDirectories, ensureBaseBrain, pushBrainChanges } from './brain-manager.js';
8
+ import { postMaintenanceReports } from './maintenance-reporter.js';
8
9
  import { initAuth, stopRefresh } from './auth-provider.js';
9
10
  import { registerBrain, startHeartbeatLoop, stopHeartbeatLoop } from './heartbeat-manager.js';
10
11
  // Track active message processing
@@ -183,6 +184,8 @@ async function processMessage(received) {
183
184
  if (queueMessage.teamvibe.brain?.brainId) {
184
185
  await pushBrainChanges(kbPath, queueMessage.teamvibe.brain.brainId, queueMessage.teamvibe.workspaceId);
185
186
  }
187
+ // Post any pending maintenance reports (fire-and-forget)
188
+ await postMaintenanceReports(kbPath, queueMessage.teamvibe.channelId);
186
189
  if (lockToken) {
187
190
  const lastMessageTs = queueMessage.response_context.slack?.message_ts;
188
191
  await releaseSessionLock(threadId, lockToken, 'idle', lastMessageTs);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamvibe/poller",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "bin": {