claude-phone-local 2.1.2 → 2.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.
@@ -159,10 +159,22 @@ SLACK DELIVERY: When the caller requests delivery to Slack (phrases like "send t
159
159
 
160
160
  The caller may hang up while you're working (they'll hear hold music). That's fine - complete the work and send to Slack. They'll see it there.
161
161
 
162
+ END OF CALL: The phone app matches a fixed list of goodbye words (bye, goodbye, hang up, etc.) to end the call automatically, so it misses anything phrased differently - "that's everything, thanks", "I'm all set", "nothing else for now", "we're done here". You understand intent better than a keyword match does, so ALSO add a third line whenever the caller's message signals the conversation is actually finished (a clear goodbye/thanks-and-done in any wording, in any language) - not for a mid-conversation pause, not for "give me a second", not merely because their immediate question was answered:
163
+
164
+ 🔚 END_CALL: true
165
+
166
+ Omit this line entirely (do not write "false") on every turn that isn't a real goodbye - most turns won't have it.
167
+
162
168
  Example query: "What's the weather in Royce City?"
163
169
  Example response:
164
170
  🗣️ VOICE_RESPONSE: It's 65 degrees and partly cloudy in Royce City right now. Great weather for being outside!
165
171
  🎯 COMPLETED: Weather lookup for Royce City done.
172
+
173
+ Example query: "Great, that's everything, thanks!"
174
+ Example response:
175
+ 🗣️ VOICE_RESPONSE: You're welcome! Have a great day.
176
+ 🎯 COMPLETED: Caller signed off, no further requests.
177
+ 🔚 END_CALL: true
166
178
  [END VOICE CONTEXT]
167
179
 
168
180
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-phone-local",
3
- "version": "2.1.2",
3
+ "version": "2.2.0",
4
4
  "description": "Local/offline fork of NetworkChuck's claude-phone: talk to Claude Code over 3CX/SIP with faster-whisper STT + Piper TTS in one Docker container.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -162,6 +162,17 @@ function extractVoiceLine(response) {
162
162
  return response.substring(0, 500).trim();
163
163
  }
164
164
 
165
+ /**
166
+ * Whether Claude's raw response signals the conversation is actually over.
167
+ * Complements isGoodbye()'s fixed phrase match on the caller's own words -
168
+ * Claude sees the full exchange and can recognize a sign-off phrased in ways
169
+ * the keyword list doesn't cover ("that's everything, thanks", "I'm all
170
+ * set"), in any language, without maintaining a growing keyword list.
171
+ */
172
+ function hasEndCallMarker(response) {
173
+ return /🔚\s*END_CALL:\s*true/i.test(response);
174
+ }
175
+
165
176
  /**
166
177
  * Play a clip the caller is allowed to interrupt.
167
178
  *
@@ -443,6 +454,13 @@ async function conversationLoop(endpoint, dialog, callUuid, options, deviceConfi
443
454
  const responseBarge = await playInterruptible(endpoint, session, responseUrl);
444
455
  if (responseBarge) {
445
456
  pendingUtterance = responseBarge;
457
+ } else if (hasEndCallMarker(claudeResponse)) {
458
+ // Claude judged this a real sign-off from the caller's own words
459
+ // (not just isGoodbye()'s fixed phrase match) - she already said
460
+ // her goodbye as part of the normal response above, so just end
461
+ // the call rather than waiting for another turn.
462
+ console.log('[' + new Date().toISOString() + '] CONVERSATION Claude signaled end of call');
463
+ break;
446
464
  }
447
465
  }
448
466