Skip to content

Commit a30fc36

Browse files
committed
feat: add server takeover, message quoting, and build metadata
1 parent d290681 commit a30fc36

File tree

24 files changed

+782
-33
lines changed

24 files changed

+782
-33
lines changed

.opencode/plugin/memory-hook.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ const SKILL_LOCATIONS = [
1010
"opencode",
1111
"skill",
1212
"project-memory",
13-
"SKILL.md"
13+
"SKILL.md",
1414
),
1515
() =>
1616
path.join(
1717
process.env.HOME || process.env.USERPROFILE || "",
1818
".claude",
1919
"skills",
2020
"project-memory",
21-
"SKILL.md"
21+
"SKILL.md",
2222
),
2323
];
2424

@@ -83,16 +83,15 @@ export const MemoryHook = async (ctx) => {
8383
if (!Array.isArray(todos)) return;
8484
if (!todos.some((t) => t.status === "completed")) return;
8585

86-
output.output += `\n\n<system-reminder>Task completed. If this work produced knowledge worth remembering (re-discovering would cost meaningful time), capture it to .memory/ following the project-memory skill. Only save decisions, patterns, bug root causes, or preferences — skip routine changes.</system-reminder>`;
86+
output.output += `\n\n<system-reminder>Task completed. If this work produced knowledge worth remembering (re-discovering would cost meaningful time), capture it to .memory/ following the project-memory skill. Only save decisions, bug root causes, or preferences — skip routine changes.</system-reminder>`;
8787
},
8888

89-
"event": async ({ event }) => {
89+
event: async ({ event }) => {
9090
if (
9191
event.type === "session.deleted" ||
9292
event.type === "session.compacted"
9393
) {
94-
const sid =
95-
event.properties?.info?.id || event.properties?.sessionID;
94+
const sid = event.properties?.info?.id || event.properties?.sessionID;
9695
if (sid) {
9796
loadedSessions.delete(sid);
9897
subagentSessions.delete(sid);
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
---
2+
shaping: true
3+
---
4+
5+
# Upstream Cherry-Pick Batch (v0.7.50 → v0.7.57) — Shaping
6+
7+
## Frame
8+
9+
**Source**: CodexMonitor releases v0.7.50 → v0.7.57
10+
11+
**Problem**: Our fork is missing useful upstream improvements: build transparency, thread stability, and composer UX.
12+
13+
**Outcome**: Users see build metadata, threads don't disappear during refresh, and users can quote messages into the composer.
14+
15+
---
16+
17+
## Requirements (R)
18+
19+
| ID | Requirement | Status |
20+
|----|-------------|--------|
21+
| **R0** | Users can identify exact build version, commit, and date for debugging/support | Core goal |
22+
| **R1** | Active/processing threads aren't lost during partial list refresh | Core goal |
23+
| **R2** | Parent thread chains preserved when child thread is visible | Core goal |
24+
| **R3** | Users can quote assistant messages into the composer | Core goal |
25+
| **R4** | Changes integrate cleanly without breaking existing functionality | Must-have |
26+
| **R5** | Minimal deviation from upstream to ease future merges | Nice-to-have |
27+
28+
---
29+
30+
## Shape A: Port Upstream with Adaptation
31+
32+
Since upstream has working implementations, the shape is to adapt their code to our codebase.
33+
34+
| Part | Mechanism | Flag |
35+
|------|-----------|:----:|
36+
| **A1** | **Build Metadata** | |
37+
| A1.1 | Add git info extraction to `vite.config.ts` (execSync for commit/branch/date) | |
38+
| A1.2 | Declare `__APP_COMMIT_HASH__`, `__APP_BUILD_DATE__`, `__APP_GIT_BRANCH__` in `vite-env.d.ts` | |
39+
| A1.3 | Add `SettingsAboutSection.tsx` displaying metadata | |
40+
| A1.4 | Add "About" to settings navigation and section containers | |
41+
| A1.5 | Update existing `AboutView.tsx` to include metadata or redirect to settings | |
42+
| **A2** | **Thread Anchor Preservation** | |
43+
| A2.1 | Extend `setThreads` case in `threadLifecycleSlice.ts` with reconciliation logic | |
44+
| A2.2 | Preserve active thread if missing from incoming list | |
45+
| A2.3 | Preserve threads with `isProcessing` status | |
46+
| A2.4 | Walk `threadParentById` to preserve parent chain | |
47+
| A2.5 | Freshen `updatedAt` using `lastAgentMessageByThread` and `processingStartedAt` | |
48+
| **A3** | **Quote Action** | |
49+
| A3.1 | Add `onQuoteMessage` prop to `Messages` component | |
50+
| A3.2 | Add `toMarkdownQuote()` helper (prefix lines with `> `) | |
51+
| A3.3 | Add `handleQuoteMessage` callback in Messages | |
52+
| A3.4 | Wire quote button in `MessageRows.tsx` for assistant messages | |
53+
| A3.5 | Connect via `buildPrimaryNodes` using existing `onInsertComposerText` | |
54+
| A3.6 | Add quote button styles to `messages.css` | |
55+
56+
---
57+
58+
## Fit Check: R × A
59+
60+
| Req | Requirement | Status | A |
61+
|-----|-------------|--------|---|
62+
| R0 | Users can identify exact build version, commit, and date for debugging/support | Core goal ||
63+
| R1 | Active/processing threads aren't lost during partial list refresh | Core goal ||
64+
| R2 | Parent thread chains preserved when child thread is visible | Core goal ||
65+
| R3 | Users can quote assistant messages into the composer | Core goal ||
66+
| R4 | Changes integrate cleanly without breaking existing functionality | Must-have ||
67+
| R5 | Minimal deviation from upstream to ease future merges | Nice-to-have ||
68+
69+
**Notes:**
70+
- R4: All mechanisms use existing patterns (Vite define, reducer extension, existing `onInsertComposerText`)
71+
- R5: Code will closely match upstream with minor naming adjustments
72+
73+
---
74+
75+
## Slices
76+
77+
Each slice is independently deployable and demo-able.
78+
79+
### V1: Build Metadata in About
80+
81+
**Demo**: Open Settings → About, see version/commit/branch/date
82+
83+
| Affordance | Type | Place |
84+
|------------|------|-------|
85+
| Version display | UI | SettingsAboutSection |
86+
| Commit hash display | UI | SettingsAboutSection |
87+
| Branch display | UI | SettingsAboutSection |
88+
| Build date display | UI | SettingsAboutSection |
89+
| Git info extraction | Non-UI | vite.config.ts |
90+
| Type declarations | Non-UI | vite-env.d.ts |
91+
92+
**Files**:
93+
- `vite.config.ts` — add git exec + define
94+
- `src/vite-env.d.ts` — declare globals
95+
- `src/features/settings/components/sections/SettingsAboutSection.tsx` — new file
96+
- `src/features/settings/components/sections/SettingsSectionContainers.tsx` — add case
97+
- `src/features/settings/components/SettingsNav.tsx` — add nav item
98+
- `src/features/settings/components/settingsTypes.ts` — add "about" to CodexSection
99+
- `src/features/settings/components/settingsViewConstants.ts` — add label
100+
101+
### V2: Thread Anchor Preservation
102+
103+
**Demo**: Start a thread, trigger list refresh while processing, thread stays visible
104+
105+
| Affordance | Type | Place |
106+
|------------|------|-------|
107+
| Thread reconciliation | Non-UI | threadLifecycleSlice |
108+
| Active thread preservation | Non-UI | threadLifecycleSlice |
109+
| Processing thread preservation | Non-UI | threadLifecycleSlice |
110+
| Parent chain walking | Non-UI | threadLifecycleSlice |
111+
112+
**Files**:
113+
- `src/features/threads/hooks/threadReducer/threadLifecycleSlice.ts` — extend setThreads case
114+
115+
### V3: Quote Action for Composer
116+
117+
**Demo**: Click quote button on assistant message → text appears in composer as blockquote
118+
119+
| Affordance | Type | Place |
120+
|------------|------|-------|
121+
| Quote button | UI | MessageRows |
122+
| Markdown quote formatter | Non-UI | Messages |
123+
| Quote handler | Non-UI | Messages |
124+
| Composer text insertion | Non-UI | buildPrimaryNodes (existing) |
125+
126+
**Files**:
127+
- `src/features/messages/components/Messages.tsx` — add prop, helper, handler
128+
- `src/features/messages/components/MessageRows.tsx` — add quote button
129+
- `src/features/layout/hooks/layoutNodes/buildPrimaryNodes.tsx` — wire onQuoteMessage
130+
- `src/styles/messages.css` — quote button styles
131+
132+
---
133+
134+
## Open Questions
135+
136+
| # | Question | Impact |
137+
|---|----------|--------|
138+
| Q1 | Should we keep the existing standalone AboutView or redirect it to Settings? | Low — can decide during V1 |
139+
| Q2 | Should quote button be always visible or appear on hover? | Low — follow upstream pattern |
140+
141+
---
142+
143+
## Validation
144+
145+
Each slice validated with:
146+
- `npm run typecheck`
147+
- `npm run test` (for slices touching tested code)
148+
- Manual testing of the demo scenario
149+
150+
---
151+
152+
## Upstream References
153+
154+
| Item | Upstream Commit | Upstream PR |
155+
|------|-----------------|-------------|
156+
| Build metadata | 40f6fcb | #490 |
157+
| Thread anchor fix | c0f144b | #494 |
158+
| Quote action | 5e656d5 | #504 |

0 commit comments

Comments
 (0)