edsger 0.28.0 → 0.28.1

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.
@@ -14,7 +14,7 @@
14
14
  * - Worker sends: { type: 'command:resume_feature', featureId }
15
15
  */
16
16
  import { randomUUID } from 'node:crypto';
17
- import { getFeatureChannel, claimPendingMessages, sendSystemMessage, } from '../../api/chat.js';
17
+ import { getFeatureChannel, claimPendingMessages, listChannels, sendSystemMessage, } from '../../api/chat.js';
18
18
  import { processHumanMessages, processPhaseCompletion, } from '../../phases/chat-processor/index.js';
19
19
  function sendMessage(msg) {
20
20
  if (process.send) {
@@ -36,12 +36,20 @@ const WORKER_ID = `chat-worker-${process.pid}-${randomUUID().slice(0, 8)}`;
36
36
  const activeChannels = new Map();
37
37
  // Poll interval in ms
38
38
  const POLL_INTERVAL = 5000;
39
+ // Refresh channel list every N polls (~30s at 5s intervals)
40
+ const CHANNEL_REFRESH_INTERVAL = 6;
41
+ let pollCount = 0;
39
42
  // ============================================================
40
43
  // Message Polling Loop
41
44
  // ============================================================
42
45
  async function pollForMessages() {
43
46
  if (!config || !isRunning)
44
47
  return;
48
+ // Periodically refresh the channel list to pick up newly created channels
49
+ pollCount++;
50
+ if (pollCount % CHANNEL_REFRESH_INTERVAL === 0) {
51
+ await refreshChannels();
52
+ }
45
53
  for (const [featureId, channelId] of activeChannels) {
46
54
  try {
47
55
  // Atomically claim messages — other workers won't see these
@@ -88,6 +96,8 @@ function stopPolling() {
88
96
  async function handleInit(msg) {
89
97
  config = msg.config;
90
98
  log('info', `Chat worker initialized (id: ${WORKER_ID})`);
99
+ // Load existing channels before starting the poll loop
100
+ await refreshChannels();
91
101
  startPolling();
92
102
  }
93
103
  async function handlePhaseCompleted(msg) {
@@ -138,6 +148,30 @@ async function handleFeatureDone(msg) {
138
148
  // ============================================================
139
149
  // Channel Management
140
150
  // ============================================================
151
+ /**
152
+ * Refresh the active channels list from the server.
153
+ * Called on init and periodically during polling to discover
154
+ * newly created channels (e.g., when a user opens a feature chat on the web).
155
+ */
156
+ async function refreshChannels() {
157
+ try {
158
+ const channels = await listChannels('feature');
159
+ let added = 0;
160
+ for (const channel of channels) {
161
+ if (channel.channel_ref_id && !activeChannels.has(channel.channel_ref_id)) {
162
+ activeChannels.set(channel.channel_ref_id, channel.id);
163
+ added++;
164
+ }
165
+ }
166
+ if (added > 0) {
167
+ log('info', `Discovered ${added} new channel(s) (total: ${activeChannels.size})`);
168
+ }
169
+ }
170
+ catch (error) {
171
+ const msg = error instanceof Error ? error.message : String(error);
172
+ log('error', `Failed to refresh channels: ${msg}`);
173
+ }
174
+ }
141
175
  async function ensureFeatureChannel(featureId) {
142
176
  if (activeChannels.has(featureId)) {
143
177
  return activeChannels.get(featureId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edsger",
3
- "version": "0.28.0",
3
+ "version": "0.28.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "edsger": "dist/index.js"