crawd 0.8.4 → 0.8.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crawd",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "CLI for crawd.bot - AI agent livestreaming platform",
5
5
  "type": "module",
6
6
  "types": "./dist/types.d.ts",
@@ -2,7 +2,7 @@ import { randomUUID } from 'crypto'
2
2
  import WebSocket from 'ws'
3
3
  import type { ChatMessage } from '../lib/chat/types'
4
4
 
5
- const BATCH_WINDOW_MS = 20_000
5
+ const DEFAULT_BATCH_WINDOW_MS = 20_000
6
6
  const SESSION_KEY = process.env.CRAWD_CHANNEL_ID || 'agent:main:crawd:live'
7
7
 
8
8
  /** Coordinator configuration */
@@ -15,6 +15,8 @@ export type CoordinatorConfig = {
15
15
  idleAfterMs: number
16
16
  /** Go sleep after this much inactivity while idle (ms). Default: 60000 (1 min) */
17
17
  sleepAfterIdleMs: number
18
+ /** Chat message batching window (ms). Default: 20000 (20 sec) */
19
+ chatBatchWindowMs: number
18
20
  /** The autonomous "vibe" prompt sent periodically */
19
21
  vibePrompt: string
20
22
  }
@@ -24,6 +26,7 @@ export const DEFAULT_CONFIG: CoordinatorConfig = {
24
26
  vibeIntervalMs: 30_000,
25
27
  idleAfterMs: 180_000,
26
28
  sleepAfterIdleMs: 180_000,
29
+ chatBatchWindowMs: DEFAULT_BATCH_WINDOW_MS,
27
30
  vibePrompt: `[CRAWD:VIBE] You are on a livestream. Make sure the crawd skill is loaded. Do one thing on the internet or ask the chat something. Respond with LIVESTREAM_REPLIED after using a tool, or NO_REPLY if you have nothing to say.`,
28
31
  }
29
32
 
@@ -554,6 +557,7 @@ export class Coordinator {
554
557
  this.config = { ...this.config, ...config }
555
558
  this.logger.log('[Coordinator] Config updated:', {
556
559
  vibeIntervalMs: this.config.vibeIntervalMs,
560
+ chatBatchWindowMs: this.config.chatBatchWindowMs,
557
561
  idleAfterMs: this.config.idleAfterMs,
558
562
  sleepAfterIdleMs: this.config.sleepAfterIdleMs,
559
563
  })
@@ -836,7 +840,7 @@ export class Coordinator {
836
840
  // Leading edge: if no timer running, flush immediately and start cooldown
837
841
  if (!this.timer) {
838
842
  this.flush()
839
- this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), BATCH_WINDOW_MS)
843
+ this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.chatBatchWindowMs)
840
844
  }
841
845
  // Otherwise, message is buffered and will be flushed when cooldown ends
842
846
  }
@@ -847,7 +851,7 @@ export class Coordinator {
847
851
  // If messages accumulated during cooldown, flush them and restart cooldown
848
852
  if (this.buffer.length > 0) {
849
853
  this.flush()
850
- this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), BATCH_WINDOW_MS)
854
+ this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.chatBatchWindowMs)
851
855
  }
852
856
  }
853
857
 
package/src/plugin.ts CHANGED
@@ -249,6 +249,36 @@ const plugin: PluginDefinition = {
249
249
  { name: 'livestream_reply' },
250
250
  )
251
251
 
252
+ // livestream_config — runtime coordinator tuning
253
+ api.registerTool(
254
+ {
255
+ name: 'livestream_config',
256
+ label: 'Livestream Config',
257
+ description:
258
+ 'Update livestream coordinator settings at runtime. Use when asked to change vibe speed/frequency, chat throttle/batch window, idle timeout, or sleep timeout.',
259
+ parameters: Type.Object({
260
+ vibeIntervalMs: Type.Optional(Type.Number({ description: 'Milliseconds between autonomous vibe prompts (lower = more frequent vibes)' })),
261
+ chatBatchWindowMs: Type.Optional(Type.Number({ description: 'Milliseconds to batch chat messages before sending to agent (lower = faster chat response, higher = more messages per batch)' })),
262
+ idleAfterMs: Type.Optional(Type.Number({ description: 'Milliseconds of inactivity before transitioning to idle state' })),
263
+ sleepAfterIdleMs: Type.Optional(Type.Number({ description: 'Milliseconds in idle before transitioning to sleep state' })),
264
+ vibeEnabled: Type.Optional(Type.Boolean({ description: 'Enable or disable autonomous vibe prompts' })),
265
+ }),
266
+ async execute(_toolCallId: string, params: unknown) {
267
+ const b = await ensureBackend()
268
+ if (!b.coordinator) {
269
+ return { content: [{ type: 'text', text: 'Coordinator not running' }] }
270
+ }
271
+ const p = params as Record<string, unknown>
272
+ b.coordinator.updateConfig(p)
273
+ const { state, config: cfg } = b.coordinator.getState()
274
+ return {
275
+ content: [{ type: 'text', text: `Config updated. state=${state}, vibeInterval=${cfg.vibeIntervalMs}ms, chatBatch=${cfg.chatBatchWindowMs}ms, idleAfter=${cfg.idleAfterMs}ms, sleepAfter=${cfg.sleepAfterIdleMs}ms, vibes=${cfg.vibeEnabled}` }],
276
+ }
277
+ },
278
+ },
279
+ { name: 'livestream_config' },
280
+ )
281
+
252
282
  // Service lifecycle
253
283
  api.registerService({
254
284
  id: 'crawd',