the lists re-read when the agent changes something
an agent deleted two proxy hosts and both stayed on screen. the person had the answer in the transcript and a stale list six inches above it — which is the one thing a chat beside a list has to get right, and the reason it is beside the list at all. so the chat panel bumps the refresh channel when a turn ran tools, and every section re-reads. gated on hadToolCalls: a turn that only talked changed nothing, and re-reading after every sentence would put six requests behind every reply. the channel is renamed with it. it was proxy-manager:connection-changed, named after its only publisher; it has two now and the second is the bigger one, so it says what it MEANS — something at NPM changed, read it again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
This commit is contained in:
+14
-9
@@ -2,7 +2,12 @@ import { useCallback, useRef } from 'react';
|
||||
import { defineChannel } from 'hooks/usePanelChannel';
|
||||
|
||||
/**
|
||||
* "The connection changed — anyone reading NPM should read it again."
|
||||
* "Something at NPM changed — anyone reading it should read it again."
|
||||
*
|
||||
* Two publishers, and naming it after the second one would have been wrong the other way round. The
|
||||
* connection being saved or removed is one. **A chat turn that ran tools is the other**, and it is the
|
||||
* bigger one: an agent that deletes a proxy host leaves every list on the screen describing a world that
|
||||
* no longer exists, and nothing else would ever tell them.
|
||||
*
|
||||
* ── Why a channel and not the URL ──
|
||||
*
|
||||
@@ -12,11 +17,11 @@ import { defineChannel } from 'hooks/usePanelChannel';
|
||||
*
|
||||
* ── Why it is needed at all ──
|
||||
*
|
||||
* The panels are siblings in a workspace layout. `ConnectionPanel` cannot call into `CertificatesPanel`
|
||||
* and should not try — they are mounted independently and neither owns the other. Before this, saving a
|
||||
* connection left both panels showing whatever they had failed to load a minute earlier, and the only fix
|
||||
* a person had was a manual refresh. Reported on 2026-08-25 the first time a connection was saved through
|
||||
* the form.
|
||||
* The panels are siblings in a workspace layout. None of them can call into another and none should try —
|
||||
* they are mounted independently and no one owns the rest. Before this, saving a connection left every
|
||||
* panel showing whatever it had failed to load a minute earlier, and the only fix a person had was a
|
||||
* manual refresh. Reported on 2026-08-25 the first time a connection was saved through the form; the chat
|
||||
* publisher was added the same day, after an agent deleted two hosts that stayed on screen.
|
||||
*
|
||||
* ── The nonce is a plain counter, and that is not an accident ──
|
||||
*
|
||||
@@ -26,12 +31,12 @@ import { defineChannel } from 'hooks/usePanelChannel';
|
||||
* re-reads. `Date.now()` has the same flaw in miniature, two bumps in one millisecond being one number.
|
||||
* A module counter never reads React state, so it cannot be wrong however often it is called.
|
||||
*/
|
||||
const useConnectionChangedChannel = defineChannel<number>('proxy-manager:connection-changed', 0);
|
||||
const useNpmChangedChannel = defineChannel<number>('proxy-manager:npm-changed', 0);
|
||||
|
||||
let nonce = 0;
|
||||
|
||||
export const useConnectionChanged = () => {
|
||||
const [signal, setSignal] = useConnectionChangedChannel();
|
||||
export const useNpmChanged = () => {
|
||||
const [signal, setSignal] = useNpmChangedChannel();
|
||||
|
||||
// The setter is a fresh closure every render and this `bump` goes into dependency lists, so it is read
|
||||
// through a ref — stable identity without freezing the first render's setter.
|
||||
|
||||
Reference in New Issue
Block a user