minecodex 0.1.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/LICENSE +21 -0
- package/README.md +56 -0
- package/apps/dashboard/app.js +387 -0
- package/apps/dashboard/favicon.svg +18 -0
- package/apps/dashboard/index.html +70 -0
- package/apps/dashboard/styles.css +297 -0
- package/features/images/README.md +106 -0
- package/features/images/codex-feature.json +24 -0
- package/features/images/src/http-server.mjs +302 -0
- package/features/images/src/image-library.mjs +582 -0
- package/features/images/src/main.mjs +52 -0
- package/features/images/src/prompt-index.mjs +182 -0
- package/features/images/src/save-as.mjs +40 -0
- package/features/images/src/thread-metadata.mjs +93 -0
- package/features/images/web/app.js +1045 -0
- package/features/images/web/index.html +162 -0
- package/features/images/web/styles.css +994 -0
- package/features/model-slider/README.md +30 -0
- package/features/model-slider/THIRD_PARTY_NOTICES.md +24 -0
- package/features/model-slider/assets/providers/anthropic.svg +1 -0
- package/features/model-slider/assets/providers/deepseek.svg +1 -0
- package/features/model-slider/assets/providers/gemini.svg +1 -0
- package/features/model-slider/assets/providers/grok.svg +1 -0
- package/features/model-slider/assets/providers/hunyuan.svg +1 -0
- package/features/model-slider/assets/providers/kimi.svg +1 -0
- package/features/model-slider/assets/providers/minimax.svg +1 -0
- package/features/model-slider/assets/providers/openai.svg +1 -0
- package/features/model-slider/assets/providers/qwen.svg +1 -0
- package/features/model-slider/assets/providers/xiaomimimo.svg +1 -0
- package/features/model-slider/assets/providers/zhipu.svg +1 -0
- package/features/model-slider/assets/ui/sparkles.svg +18 -0
- package/features/model-slider/assets/ui/star-off.svg +17 -0
- package/features/model-slider/assets/ui/star.svg +15 -0
- package/features/model-slider/codex-feature.json +56 -0
- package/features/model-slider/vendor/cc-switch-LICENSE +21 -0
- package/features/model-slider/vendor/lucide-LICENSE +35 -0
- package/features/notes/README.md +106 -0
- package/features/notes/assets/icons/circle.svg +15 -0
- package/features/notes/assets/icons/ellipsis.svg +17 -0
- package/features/notes/assets/icons/external-link.svg +17 -0
- package/features/notes/assets/icons/list-todo.svg +19 -0
- package/features/notes/assets/icons/message-square-quote.svg +17 -0
- package/features/notes/assets/icons/paperclip.svg +15 -0
- package/features/notes/assets/icons/star-off.svg +17 -0
- package/features/notes/assets/icons/star.svg +15 -0
- package/features/notes/assets/icons/sticky-note.svg +16 -0
- package/features/notes/assets/icons/trash-2.svg +19 -0
- package/features/notes/codex-feature.json +90 -0
- package/features/notes/src/http-server.mjs +541 -0
- package/features/notes/src/main.mjs +54 -0
- package/features/notes/src/product.mjs +771 -0
- package/features/notes/web/app.js +1495 -0
- package/features/notes/web/codex-artifact-document.svg +1 -0
- package/features/notes/web/codex-attachment.svg +1 -0
- package/features/notes/web/codex-build.svg +1 -0
- package/features/notes/web/codex-code.svg +1 -0
- package/features/notes/web/codex-cplusplus.svg +1 -0
- package/features/notes/web/codex-css.svg +1 -0
- package/features/notes/web/codex-document.svg +1 -0
- package/features/notes/web/codex-file.svg +1 -0
- package/features/notes/web/codex-folder.svg +1 -0
- package/features/notes/web/codex-hashes.svg +1 -0
- package/features/notes/web/codex-html.svg +1 -0
- package/features/notes/web/codex-image.svg +1 -0
- package/features/notes/web/codex-java.svg +1 -0
- package/features/notes/web/codex-javascript.svg +1 -0
- package/features/notes/web/codex-json.svg +1 -0
- package/features/notes/web/codex-notebook.svg +1 -0
- package/features/notes/web/codex-pdf.svg +1 -0
- package/features/notes/web/codex-pencil.svg +3 -0
- package/features/notes/web/codex-php.svg +1 -0
- package/features/notes/web/codex-plus.svg +3 -0
- package/features/notes/web/codex-presentation.svg +1 -0
- package/features/notes/web/codex-python.svg +1 -0
- package/features/notes/web/codex-react.svg +1 -0
- package/features/notes/web/codex-rust.svg +1 -0
- package/features/notes/web/codex-shell.svg +1 -0
- package/features/notes/web/codex-skill.svg +1 -0
- package/features/notes/web/codex-spreadsheet.svg +1 -0
- package/features/notes/web/codex-task.svg +3 -0
- package/features/notes/web/codex-terminal.svg +1 -0
- package/features/notes/web/codex-toml.svg +1 -0
- package/features/notes/web/codex-typescript.svg +1 -0
- package/features/notes/web/codex-view-all.svg +3 -0
- package/features/notes/web/index.html +15 -0
- package/features/notes/web/styles.css +1155 -0
- package/package.json +67 -0
- package/packages/cli/bin/mcx.mjs +7 -0
- package/packages/cli/src/browser-exchange.mjs +31 -0
- package/packages/cli/src/commands.mjs +389 -0
- package/packages/cli/src/config.mjs +101 -0
- package/packages/cli/src/control-server.mjs +371 -0
- package/packages/cli/src/npm-adapter.mjs +40 -0
- package/packages/cli/src/paths.mjs +33 -0
- package/packages/cli/src/platform.mjs +368 -0
- package/packages/cli/src/runtime-manager.mjs +338 -0
- package/packages/runtime-host/README.md +171 -0
- package/packages/runtime-host/src/codex-runtime.mjs +4311 -0
- package/packages/runtime-host/src/feature-registry.mjs +827 -0
- package/packages/runtime-host/src/main.mjs +98 -0
- package/packages/runtime-host/src/pid-file.mjs +23 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light;
|
|
3
|
+
--canvas: oklch(0.982 0.002 260);
|
|
4
|
+
--surface: oklch(1 0 0);
|
|
5
|
+
--surface-muted: oklch(0.962 0.004 260);
|
|
6
|
+
--ink: oklch(0.235 0.012 260);
|
|
7
|
+
--ink-secondary: oklch(0.43 0.012 260);
|
|
8
|
+
--ink-tertiary: oklch(0.52 0.012 260);
|
|
9
|
+
--border: oklch(0.89 0.006 260);
|
|
10
|
+
--border-heavy: oklch(0.8 0.008 260);
|
|
11
|
+
--accent: oklch(0.58 0.19 255);
|
|
12
|
+
--accent-hover: oklch(0.53 0.2 255);
|
|
13
|
+
--accent-soft: oklch(0.95 0.03 255);
|
|
14
|
+
--success: oklch(0.56 0.15 150);
|
|
15
|
+
--warning: oklch(0.61 0.14 70);
|
|
16
|
+
--danger: oklch(0.56 0.2 27);
|
|
17
|
+
--shadow: 0 1px 2px color-mix(in oklch, var(--ink) 7%, transparent), 0 8px 28px color-mix(in oklch, var(--ink) 5%, transparent);
|
|
18
|
+
--focus: 0 0 0 3px color-mix(in oklch, var(--accent) 28%, transparent);
|
|
19
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@media (prefers-color-scheme: dark) {
|
|
23
|
+
:root {
|
|
24
|
+
color-scheme: dark;
|
|
25
|
+
--canvas: oklch(0.17 0.008 260);
|
|
26
|
+
--surface: oklch(0.215 0.009 260);
|
|
27
|
+
--surface-muted: oklch(0.25 0.01 260);
|
|
28
|
+
--ink: oklch(0.94 0.006 260);
|
|
29
|
+
--ink-secondary: oklch(0.76 0.008 260);
|
|
30
|
+
--ink-tertiary: oklch(0.67 0.008 260);
|
|
31
|
+
--border: oklch(0.32 0.01 260);
|
|
32
|
+
--border-heavy: oklch(0.41 0.012 260);
|
|
33
|
+
--accent: oklch(0.7 0.16 255);
|
|
34
|
+
--accent-hover: oklch(0.75 0.14 255);
|
|
35
|
+
--accent-soft: oklch(0.27 0.04 255);
|
|
36
|
+
--success: oklch(0.7 0.14 150);
|
|
37
|
+
--warning: oklch(0.74 0.13 75);
|
|
38
|
+
--danger: oklch(0.72 0.16 27);
|
|
39
|
+
--shadow: 0 1px 2px oklch(0 0 0 / 0.3), 0 12px 34px oklch(0 0 0 / 0.24);
|
|
40
|
+
}
|
|
41
|
+
.plugin-icon img { filter: invert(1); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
* { box-sizing: border-box; }
|
|
45
|
+
|
|
46
|
+
body {
|
|
47
|
+
min-width: 320px;
|
|
48
|
+
margin: 0;
|
|
49
|
+
background: var(--canvas);
|
|
50
|
+
color: var(--ink);
|
|
51
|
+
font-size: 13px;
|
|
52
|
+
-webkit-font-smoothing: antialiased;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
button, input { font: inherit; }
|
|
56
|
+
|
|
57
|
+
button:focus-visible, input:focus-visible + .switch-track {
|
|
58
|
+
outline: none;
|
|
59
|
+
box-shadow: var(--focus);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.shell {
|
|
63
|
+
width: min(100% - 40px, 880px);
|
|
64
|
+
margin: 0 auto;
|
|
65
|
+
padding: 42px 0 32px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.page-header, .section-heading, .restart-notice, .diagnostics, .plugin-card {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.page-header {
|
|
74
|
+
justify-content: space-between;
|
|
75
|
+
gap: 24px;
|
|
76
|
+
margin-bottom: 28px;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
h1, h2, p { margin: 0; }
|
|
80
|
+
h1 { font-size: 20px; font-weight: 650; letter-spacing: -0.015em; }
|
|
81
|
+
h2 { font-size: 14px; font-weight: 620; }
|
|
82
|
+
|
|
83
|
+
.subtitle, #plugins-copy, .restart-notice p, .plugin-description, .error-state p {
|
|
84
|
+
color: var(--ink-secondary);
|
|
85
|
+
line-height: 1.5;
|
|
86
|
+
text-wrap: pretty;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.subtitle { margin-top: 4px; }
|
|
90
|
+
|
|
91
|
+
.runtime-state, .plugin-state {
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
gap: 7px;
|
|
95
|
+
color: var(--ink-secondary);
|
|
96
|
+
font-size: 12px;
|
|
97
|
+
white-space: nowrap;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.status-dot {
|
|
101
|
+
width: 7px;
|
|
102
|
+
height: 7px;
|
|
103
|
+
border-radius: 50%;
|
|
104
|
+
background: var(--ink-tertiary);
|
|
105
|
+
box-shadow: 0 0 0 3px color-mix(in oklch, var(--ink-tertiary) 12%, transparent);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.status-dot.is-active { background: var(--success); box-shadow: 0 0 0 3px color-mix(in oklch, var(--success) 14%, transparent); }
|
|
109
|
+
.status-dot.is-warning { background: var(--warning); box-shadow: 0 0 0 3px color-mix(in oklch, var(--warning) 14%, transparent); }
|
|
110
|
+
.status-dot.is-failed { background: var(--danger); box-shadow: 0 0 0 3px color-mix(in oklch, var(--danger) 14%, transparent); }
|
|
111
|
+
.status-dot.is-stopped { background: var(--ink-tertiary); box-shadow: 0 0 0 3px color-mix(in oklch, var(--ink-tertiary) 12%, transparent); }
|
|
112
|
+
|
|
113
|
+
.restart-notice {
|
|
114
|
+
justify-content: space-between;
|
|
115
|
+
gap: 24px;
|
|
116
|
+
margin-bottom: 28px;
|
|
117
|
+
padding: 14px 16px;
|
|
118
|
+
border: 1px solid color-mix(in oklch, var(--accent) 22%, var(--border));
|
|
119
|
+
border-radius: 12px;
|
|
120
|
+
background: var(--accent-soft);
|
|
121
|
+
animation: notice-in 180ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.restart-notice p { margin-top: 3px; }
|
|
125
|
+
|
|
126
|
+
.section-heading {
|
|
127
|
+
justify-content: space-between;
|
|
128
|
+
gap: 20px;
|
|
129
|
+
margin-bottom: 12px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.section-heading h2 { margin-bottom: 3px; }
|
|
133
|
+
.save-state { min-height: 18px; color: var(--ink-tertiary); font-size: 12px; }
|
|
134
|
+
|
|
135
|
+
.plugin-list {
|
|
136
|
+
overflow: hidden;
|
|
137
|
+
border: 1px solid var(--border);
|
|
138
|
+
border-radius: 14px;
|
|
139
|
+
background: var(--surface);
|
|
140
|
+
box-shadow: var(--shadow);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.plugin-card {
|
|
144
|
+
min-height: 106px;
|
|
145
|
+
gap: 14px;
|
|
146
|
+
padding: 18px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.plugin-card + .plugin-card { border-top: 1px solid var(--border); }
|
|
150
|
+
|
|
151
|
+
.plugin-icon {
|
|
152
|
+
display: grid;
|
|
153
|
+
width: 34px;
|
|
154
|
+
height: 34px;
|
|
155
|
+
flex: 0 0 34px;
|
|
156
|
+
place-items: center;
|
|
157
|
+
border-radius: 9px;
|
|
158
|
+
background: var(--surface-muted);
|
|
159
|
+
color: var(--ink-secondary);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.plugin-icon img { width: 18px; height: 18px; opacity: 0.78; }
|
|
163
|
+
.plugin-copy { min-width: 0; flex: 1; }
|
|
164
|
+
.plugin-title-line { display: flex; align-items: baseline; gap: 8px; }
|
|
165
|
+
.plugin-name { font-size: 14px; font-weight: 620; }
|
|
166
|
+
.plugin-version { color: var(--ink-tertiary); font-size: 11px; }
|
|
167
|
+
.plugin-description { max-width: 66ch; margin-top: 5px; }
|
|
168
|
+
|
|
169
|
+
.plugin-control {
|
|
170
|
+
display: flex;
|
|
171
|
+
min-width: 138px;
|
|
172
|
+
flex: 0 0 138px;
|
|
173
|
+
flex-direction: column;
|
|
174
|
+
align-items: flex-end;
|
|
175
|
+
gap: 9px;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.switch { position: relative; display: inline-flex; cursor: pointer; }
|
|
179
|
+
.switch input {
|
|
180
|
+
position: absolute;
|
|
181
|
+
z-index: 1;
|
|
182
|
+
inset: 0;
|
|
183
|
+
width: 36px;
|
|
184
|
+
height: 21px;
|
|
185
|
+
margin: 0;
|
|
186
|
+
cursor: pointer;
|
|
187
|
+
opacity: 0;
|
|
188
|
+
}
|
|
189
|
+
.switch-track {
|
|
190
|
+
position: relative;
|
|
191
|
+
pointer-events: none;
|
|
192
|
+
width: 36px;
|
|
193
|
+
height: 21px;
|
|
194
|
+
border: 1px solid var(--border-heavy);
|
|
195
|
+
border-radius: 999px;
|
|
196
|
+
background: var(--surface-muted);
|
|
197
|
+
transition: background 170ms ease-out, border-color 170ms ease-out;
|
|
198
|
+
}
|
|
199
|
+
.switch-track::after {
|
|
200
|
+
content: "";
|
|
201
|
+
position: absolute;
|
|
202
|
+
top: 2px;
|
|
203
|
+
left: 2px;
|
|
204
|
+
width: 15px;
|
|
205
|
+
height: 15px;
|
|
206
|
+
border-radius: 50%;
|
|
207
|
+
background: var(--surface);
|
|
208
|
+
box-shadow: 0 1px 3px oklch(0 0 0 / 0.25);
|
|
209
|
+
transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
210
|
+
}
|
|
211
|
+
.switch input:checked + .switch-track { border-color: var(--accent); background: var(--accent); }
|
|
212
|
+
.switch input:checked + .switch-track::after { transform: translateX(15px); }
|
|
213
|
+
.switch input:disabled + .switch-track { cursor: wait; opacity: 0.58; }
|
|
214
|
+
|
|
215
|
+
.button {
|
|
216
|
+
min-height: 32px;
|
|
217
|
+
border: 1px solid transparent;
|
|
218
|
+
border-radius: 8px;
|
|
219
|
+
padding: 6px 12px;
|
|
220
|
+
cursor: pointer;
|
|
221
|
+
font-weight: 560;
|
|
222
|
+
transition: background 160ms ease-out, border-color 160ms ease-out, transform 80ms ease-out;
|
|
223
|
+
}
|
|
224
|
+
.button:active { transform: translateY(1px); }
|
|
225
|
+
.button:disabled { cursor: wait; opacity: 0.62; }
|
|
226
|
+
.button.primary { background: var(--accent); color: white; }
|
|
227
|
+
.button.primary:hover:not(:disabled) { background: var(--accent-hover); }
|
|
228
|
+
.button.secondary { border-color: var(--border-heavy); background: var(--surface); color: var(--ink); }
|
|
229
|
+
.button.secondary:hover:not(:disabled), .button.quiet:hover:not(:disabled) { background: var(--surface-muted); }
|
|
230
|
+
.button.quiet { border-color: transparent; background: transparent; color: var(--ink-secondary); }
|
|
231
|
+
|
|
232
|
+
.plugin-skeleton {
|
|
233
|
+
height: 106px;
|
|
234
|
+
background: linear-gradient(90deg, transparent, color-mix(in oklch, var(--ink) 5%, transparent), transparent);
|
|
235
|
+
background-size: 220% 100%;
|
|
236
|
+
animation: skeleton 1.2s linear infinite;
|
|
237
|
+
}
|
|
238
|
+
.plugin-skeleton + .plugin-skeleton { border-top: 1px solid var(--border); }
|
|
239
|
+
|
|
240
|
+
.error-state {
|
|
241
|
+
display: flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
justify-content: space-between;
|
|
244
|
+
gap: 20px;
|
|
245
|
+
padding: 18px;
|
|
246
|
+
border: 1px solid color-mix(in oklch, var(--danger) 30%, var(--border));
|
|
247
|
+
border-radius: 12px;
|
|
248
|
+
background: color-mix(in oklch, var(--danger) 7%, var(--surface));
|
|
249
|
+
}
|
|
250
|
+
.error-state p { margin-top: 4px; }
|
|
251
|
+
|
|
252
|
+
.diagnostics {
|
|
253
|
+
justify-content: space-between;
|
|
254
|
+
gap: 24px;
|
|
255
|
+
margin-top: 26px;
|
|
256
|
+
padding-top: 18px;
|
|
257
|
+
border-top: 1px solid var(--border);
|
|
258
|
+
}
|
|
259
|
+
.diagnostics dl { display: flex; flex-wrap: wrap; gap: 10px 24px; margin: 0; }
|
|
260
|
+
.diagnostics dl div { display: flex; gap: 6px; }
|
|
261
|
+
.diagnostics dt { color: var(--ink-tertiary); }
|
|
262
|
+
.diagnostics dd { margin: 0; color: var(--ink-secondary); }
|
|
263
|
+
|
|
264
|
+
.toast {
|
|
265
|
+
position: fixed;
|
|
266
|
+
right: 20px;
|
|
267
|
+
bottom: 20px;
|
|
268
|
+
max-width: min(360px, calc(100vw - 40px));
|
|
269
|
+
border: 1px solid var(--border-heavy);
|
|
270
|
+
border-radius: 10px;
|
|
271
|
+
padding: 10px 12px;
|
|
272
|
+
background: var(--surface);
|
|
273
|
+
box-shadow: var(--shadow);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
[hidden] { display: none !important; }
|
|
277
|
+
|
|
278
|
+
@keyframes notice-in { from { opacity: 0; transform: translateY(-4px); } }
|
|
279
|
+
@keyframes skeleton { to { background-position: -220% 0; } }
|
|
280
|
+
|
|
281
|
+
@media (max-width: 640px) {
|
|
282
|
+
.shell { width: min(100% - 24px, 880px); padding-top: 26px; }
|
|
283
|
+
.page-header { align-items: flex-start; }
|
|
284
|
+
.restart-notice, .diagnostics { align-items: stretch; flex-direction: column; }
|
|
285
|
+
.restart-notice .button { width: 100%; }
|
|
286
|
+
.plugin-card { align-items: flex-start; flex-wrap: wrap; }
|
|
287
|
+
.plugin-copy { flex-basis: calc(100% - 48px); }
|
|
288
|
+
.plugin-control { width: 100%; min-width: 0; flex: 1 0 100%; flex-direction: row-reverse; justify-content: space-between; align-items: flex-start; padding-left: 48px; }
|
|
289
|
+
.plugin-control .switch { flex: 0 0 auto; }
|
|
290
|
+
.plugin-control .plugin-state { min-width: 0; align-items: flex-start; white-space: normal; line-height: 1.4; }
|
|
291
|
+
.plugin-control .plugin-state .status-dot { flex: 0 0 auto; margin-top: 5px; }
|
|
292
|
+
.diagnostics .button { align-self: flex-start; }
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
@media (prefers-reduced-motion: reduce) {
|
|
296
|
+
*, *::before, *::after { scroll-behavior: auto !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
|
|
297
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# CodexImageHost
|
|
2
|
+
|
|
3
|
+
CodexImageHost 给 Codex 增加一个轻量的 `Images` 入口。它自动汇集不同 Thread 中的 ImageGen PNG,但不复制图片。
|
|
4
|
+
|
|
5
|
+
## 当前功能
|
|
6
|
+
|
|
7
|
+
- 服务先初始化路径索引并开放 HTTP health,再在后台扫描 `~/.codex/generated_images` 中已有的图片;扫描完成后开始文件监听。
|
|
8
|
+
- 运行时监听新图片,自动加入 Images。
|
|
9
|
+
- 通过 All images、Chats 或有图片的 Project 筛选来源;数量直接显示在筛选菜单中。
|
|
10
|
+
- 工具栏内直接提供 2–6 列 Grid 滑条,使用无描边的 4px 轨道;首次打开按可用宽度给一个初始列数,之后只记住用户自己的选择。每张卡片显示来源 Project 或独立 Chat,以及生成时间。
|
|
11
|
+
- 可按 Thread 聚合成图板;进入图板后,左侧图片选择带只保留该 Thread 的图片,关闭详情即返回原图板位置。
|
|
12
|
+
- 标题栏固定在独立滚动区上方;图片按 36 张一批渐进加载,滚动条保持至少 48px 的可抓取高度。
|
|
13
|
+
- 点击图片后,以左侧图片选择带 + 右侧详情区的 20/80 布局查看原图。
|
|
14
|
+
- 按需读取该次 ImageGen 实际使用的 Prompt,并显示 Project、Thread、尺寸、时间与文件大小。
|
|
15
|
+
- 通过 `Save as` 打开 macOS 系统保存面板并保存原始 PNG。
|
|
16
|
+
- 从详情区通过 `Open Thread` 打开真实来源 Thread。
|
|
17
|
+
- 已归档 Thread 的图片仍可查看和 Save as,但 `Open Thread` 会禁用并在悬浮时说明原因。
|
|
18
|
+
- 通过上层同级项目 `CodexRuntimeHost` 启动一个统一宿主,在 Codex 左侧栏注册 Images。
|
|
19
|
+
|
|
20
|
+
不包含收藏按钮、图片副本、Asset Store、标签、Collection 或删除功能。Codex 的 PNG 是原图,SQLite 只是路径索引。
|
|
21
|
+
|
|
22
|
+
## 运行
|
|
23
|
+
|
|
24
|
+
需要 Node.js 22.5 或更高版本,不需要安装第三方 npm 依赖。
|
|
25
|
+
|
|
26
|
+
启动统一宿主;它会读取 `codex-feature.json`、启动 Images 服务并注册侧边入口:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm start
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
只启动独立 Web UI:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run service
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
然后打开 <http://127.0.0.1:47831>。
|
|
39
|
+
|
|
40
|
+
运行测试:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npm test
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
服务运行时,路径索引默认保存在 `~/.codex-image-host/library.sqlite`。统一宿主暂时沿用 `~/.codex-image-host/codex-profile`,避免迁移后丢失现有专用 Codex 实例状态。项目不会写入或删除 `~/.codex/generated_images` 中的文件。
|
|
47
|
+
|
|
48
|
+
## 精简结构
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
~/.codex/generated_images
|
|
52
|
+
│ scan + watch
|
|
53
|
+
▼
|
|
54
|
+
ImageLibrary ── SQLite path index
|
|
55
|
+
│ Codex state + session index
|
|
56
|
+
│ ├─ Project / Chat / Thread 名称与 Archive 状态
|
|
57
|
+
│ └─ revised_prompt(按需读取 Session JSONL)
|
|
58
|
+
▼
|
|
59
|
+
HTTP + Images UI
|
|
60
|
+
│
|
|
61
|
+
└── codex-feature.json
|
|
62
|
+
│ sibling discovery
|
|
63
|
+
▼
|
|
64
|
+
../CodexRuntimeHost
|
|
65
|
+
└── Codex sidebar + Theme Bridge + open Thread
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- `src/image-library.mjs`:扫描、监听和路径索引,是产品核心。
|
|
69
|
+
- `src/thread-metadata.mjs`:读取 Codex 当前 Project、projectless Chat、Thread 名称与 Archive 状态。
|
|
70
|
+
- `src/prompt-index.mjs`:按 Thread 与 ImageGen item 定位真实 `revised_prompt`。
|
|
71
|
+
- `src/http-server.mjs`:图片列表、来源 facets、Thread 图板、原图读取、系统 Save as 和静态页面。
|
|
72
|
+
- `codex-feature.json`:Images 对统一宿主的最小声明,不包含图片业务逻辑。
|
|
73
|
+
- `../CodexRuntimeHost`:可复用的 CDP 集成,统一负责多个个人功能的入口、Surface、主题与导航。
|
|
74
|
+
- `web/`:零框架 Images 页面。
|
|
75
|
+
|
|
76
|
+
## Codex 设计语言与主题
|
|
77
|
+
|
|
78
|
+
- Images 不维护独立品牌皮肤,而是通过 Theme Bridge 读取当前 Codex Renderer 已解析的 semantic tokens。
|
|
79
|
+
- 支持 Codex 的明亮 / 暗黑主题,并监听根节点 theme class 与 style 变化。
|
|
80
|
+
- 用户修改 accent、ink 或 surface 后,新的 resolved tokens 会同步到 iframe,不需要重新读取或猜测内部配置文件位置。
|
|
81
|
+
- 侧边栏 Images 入口克隆原生 Plugins 控件的布局与状态,再替换为 Codex 图标体系中的独立 Image 图标;iframe 内不导入 Codex 私有 React 模块或 hashed CSS bundle,以免 Codex 更新后直接失效。
|
|
82
|
+
|
|
83
|
+
取证、token Interface 和代码复用边界见 [`docs/CODEX_DESIGN_LANGUAGE.md`](docs/CODEX_DESIGN_LANGUAGE.md)。
|
|
84
|
+
|
|
85
|
+
## 当前边界
|
|
86
|
+
|
|
87
|
+
- Images 服务需要保持运行,才会持续监听新图片;侧边栏注册由 `CodexRuntimeHost` 统一维持。
|
|
88
|
+
- 每次服务启动都会先开放 health,再在后台补扫停机期间新增的图片并刷新来源名称;初始补扫完成后,运行期间的新图片由文件监听自动加入。手动 Refresh 会再次补扫来源和 Archive 状态,但不会重置筛选、图板模式、详情、滚动位置或列数。刷新 ring 至少显示 1 秒。
|
|
89
|
+
- 侧边栏使用 Codex 当前未公开的 CDP / DOM 能力,Codex UI 更新后只需调整统一宿主;独立 Web UI 和路径索引不受影响。
|
|
90
|
+
- 当前 Codex 的 CSP 会屏蔽普通本地 iframe。统一宿主会先等待原生侧栏完成渲染,再启用 CSP bypass、注册 document-start 脚本,并替换当前 document 中旧的 MineCodex runtime 后显式完成注入;当前实现不会调用会让用户看到页面刷新的 `Page.reload`(Issue #1)。
|
|
91
|
+
- 详情打开时会从本机 Session JSONL 按需读取该 ImageGen item 的真实 `revised_prompt` 并缓存到索引;历史记录缺少该事件时明确显示 Prompt 不可用,不从附近文本猜测。
|
|
92
|
+
- 当前没有发现 Codex 会因运行时间增长而自动清理 `generated_images` 的证据。如果未来观察到真实清理,再决定是否增加可选备份。
|
|
93
|
+
|
|
94
|
+
Phase 0 的原图、来源元数据与 Thread 导航证据见 [`spikes/phase0/README.md`](spikes/phase0/README.md)。
|
|
95
|
+
|
|
96
|
+
需要验证 Codex 内的 iframe 是否真正加载时,可在 `npm start` 运行期间执行:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
node spikes/phase0/cdp-probe.mjs frame-check --port 9231 \
|
|
100
|
+
--url http://127.0.0.1:47831/
|
|
101
|
+
|
|
102
|
+
node spikes/phase0/cdp-probe.mjs overlay-check --port 9231 \
|
|
103
|
+
--url http://127.0.0.1:47831/
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`overlay-check` 会打开 Codex 原生帮助菜单,验证菜单能覆盖 Images,同时确认 iframe 本身仍可交互。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"id": "images",
|
|
4
|
+
"version": "0.1.0",
|
|
5
|
+
"label": {
|
|
6
|
+
"en": "Images",
|
|
7
|
+
"zh-CN": "图片"
|
|
8
|
+
},
|
|
9
|
+
"description": {
|
|
10
|
+
"en": "Browse generated images, inspect prompts and sources, and return to the original task.",
|
|
11
|
+
"zh-CN": "集中浏览生成图片,查看提示词和来源任务,并保存原图或返回原任务。"
|
|
12
|
+
},
|
|
13
|
+
"surfaceUrl": "http://127.0.0.1:47831/",
|
|
14
|
+
"healthUrl": "http://127.0.0.1:47831/api/health",
|
|
15
|
+
"placement": {
|
|
16
|
+
"after": "sites",
|
|
17
|
+
"order": 10
|
|
18
|
+
},
|
|
19
|
+
"command": ["node", "src/main.mjs"],
|
|
20
|
+
"icon": {
|
|
21
|
+
"viewBox": "0 0 24 24",
|
|
22
|
+
"markup": "<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"></rect><circle cx=\"9\" cy=\"9\" r=\"2\"></circle><path d=\"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\"></path>"
|
|
23
|
+
}
|
|
24
|
+
}
|