kira-glasses-bridge 2.29.0 → 2.30.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kira-glasses-bridge",
3
- "version": "2.29.0",
3
+ "version": "2.30.0",
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
6
  "bin": {
@@ -29,9 +29,14 @@ export function roleLayer(toml) {
29
29
  return { instructions: typeof said === 'string' ? said.trim() : '', config: flatten(rest) }
30
30
  }
31
31
 
32
+ /** What every thread run through Kira is told about where the person sees it. */
33
+ export const IN_KIRA =
34
+ 'The person sees this thread in Kira, not in a terminal: images you generate are shown to them there, so ' +
35
+ "don't link their paths on this Mac, and never say you showed or opened something you didn't."
36
+
32
37
  /** The thread's developer instructions: the agent's own, then what Kira adds for this run. */
33
38
  export const developerInstructions = (role, persona) =>
34
- [role?.instructions, persona?.systemPrompt].filter(Boolean).join('\n\n')
39
+ [role?.instructions, persona?.systemPrompt, IN_KIRA].filter(Boolean).join('\n\n')
35
40
 
36
41
  /** The Codex agent a job runs as (null for none); throws, saying where, when its file isn't there. */
37
42
  export async function codexAgentOf(persona, root = FOLDERS.codex.agents()) {
@@ -80,11 +80,21 @@ export function itemAction(item, cwd) {
80
80
  return act('plan', 'Plan', short(item.text, 160), { tool: 'Plan' })
81
81
  case 'collabAgentToolCall':
82
82
  return act('delegate', 'Subtask', short(item.prompt ?? '', 160), { tool: 'Subtask' })
83
+ case 'imageGeneration':
84
+ return act('other', 'Make an image', short(item.revisedPrompt ?? '', 160), { tool: 'ImageGeneration' })
83
85
  default:
84
86
  return null
85
87
  }
86
88
  }
87
89
 
90
+ /** The image a finished image generation saved on the Mac, as an event Kira stores and shows (null when none). */
91
+ export function imageOf(item) {
92
+ if (item.type !== 'imageGeneration' || item.status !== 'completed' || !item.savedPath) return null
93
+ const name = String(item.savedPath).split('/').pop()
94
+ const prompt = item.revisedPrompt ? { prompt: short(item.revisedPrompt, 400) } : {}
95
+ return { kind: 'image', id: item.id, path: String(item.savedPath), name, ...prompt }
96
+ }
97
+
88
98
  /** A finished item's outcome: whether it went through, and what it said. */
89
99
  export function itemResult(item) {
90
100
  if (item.type === 'commandExecution') {
@@ -92,5 +102,9 @@ export function itemResult(item) {
92
102
  return { ok, preview: short(String(item.aggregatedOutput ?? '').trim(), 240) }
93
103
  }
94
104
  if (item.type === 'mcpToolCall') return { ok: !item.error && item.status === 'completed', preview: '' }
105
+ if (item.type === 'imageGeneration') {
106
+ const limited = item.failure?.type === 'usageLimitExceeded' ? 'Your image limit is used up for now' : ''
107
+ return { ok: item.status === 'completed' && !item.failure, preview: limited }
108
+ }
95
109
  return { ok: item.status ? item.status === 'completed' : true, preview: '' }
96
110
  }
@@ -3,7 +3,7 @@
3
3
  // change Codex asks about is decided by Kira's rules (io.check), and by the person when they ask.
4
4
  import { permissionOptions, requestId } from './protocol.mjs'
5
5
  import { TEXT_CAP, short } from './claude-calls.mjs'
6
- import { callsOf, codexOptionsFor, itemAction, itemResult, strictest } from './codex-items.mjs'
6
+ import { callsOf, codexOptionsFor, imageOf, itemAction, itemResult, strictest } from './codex-items.mjs'
7
7
  import { codexBin, openCodex } from './codex-rpc.mjs'
8
8
  import { kiraDecides } from './checks.mjs'
9
9
  import { codexAgentOf, developerInstructions } from './codex-agent.mjs'
@@ -87,6 +87,8 @@ async function run({ prompt, sessionId, cwd, persona, settings, abort }, io) {
87
87
  io.emit({ kind: 'message', text: short(p.item.text, TEXT_CAP) })
88
88
  } else if (itemAction(p.item, cwd)) {
89
89
  io.emit({ kind: 'action_result', id: p.item.id, ...itemResult(p.item) })
90
+ const image = imageOf(p.item)
91
+ if (image) io.emit(image)
90
92
  }
91
93
  changes.delete(p.item.id)
92
94
  } else if (method === 'error' && !p.willRetry) {
@@ -119,8 +121,7 @@ async function run({ prompt, sessionId, cwd, persona, settings, abort }, io) {
119
121
  const roots = await kiraSkillRoots(persona)
120
122
  if (roots.length) await codex.request('skills/extraRoots/set', { extraRoots: roots })
121
123
  const config = { ...role?.config, ...(persona?.kiraTools ? kiraServer(persona.kiraTools) : {}) }
122
- const said = developerInstructions(role, persona)
123
- const instructions = said ? { developerInstructions: said } : {}
124
+ const instructions = { developerInstructions: developerInstructions(role, persona) }
124
125
  const opened = thread
125
126
  ? await codex.request('thread/resume', { threadId: thread, cwd, ...options, ...instructions, config })
126
127
  : await codex.request('thread/start', { cwd, ...options, ...instructions, config })