crawd 0.8.6 → 0.8.7

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/dist/cli.js CHANGED
@@ -84,7 +84,9 @@ var ConfigSchema = z.object({
84
84
  /** Seconds of inactivity before going idle */
85
85
  idleAfter: z.number().default(180),
86
86
  /** Seconds of inactivity before going to sleep (must be > idleAfter) */
87
- sleepAfter: z.number().default(360)
87
+ sleepAfter: z.number().default(360),
88
+ /** Seconds for chat batch throttle window (leading-edge) */
89
+ chatBatchWindow: z.number().default(20)
88
90
  }).default({}),
89
91
  /** Stream configuration */
90
92
  stream: z.object({
@@ -512,6 +514,9 @@ crawd config set vibe.idleAfter 180
512
514
  # Seconds of inactivity before going to sleep (default: 360)
513
515
  crawd config set vibe.sleepAfter 360
514
516
 
517
+ # Chat batch throttle window in seconds (default: 20)
518
+ crawd config set vibe.chatBatchWindow 20
519
+
515
520
  # Disable vibing entirely
516
521
  crawd config set vibe.enabled false
517
522
  \`\`\`
@@ -691,6 +696,7 @@ function buildEnv(config) {
691
696
  env.VIBE_INTERVAL_MS = String(config.vibe.interval * 1e3);
692
697
  env.IDLE_AFTER_MS = String(config.vibe.idleAfter * 1e3);
693
698
  env.SLEEP_AFTER_IDLE_MS = String((config.vibe.sleepAfter - config.vibe.idleAfter) * 1e3);
699
+ env.CHAT_BATCH_WINDOW_MS = String(config.vibe.chatBatchWindow * 1e3);
694
700
  env.YOUTUBE_ENABLED = String(config.chat.youtube.enabled);
695
701
  if (config.chat.youtube.videoId) {
696
702
  env.YOUTUBE_VIDEO_ID = config.chat.youtube.videoId;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "crawd",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "description": "CLI for crawd.bot - AI agent livestreaming platform",
5
5
  "type": "module",
6
6
  "types": "./dist/types.d.ts",
@@ -23,14 +23,6 @@
23
23
  "bin": {
24
24
  "crawd": "./dist/cli.js"
25
25
  },
26
- "scripts": {
27
- "dev": "tsx src/cli.ts",
28
- "build": "tsup src/cli.ts src/types.ts src/client.ts --format esm --dts --clean",
29
- "build:backend": "tsup src/backend/index.ts --format esm --out-dir dist/backend --clean",
30
- "build:plugin": "tsup src/plugin.ts --format esm --out-dir dist --dts",
31
- "build:all": "pnpm build && pnpm build:backend",
32
- "typecheck": "tsc --noEmit"
33
- },
34
26
  "keywords": [
35
27
  "ai",
36
28
  "agent",
@@ -82,5 +74,13 @@
82
74
  "openclaw": {
83
75
  "optional": true
84
76
  }
77
+ },
78
+ "scripts": {
79
+ "dev": "tsx src/cli.ts",
80
+ "build": "tsup src/cli.ts src/types.ts src/client.ts --format esm --dts --clean",
81
+ "build:backend": "tsup src/backend/index.ts --format esm --out-dir dist/backend --clean",
82
+ "build:plugin": "tsup src/plugin.ts --format esm --out-dir dist --dts",
83
+ "build:all": "pnpm build && pnpm build:backend",
84
+ "typecheck": "tsc --noEmit"
85
85
  }
86
- }
86
+ }
@@ -2,7 +2,6 @@ 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
6
5
  const SESSION_KEY = process.env.CRAWD_CHANNEL_ID || 'agent:main:crawd:live'
7
6
 
8
7
  /** Coordinator configuration */
@@ -15,6 +14,8 @@ export type CoordinatorConfig = {
15
14
  idleAfterMs: number
16
15
  /** Go sleep after this much inactivity while idle (ms). Default: 60000 (1 min) */
17
16
  sleepAfterIdleMs: number
17
+ /** Chat batch throttle window (ms). Default: 20000 (20 sec) */
18
+ batchWindowMs: number
18
19
  /** The autonomous "vibe" prompt sent periodically */
19
20
  vibePrompt: string
20
21
  }
@@ -24,6 +25,7 @@ export const DEFAULT_CONFIG: CoordinatorConfig = {
24
25
  vibeIntervalMs: 30_000,
25
26
  idleAfterMs: 180_000,
26
27
  sleepAfterIdleMs: 180_000,
28
+ batchWindowMs: 20_000,
27
29
  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
30
  }
29
31
 
@@ -556,6 +558,7 @@ export class Coordinator {
556
558
  vibeIntervalMs: this.config.vibeIntervalMs,
557
559
  idleAfterMs: this.config.idleAfterMs,
558
560
  sleepAfterIdleMs: this.config.sleepAfterIdleMs,
561
+ batchWindowMs: this.config.batchWindowMs,
559
562
  })
560
563
  }
561
564
 
@@ -588,6 +591,7 @@ export class Coordinator {
588
591
  vibeIntervalMs: this.config.vibeIntervalMs,
589
592
  idleAfterMs: this.config.idleAfterMs,
590
593
  sleepAfterIdleMs: this.config.sleepAfterIdleMs,
594
+ batchWindowMs: this.config.batchWindowMs,
591
595
  })
592
596
  }
593
597
 
@@ -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.batchWindowMs)
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.batchWindowMs)
851
855
  }
852
856
  }
853
857
 
@@ -46,6 +46,7 @@ export type CrawdConfig = {
46
46
  intervalMs: number
47
47
  idleAfterMs: number
48
48
  sleepAfterIdleMs: number
49
+ batchWindowMs: number
49
50
  prompt?: string
50
51
  }
51
52
  chat: {
@@ -391,6 +392,7 @@ export class CrawdBackend {
391
392
  vibeIntervalMs: this.config.vibe.intervalMs,
392
393
  idleAfterMs: this.config.vibe.idleAfterMs,
393
394
  sleepAfterIdleMs: this.config.vibe.sleepAfterIdleMs,
395
+ batchWindowMs: this.config.vibe.batchWindowMs,
394
396
  }
395
397
  if (this.config.vibe.prompt) {
396
398
  coordConfig.vibePrompt = this.config.vibe.prompt
@@ -432,6 +434,11 @@ export class CrawdBackend {
432
434
  socket.emit('crawd:mcap', { mcap: this.latestMcap })
433
435
  }
434
436
 
437
+ // Sync current coordinator state so the overlay knows the initial animation
438
+ if (this.coordinator) {
439
+ socket.emit('crawd:status', { status: this.coordinator.state })
440
+ }
441
+
435
442
  socket.on('crawd:talk:done', (data: { id?: string }) => {
436
443
  if (data?.id) {
437
444
  this.logger.info(`Talk ack received: ${data.id}`)
@@ -620,6 +627,7 @@ export function configFromEnv(): CrawdConfig {
620
627
  intervalMs: Number(process.env.VIBE_INTERVAL_MS || 30_000),
621
628
  idleAfterMs: Number(process.env.IDLE_AFTER_MS || 180_000),
622
629
  sleepAfterIdleMs: Number(process.env.SLEEP_AFTER_IDLE_MS || 180_000),
630
+ batchWindowMs: Number(process.env.CHAT_BATCH_WINDOW_MS || 20_000),
623
631
  prompt: process.env.VIBE_PROMPT,
624
632
  },
625
633
  chat: {
@@ -110,6 +110,9 @@ crawd config set vibe.idleAfter 180
110
110
  # Seconds of inactivity before going to sleep (default: 360)
111
111
  crawd config set vibe.sleepAfter 360
112
112
 
113
+ # Chat batch throttle window in seconds (default: 20)
114
+ crawd config set vibe.chatBatchWindow 20
115
+
113
116
  # Disable vibing entirely
114
117
  crawd config set vibe.enabled false
115
118
  \`\`\`
@@ -54,6 +54,7 @@ function buildEnv(config: Config): NodeJS.ProcessEnv {
54
54
  env.VIBE_INTERVAL_MS = String(config.vibe.interval * 1000)
55
55
  env.IDLE_AFTER_MS = String(config.vibe.idleAfter * 1000)
56
56
  env.SLEEP_AFTER_IDLE_MS = String((config.vibe.sleepAfter - config.vibe.idleAfter) * 1000)
57
+ env.CHAT_BATCH_WINDOW_MS = String(config.vibe.chatBatchWindow * 1000)
57
58
 
58
59
  env.YOUTUBE_ENABLED = String(config.chat.youtube.enabled)
59
60
  if (config.chat.youtube.videoId) {
@@ -50,6 +50,8 @@ export const ConfigSchema = z.object({
50
50
  idleAfter: z.number().default(180),
51
51
  /** Seconds of inactivity before going to sleep (must be > idleAfter) */
52
52
  sleepAfter: z.number().default(360),
53
+ /** Seconds for chat batch throttle window (leading-edge) */
54
+ chatBatchWindow: z.number().default(20),
53
55
  }).default({}),
54
56
 
55
57
  /** Stream configuration */
package/src/plugin.ts CHANGED
@@ -99,6 +99,7 @@ function parsePluginConfig(raw: Record<string, unknown> | undefined): CrawdConfi
99
99
  intervalMs: typeof vibe.intervalMs === 'number' ? vibe.intervalMs : 10_000,
100
100
  idleAfterMs: typeof vibe.idleAfterMs === 'number' ? vibe.idleAfterMs : 30_000,
101
101
  sleepAfterIdleMs: typeof vibe.sleepAfterIdleMs === 'number' ? vibe.sleepAfterIdleMs : 60_000,
102
+ batchWindowMs: typeof vibe.batchWindowMs === 'number' ? vibe.batchWindowMs : 20_000,
102
103
  prompt: typeof vibe.prompt === 'string' ? vibe.prompt : undefined,
103
104
  },
104
105
  chat: {
@@ -145,6 +146,7 @@ const crawdConfigSchema = {
145
146
  'vibe.intervalMs': { label: 'Vibe Interval (ms)', advanced: true },
146
147
  'vibe.idleAfterMs': { label: 'Idle After (ms)', advanced: true },
147
148
  'vibe.sleepAfterIdleMs': { label: 'Sleep After Idle (ms)', advanced: true },
149
+ 'vibe.batchWindowMs': { label: 'Chat Batch Window (ms)', advanced: true },
148
150
  'vibe.prompt': { label: 'Vibe Prompt', advanced: true },
149
151
  'chat.youtube.enabled': { label: 'YouTube Chat' },
150
152
  'chat.youtube.videoId': { label: 'YouTube Video ID' },