mercury-agent 0.4.22 → 0.4.23

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.
@@ -0,0 +1,168 @@
1
+ # Bug: mercury run fails when registry pull fails but local build exists
2
+
3
+ **Severity:** P1 — blocks users who build locally but have a registry image configured
4
+ **Introduced in:** 0.4.22 (commit 75e8e71)
5
+ **File:** `src/cli/mercury.ts`, `runAction()` (~line 187)
6
+
7
+ ## Symptom
8
+
9
+ ```
10
+ $ mercury build # succeeds → mercury-agent:latest exists locally
11
+ $ mercury run
12
+ Image 'ghcr.io/avishai-tsabari/mercury-agent:latest' not found locally, pulling...
13
+ Error response from daemon: unauthorized
14
+
15
+ Error: Failed to pull 'ghcr.io/avishai-tsabari/mercury-agent:latest'.
16
+ If this is a private registry, authenticate first:
17
+ docker login ghcr.io
18
+ ```
19
+
20
+ The user has a working local image (`mercury-agent:latest`) from `mercury build`,
21
+ but `mercury run` exits with an error because the configured registry image
22
+ can't be pulled (private registry, no auth, offline, etc.).
23
+
24
+ ## Root cause
25
+
26
+ The 0.4.22 change replaced the local-fallback logic with auto-pull. The old
27
+ code tried `mercury-agent:latest` as a fallback when the configured image
28
+ wasn't found. The new code attempts `docker pull` and hard-exits on failure —
29
+ it never checks whether a locally built image exists.
30
+
31
+ ### Before (0.4.21)
32
+
33
+ ```
34
+ configured image not found?
35
+ → try mercury-agent:latest locally
36
+ → found? use it (with warning)
37
+ → not found? error: pull or build
38
+ ```
39
+
40
+ ### After (0.4.22)
41
+
42
+ ```
43
+ configured image not found?
44
+ → is registry image? attempt pull
45
+ → pull fails? hard exit ← BUG: should fall back to local
46
+ → not registry? error: run mercury build
47
+ ```
48
+
49
+ ## Fix
50
+
51
+ After a failed pull of a registry image, check if `mercury-agent:latest`
52
+ exists locally before giving up. If it does, use it with a warning.
53
+
54
+ ### Implementation (lines ~187–213 of `src/cli/mercury.ts`)
55
+
56
+ Replace the current block:
57
+
58
+ ```typescript
59
+ if (imageCheck.status !== 0) {
60
+ const isRegistryImage = imageName.includes("/");
61
+ if (isRegistryImage) {
62
+ console.log(`Image '${imageName}' not found locally, pulling...`);
63
+ const pull = spawnSync("docker", ["pull", imageName], {
64
+ stdio: "inherit",
65
+ });
66
+ if (pull.signal) {
67
+ process.exit(1);
68
+ }
69
+ if (pull.status !== 0) {
70
+ const firstSegment = imageName.split("/")[0];
71
+ const registry = firstSegment.includes(".")
72
+ ? firstSegment
73
+ : "docker.io";
74
+ console.error(`\nError: Failed to pull '${imageName}'.`);
75
+ console.error(
76
+ "If this is a private registry, authenticate first:\n" +
77
+ ` docker login ${registry}`,
78
+ );
79
+ process.exit(1);
80
+ }
81
+ } else {
82
+ console.error(`Error: Container image '${imageName}' not found.`);
83
+ console.error("Run 'mercury build' to build it.");
84
+ process.exit(1);
85
+ }
86
+ }
87
+ ```
88
+
89
+ With:
90
+
91
+ ```typescript
92
+ if (imageCheck.status !== 0) {
93
+ const isRegistryImage = imageName.includes("/");
94
+ let resolved = false;
95
+
96
+ if (isRegistryImage) {
97
+ console.log(`Image '${imageName}' not found locally, pulling...`);
98
+ const pull = spawnSync("docker", ["pull", imageName], {
99
+ stdio: "inherit",
100
+ });
101
+ if (pull.signal) {
102
+ process.exit(1);
103
+ }
104
+ if (pull.status === 0) {
105
+ resolved = true;
106
+ }
107
+ }
108
+
109
+ // Fallback: if the configured image isn't available (pull failed, not a
110
+ // registry image, or never pulled), try the local build tag.
111
+ if (!resolved) {
112
+ const localTag = "mercury-agent:latest";
113
+ if (imageName !== localTag) {
114
+ const localCheck = spawnSync("docker", ["image", "inspect", localTag], {
115
+ stdio: "pipe",
116
+ });
117
+ if (localCheck.status === 0) {
118
+ console.log(
119
+ `\nℹ️ Using locally built ${localTag} (configured image unavailable)\n`,
120
+ );
121
+ process.env.MERCURY_AGENT_IMAGE = localTag;
122
+ resolved = true;
123
+ }
124
+ }
125
+ }
126
+
127
+ if (!resolved) {
128
+ if (isRegistryImage) {
129
+ const firstSegment = imageName.split("/")[0];
130
+ const registry = firstSegment.includes(".")
131
+ ? firstSegment
132
+ : "docker.io";
133
+ console.error(`\nError: Failed to pull '${imageName}'.`);
134
+ console.error(
135
+ "If this is a private registry, authenticate first:\n" +
136
+ ` docker login ${registry}\n` +
137
+ "Or build locally:\n" +
138
+ " mercury build",
139
+ );
140
+ } else {
141
+ console.error(`Error: Container image '${imageName}' not found.`);
142
+ console.error("Run 'mercury build' to build it.");
143
+ }
144
+ process.exit(1);
145
+ }
146
+ }
147
+ ```
148
+
149
+ ### Behavior after fix
150
+
151
+ ```
152
+ configured image not found?
153
+ → is registry image? attempt pull
154
+ → pull succeeds? use it ✓
155
+ → pull fails? continue to fallback
156
+ → try mercury-agent:latest locally
157
+ → found? use it (with info message) ✓
158
+ → not found? error with both suggestions (login + build) ✓
159
+ ```
160
+
161
+ ## How to verify
162
+
163
+ 1. Build locally: `mercury build`
164
+ 2. Ensure no GHCR auth: `docker logout ghcr.io`
165
+ 3. Set `.env` to `MERCURY_AGENT_IMAGE=ghcr.io/avishai-tsabari/mercury-agent:latest`
166
+ 4. Run `mercury run` — should fall back to local image with info message
167
+ 5. Remove local image: `docker rmi mercury-agent:latest`
168
+ 6. Run `mercury run` — should error with both `docker login` and `mercury build` suggestions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mercury-agent",
3
- "version": "0.4.22",
3
+ "version": "0.4.23",
4
4
  "description": "Personal AI assistant for chat platforms (WhatsApp, Slack, Discord, Telegram)",
5
5
  "license": "MIT",
6
6
  "author": "Avishai Tsabari",