crawd 0.8.5 → 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 +7 -1
- package/package.json +10 -10
- package/src/backend/coordinator.ts +7 -7
- package/src/backend/server.ts +8 -0
- package/src/commands/skill.ts +3 -0
- package/src/commands/start.ts +1 -0
- package/src/config/schema.ts +2 -0
- package/src/plugin.ts +2 -30
- package/dist/backend/chunk-QITCQHSS.js +0 -2087
- package/dist/backend/fileFromPath-WZUZ37JN.js +0 -127
- package/dist/backend/index.js +0 -12420
- package/dist/chunk-QITCQHSS.js +0 -2087
- package/dist/fileFromPath-WZUZ37JN.js +0 -127
- package/dist/plugin.d.ts +0 -27
- package/dist/plugin.js +0 -12392
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.
|
|
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 DEFAULT_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,8 +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
|
|
18
|
-
/** Chat
|
|
19
|
-
|
|
17
|
+
/** Chat batch throttle window (ms). Default: 20000 (20 sec) */
|
|
18
|
+
batchWindowMs: number
|
|
20
19
|
/** The autonomous "vibe" prompt sent periodically */
|
|
21
20
|
vibePrompt: string
|
|
22
21
|
}
|
|
@@ -26,7 +25,7 @@ export const DEFAULT_CONFIG: CoordinatorConfig = {
|
|
|
26
25
|
vibeIntervalMs: 30_000,
|
|
27
26
|
idleAfterMs: 180_000,
|
|
28
27
|
sleepAfterIdleMs: 180_000,
|
|
29
|
-
|
|
28
|
+
batchWindowMs: 20_000,
|
|
30
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.`,
|
|
31
30
|
}
|
|
32
31
|
|
|
@@ -557,9 +556,9 @@ export class Coordinator {
|
|
|
557
556
|
this.config = { ...this.config, ...config }
|
|
558
557
|
this.logger.log('[Coordinator] Config updated:', {
|
|
559
558
|
vibeIntervalMs: this.config.vibeIntervalMs,
|
|
560
|
-
chatBatchWindowMs: this.config.chatBatchWindowMs,
|
|
561
559
|
idleAfterMs: this.config.idleAfterMs,
|
|
562
560
|
sleepAfterIdleMs: this.config.sleepAfterIdleMs,
|
|
561
|
+
batchWindowMs: this.config.batchWindowMs,
|
|
563
562
|
})
|
|
564
563
|
}
|
|
565
564
|
|
|
@@ -592,6 +591,7 @@ export class Coordinator {
|
|
|
592
591
|
vibeIntervalMs: this.config.vibeIntervalMs,
|
|
593
592
|
idleAfterMs: this.config.idleAfterMs,
|
|
594
593
|
sleepAfterIdleMs: this.config.sleepAfterIdleMs,
|
|
594
|
+
batchWindowMs: this.config.batchWindowMs,
|
|
595
595
|
})
|
|
596
596
|
}
|
|
597
597
|
|
|
@@ -840,7 +840,7 @@ export class Coordinator {
|
|
|
840
840
|
// Leading edge: if no timer running, flush immediately and start cooldown
|
|
841
841
|
if (!this.timer) {
|
|
842
842
|
this.flush()
|
|
843
|
-
this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.
|
|
843
|
+
this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.batchWindowMs)
|
|
844
844
|
}
|
|
845
845
|
// Otherwise, message is buffered and will be flushed when cooldown ends
|
|
846
846
|
}
|
|
@@ -851,7 +851,7 @@ export class Coordinator {
|
|
|
851
851
|
// If messages accumulated during cooldown, flush them and restart cooldown
|
|
852
852
|
if (this.buffer.length > 0) {
|
|
853
853
|
this.flush()
|
|
854
|
-
this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.
|
|
854
|
+
this.timer = this.clock.setTimeout(() => this.onCooldownEnd(), this.config.batchWindowMs)
|
|
855
855
|
}
|
|
856
856
|
}
|
|
857
857
|
|
package/src/backend/server.ts
CHANGED
|
@@ -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: {
|
package/src/commands/skill.ts
CHANGED
|
@@ -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
|
\`\`\`
|
package/src/commands/start.ts
CHANGED
|
@@ -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) {
|
package/src/config/schema.ts
CHANGED
|
@@ -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' },
|
|
@@ -249,36 +251,6 @@ const plugin: PluginDefinition = {
|
|
|
249
251
|
{ name: 'livestream_reply' },
|
|
250
252
|
)
|
|
251
253
|
|
|
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
|
-
|
|
282
254
|
// Service lifecycle
|
|
283
255
|
api.registerService({
|
|
284
256
|
id: 'crawd',
|