claude-remote 0.1.9 → 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 (2) hide show
  1. package/package.json +1 -1
  2. package/server.js +28 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-remote",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "description": "Remote control bridge for Claude Code REPL - drive from phone/WebUI",
5
5
  "main": "server.js",
6
6
  "bin": {
package/server.js CHANGED
@@ -550,14 +550,14 @@ wss.on('connection', (ws, req) => {
550
550
  if (claudeProc) {
551
551
  const text = msg.text;
552
552
  log(`Chat input → PTY: "${text.substring(0, 80)}"`);
553
- const isClear = /^\/clear\s*$/i.test(text.trim());
554
- if (isClear) {
553
+ const slashCommand = extractSlashCommand(text);
554
+ if (slashCommand === '/clear') {
555
555
  markExpectingSwitch();
556
556
  }
557
557
  // Slash commands (e.g. /clear, /help, /compact) are internal CLI
558
558
  // commands, not AI turns — the stop hook will never fire, so don't
559
559
  // enter the waiting state.
560
- if (!text.trim().startsWith('/')) {
560
+ if (!slashCommand) {
561
561
  broadcast({ type: 'working_started' });
562
562
  }
563
563
  claudeProc.write(text);
@@ -850,6 +850,28 @@ function fileLooksLikeTranscript(filePath) {
850
850
  return false;
851
851
  }
852
852
 
853
+ function flattenUserContent(content) {
854
+ if (typeof content === 'string') return content;
855
+ if (!Array.isArray(content)) return '';
856
+ return content.map(block => {
857
+ if (!block || typeof block !== 'object') return '';
858
+ if (typeof block.text === 'string') return block.text;
859
+ if (typeof block.content === 'string') return block.content;
860
+ return '';
861
+ }).filter(Boolean).join('\n');
862
+ }
863
+
864
+ function extractSlashCommand(content) {
865
+ const text = flattenUserContent(content).trim();
866
+ if (!text) return '';
867
+
868
+ const commandTagMatch = text.match(/<command-name>\s*(\/[^\s<]+)\s*<\/command-name>/i);
869
+ if (commandTagMatch) return commandTagMatch[1].trim().toLowerCase();
870
+
871
+ const inlineMatch = text.match(/^(\/\S+)/);
872
+ return inlineMatch ? inlineMatch[1].trim().toLowerCase() : '';
873
+ }
874
+
853
875
  function attachTranscript(target, startOffset = 0) {
854
876
  transcriptPath = target.full;
855
877
  currentSessionId = path.basename(transcriptPath, '.jsonl');
@@ -960,14 +982,14 @@ function startTailing() {
960
982
  // Detect /clear from JSONL events (covers terminal direct input)
961
983
  if (event.type === 'user' || (event.message && event.message.role === 'user')) {
962
984
  const content = event.message && event.message.content;
963
- const isSlashCmd = typeof content === 'string' && content.trim().startsWith('/');
985
+ const slashCommand = extractSlashCommand(content);
964
986
  // Only broadcast working_started for live (new) user messages,
965
987
  // not for historical events during catch-up, and not for slash
966
988
  // commands (which are CLI commands, not AI turns).
967
- if (!tailCatchingUp && !isSlashCmd) {
989
+ if (!tailCatchingUp && !slashCommand) {
968
990
  broadcast({ type: 'working_started' });
969
991
  }
970
- if (typeof content === 'string' && /^\/clear\s*$/i.test(content.trim())) {
992
+ if (slashCommand === '/clear') {
971
993
  markExpectingSwitch();
972
994
  }
973
995
  }