kira-glasses-bridge 2.40.1 → 2.41.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.40.1",
3
+ "version": "2.41.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": {
@@ -0,0 +1,36 @@
1
+ // Auto mode: the person is not asked anything, ever. Every request a job's agent would put to them
2
+ // (a permission, a plan to approve, a question, an MCP server's form) is answered here at once, for
3
+ // Claude Code and Codex alike (job-tools.mjs wraps io.ask and io.emit with autoIo). Kira's deny rules
4
+ // still refuse before anything is asked (checks.mjs): a refusal is not a question.
5
+ import { modeOf } from './settings.mjs'
6
+
7
+ /** What a question gets in Auto mode, as its answer. */
8
+ export const AUTO_WORDS =
9
+ 'Auto mode: the person is not taking questions. ' +
10
+ 'Go with the sensible default, say your assumption in one line, and carry on.'
11
+
12
+ /** Whether the person chose Auto mode for this job. */
13
+ export const isAuto = settings => modeOf(settings) === 'auto'
14
+
15
+ /** Auto mode's answer to a request: go ahead; a question gets AUTO_WORDS. Never "always" (that writes a rule). */
16
+ export function autoAnswer(request) {
17
+ if (request?.type === 'plan') return { optionIds: ['approve'] }
18
+ if (request?.type === 'choice' || request?.type === 'text') return { optionIds: [], text: AUTO_WORDS }
19
+ return { optionIds: ['allow', 'accept'] }
20
+ }
21
+
22
+ /** A request, or its answer by Auto mode: neither leaves the Mac, so no card and nothing for the API to file. */
23
+ const unseen = event => event?.kind === 'request' || (event?.kind === 'request_resolved' && event.by === 'auto')
24
+
25
+ /**
26
+ * The job's io for Auto mode: a request is never shown (no card, no push to the phone or glasses)
27
+ * and is answered at once, by 'auto'. Other modes get io back as it is.
28
+ */
29
+ export function autoIo(io, settings) {
30
+ if (!isAuto(settings)) return io
31
+ return {
32
+ ...io,
33
+ emit: event => (unseen(event) ? undefined : io.emit(event)),
34
+ ask: async request => ({ answer: autoAnswer(request), by: 'auto' }),
35
+ }
36
+ }
@@ -10,14 +10,19 @@ const MODES = new Set(['acceptEdits', 'default', 'plan', 'auto'])
10
10
  /** The id an older Kira API sent for ask before edits. */
11
11
  const OLD = { ask: 'default' }
12
12
 
13
+ /** The mode the person chose, by Claude Code's id; accept edits when it names none. */
14
+ export function modeOf(settings) {
15
+ const said = Object.hasOwn(OLD, settings?.mode ?? '') ? OLD[settings.mode] : settings?.mode
16
+ return MODES.has(said) ? said : 'acceptEdits'
17
+ }
18
+
13
19
  /**
14
20
  * The SDK's query options for these settings (left out when unset, so Claude Code's defaults stand).
15
21
  * `kiraDecides`: Kira's rules check each call (checks.mjs); without them, edits are asked about.
16
22
  */
17
23
  export function sdkOptionsFor(settings, kiraDecides = true) {
18
24
  const s = settings ?? {}
19
- const said = Object.hasOwn(OLD, s.mode) ? OLD[s.mode] : s.mode
20
- const mode = MODES.has(said) ? said : 'acceptEdits'
25
+ const mode = modeOf(s)
21
26
  return {
22
27
  permissionMode: kiraDecides ? mode : mode === 'plan' ? 'plan' : 'default',
23
28
  ...(typeof s.model === 'string' && MODEL.test(s.model) ? { model: s.model } : {}),
package/src/job-tools.mjs CHANGED
@@ -2,6 +2,7 @@
2
2
  // reported when done), stopping one, and steering one (words into its turn at work).
3
3
  import { agentById } from './agents/index.mjs'
4
4
  import { awaitAnswer, forgetJob } from './agents/answers.mjs'
5
+ import { autoIo } from './agents/auto.mjs'
5
6
  import { resolveCwd, folderExists } from './claude-run.mjs'
6
7
  import { readSession } from './claude-sessions.mjs'
7
8
  import { changesSince, display, snapshot } from './git.mjs'
@@ -44,18 +45,19 @@ export const jobTools = {
44
45
  const abort = new AbortController()
45
46
  const live = { abort, steer: null }
46
47
  let seq = 0
47
- const io = {
48
+ const settings = args.settings ?? null
49
+ // Auto mode answers every request itself: nothing waits on the person (auto.mjs).
50
+ const io = autoIo({
48
51
  emit: event => sendLive({ type: 'job.event', jobId, seq: ++seq, at: new Date().toISOString(), event }),
49
52
  ask: (request, signal) => awaitAnswer(jobId, request, signal),
50
53
  check: call => checkCall(jobId, call, sendIfLive),
51
54
  steerable: steer => (live.steer = steer),
52
- }
55
+ }, settings)
53
56
  running.set(jobId, live)
54
57
  // Started is said at once. The git snapshot (what changed, reported at the end) is taken first but
55
58
  // in the background: in a big repository it takes longer than the API waits for this answer.
56
59
  const before = snapshot(dir).catch(() => null)
57
60
  const persona = args.persona ?? null
58
- const settings = args.settings ?? null
59
61
  // What came with it from Kira, already copied here (the prompt names their paths): codex-input.mjs.
60
62
  const attachments = Array.isArray(args.attachments) ? args.attachments : []
61
63
  const job = { prompt, attachments, sessionId, cwd: dir, persona, settings, abort }