@poolzin/pool-bot 2026.1.29 → 2026.1.30

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 (39) hide show
  1. package/CHANGELOG.md +29 -1
  2. package/README.md +11 -0
  3. package/dist/agents/system-prompt.js +16 -16
  4. package/dist/agents/tools/memory-tool.js +2 -1
  5. package/dist/build-info.json +3 -3
  6. package/dist/cli/program/command-registry.js +5 -0
  7. package/dist/cli/program/register.completion.js +355 -0
  8. package/dist/gateway/hooks/index.js +53 -0
  9. package/dist/gateway/hooks/lifecycle-hooks-integration.js +256 -0
  10. package/dist/gateway/hooks/lifecycle-hooks.js +236 -0
  11. package/dist/gateway/hooks/progressive-disclosure-details.js +237 -0
  12. package/dist/gateway/hooks/progressive-disclosure-index.js +354 -0
  13. package/dist/gateway/hooks/progressive-disclosure-timeline.js +231 -0
  14. package/dist/gateway/hooks/progressive-disclosure-types.js +65 -0
  15. package/dist/gateway/hooks/progressive-disclosure.js +242 -0
  16. package/dist/gateway/hooks/tool-usage-capture.js +253 -0
  17. package/dist/gateway/hooks/tool-usage-storage.js +144 -0
  18. package/dist/gateway/server-methods/nodes.js +2 -0
  19. package/dist/gateway/server.impl.js +4 -0
  20. package/dist/imessage/monitor/monitor-provider.js +14 -1
  21. package/dist/media/store.js +37 -1
  22. package/dist/memory/index.js +5 -0
  23. package/dist/memory/manager.js +25 -2
  24. package/docs/WHATSAPP-HEARTBEAT-TROUBLESHOOTING.md +319 -0
  25. package/package.json +1 -1
  26. package/skills/webgpu-threejs-tsl/REFERENCE.md +283 -0
  27. package/skills/webgpu-threejs-tsl/SKILL.md +91 -0
  28. package/skills/webgpu-threejs-tsl/docs/compute-shaders.md +404 -0
  29. package/skills/webgpu-threejs-tsl/docs/core-concepts.md +453 -0
  30. package/skills/webgpu-threejs-tsl/docs/materials.md +353 -0
  31. package/skills/webgpu-threejs-tsl/docs/post-processing.md +434 -0
  32. package/skills/webgpu-threejs-tsl/docs/wgsl-integration.md +324 -0
  33. package/skills/webgpu-threejs-tsl/examples/basic-setup.js +87 -0
  34. package/skills/webgpu-threejs-tsl/examples/custom-material.js +170 -0
  35. package/skills/webgpu-threejs-tsl/examples/earth-shader.js +292 -0
  36. package/skills/webgpu-threejs-tsl/examples/particle-system.js +259 -0
  37. package/skills/webgpu-threejs-tsl/examples/post-processing.js +199 -0
  38. package/skills/webgpu-threejs-tsl/templates/compute-shader.js +305 -0
  39. package/skills/webgpu-threejs-tsl/templates/webgpu-project.js +276 -0
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Progressive Disclosure - Timeline Layer (Phase 3)
3
+ *
4
+ * Load contextual timeline information for search results
5
+ * Safe: Read-only, lazy loading, batched I/O
6
+ *
7
+ * Purpose:
8
+ * - After user sees index results, load timeline context
9
+ * - Provides: Date summaries, result counts, temporal context
10
+ * - Called only when user drills down (not automatic)
11
+ */
12
+ import { readFile } from "node:fs/promises";
13
+ import { join } from "node:path";
14
+ // ============================================================================
15
+ // Constants
16
+ // ============================================================================
17
+ const MEMORY_DIR = "/root/pool";
18
+ const MAX_SUMMARY_LENGTH = 300;
19
+ // ============================================================================
20
+ // Timeline Layer Implementation
21
+ // ============================================================================
22
+ /**
23
+ * Load timeline context for given result IDs
24
+ * Safe: Read-only, handles errors gracefully
25
+ *
26
+ * @param ids - Result IDs (format: "memory/YYYY-MM-DD.md#L123")
27
+ * @returns Map of date strings to TimelineEntry
28
+ */
29
+ export async function loadTimelineContext(ids) {
30
+ // Validate inputs
31
+ if (!ids || ids.length === 0) {
32
+ return {};
33
+ }
34
+ try {
35
+ // Extract unique dates from IDs
36
+ const dates = extractUniqueDates(ids);
37
+ // Load timeline for each date
38
+ const timeline = {};
39
+ for (const date of dates) {
40
+ const entry = await loadTimelineForDate(date);
41
+ if (entry) {
42
+ timeline[date] = entry;
43
+ }
44
+ }
45
+ return timeline;
46
+ }
47
+ catch (err) {
48
+ console.error("[pd-timeline] Failed to load timeline:", err);
49
+ return {};
50
+ }
51
+ }
52
+ /**
53
+ * Extract unique dates from result IDs
54
+ * Safe: Handles invalid ID formats gracefully
55
+ */
56
+ function extractUniqueDates(ids) {
57
+ const dates = new Set();
58
+ for (const id of ids) {
59
+ try {
60
+ // Extract date from ID: "memory/2026-02-04.md#L123" -> "2026-02-04"
61
+ const match = id.match(/(\d{4}-\d{2}-\d{2})\.md/);
62
+ if (match) {
63
+ dates.add(match[1]);
64
+ }
65
+ }
66
+ catch (err) {
67
+ // Skip invalid IDs
68
+ if (PROGRESSIVE_DISCLOSURE_FLAGS.DEBUG_MODE) {
69
+ console.warn(`[pd-timeline] Invalid ID format: ${id}`);
70
+ }
71
+ }
72
+ }
73
+ return Array.from(dates).sort(); // Sort chronologically
74
+ }
75
+ /**
76
+ * Load timeline entry for a specific date
77
+ * Safe: Returns null if file doesn't exist or can't be read
78
+ */
79
+ async function loadTimelineForDate(date) {
80
+ try {
81
+ // Try daily memory file first
82
+ const dailyPath = join(MEMORY_DIR, "memory", `${date}.md`);
83
+ const content = await readFile(dailyPath, "utf-8");
84
+ return parseTimelineEntry(date, content);
85
+ }
86
+ catch (err) {
87
+ // Daily file doesn't exist, try MEMORY.md
88
+ if (err.code === "ENOENT") {
89
+ try {
90
+ const memoryPath = join(MEMORY_DIR, "MEMORY.md");
91
+ const content = await readFile(memoryPath, "utf-8");
92
+ // For MEMORY.md, use today's date
93
+ return parseTimelineEntry(date, content);
94
+ }
95
+ catch (memoryErr) {
96
+ // MEMORY.md also doesn't exist or can't be read
97
+ return null;
98
+ }
99
+ }
100
+ // Other error (permission, etc)
101
+ return null;
102
+ }
103
+ }
104
+ /**
105
+ * Parse timeline entry from content
106
+ * Safe: Handles malformed content gracefully
107
+ */
108
+ function parseTimelineEntry(date, content) {
109
+ // Extract title (first heading)
110
+ const title = extractTitle(content) || `Memory: ${date}`;
111
+ // Extract summary (first paragraph or heading)
112
+ const summary = extractSummary(content);
113
+ // Count results (rough estimate: count headings)
114
+ const resultCount = countHeadings(content);
115
+ return {
116
+ date,
117
+ title,
118
+ summary,
119
+ resultCount,
120
+ };
121
+ }
122
+ /**
123
+ * Extract title from content (first # heading)
124
+ */
125
+ function extractTitle(content) {
126
+ const match = content.match(/^#\s+(.+)$/m);
127
+ return match ? match[1].trim() : undefined;
128
+ }
129
+ /**
130
+ * Extract summary from content
131
+ * Safe: Returns first meaningful text
132
+ */
133
+ function extractSummary(content) {
134
+ // Try to find first paragraph
135
+ const lines = content.split("\n");
136
+ for (const line of lines) {
137
+ const trimmed = line.trim();
138
+ // Skip empty lines, headings, code blocks
139
+ if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("```")) {
140
+ continue;
141
+ }
142
+ // Found first paragraph
143
+ if (trimmed.length > MAX_SUMMARY_LENGTH) {
144
+ return trimmed.slice(0, MAX_SUMMARY_LENGTH) + "...";
145
+ }
146
+ return trimmed;
147
+ }
148
+ // No summary found, return generic
149
+ return "No summary available";
150
+ }
151
+ /**
152
+ * Count headings in content (rough result count estimate)
153
+ */
154
+ function countHeadings(content) {
155
+ const matches = content.match(/^#{2,}\s+.+$/gm);
156
+ return matches ? matches.length : 0;
157
+ }
158
+ // ============================================================================
159
+ // Batch Loading (Performance Optimization)
160
+ // ============================================================================
161
+ /**
162
+ * Load timeline for multiple date ranges in parallel
163
+ * Safe: Limits concurrency, handles errors
164
+ *
165
+ * @param dateRanges - Array of date ranges to load
166
+ * @returns Map of dates to TimelineEntry
167
+ */
168
+ export async function loadTimelineBatch(dateRanges) {
169
+ const timeline = {};
170
+ // Process ranges in parallel (with limit)
171
+ const promises = dateRanges.map((range) => loadDateRange(range));
172
+ const results = await Promise.allSettled(promises);
173
+ // Merge results
174
+ for (const result of results) {
175
+ if (result.status === "fulfilled") {
176
+ Object.assign(timeline, result.value);
177
+ }
178
+ }
179
+ return timeline;
180
+ }
181
+ /**
182
+ * Load timeline for a date range
183
+ */
184
+ async function loadDateRange(range) {
185
+ const timeline = {};
186
+ const startDate = new Date(range.start);
187
+ const endDate = new Date(range.end);
188
+ const currentDate = new Date(startDate);
189
+ while (currentDate <= endDate) {
190
+ const dateStr = currentDate.toISOString().split("T")[0];
191
+ const entry = await loadTimelineForDate(dateStr);
192
+ if (entry) {
193
+ timeline[dateStr] = entry;
194
+ }
195
+ // Next day
196
+ currentDate.setDate(currentDate.getDate() + 1);
197
+ }
198
+ return timeline;
199
+ }
200
+ // ============================================================================
201
+ // Utilities (for testing)
202
+ // ============================================================================
203
+ /**
204
+ * Parse date from result ID
205
+ * Safe: Returns null if invalid format
206
+ */
207
+ export function parseDateFromId(id) {
208
+ const match = id.match(/(\d{4}-\d{2}-\d{2})\.md/);
209
+ return match ? match[1] : null;
210
+ }
211
+ /**
212
+ * Format date for display
213
+ * Safe: Returns original if invalid format
214
+ */
215
+ export function formatTimelineDate(date) {
216
+ try {
217
+ const d = new Date(date);
218
+ return d.toLocaleDateString("en-US", {
219
+ year: "numeric",
220
+ month: "short",
221
+ day: "numeric",
222
+ });
223
+ }
224
+ catch {
225
+ return date;
226
+ }
227
+ }
228
+ // ============================================================================
229
+ // Feature Flags (imported from types)
230
+ // ============================================================================
231
+ import { PROGRESSIVE_DISCLOSURE_FLAGS } from "./progressive-disclosure-types.js";
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Progressive Disclosure - Type Definitions
3
+ *
4
+ * Phase 1: Type definitions for memory search v2
5
+ * Safe: All new types, backward compatible, no breaking changes
6
+ *
7
+ * Concept:
8
+ * - Layer 1 (index): IDs + snippets (~90% token savings)
9
+ * - Layer 2 (timeline): Contextual information by date
10
+ * - Layer 3 (details): Full content on-demand
11
+ */
12
+ // ============================================================================
13
+ // Feature Flags
14
+ // ============================================================================
15
+ /**
16
+ * Progressive disclosure feature flags
17
+ */
18
+ export const PROGRESSIVE_DISCLOSURE_FLAGS = {
19
+ /**
20
+ * Master switch for progressive disclosure
21
+ * Default: false (opt-in for safety)
22
+ */
23
+ ENABLED: false,
24
+ /**
25
+ * Enable index caching (performance optimization)
26
+ * Default: true (safe to enable)
27
+ */
28
+ CACHE_ENABLED: true,
29
+ /**
30
+ * Maximum cache size (number of entries)
31
+ * Default: 100
32
+ */
33
+ CACHE_MAX_SIZE: 100,
34
+ /**
35
+ * Cache TTL in milliseconds (5 minutes)
36
+ * Default: 300000
37
+ */
38
+ CACHE_TTL_MS: 300000,
39
+ /**
40
+ * Enable debug logging
41
+ * Default: false
42
+ */
43
+ DEBUG_MODE: false,
44
+ };
45
+ // ============================================================================
46
+ // Type Guards (safe runtime checking)
47
+ // ============================================================================
48
+ /**
49
+ * Check if search result is success
50
+ */
51
+ export function isSearchSuccess(result) {
52
+ return result.success === true;
53
+ }
54
+ /**
55
+ * Check if search result is error
56
+ */
57
+ export function isSearchError(result) {
58
+ return result.success === false;
59
+ }
60
+ /**
61
+ * Check if layer is valid
62
+ */
63
+ export function isValidLayer(layer) {
64
+ return layer === "index" || layer === "timeline" || layer === "details";
65
+ }
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Progressive Disclosure - Integration Layer (Phase 5)
3
+ *
4
+ * Main entry point: memory_search_v2
5
+ * Safe: Feature-flagged, backward compatible, never throws
6
+ *
7
+ * This is the ONLY file that exports the public API.
8
+ * All other files are internal implementation details.
9
+ */
10
+ import { PROGRESSIVE_DISCLOSURE_FLAGS } from "./progressive-disclosure-types.js";
11
+ import { searchIndexOnly, clearIndexCache } from "./progressive-disclosure-index.js";
12
+ import { loadTimelineContext } from "./progressive-disclosure-timeline.js";
13
+ import { loadFullDetails, resetRateLimiter } from "./progressive-disclosure-details.js";
14
+ // ============================================================================
15
+ // Feature Flag (MASTER SWITCH)
16
+ // ============================================================================
17
+ /**
18
+ * Main feature flag for progressive disclosure
19
+ * Default: OFF (opt-in for safety)
20
+ *
21
+ * To enable: Set PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED = true
22
+ * To disable: Set PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED = false
23
+ *
24
+ * When disabled: memory_search_v2 throws error "Progressive disclosure not enabled"
25
+ * When enabled: memory_search_v2 works normally
26
+ */
27
+ export const PROGRESSIVE_DISCLOSURE_ENABLED = PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED;
28
+ // ============================================================================
29
+ // Main API: memory_search_v2
30
+ // ============================================================================
31
+ /**
32
+ * Progressive disclosure memory search v2
33
+ *
34
+ * 3-layer search for token efficiency:
35
+ * - Layer 1 (index): IDs + snippets (~90% token savings)
36
+ * - Layer 2 (timeline): Contextual information by date
37
+ * - Layer 3 (details): Full content on-demand
38
+ *
39
+ * Safe:
40
+ * - Feature-flagged (throws when disabled)
41
+ * - Never throws (returns error object on failure)
42
+ * - Backward compatible (memory_search v1 still works)
43
+ *
44
+ * @param query - Search query string
45
+ * @param options - Search options (layer, maxResults, filters)
46
+ * @returns Search result or error object (never throws)
47
+ *
48
+ * @example
49
+ * ```ts
50
+ * // Index only (default, fastest)
51
+ * const result = await memory_search_v2('decision');
52
+ * // → { index: [...], timeline: {}, details: {} }
53
+ *
54
+ * // Index + timeline
55
+ * const result = await memory_search_v2('decision', { layer: 'timeline' });
56
+ * // → { index: [...], timeline: {...}, details: {} }
57
+ *
58
+ * // Full details (slowest, most tokens)
59
+ * const result = await memory_search_v2('decision', { layer: 'details' });
60
+ * // → { index: [...], timeline: {...}, details: {...} }
61
+ * ```
62
+ */
63
+ export async function memory_search_v2(query, options = {}) {
64
+ // Feature flag check (safe exit)
65
+ if (!PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED) {
66
+ return {
67
+ success: false,
68
+ error: {
69
+ code: "FEATURE_DISABLED",
70
+ message: "Progressive disclosure is not enabled. Set PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED = true to use memory_search_v2.",
71
+ query,
72
+ recoverable: false,
73
+ },
74
+ };
75
+ }
76
+ const startTime = Date.now();
77
+ try {
78
+ // Validate inputs
79
+ const safeQuery = query?.trim() || "";
80
+ if (!safeQuery) {
81
+ return {
82
+ success: false,
83
+ error: {
84
+ code: "INVALID_QUERY",
85
+ message: "Query cannot be empty",
86
+ query,
87
+ recoverable: false,
88
+ },
89
+ };
90
+ }
91
+ const layer = options.layer || "index";
92
+ const maxResults = options.maxResults || 10;
93
+ // Execute search (layer by layer)
94
+ const result = await executeSearch(safeQuery, layer, maxResults, options);
95
+ return {
96
+ success: true,
97
+ data: result,
98
+ };
99
+ }
100
+ catch (err) {
101
+ // Never throw: return error object
102
+ return {
103
+ success: false,
104
+ error: {
105
+ code: "SEARCH_FAILED",
106
+ message: err instanceof Error ? err.message : "Unknown error",
107
+ query,
108
+ layer: options.layer,
109
+ recoverable: true,
110
+ },
111
+ };
112
+ }
113
+ finally {
114
+ if (PROGRESSIVE_DISCLOSURE_FLAGS.DEBUG_MODE) {
115
+ const duration = Date.now() - startTime;
116
+ console.log(`[pd-v2] Search completed in ${duration}ms`);
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * Execute search layer by layer
122
+ * Safe: Handles all errors, returns complete result
123
+ */
124
+ async function executeSearch(query, layer, maxResults, options) {
125
+ const startTime = Date.now();
126
+ // Layer 1: Index (always executed)
127
+ const index = await searchIndexOnly(query, {
128
+ maxResults,
129
+ threshold: options.threshold,
130
+ tags: options.tags,
131
+ dateRange: options.dateRange,
132
+ });
133
+ // Layer 2: Timeline (optional)
134
+ let timeline = {};
135
+ if (layer === "timeline" || layer === "details") {
136
+ const ids = index.map((r) => r.id);
137
+ timeline = await loadTimelineContext(ids);
138
+ }
139
+ // Layer 3: Details (optional)
140
+ let details = {};
141
+ if (layer === "details") {
142
+ const ids = index.map((r) => r.id);
143
+ details = await loadFullDetails(ids);
144
+ }
145
+ const executionTimeMs = Date.now() - startTime;
146
+ // Estimate token usage (rough approximation)
147
+ const tokensEstimated = {
148
+ index: index.length * 50, // ~50 tokens per index result
149
+ timeline: Object.keys(timeline).length * 100, // ~100 tokens per timeline entry
150
+ details: Object.values(details).reduce((sum, d) => sum + (d?.content?.length || 0) / 4, 0), // ~4 chars per token
151
+ total: 0, // Calculated below
152
+ };
153
+ tokensEstimated.total =
154
+ tokensEstimated.index + tokensEstimated.timeline + tokensEstimated.details;
155
+ return {
156
+ query,
157
+ layer,
158
+ index,
159
+ timeline: timeline,
160
+ details: details,
161
+ metadata: {
162
+ totalResults: index.length,
163
+ executionTimeMs,
164
+ layerExecuted: layer,
165
+ tokensEstimated: tokensEstimated,
166
+ timestamp: Date.now(),
167
+ },
168
+ };
169
+ }
170
+ // ============================================================================
171
+ // Convenience Functions (for ease of use)
172
+ // ============================================================================
173
+ /**
174
+ * Search index only (fastest, least tokens)
175
+ * Convenience wrapper for memory_search_v2(query, { layer: 'index' })
176
+ */
177
+ export async function searchIndex(query, maxResults) {
178
+ return memory_search_v2(query, { layer: "index", maxResults });
179
+ }
180
+ /**
181
+ * Search with timeline (medium speed, medium tokens)
182
+ * Convenience wrapper for memory_search_v2(query, { layer: 'timeline' })
183
+ */
184
+ export async function searchTimeline(query, maxResults) {
185
+ return memory_search_v2(query, { layer: "timeline", maxResults });
186
+ }
187
+ /**
188
+ * Search with full details (slowest, most tokens)
189
+ * Convenience wrapper for memory_search_v2(query, { layer: 'details' })
190
+ */
191
+ export async function searchDetails(query, maxResults) {
192
+ return memory_search_v2(query, { layer: "details", maxResults });
193
+ }
194
+ // ============================================================================
195
+ // Cache Management (for testing and optimization)
196
+ // ============================================================================
197
+ /**
198
+ * Clear all progressive disclosure caches
199
+ * Safe: No-op when feature flag is disabled
200
+ */
201
+ export function clearProgressiveDisclosureCache() {
202
+ if (!PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED) {
203
+ return;
204
+ }
205
+ clearIndexCache();
206
+ }
207
+ /**
208
+ * Reset progressive disclosure state (for testing)
209
+ * Safe: No-op when feature flag is disabled
210
+ */
211
+ export function resetProgressiveDisclosure() {
212
+ if (!PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED) {
213
+ return;
214
+ }
215
+ clearIndexCache();
216
+ resetRateLimiter();
217
+ }
218
+ // ============================================================================
219
+ // Statistics (for monitoring and debugging)
220
+ // ============================================================================
221
+ /**
222
+ * Get progressive disclosure statistics
223
+ * Safe: Returns empty stats when feature flag is disabled
224
+ */
225
+ export function getProgressiveDisclosureStats() {
226
+ if (!PROGRESSIVE_DISCLOSURE_FLAGS.ENABLED) {
227
+ return {
228
+ enabled: false,
229
+ cache: { size: 0 },
230
+ rateLimiter: { lastLoadTime: 0 },
231
+ };
232
+ }
233
+ // Import dynamically to avoid circular dependencies
234
+ const { getIndexCacheStats } = require("./progressive-disclosure-index.js");
235
+ const { getRateLimiterStats } = require("./progressive-disclosure-details.js");
236
+ return {
237
+ enabled: true,
238
+ featureFlags: PROGRESSIVE_DISCLOSURE_FLAGS,
239
+ cache: getIndexCacheStats(),
240
+ rateLimiter: getRateLimiterStats(),
241
+ };
242
+ }