verbalcoding 0.2.0

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.
Files changed (85) hide show
  1. package/.env.example +83 -0
  2. package/LICENSE +21 -0
  3. package/README.md +157 -0
  4. package/app-node/agent_adapters.mjs +576 -0
  5. package/app-node/agent_adapters.test.mjs +455 -0
  6. package/app-node/agent_contract.mjs +45 -0
  7. package/app-node/barge_in.mjs +148 -0
  8. package/app-node/barge_in.test.mjs +179 -0
  9. package/app-node/bridge_logger.mjs +66 -0
  10. package/app-node/bridge_logger.test.mjs +73 -0
  11. package/app-node/bridge_state.mjs +104 -0
  12. package/app-node/bridge_state.test.mjs +64 -0
  13. package/app-node/cli_install.test.mjs +97 -0
  14. package/app-node/deferred_queue.mjs +12 -0
  15. package/app-node/deferred_queue.test.mjs +20 -0
  16. package/app-node/discord_invite_cli.test.mjs +31 -0
  17. package/app-node/discord_text.mjs +29 -0
  18. package/app-node/discord_text.test.mjs +32 -0
  19. package/app-node/hermes_profiles.mjs +164 -0
  20. package/app-node/hermes_profiles.test.mjs +276 -0
  21. package/app-node/install_config.mjs +263 -0
  22. package/app-node/install_config.test.mjs +205 -0
  23. package/app-node/instance_doctor.mjs +137 -0
  24. package/app-node/instance_doctor.test.mjs +128 -0
  25. package/app-node/instance_profile_lifecycle.mjs +16 -0
  26. package/app-node/instances.mjs +153 -0
  27. package/app-node/instances.test.mjs +102 -0
  28. package/app-node/language_config.mjs +73 -0
  29. package/app-node/language_config.test.mjs +51 -0
  30. package/app-node/latency_metrics.mjs +133 -0
  31. package/app-node/latency_metrics.test.mjs +71 -0
  32. package/app-node/main.mjs +1771 -0
  33. package/app-node/mcp_tools.mjs +198 -0
  34. package/app-node/mcp_tools.test.mjs +39 -0
  35. package/app-node/progress_cache.mjs +7 -0
  36. package/app-node/progress_cache.test.mjs +23 -0
  37. package/app-node/progress_speech.mjs +102 -0
  38. package/app-node/progress_speech.test.mjs +48 -0
  39. package/app-node/project_sessions.mjs +148 -0
  40. package/app-node/project_sessions.test.mjs +77 -0
  41. package/app-node/restart_notice.mjs +57 -0
  42. package/app-node/restart_notice.test.mjs +37 -0
  43. package/app-node/restart_policy.mjs +27 -0
  44. package/app-node/restart_policy.test.mjs +33 -0
  45. package/app-node/text_routing.mjs +8 -0
  46. package/app-node/text_routing.test.mjs +18 -0
  47. package/app-node/tts_backends.mjs +251 -0
  48. package/app-node/tts_backends.test.mjs +400 -0
  49. package/app-node/tts_chunks.mjs +57 -0
  50. package/app-node/tts_chunks.test.mjs +35 -0
  51. package/app-node/tts_prefetch.mjs +38 -0
  52. package/app-node/tts_prefetch.test.mjs +49 -0
  53. package/app-node/tts_settings.mjs +72 -0
  54. package/app-node/tts_settings.test.mjs +127 -0
  55. package/app-node/tts_voice_config.mjs +127 -0
  56. package/app-node/tts_voice_config.test.mjs +64 -0
  57. package/app-node/voice_clone_capture.mjs +76 -0
  58. package/app-node/voice_clone_capture.test.mjs +51 -0
  59. package/app-node/voice_messages.mjs +62 -0
  60. package/app-node/voice_messages.test.mjs +33 -0
  61. package/docs/CONFIGURATION.md +183 -0
  62. package/docs/FRESH_INSTALL.md +193 -0
  63. package/docs/MULTI_INSTANCE.md +183 -0
  64. package/docs/RELEASE.md +72 -0
  65. package/docs/USAGE.md +108 -0
  66. package/docs/assets/figures/verbalcoding-flow.svg +63 -0
  67. package/docs/i18n/README.es.md +121 -0
  68. package/docs/i18n/README.fr.md +121 -0
  69. package/docs/i18n/README.ja.md +121 -0
  70. package/docs/i18n/README.ko.md +121 -0
  71. package/docs/i18n/README.ru.md +121 -0
  72. package/docs/i18n/README.zh.md +121 -0
  73. package/package.json +58 -0
  74. package/run.sh +82 -0
  75. package/scripts/bootstrap_prereqs.sh +193 -0
  76. package/scripts/cli.mjs +369 -0
  77. package/scripts/docker_ubuntu_smoke.sh +76 -0
  78. package/scripts/doctor.mjs +134 -0
  79. package/scripts/install.mjs +108 -0
  80. package/scripts/install.sh +44 -0
  81. package/scripts/mcp-server.mjs +84 -0
  82. package/scripts/openvoice_smoke.py +34 -0
  83. package/scripts/openvoice_synth.py +103 -0
  84. package/scripts/setup_openvoice.sh +34 -0
  85. package/scripts/setup_supertonic.sh +18 -0
@@ -0,0 +1,71 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+
4
+ import {
5
+ createLatencyTurn,
6
+ summarizeLatencyRecords,
7
+ formatLatencySummary,
8
+ } from './latency_metrics.mjs';
9
+
10
+ test('createLatencyTurn records stage timings and derived total latency', () => {
11
+ let now = 1000;
12
+ const writes = [];
13
+ const turn = createLatencyTurn({
14
+ id: 'turn-1',
15
+ userId: 'u1',
16
+ startedAtMs: now,
17
+ now: () => now,
18
+ writeRecord: record => writes.push(record),
19
+ });
20
+
21
+ now = 1200;
22
+ turn.mark('voice_first_packet');
23
+ now = 1800;
24
+ turn.mark('voice_segment_end');
25
+ now = 2100;
26
+ turn.stage('stt', 500, { transcriptChars: 12 });
27
+ now = 3000;
28
+ turn.stage('agent', 900, { answerChars: 30 });
29
+ now = 3500;
30
+ turn.stage('tts_synth', 400, { chunks: 2 });
31
+ now = 4300;
32
+ const record = turn.finish({ status: 'ok' });
33
+
34
+ assert.equal(writes.length, 1);
35
+ assert.equal(record.id, 'turn-1');
36
+ assert.equal(record.status, 'ok');
37
+ assert.equal(record.durations.total_ms, 3300);
38
+ assert.equal(record.durations.voice_capture_ms, 600);
39
+ assert.equal(record.durations.stt_ms, 500);
40
+ assert.equal(record.durations.agent_ms, 900);
41
+ assert.equal(record.durations.tts_synth_ms, 400);
42
+ assert.equal(record.meta.transcriptChars, 12);
43
+ assert.equal(record.meta.answerChars, 30);
44
+ });
45
+
46
+ test('summarizeLatencyRecords reports count averages and p95', () => {
47
+ const summary = summarizeLatencyRecords([
48
+ { status: 'ok', durations: { total_ms: 1000, stt_ms: 100, agent_ms: 500 } },
49
+ { status: 'ok', durations: { total_ms: 2000, stt_ms: 300, agent_ms: 700 } },
50
+ { status: 'empty_transcript', durations: { total_ms: 500, stt_ms: 100 } },
51
+ ]);
52
+
53
+ assert.equal(summary.count, 3);
54
+ assert.equal(summary.ok, 2);
55
+ assert.equal(summary.statuses.empty_transcript, 1);
56
+ assert.equal(summary.durations.total_ms.avg, 1167);
57
+ assert.equal(summary.durations.stt_ms.avg, 167);
58
+ assert.equal(summary.durations.agent_ms.avg, 600);
59
+ assert.equal(summary.durations.total_ms.p95, 2000);
60
+ });
61
+
62
+ test('formatLatencySummary is compact and readable', () => {
63
+ const text = formatLatencySummary(summarizeLatencyRecords([
64
+ { status: 'ok', durations: { total_ms: 1234, stt_ms: 111, tts_total_ms: 222 } },
65
+ ]));
66
+
67
+ assert.match(text, /처리량: 1턴/);
68
+ assert.match(text, /total/);
69
+ assert.match(text, /stt/);
70
+ assert.match(text, /tts_total/);
71
+ });