kira-glasses-bridge 1.0.0 → 1.0.1

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/package.json CHANGED
@@ -1,18 +1,31 @@
1
1
  {
2
2
  "name": "kira-glasses-bridge",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Connects your Mac to Kira, the assistant for Even G2 glasses: Claude Code sessions, files, folders and apps, by voice.",
5
5
  "type": "module",
6
- "bin": { "kira-bridge": "./src/cli.mjs" },
7
- "files": ["src", "README.md"],
8
- "engines": { "node": ">=20" },
6
+ "bin": {
7
+ "kira-bridge": "src/cli.mjs"
8
+ },
9
+ "files": [
10
+ "src",
11
+ "README.md"
12
+ ],
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
9
16
  "scripts": {
10
17
  "start": "node src/cli.mjs run"
11
18
  },
12
19
  "dependencies": {
13
20
  "ws": "^8.18.0"
14
21
  },
15
- "keywords": ["even-realities", "g2", "smart-glasses", "claude-code", "kira"],
22
+ "keywords": [
23
+ "even-realities",
24
+ "g2",
25
+ "smart-glasses",
26
+ "claude-code",
27
+ "kira"
28
+ ],
16
29
  "license": "MIT",
17
30
  "homepage": "https://hackchild.xyz/kira"
18
31
  }
@@ -2,7 +2,7 @@
2
2
  import { spawn } from 'node:child_process'
3
3
  import { existsSync } from 'node:fs'
4
4
  import { homedir } from 'node:os'
5
- import { join } from 'node:path'
5
+ import { isAbsolute, join, resolve } from 'node:path'
6
6
 
7
7
  /**
8
8
  * Find the claude binary. The bridge may be started from a shell whose PATH
@@ -23,32 +23,41 @@ export function findClaude() {
23
23
 
24
24
  const MAX_MS = 15 * 60 * 1000
25
25
 
26
+ /** Kira's paths are relative to home unless absolute, like the file tools. */
27
+ export function resolveCwd(cwd) {
28
+ if (!cwd) return homedir()
29
+ const s = String(cwd).replace(/^~(?=\/|$)/, homedir())
30
+ return isAbsolute(s) ? resolve(s) : resolve(homedir(), s)
31
+ }
32
+
26
33
  export function runClaude({ prompt, sessionId, cwd }) {
27
- return new Promise(resolve => {
34
+ return new Promise(done => {
35
+ const dir = resolveCwd(cwd)
36
+ if (!existsSync(dir)) return done({ error: `folder not found: ${dir}` })
28
37
  const args = ['-p', '--output-format', 'json', '--permission-mode', 'acceptEdits']
29
38
  if (sessionId) args.push('--resume', sessionId)
30
39
  args.push(prompt)
31
- const child = spawn(findClaude(), args, { cwd: cwd || process.env.HOME, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] })
40
+ const child = spawn(findClaude(), args, { cwd: dir, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] })
32
41
  let out = ''
33
42
  let err = ''
34
43
  const timer = setTimeout(() => {
35
44
  child.kill('SIGTERM')
36
- resolve({ error: `Claude did not finish within ${MAX_MS / 60000} minutes` })
45
+ done({ error: `Claude did not finish within ${MAX_MS / 60000} minutes` })
37
46
  }, MAX_MS)
38
47
  child.stdout.on('data', d => (out += d))
39
48
  child.stderr.on('data', d => (err += d))
40
49
  child.on('error', e => {
41
50
  clearTimeout(timer)
42
51
  const hint = e.code === 'ENOENT' ? 'Claude Code is not installed or not on the bridge\'s PATH. Install it, or set KIRA_CLAUDE_BIN=/path/to/claude when starting the bridge.' : e.message
43
- resolve({ error: `could not start claude: ${hint}` })
52
+ done({ error: `could not start claude: ${hint}` })
44
53
  })
45
54
  child.on('close', code => {
46
55
  clearTimeout(timer)
47
56
  try {
48
57
  const j = JSON.parse(out)
49
- resolve({ session_id: j.session_id, result: j.result, is_error: !!j.is_error, cost_usd: j.total_cost_usd, duration_ms: j.duration_ms, num_turns: j.num_turns })
58
+ done({ session_id: j.session_id, result: j.result, is_error: !!j.is_error, cost_usd: j.total_cost_usd, duration_ms: j.duration_ms, num_turns: j.num_turns })
50
59
  } catch {
51
- resolve({ error: `claude exited with code ${code}: ${(err || out).slice(0, 500)}` })
60
+ done({ error: `claude exited with code ${code}: ${(err || out).slice(0, 500)}` })
52
61
  }
53
62
  })
54
63
  })
package/src/index.mjs CHANGED
@@ -60,7 +60,7 @@ const tools = {
60
60
  // Acknowledge now, report the result as a job when Claude finishes.
61
61
  async ask_claude(args, ws) {
62
62
  const jobId = String(args.job_id ?? '')
63
- const prompt = String(args.prompt ?? '')
63
+ const prompt = String(args.prompt ?? args.message ?? args.text ?? args.instruction ?? '').trim()
64
64
  if (!prompt) return { error: 'prompt is required' }
65
65
  log(`ask_claude job=${jobId.slice(0, 8)} session=${args.session_id ?? 'new'}: ${prompt.slice(0, 80)}`)
66
66
  void runClaude({ prompt, sessionId: args.session_id, cwd: args.cwd }).then(result => {