@h-ear/openclaw 0.2.0-dev.202604052111 → 0.2.0-dev.202604060442

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.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * h-ear CLI — OpenClaw-friendly command-line interface for H-ear audio classification.
4
+ *
5
+ * Usage:
6
+ * h-ear health Check API status
7
+ * h-ear sounds [search] List sound classes
8
+ * h-ear usage Show API usage
9
+ * h-ear classify <file-or-url> Classify audio (sync, polls for results)
10
+ * h-ear capture [--duration 15] Capture audio from RTSP camera and classify
11
+ * h-ear jobs [--limit 5] List recent jobs
12
+ *
13
+ * Environment:
14
+ * HEAR_API_KEY API key (required)
15
+ * HEAR_ENV Environment: dev, staging, prod (default: prod)
16
+ * LISTEN_RTSP_URL RTSP source URL (for capture command)
17
+ */
18
+ export {};
19
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
package/dist/cli.js ADDED
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * h-ear CLI — OpenClaw-friendly command-line interface for H-ear audio classification.
4
+ *
5
+ * Usage:
6
+ * h-ear health Check API status
7
+ * h-ear sounds [search] List sound classes
8
+ * h-ear usage Show API usage
9
+ * h-ear classify <file-or-url> Classify audio (sync, polls for results)
10
+ * h-ear capture [--duration 15] Capture audio from RTSP camera and classify
11
+ * h-ear jobs [--limit 5] List recent jobs
12
+ *
13
+ * Environment:
14
+ * HEAR_API_KEY API key (required)
15
+ * HEAR_ENV Environment: dev, staging, prod (default: prod)
16
+ * LISTEN_RTSP_URL RTSP source URL (for capture command)
17
+ */
18
+ import { readFileSync, unlinkSync, existsSync, mkdirSync } from 'fs';
19
+ import { spawnSync } from 'child_process';
20
+ import { join } from 'path';
21
+ import { tmpdir } from 'os';
22
+ import { createSkill } from './index.js';
23
+ import { healthCommand } from './commands/health.js';
24
+ import { soundsCommand } from './commands/sounds.js';
25
+ import { usageCommand } from './commands/usage.js';
26
+ import { classifySyncCommand } from './commands/classify.js';
27
+ import { jobsCommand } from './commands/jobs.js';
28
+ import { formatClassifyResult } from './formatter.js';
29
+ // --- Arg parsing -------------------------------------------------------------
30
+ const args = process.argv.slice(2);
31
+ const command = args[0] ?? 'help';
32
+ function getFlag(flag) {
33
+ const idx = args.indexOf(flag);
34
+ return idx >= 0 && args[idx + 1] ? args[idx + 1] : null;
35
+ }
36
+ function hasFlag(flag) {
37
+ return args.includes(flag);
38
+ }
39
+ // --- Capture -----------------------------------------------------------------
40
+ function captureAudio(sourceUrl, durationSec) {
41
+ const tmpDir = join(tmpdir(), 'h-ear-listen');
42
+ if (!existsSync(tmpDir))
43
+ mkdirSync(tmpDir, { recursive: true });
44
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-').replace('T', '_').slice(0, 19);
45
+ const outFile = join(tmpDir, `capture_${timestamp}_${durationSec}s.wav`);
46
+ const ffmpegArgs = ['-y'];
47
+ if (sourceUrl.startsWith('rtsp://'))
48
+ ffmpegArgs.push('-rtsp_transport', 'tcp');
49
+ ffmpegArgs.push('-i', sourceUrl, '-vn', '-ac', '1', '-ar', '16000', '-acodec', 'pcm_s16le', '-t', String(durationSec), '-f', 'wav', outFile);
50
+ const result = spawnSync('ffmpeg', ffmpegArgs, {
51
+ stdio: ['pipe', 'pipe', 'pipe'],
52
+ encoding: 'utf-8',
53
+ timeout: (durationSec + 30) * 1000,
54
+ });
55
+ if (result.status !== 0 || !existsSync(outFile)) {
56
+ const stderr = (result.stderr || '').trim().split('\n').slice(-3).join('\n');
57
+ throw new Error(`ffmpeg capture failed (exit ${result.status}): ${stderr}`);
58
+ }
59
+ const buffer = readFileSync(outFile);
60
+ try {
61
+ unlinkSync(outFile);
62
+ }
63
+ catch (err) {
64
+ console.error(` Cleanup warning: failed to remove temp file ${outFile}`, err);
65
+ }
66
+ return { buffer: Buffer.from(buffer), fileName: `capture_${timestamp}_${durationSec}s.wav` };
67
+ }
68
+ // --- Main --------------------------------------------------------------------
69
+ async function main() {
70
+ if (command === 'help' || command === '--help' || command === '-h') {
71
+ console.log(`h-ear — Sound Intelligence CLI
72
+
73
+ Usage:
74
+ h-ear health Check API status
75
+ h-ear sounds [search] List sound classes (521+)
76
+ h-ear usage Show API usage stats
77
+ h-ear classify <file-or-url> Classify audio (waits for results)
78
+ h-ear capture [--duration 15] Capture from RTSP camera and classify
79
+ h-ear jobs [--limit 5] List recent jobs
80
+
81
+ Environment:
82
+ HEAR_API_KEY H-ear API key (required)
83
+ HEAR_ENV dev | staging | prod (default: prod)
84
+ LISTEN_RTSP_URL RTSP camera URL (for capture command)`);
85
+ return;
86
+ }
87
+ const { client } = createSkill();
88
+ switch (command) {
89
+ case 'health': {
90
+ console.log(await healthCommand(client));
91
+ break;
92
+ }
93
+ case 'sounds': {
94
+ const search = args[1] && !args[1].startsWith('-') ? args[1] : undefined;
95
+ const limit = parseInt(getFlag('--limit') ?? '20', 10);
96
+ console.log(await soundsCommand(client, search, { limit }));
97
+ break;
98
+ }
99
+ case 'usage': {
100
+ console.log(await usageCommand(client));
101
+ break;
102
+ }
103
+ case 'classify': {
104
+ const target = args[1];
105
+ if (!target) {
106
+ console.error('Error: h-ear classify <file-or-url>');
107
+ process.exit(1);
108
+ }
109
+ if (target.startsWith('http://') || target.startsWith('https://')) {
110
+ // URL mode — use existing sync command
111
+ console.log(await classifySyncCommand(client, target, undefined, (msg) => console.error(` ${msg}`)));
112
+ }
113
+ else {
114
+ // File mode — read and upload
115
+ if (!existsSync(target)) {
116
+ console.error(`Error: file not found: ${target}`);
117
+ process.exit(1);
118
+ }
119
+ const buffer = readFileSync(target);
120
+ const fileName = target.split(/[/\\]/).pop() ?? 'audio.wav';
121
+ console.error(` Uploading ${fileName} (${(buffer.length / 1024).toFixed(0)} KB)...`);
122
+ const accepted = await client.submitClassifyFile(buffer, fileName, { threshold: 0.3 });
123
+ console.error(` Job ${accepted.requestId} queued, polling...`);
124
+ const result = await client.pollJob(accepted.requestId, (msg) => console.error(` ${msg}`));
125
+ console.log(formatClassifyResult(result));
126
+ }
127
+ break;
128
+ }
129
+ case 'listen':
130
+ case 'capture': {
131
+ const rtspUrl = getFlag('--rtsp') ?? process.env.LISTEN_RTSP_URL;
132
+ if (!rtspUrl) {
133
+ console.error('Error: RTSP URL required. Pass --rtsp <url> or set LISTEN_RTSP_URL');
134
+ process.exit(1);
135
+ }
136
+ const duration = parseInt(getFlag('--duration') ?? '15', 10);
137
+ const classifyAfter = !hasFlag('--no-classify');
138
+ console.error(` Capturing ${duration}s audio from ${rtspUrl}...`);
139
+ const { buffer, fileName } = captureAudio(rtspUrl, duration);
140
+ console.error(` Captured ${(buffer.length / 1024).toFixed(0)} KB`);
141
+ if (classifyAfter) {
142
+ console.error(` Uploading ${fileName}...`);
143
+ const accepted = await client.submitClassifyFile(buffer, fileName, { threshold: 0.3 });
144
+ console.error(` Job ${accepted.requestId} queued, polling...`);
145
+ const result = await client.pollJob(accepted.requestId, (msg) => console.error(` ${msg}`));
146
+ console.log(formatClassifyResult(result));
147
+ }
148
+ else {
149
+ console.log(`Captured: ${fileName} (${(buffer.length / 1024).toFixed(0)} KB)`);
150
+ }
151
+ break;
152
+ }
153
+ case 'jobs': {
154
+ const limit = parseInt(getFlag('--limit') ?? '5', 10);
155
+ console.log(await jobsCommand(client, { limit }));
156
+ break;
157
+ }
158
+ default: {
159
+ console.error(`Unknown command: ${command}. Run 'h-ear help' for usage.`);
160
+ process.exit(1);
161
+ }
162
+ }
163
+ }
164
+ main().catch((err) => {
165
+ console.error(`Error: ${err.message}`);
166
+ process.exit(1);
167
+ });
168
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,gFAAgF;AAEhF,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;AAElC,SAAS,OAAO,CAAC,IAAY;IACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,gFAAgF;AAEhF,SAAS,YAAY,CAAC,SAAiB,EAAE,WAAmB;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,cAAc,CAAC,CAAC;IAC9C,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEhE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,WAAW,SAAS,IAAI,WAAW,OAAO,CAAC,CAAC;IAEzE,MAAM,UAAU,GAAa,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAC/E,UAAU,CAAC,IAAI,CACX,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EACzD,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAClD,CAAC;IAEF,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE;QAC3C,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;QAC/B,QAAQ,EAAE,OAAO;QACjB,OAAO,EAAE,CAAC,WAAW,GAAG,EAAE,CAAC,GAAG,IAAI;KACrC,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,IAAI,KAAK,CAAC,+BAA+B,MAAM,CAAC,MAAM,MAAM,MAAM,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,IAAI,CAAC;QAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAAC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,iDAAiD,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;IAAC,CAAC;IAC5H,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,SAAS,IAAI,WAAW,OAAO,EAAE,CAAC;AACjG,CAAC;AAED,gFAAgF;AAEhF,KAAK,UAAU,IAAI;IACf,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;0DAasC,CAAC,CAAC;QACpD,OAAO;IACX,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;IAEjC,QAAQ,OAAO,EAAE,CAAC;QACd,KAAK,QAAQ,CAAC,CAAC,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;YACzC,MAAM;QACV,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5D,MAAM;QACV,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,MAAM;QACV,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACvB,IAAI,CAAC,MAAM,EAAE,CAAC;gBAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;gBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,CAAC;YAEvF,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAChE,uCAAuC;gBACvC,OAAO,CAAC,GAAG,CAAC,MAAM,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;YAC1G,CAAC;iBAAM,CAAC;gBACJ,8BAA8B;gBAC9B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBAAC,OAAO,CAAC,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;oBAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAAC,CAAC;gBAChG,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;gBACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC;gBAC5D,OAAO,CAAC,KAAK,CAAC,eAAe,QAAQ,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBACtF,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBACvF,OAAO,CAAC,KAAK,CAAC,SAAS,QAAQ,CAAC,SAAS,qBAAqB,CAAC,CAAC;gBAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC5F,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;YAC9C,CAAC;YACD,MAAM;QACV,CAAC;QACD,KAAK,QAAQ,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YACb,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;YACjE,IAAI,CAAC,OAAO,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;gBACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC;YACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YAC7D,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAEhD,OAAO,CAAC,KAAK,CAAC,eAAe,QAAQ,gBAAgB,OAAO,KAAK,CAAC,CAAC;YACnE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC7D,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAEpE,IAAI,aAAa,EAAE,CAAC;gBAChB,OAAO,CAAC,KAAK,CAAC,eAAe,QAAQ,KAAK,CAAC,CAAC;gBAC5C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;gBACvF,OAAO,CAAC,KAAK,CAAC,SAAS,QAAQ,CAAC,SAAS,qBAAqB,CAAC,CAAC;gBAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC5F,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;YAC9C,CAAC;iBAAM,CAAC;gBACJ,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACnF,CAAC;YACD,MAAM;QACV,CAAC;QACD,KAAK,MAAM,CAAC,CAAC,CAAC;YACV,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM;QACV,CAAC;QACD,OAAO,CAAC,CAAC,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,+BAA+B,CAAC,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACL,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACxB,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,wBAAsB,cAAc,CAChC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,wBAAsB,eAAe,CACjC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
1
+ {"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wBAAsB,cAAc,CAChC,MAAM,EAAE,aAAa,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,eAAe,CACjC,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAGjB"}
@@ -1,9 +1,9 @@
1
1
  import { formatAlertRegistered, formatAlertDeregistered } from '../formatter.js';
2
- /** Default gateway webhook receiver — OpenClaw routes alerts back to the user's channel. */
3
- const GATEWAY_CALLBACK = 'https://gateway.openclaw.ai/webhooks/h-ear';
4
2
  export async function alertOnCommand(client, soundClass, options) {
3
+ if (!options?.callbackUrl)
4
+ throw new Error('callbackUrl is required for alert registration');
5
5
  await client.registerWebhook({
6
- url: options?.callbackUrl ?? GATEWAY_CALLBACK,
6
+ url: options.callbackUrl,
7
7
  events: ['job.completed'],
8
8
  soundClass,
9
9
  });
@@ -1 +1 @@
1
- {"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAEjF,4FAA4F;AAC5F,MAAM,gBAAgB,GAAG,4CAA4C,CAAC;AAEtE,MAAM,CAAC,KAAK,UAAU,cAAc,CAChC,MAAqB,EACrB,UAAkB,EAClB,OAAkC;IAElC,MAAM,MAAM,CAAC,eAAe,CAAC;QACzB,GAAG,EAAE,OAAO,EAAE,WAAW,IAAI,gBAAgB;QAC7C,MAAM,EAAE,CAAC,eAAe,CAAC;QACzB,UAAU;KACb,CAAC,CAAC;IACH,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,MAAqB,EACrB,SAAiB,EACjB,UAAkB;IAElB,MAAM,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;AAC/C,CAAC"}
1
+ {"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAEjF,MAAM,CAAC,KAAK,UAAU,cAAc,CAChC,MAAqB,EACrB,UAAkB,EAClB,OAAkC;IAElC,IAAI,CAAC,OAAO,EAAE,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAC7F,MAAM,MAAM,CAAC,eAAe,CAAC;QACzB,GAAG,EAAE,OAAO,CAAC,WAAW;QACxB,MAAM,EAAE,CAAC,eAAe,CAAC;QACzB,UAAU;KACb,CAAC,CAAC;IACH,OAAO,qBAAqB,CAAC,UAAU,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,MAAqB,EACrB,SAAiB,EACjB,UAAkB;IAElB,MAAM,MAAM,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC1C,OAAO,uBAAuB,CAAC,UAAU,CAAC,CAAC;AAC/C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"classify-batch.d.ts","sourceRoot":"","sources":["../../src/commands/classify-batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAejB"}
1
+ {"version":3,"file":"classify-batch.d.ts","sourceRoot":"","sources":["../../src/commands/classify-batch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAejB"}
@@ -1,10 +1,8 @@
1
- /** Default gateway webhook receiver — OpenClaw routes results back to the user's channel. */
2
- const GATEWAY_CALLBACK = 'https://gateway.openclaw.ai/webhooks/h-ear';
3
1
  export async function classifyBatchCommand(client, urls, options) {
4
2
  const files = urls.map((url, i) => ({ url, id: `file-${i + 1}` }));
5
3
  const result = await client.classifyBatch({
6
4
  files,
7
- callbackUrl: options?.callbackUrl ?? GATEWAY_CALLBACK,
5
+ callbackUrl: options?.callbackUrl ?? '',
8
6
  threshold: options?.threshold ?? 0.3,
9
7
  });
10
8
  return [
@@ -1 +1 @@
1
- {"version":3,"file":"classify-batch.js","sourceRoot":"","sources":["../../src/commands/classify-batch.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,MAAM,gBAAgB,GAAG,4CAA4C,CAAC;AAEtE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,MAAqB,EACrB,IAAc,EACd,OAAsD;IAEtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;QACtC,KAAK;QACL,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,gBAAgB;QACrD,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG;KACvC,CAAC,CAAC;IAEH,OAAO;QACH,qBAAqB;QACrB,aAAa,MAAM,CAAC,OAAO,EAAE;QAC7B,UAAU,MAAM,CAAC,SAAS,EAAE;QAC5B,eAAe,MAAM,CAAC,0BAA0B,MAAM;QACtD,WAAW,MAAM,CAAC,MAAM,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"classify-batch.js","sourceRoot":"","sources":["../../src/commands/classify-batch.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,MAAqB,EACrB,IAAc,EACd,OAAsD;IAEtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC;QACtC,KAAK;QACL,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,EAAE;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG;KACvC,CAAC,CAAC;IAEH,OAAO;QACH,qBAAqB;QACrB,aAAa,MAAM,CAAC,OAAO,EAAE;QAC7B,UAAU,MAAM,CAAC,SAAS,EAAE;QAC5B,eAAe,MAAM,CAAC,0BAA0B,MAAM;QACtD,WAAW,MAAM,CAAC,MAAM,EAAE;KAC7B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACjB,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { HearApiClient } from '@h-ear/core';
2
- /** Async submit — returns immediately with job ID. Results delivered via callbackUrl. */
2
+ /** Async submit — returns immediately with job ID. callbackUrl is optional; client defaults to noop. */
3
3
  export declare function classifyCommand(client: HearApiClient, url: string, options?: {
4
4
  threshold?: number;
5
5
  callbackUrl?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,yFAAyF;AACzF,wBAAsB,eAAe,CACjC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,+EAA+E;AAC/E,wBAAsB,mBAAmB,CACrC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAChC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACnC,OAAO,CAAC,MAAM,CAAC,CAMjB"}
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,wGAAwG;AACxG,wBAAsB,eAAe,CACjC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAOjB;AAED,+EAA+E;AAC/E,wBAAsB,mBAAmB,CACrC,MAAM,EAAE,aAAa,EACrB,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,EAChC,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GACnC,OAAO,CAAC,MAAM,CAAC,CAMjB"}
@@ -1,12 +1,10 @@
1
1
  import { formatClassifySubmitted, formatClassifyResult } from '../formatter.js';
2
- /** Default gateway webhook receiver OpenClaw routes results back to the user's channel. */
3
- const GATEWAY_CALLBACK = 'https://gateway.openclaw.ai/webhooks/h-ear';
4
- /** Async submit — returns immediately with job ID. Results delivered via callbackUrl. */
2
+ /** Async submit returns immediately with job ID. callbackUrl is optional; client defaults to noop. */
5
3
  export async function classifyCommand(client, url, options) {
6
4
  const accepted = await client.submitClassify({
7
5
  url,
8
6
  threshold: options?.threshold ?? 0.3,
9
- callbackUrl: options?.callbackUrl ?? GATEWAY_CALLBACK,
7
+ ...(options?.callbackUrl ? { callbackUrl: options.callbackUrl } : {}),
10
8
  });
11
9
  return formatClassifySubmitted(accepted);
12
10
  }
@@ -1 +1 @@
1
- {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,6FAA6F;AAC7F,MAAM,gBAAgB,GAAG,4CAA4C,CAAC;AAEtE,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,MAAqB,EACrB,GAAW,EACX,OAAsD;IAEtD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;QACzC,GAAG;QACH,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG;QACpC,WAAW,EAAE,OAAO,EAAE,WAAW,IAAI,gBAAgB;KACxD,CAAC,CAAC;IACH,OAAO,uBAAuB,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,MAAqB,EACrB,GAAW,EACX,OAAgC,EAChC,UAAkC;IAElC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAChC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG,EAAE,EAC7C,UAAU,CACb,CAAC;IACF,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC"}
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/commands/classify.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,wGAAwG;AACxG,MAAM,CAAC,KAAK,UAAU,eAAe,CACjC,MAAqB,EACrB,GAAW,EACX,OAAsD;IAEtD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC;QACzC,GAAG;QACH,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG;QACpC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxE,CAAC,CAAC;IACH,OAAO,uBAAuB,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACrC,MAAqB,EACrB,GAAW,EACX,OAAgC,EAChC,UAAkC;IAElC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAChC,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,IAAI,GAAG,EAAE,EAC7C,UAAU,CACb,CAAC;IACF,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "@h-ear/openclaw",
3
- "version": "0.2.0-dev.202604052111",
3
+ "version": "0.2.0-dev.202604060442",
4
4
  "description": "OpenClaw skill for H-ear World audio classification — sound intelligence in WhatsApp, Telegram, Slack, Discord, and Teams",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "h-ear": "./dist/cli.js"
10
+ },
8
11
  "exports": {
9
12
  ".": {
10
13
  "import": "./dist/index.js",