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 +18 -5
- package/src/claude-run.mjs +16 -7
- package/src/index.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kira-glasses-bridge",
|
|
3
|
-
"version": "1.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": {
|
|
7
|
-
|
|
8
|
-
|
|
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": [
|
|
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
|
}
|
package/src/claude-run.mjs
CHANGED
|
@@ -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(
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 => {
|