@gotcos/glasses-server 6.3.1 → 6.6.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/.env.example +23 -7
- package/CHANGELOG.md +108 -0
- package/README.md +28 -8
- package/bin/cli.cjs +22 -10
- package/package.json +18 -6
- package/server/bin/cos-output-image-publisher.mjs +324 -0
- package/server/bootstrap.ts +16 -0
- package/server/index.ts +61 -21
- package/server/lib/activity-preview.ts +168 -0
- package/server/lib/archive.ts +20 -6
- package/server/lib/claude-bridge.ts +215 -60
- package/server/lib/claude-run-ledger.ts +7 -2
- package/server/lib/codex-bridge.ts +186 -71
- package/server/lib/codex-engine-sessions.ts +24 -2
- package/server/lib/codex-model-catalog.ts +450 -0
- package/server/lib/codex-run-ledger.ts +20 -4
- package/server/lib/conversation.ts +64 -2
- package/server/lib/display-bus.ts +61 -3
- package/server/lib/image-safety.ts +458 -0
- package/server/lib/listener-startup.ts +29 -0
- package/server/lib/media-store.ts +833 -0
- package/server/lib/model-image-input.ts +27 -0
- package/server/lib/model-router.ts +67 -8
- package/server/lib/query-attachments.ts +132 -0
- package/server/lib/run-output-images.ts +442 -0
- package/server/lib/server-instance-id.ts +55 -0
- package/server/lib/server-instance-lock.ts +122 -0
- package/server/lib/server-metrics.ts +7 -0
- package/server/routes/display.ts +43 -22
- package/server/routes/health.ts +19 -2
- package/server/routes/media.ts +285 -0
- package/server/routes/message-ref.ts +18 -6
- package/server/routes/openai-compat.ts +44 -11
- package/server/routes/query.ts +51 -16
- package/server/routes/sessions.ts +33 -4
- package/shared/media-attachment.ts +126 -0
- package/shared/model-preference.ts +140 -17
package/.env.example
CHANGED
|
@@ -19,18 +19,34 @@ BIND_HOST=0.0.0.0
|
|
|
19
19
|
# here for a stable token across restarts.
|
|
20
20
|
# COS_API_TOKEN=pick-any-long-random-string
|
|
21
21
|
|
|
22
|
+
# Optional durable image-store location. Defaults to
|
|
23
|
+
# ~/.cos-glasses/data/media alongside the standalone conversation/archive data.
|
|
24
|
+
# COS_MEDIA_ROOT=/path/on-a-local-volume/media
|
|
25
|
+
|
|
26
|
+
# Optional logical server identity location. Most installs should keep the
|
|
27
|
+
# default (~/.cos-glasses/server-instance-id) so reconnects can verify the same
|
|
28
|
+
# server after Wi-Fi/Tailscale changes and process restarts.
|
|
29
|
+
# COS_SERVER_INSTANCE_ID_PATH=/path/to/server-instance-id
|
|
30
|
+
|
|
22
31
|
# ── THE LLM (chat) ──────────────────────────────────────────────────────
|
|
23
32
|
# Chat runs through your LOCAL agent CLI — NOT an API key:
|
|
24
|
-
# Opus /
|
|
25
|
-
#
|
|
33
|
+
# Opus / Fable / Sonnet -> Claude Code CLI (https://claude.ai/download, then `claude login`)
|
|
34
|
+
# GPT Frontier/Balanced -> Codex CLI (https://developers.openai.com/codex/, then `codex login`)
|
|
26
35
|
# Install at least one. Pick the default model the glasses use:
|
|
27
|
-
# COS_G2_DEFAULT_MODEL=sonnet # opus | sonnet |
|
|
36
|
+
# COS_G2_DEFAULT_MODEL=sonnet # opus | fable | sonnet | codex-frontier | codex-balanced
|
|
28
37
|
#
|
|
29
|
-
# Codex
|
|
30
|
-
#
|
|
31
|
-
#
|
|
38
|
+
# GPT slots refresh from the Codex model catalog every 15 minutes and retain
|
|
39
|
+
# their last-known-good resolution if discovery is temporarily unavailable.
|
|
40
|
+
# COS_CODEX_MODEL_REFRESH_TTL_MS=900000
|
|
41
|
+
# COS_CODEX_MODEL_REFRESH_TIMEOUT_MS=7000
|
|
42
|
+
#
|
|
43
|
+
# Legacy explicit overrides remain supported for migrated codex-high/frontier
|
|
44
|
+
# installs. Leave blank for auto-latest; Balanced always stays auto-catalog.
|
|
32
45
|
# COS_CODEX_MODEL=
|
|
33
|
-
# COS_CODEX_REASONING_EFFORT=high
|
|
46
|
+
# COS_CODEX_REASONING_EFFORT=high # low | medium | high | xhigh | max | ultra
|
|
47
|
+
#
|
|
48
|
+
# Codex remains read-only by default. This is the only broader trust opt-in:
|
|
49
|
+
# COS_CODEX_SANDBOX=workspace-write
|
|
34
50
|
|
|
35
51
|
# ── VOICE (optional) ────────────────────────────────────────────────────
|
|
36
52
|
# Local transcription is FREE via whisper.cpp (brew install whisper-cpp; the
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,113 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 6.6.0
|
|
4
|
+
|
|
5
|
+
Reconnect compatibility for COS Glasses build 188, without importing private
|
|
6
|
+
COS day-context or Mac service-control behavior into the public package.
|
|
7
|
+
|
|
8
|
+
- **Stable logical server identity.** The server creates one atomic UUID under
|
|
9
|
+
`~/.cos-glasses/server-instance-id`, preserves it across process and network
|
|
10
|
+
restarts, and returns it from authenticated `/api/models` probes. Files are
|
|
11
|
+
mode `0600`; identity is minted only after every required listener binds.
|
|
12
|
+
- **Boot-scoped display cursors.** Display events receive one publish-owned ID
|
|
13
|
+
before fan-out, so multiple subscribers see the same cursor and cannot
|
|
14
|
+
duplicate replay records. Each process boot has a distinct UUID.
|
|
15
|
+
- **Deterministic reconnect handshake.** `/api/display-stream` emits `ready`
|
|
16
|
+
before application events, accepts boot/event cursors, replays the last 200
|
|
17
|
+
publish-owned events, and reports typed `boot_changed`, `cursor_ahead`, or
|
|
18
|
+
`buffer_overflow` gaps so clients reconcile durable history instead of
|
|
19
|
+
guessing or silently dropping replies.
|
|
20
|
+
- **Privacy boundary preserved.** Authenticated query activity remains off the
|
|
21
|
+
unauthenticated global display bus. The npm server does not include private
|
|
22
|
+
daily evidence exports, personal COS paths, launchd ownership, or remote
|
|
23
|
+
machine-restart controls.
|
|
24
|
+
- **Backward compatible.** Older clients can continue opening the same SSE
|
|
25
|
+
endpoint and ignoring the additive `ready`, cursor metadata, and replay-gap
|
|
26
|
+
events.
|
|
27
|
+
|
|
28
|
+
## 6.5.0
|
|
29
|
+
|
|
30
|
+
Durable phone photos and assistant-selected output images for COS Glasses
|
|
31
|
+
build 179, while preserving the public server's sandbox and privacy boundary.
|
|
32
|
+
|
|
33
|
+
- **One media contract.** Authenticated phone uploads become opaque attachment
|
|
34
|
+
refs, survive queues/restarts/archives/numbered-message recall, and resolve to
|
|
35
|
+
normalized server-owned files for Claude/Codex. Bytes and storage paths never
|
|
36
|
+
enter SSE, run ledgers, or archives.
|
|
37
|
+
- **Answer images.** Claude or Codex can publish an already-local generated,
|
|
38
|
+
researched, or explicitly used email image through a private run-scoped
|
|
39
|
+
capability. The server accepts JPEG/PNG/WebP/HEIC/HEIF/AVIF up to 16 MiB and
|
|
40
|
+
16 megapixels, strips metadata, re-encodes through the existing media store,
|
|
41
|
+
and appends refs to the completed answer.
|
|
42
|
+
- **No mailbox or URL crawler.** The publisher rejects URLs, data URIs, base64,
|
|
43
|
+
unrelated discovery, symlinks, directory replacement, content-id tampering,
|
|
44
|
+
over-capacity output, and manifest fields that could carry private paths.
|
|
45
|
+
- **Codex remains read-only.** Output publishing adds only the random private
|
|
46
|
+
run directory via `codex exec --add-dir`; global sandbox flags precede
|
|
47
|
+
`resume`. Older CLIs without `--add-dir` keep chat working and simply disable
|
|
48
|
+
Codex output-image publishing. There is no full-access fallback.
|
|
49
|
+
- **Durable finalization.** Assistant text is persisted before image
|
|
50
|
+
normalization, request media associates even if SSE disconnects, partial
|
|
51
|
+
image failures do not discard successful refs, and completion emits one
|
|
52
|
+
canonical `attachments` list with safe aggregate stats.
|
|
53
|
+
- **Lens contract.** `/api/health` advertises `mediaProcessingReady` and
|
|
54
|
+
`g2LensVariant=png-288x144-v1`; the media endpoint serves the validated phone,
|
|
55
|
+
thumbnail, and exact 288×144 G2 variants expected by build 179.
|
|
56
|
+
- **Fresh-install diagnostics.** The npm launcher now reports whether ffmpeg is
|
|
57
|
+
ready for phone/output/lens images, gives a non-blocking install command when
|
|
58
|
+
absent, and sends setup questions directly to `gotcos.com/wizard/`.
|
|
59
|
+
- **One server owner.** The public runner now claims the same atomic
|
|
60
|
+
machine-wide lock as the installed LaunchAgent before mutable modules load.
|
|
61
|
+
A duplicate exits with code 75, and HTTP/HTTPS listeners bind as one required
|
|
62
|
+
set: if either port is occupied, any earlier listener closes and the process
|
|
63
|
+
exits instead of surviving half-bound with separate SSE and media state.
|
|
64
|
+
|
|
65
|
+
Release evidence: TypeScript, 130/130 tests across 23 files, package dry-run
|
|
66
|
+
including the executable publisher and startup hardening, and a live duplicate
|
|
67
|
+
start against the installed LaunchAgent rejected before server initialization.
|
|
68
|
+
|
|
69
|
+
## 6.4.0
|
|
70
|
+
|
|
71
|
+
Fresh-install parity for COS Glasses builds 170–173, without weakening the
|
|
72
|
+
public server's sandbox defaults.
|
|
73
|
+
|
|
74
|
+
- **Auto-updating GPT Frontier + Balanced.** Stable client slots resolve to the
|
|
75
|
+
top two capable models in the newest visible GPT generation through Codex's
|
|
76
|
+
official `model/list` catalog. The server refreshes at boot and every 15
|
|
77
|
+
minutes, and each Codex run awaits the same TTL-cached/coalesced refresh
|
|
78
|
+
before resolving its slot. It preserves the last-known-good catalog on
|
|
79
|
+
failures and falls back to the CLI default only before any discovery succeeds.
|
|
80
|
+
- **Fable + effort controls.** Fable joins Opus and Sonnet as a first-class
|
|
81
|
+
Claude tier alias, and High / Extra High / Max / Ultracode now propagate from
|
|
82
|
+
`/api/query` to both Claude and Codex. Claude aliases remain versionless and
|
|
83
|
+
1M-context capable; Codex effort is clamped to each live model's advertised
|
|
84
|
+
support. Per-run ledgers record the concrete resolved model and effort.
|
|
85
|
+
- **Safe live job activity.** `activityToolMode` supports off, status-only, or
|
|
86
|
+
bounded observable tool input/output previews. ANSI/control data, credential
|
|
87
|
+
assignments, auth headers, provider tokens, JWTs, URL credentials, and opaque
|
|
88
|
+
blobs are redacted, including 40–72-character PEM/private-key body chunks.
|
|
89
|
+
Hidden reasoning is never surfaced.
|
|
90
|
+
- **Same-session run safety.** Turns for one conversation now serialize until
|
|
91
|
+
the active bridge sends a terminal callback, while different sessions remain
|
|
92
|
+
concurrent. Failed or cancelled Claude/Codex runs remove the exact pending
|
|
93
|
+
user exchange by object identity, preventing phantom prompts, duplicate-text
|
|
94
|
+
deletion, and resume-history contamination.
|
|
95
|
+
- **Authenticated transport boundary.** Activity lines are returned only on the
|
|
96
|
+
authenticated `/api/query` SSE stream. They are deliberately excluded from
|
|
97
|
+
the unauthenticated global display bus and its replay buffer.
|
|
98
|
+
- **Public trust model retained.** Codex remains read-only by default with only
|
|
99
|
+
the existing `workspace-write` opt-in. Existing archive traversal, local-day,
|
|
100
|
+
malformed-file, starter-kit launch-directory, and conversation behavior are
|
|
101
|
+
unchanged. Legacy `codex-high` state migrates to the frontier slot without
|
|
102
|
+
changing saved thread trust mode.
|
|
103
|
+
- **Diagnostics and compatibility.** `/api/models`, health data, and `/v1/models`
|
|
104
|
+
expose stable slots plus concrete live models. `cos-codex-high` remains an
|
|
105
|
+
accepted alias for older clients. Existing `COS_CODEX_MODEL` and
|
|
106
|
+
`COS_CODEX_REASONING_EFFORT` overrides continue to apply to the migrated
|
|
107
|
+
legacy/frontier slot; leave them unset for auto-latest. A new regression suite covers catalog
|
|
108
|
+
selection/fallback/refresh, sandbox arguments, migrations, effort mappings,
|
|
109
|
+
activity redaction, and the display-bus security boundary.
|
|
110
|
+
|
|
3
111
|
## 6.3.1
|
|
4
112
|
|
|
5
113
|
Security + robustness hardening on the 6.3.0 archive routes, from a 3-agent QA pass. (6.3.0 was never published; 6.3.1 is the first release of the expanded route set.)
|
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# COS Glasses Server
|
|
2
2
|
|
|
3
3
|
Self-hosted AI heads-up display for **Even G2 smart glasses**. Runs on your Mac,
|
|
4
|
-
talks to your local **Claude Code** CLI, and pushes answers, voice
|
|
4
|
+
talks to your local **Claude Code or Codex** CLI, and pushes answers, voice
|
|
5
5
|
transcription, and notes to the lens. Your data never leaves your machine, and no
|
|
6
6
|
API key is pasted into the phone for chat.
|
|
7
7
|
|
|
@@ -11,22 +11,34 @@ API key is pasted into the phone for chat.
|
|
|
11
11
|
npx @gotcos/glasses-server
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
The launcher checks Node, finds your CLI,
|
|
15
|
-
`~/.cos-glasses/.env`, and
|
|
16
|
-
|
|
14
|
+
The launcher checks Node, finds your CLI, checks voice and image processing,
|
|
15
|
+
downloads the local voice model when needed, writes `~/.cos-glasses/.env`, and
|
|
16
|
+
starts the server on `0.0.0.0:3141`. On boot it prints
|
|
17
|
+
an **API token** — paste that into the COS Glasses app. Only one COS Glasses
|
|
18
|
+
server may run on a Mac at a time; a second `npx` or source runner exits before
|
|
19
|
+
opening ports or touching shared conversation/media state. Version 6.6.0 also
|
|
20
|
+
gives that server a durable identity and boot-scoped display replay, allowing
|
|
21
|
+
build 188+ to reconnect after a Tailscale, Wi-Fi, or process interruption
|
|
22
|
+
without silently losing completed replies.
|
|
17
23
|
|
|
18
24
|
## Requirements
|
|
19
25
|
|
|
20
26
|
- **Node.js 20.11+** — https://nodejs.org
|
|
21
|
-
- **Claude Code CLI** (Opus/Sonnet
|
|
22
|
-
_or_ **Codex CLI** (
|
|
27
|
+
- **Claude Code CLI** (Opus/Fable/Sonnet) — https://claude.ai/download, then `claude login`
|
|
28
|
+
_or_ **Codex CLI** (GPT Frontier/Balanced) — https://developers.openai.com/codex/, then `codex login`
|
|
23
29
|
- **Even G2 glasses** + the **COS Glasses** app from the Even Hub
|
|
24
30
|
- _Optional:_ `brew install whisper-cpp` for free local voice (otherwise OpenAI API)
|
|
31
|
+
- _Optional:_ `brew install ffmpeg` for phone/output image attachments (text chat remains available without it)
|
|
25
32
|
- _Optional:_ **Tailscale** so your phone reaches your Mac from anywhere
|
|
26
33
|
|
|
27
34
|
> No `ANTHROPIC_API_KEY` is needed — chat runs through your installed CLI, billed
|
|
28
35
|
> to your existing Claude or Codex subscription. Pick either per query, or set a
|
|
29
|
-
> default with `COS_G2_DEFAULT_MODEL` (`opus`|`sonnet`|`
|
|
36
|
+
> default with `COS_G2_DEFAULT_MODEL` (`opus`|`fable`|`sonnet`|`codex-frontier`|`codex-balanced`).
|
|
37
|
+
> Claude tier aliases and the two GPT slots resolve dynamically, so new model
|
|
38
|
+
> releases do not require a new glasses package. GPT discovery refreshes every
|
|
39
|
+
> 15 minutes and retains its last-known-good catalog through transient failures.
|
|
40
|
+
> Existing `COS_CODEX_MODEL` / `COS_CODEX_REASONING_EFFORT` settings remain
|
|
41
|
+
> supported on the migrated Frontier slot; leave them blank for auto-latest.
|
|
30
42
|
> Codex runs **sandboxed read-only** by default (`COS_CODEX_SANDBOX` to adjust).
|
|
31
43
|
|
|
32
44
|
## Connect your phone (the one gotcha)
|
|
@@ -44,8 +56,13 @@ The built-in IP allowlist blocks public-internet traffic regardless.
|
|
|
44
56
|
## What it does
|
|
45
57
|
|
|
46
58
|
- Ask anything, get a streamed answer on the lens (`/api/query`, `/v1/chat/completions`)
|
|
59
|
+
- Choose Opus, Fable, Sonnet, GPT Frontier, or GPT Balanced plus High, Extra
|
|
60
|
+
High, Max, or Ultracode effort; optional redacted tool activity streams only
|
|
61
|
+
to the authenticated query that requested it
|
|
47
62
|
- Message History + cross-day "reference message N" — your chats are archived by day
|
|
48
63
|
and every message keeps a permanent number you can recall (`/api/archive`, `/api/message/:num`)
|
|
64
|
+
- Send phone photos with queued prompts, and review assistant-selected generated,
|
|
65
|
+
research, or explicitly used email images in Messages and on the G2 lens
|
|
49
66
|
- Live voice capture + transcription during meetings
|
|
50
67
|
- Local whisper.cpp transcription (free) with OpenAI fallback (optional)
|
|
51
68
|
- Tasks / calendar / people context **if** you run the
|
|
@@ -57,7 +74,8 @@ The built-in IP allowlist blocks public-internet traffic regardless.
|
|
|
57
74
|
Config lives at `~/.cos-glasses/.env` (created on first run). Every key is
|
|
58
75
|
optional except an installed CLI. Highlights: `BIND_HOST`, `PORT`,
|
|
59
76
|
`COS_API_TOKEN` (auto if unset), `OPENAI_API_KEY` (cloud voice fallback),
|
|
60
|
-
`COS_SCRIPTS_DIR` (full pipeline)
|
|
77
|
+
`COS_SCRIPTS_DIR` (full pipeline), and `COS_MEDIA_ROOT` (optional image-store
|
|
78
|
+
location; default `~/.cos-glasses/data/media`). Your name + transcription vocabulary live in
|
|
61
79
|
`~/.cos-glasses/.cos-profile.json` (see `.cos-profile.example.json`).
|
|
62
80
|
|
|
63
81
|
## Run from source
|
|
@@ -72,8 +90,10 @@ BIND_HOST=0.0.0.0 npm run start:server
|
|
|
72
90
|
## Troubleshooting
|
|
73
91
|
|
|
74
92
|
- *Phone can't connect* — check `BIND_HOST=0.0.0.0`, the same Tailscale account on both devices, and the correct `100.x` IP + token.
|
|
93
|
+
- *Safari connects but the app does not* — confirm `npx @gotcos/glasses-server@latest` is 6.6.0+, then use the app's server reconnect/edit control to verify the current URL and token. Do not run a second source or `npx` server alongside it.
|
|
75
94
|
- *AI queries fail* — run `claude --version` / `codex --version`, then `claude login` / `codex login`.
|
|
76
95
|
- *Voice getting billed?* — install `whisper-cpp` for free local transcription.
|
|
96
|
+
- *Photos unavailable?* — install `ffmpeg`, restart the server, and confirm `/api/health` reports `features.mediaProcessingReady: true`.
|
|
77
97
|
|
|
78
98
|
## License
|
|
79
99
|
|
package/bin/cli.cjs
CHANGED
|
@@ -34,13 +34,13 @@ if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
|
34
34
|
console.log('')
|
|
35
35
|
console.log(' Requirements:')
|
|
36
36
|
console.log(' - Node.js 20.11+')
|
|
37
|
-
console.log(' - Claude Code CLI (Opus /
|
|
37
|
+
console.log(' - Claude Code CLI (Opus / Fable / Sonnet) or Codex CLI (GPT Frontier / Balanced)')
|
|
38
38
|
console.log(' - Even G2 smart glasses + the COS Glasses app (Even Hub)')
|
|
39
39
|
console.log('')
|
|
40
40
|
console.log(' No API key is needed for chat — it runs through your installed CLI.')
|
|
41
41
|
console.log(' Config persists at ~/.cos-glasses/.env')
|
|
42
42
|
console.log('')
|
|
43
|
-
console.log(' Setup guide: https://www.gotcos.com')
|
|
43
|
+
console.log(' Setup guide: https://www.gotcos.com/wizard/')
|
|
44
44
|
console.log('')
|
|
45
45
|
process.exit(0)
|
|
46
46
|
}
|
|
@@ -60,9 +60,9 @@ if (nodeMajor < 20 || (nodeMajor === 20 && nodeMinor < 11)) {
|
|
|
60
60
|
console.log(green(' ✓') + ` Node.js ${process.versions.node}`)
|
|
61
61
|
|
|
62
62
|
// Step 2: agent CLI detection — at least one of Claude Code / Codex is required
|
|
63
|
-
function getCliVersion(command) {
|
|
63
|
+
function getCliVersion(command, versionArg = '--version') {
|
|
64
64
|
try {
|
|
65
|
-
return execSync(`${command}
|
|
65
|
+
return execSync(`${command} ${versionArg} 2>&1`, { shell: '/bin/sh', stdio: 'pipe', timeout: 5000 }).toString().trim()
|
|
66
66
|
} catch {
|
|
67
67
|
return null
|
|
68
68
|
}
|
|
@@ -75,15 +75,15 @@ function normalizeCodexVersion(raw) {
|
|
|
75
75
|
const claudeVersion = getCliVersion('claude')
|
|
76
76
|
const codexVersion = getCliVersion('codex')
|
|
77
77
|
if (claudeVersion) {
|
|
78
|
-
console.log(green(' ✓') + ` Claude Code ${claudeVersion} ` + dim('(Opus /
|
|
78
|
+
console.log(green(' ✓') + ` Claude Code ${claudeVersion} ` + dim('(Opus / Fable / Sonnet)'))
|
|
79
79
|
} else {
|
|
80
|
-
console.log(yellow(' ⚠') + ' Claude Code CLI not found ' + dim('— Opus/Sonnet
|
|
80
|
+
console.log(yellow(' ⚠') + ' Claude Code CLI not found ' + dim('— Opus/Fable/Sonnet unavailable'))
|
|
81
81
|
console.log(' Install: ' + bold('https://claude.ai/download'))
|
|
82
82
|
}
|
|
83
83
|
if (codexVersion) {
|
|
84
|
-
console.log(green(' ✓') + ` Codex CLI ${normalizeCodexVersion(codexVersion)} ` + dim('(
|
|
84
|
+
console.log(green(' ✓') + ` Codex CLI ${normalizeCodexVersion(codexVersion)} ` + dim('(GPT Frontier / Balanced)'))
|
|
85
85
|
} else {
|
|
86
|
-
console.log(yellow(' ⚠') + ' Codex CLI not found ' + dim('—
|
|
86
|
+
console.log(yellow(' ⚠') + ' Codex CLI not found ' + dim('— GPT Frontier/Balanced unavailable'))
|
|
87
87
|
}
|
|
88
88
|
if (!claudeVersion && !codexVersion) {
|
|
89
89
|
console.log('')
|
|
@@ -184,13 +184,25 @@ if (whisperCliPath && hasValidModel) {
|
|
|
184
184
|
console.log(' Free local voice: ' + bold('brew install whisper-cpp') + dim(' (no Homebrew? https://brew.sh)'))
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
// Step 6:
|
|
187
|
+
// Step 6: image capability — ffmpeg validates, strips metadata, normalizes,
|
|
188
|
+
// and builds the exact 288x144 G2 variant. It is optional so text/voice remain
|
|
189
|
+
// useful on a minimal install, but the launcher should make the gap visible.
|
|
190
|
+
const ffmpegVersion = getCliVersion('ffmpeg', '-version')
|
|
191
|
+
if (ffmpegVersion) {
|
|
192
|
+
const firstLine = ffmpegVersion.split('\n')[0].trim()
|
|
193
|
+
console.log(green(' ✓') + ` ${firstLine} ` + dim('— phone + lens images ready'))
|
|
194
|
+
} else {
|
|
195
|
+
console.log(yellow(' ⚠') + ' ffmpeg not installed ' + dim('— phone and answer images disabled'))
|
|
196
|
+
console.log(' Enable photos: ' + bold('brew install ffmpeg') + dim(' (text + voice still work)'))
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Step 7: phone reachability — the glasses' phone app must reach this server.
|
|
188
200
|
if (!process.env.BIND_HOST) {
|
|
189
201
|
process.env.BIND_HOST = '0.0.0.0'
|
|
190
202
|
console.log(yellow(' ⚠') + ' BIND_HOST not set — defaulting to 0.0.0.0 so your phone can reach the server')
|
|
191
203
|
}
|
|
192
204
|
|
|
193
|
-
// Step
|
|
205
|
+
// Step 8: start the bundled server
|
|
194
206
|
try {
|
|
195
207
|
const ld = process.env.COS_LAUNCH_DIR
|
|
196
208
|
if (ld && (existsSync(join(ld, '.cos', 'manifest.json')) || existsSync(join(ld, 'AGENTS.md')) || existsSync(join(ld, 'CLAUDE.md')))) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gotcos/glasses-server",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.0",
|
|
4
4
|
"description": "COS Glasses — self-hosted AI heads-up-display server for Even G2 smart glasses, powered by your local Claude Code or Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -9,14 +9,25 @@
|
|
|
9
9
|
"scripts": {
|
|
10
10
|
"start": "node bin/cli.cjs",
|
|
11
11
|
"start:server": "node --import tsx/esm server/index.ts",
|
|
12
|
+
"test": "vitest run",
|
|
12
13
|
"typecheck": "tsc --noEmit"
|
|
13
14
|
},
|
|
14
|
-
"keywords": [
|
|
15
|
+
"keywords": [
|
|
16
|
+
"even-g2",
|
|
17
|
+
"smart-glasses",
|
|
18
|
+
"claude-code",
|
|
19
|
+
"codex",
|
|
20
|
+
"ai",
|
|
21
|
+
"cos",
|
|
22
|
+
"heads-up-display",
|
|
23
|
+
"whisper"
|
|
24
|
+
],
|
|
15
25
|
"files": [
|
|
16
26
|
"bin/cli.cjs",
|
|
17
|
-
"server
|
|
18
|
-
"
|
|
19
|
-
"
|
|
27
|
+
"server",
|
|
28
|
+
"shared",
|
|
29
|
+
"!server/**/*.test.ts",
|
|
30
|
+
"!shared/**/*.test.ts",
|
|
20
31
|
".env.example",
|
|
21
32
|
".cos-profile.example.json",
|
|
22
33
|
"README.md",
|
|
@@ -48,6 +59,7 @@
|
|
|
48
59
|
"@types/cors": "^2.8.19",
|
|
49
60
|
"@types/express": "^5.0.6",
|
|
50
61
|
"@types/node": "^22.10.0",
|
|
51
|
-
"typescript": "^5.9.3"
|
|
62
|
+
"typescript": "^5.9.3",
|
|
63
|
+
"vitest": "^3.2.7"
|
|
52
64
|
}
|
|
53
65
|
}
|