@cueloop/client 0.1.0-alpha.96 → 0.1.0-alpha.98
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/package.json +5 -5
- package/src/annotations/components/AnnotationCards.test.tsx +42 -0
- package/src/annotations/components/AnnotationCards.tsx +29 -6
- package/src/annotations/use-annotation-surface.tsx +245 -30
- package/src/app/App.thread-agent.test.ts +12 -0
- package/src/app/App.tsx +217 -97
- package/src/app/app-screens.tsx +2 -0
- package/src/app/components/AppShell.zoom.test.tsx +4 -3
- package/src/app/intent-dispatch.test.ts +1 -0
- package/src/diff/components/AnnotatableFileView.tsx +6 -0
- package/src/diff/components/DiffContentView.tsx +9 -0
- package/src/markdown/components/ThreadView.tsx +60 -16
- package/src/settings/config.test.ts +15 -0
- package/src/settings/config.ts +14 -4
- package/src/stories/__snapshots__/stories.test.tsx.snap +74 -0
- package/src/thread/agent-continuation.test.ts +32 -0
- package/src/thread/agent-continuation.ts +13 -0
- package/src/thread/agent-transcript.test.ts +161 -0
- package/src/thread/agent-transcript.ts +332 -0
- package/src/thread/components/AgentConfigControls.stories.tsx +39 -0
- package/src/thread/components/AgentConfigControls.test.tsx +110 -0
- package/src/thread/components/AgentConfigControls.tsx +114 -0
- package/src/thread/components/AgentThreadPane.stories.tsx +105 -0
- package/src/thread/components/AgentThreadPane.test.tsx +780 -0
- package/src/thread/components/AgentThreadPane.tsx +356 -0
- package/src/thread/components/ThreadFooter.tsx +3 -0
- package/src/thread/components/ThreadTree.test.tsx +41 -0
- package/src/thread/components/ThreadTree.tsx +25 -5
- package/src/thread/thread-controller.ts +34 -0
- package/src/thread/use-thread-agent.test.tsx +65 -0
- package/src/thread/use-thread-agent.ts +101 -0
- package/src/workbench/components/GridTabContent.tsx +6 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { DaemonClient } from "@cueloop/daemon/client";
|
|
3
|
+
import type { ThreadAgentState } from "@cueloop/schema";
|
|
4
|
+
|
|
5
|
+
/** Agent transport is injectable for frame tests; production uses the daemon socket. */
|
|
6
|
+
export type ThreadAgentClient = Pick<
|
|
7
|
+
DaemonClient,
|
|
8
|
+
"agentGet" | "agentPrompt" | "agentCancel" | "agentComment" | "agentPermission"
|
|
9
|
+
> &
|
|
10
|
+
Partial<Pick<DaemonClient, "agentConfigure">>;
|
|
11
|
+
|
|
12
|
+
/** Subscribe to durable agent state; unmount closes only this client connection. */
|
|
13
|
+
export function useThreadAgent(id: string, home?: string, injected?: ThreadAgentClient) {
|
|
14
|
+
const [client, setClient] = useState<ThreadAgentClient | null>(injected ?? null);
|
|
15
|
+
const [state, setState] = useState<ThreadAgentState>({
|
|
16
|
+
threadId: id,
|
|
17
|
+
phase: { kind: "idle" },
|
|
18
|
+
messages: [],
|
|
19
|
+
tools: [],
|
|
20
|
+
comments: [],
|
|
21
|
+
});
|
|
22
|
+
const revision = useRef(0);
|
|
23
|
+
const [error, setError] = useState("");
|
|
24
|
+
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
let cancelled = false;
|
|
27
|
+
let connection: DaemonClient | undefined;
|
|
28
|
+
let unsubscribe: (() => void) | undefined;
|
|
29
|
+
revision.current++;
|
|
30
|
+
const refresh = async (api: ThreadAgentClient) => {
|
|
31
|
+
const requested = ++revision.current;
|
|
32
|
+
const result = await api.agentGet(id);
|
|
33
|
+
|
|
34
|
+
if (!cancelled && requested === revision.current) setState(result);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const configure = async (api: ThreadAgentClient): Promise<void> => {
|
|
38
|
+
if (!api.agentConfigure) return;
|
|
39
|
+
const requested = ++revision.current;
|
|
40
|
+
const configured = await api.agentConfigure({ id });
|
|
41
|
+
|
|
42
|
+
if (!cancelled && requested === revision.current) setState(configured);
|
|
43
|
+
await refresh(api);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
void (async () => {
|
|
47
|
+
try {
|
|
48
|
+
if (injected) {
|
|
49
|
+
await refresh(injected);
|
|
50
|
+
await configure(injected);
|
|
51
|
+
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
connection = await DaemonClient.connect({ home, autostart: true });
|
|
55
|
+
if (cancelled) {
|
|
56
|
+
connection.close();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
setClient(connection);
|
|
60
|
+
unsubscribe = connection.onEvent((event) => {
|
|
61
|
+
if (event.event === "agent.updated" && event.sessionId === id)
|
|
62
|
+
void refresh(connection!).catch((error) => {
|
|
63
|
+
if (!cancelled) setError(String(error));
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
await connection.subscribe();
|
|
67
|
+
await refresh(connection);
|
|
68
|
+
await configure(connection);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (!cancelled) setError(error instanceof Error ? error.message : String(error));
|
|
71
|
+
}
|
|
72
|
+
})();
|
|
73
|
+
|
|
74
|
+
return () => {
|
|
75
|
+
cancelled = true;
|
|
76
|
+
unsubscribe?.();
|
|
77
|
+
connection?.close();
|
|
78
|
+
};
|
|
79
|
+
}, [id, home, injected]);
|
|
80
|
+
|
|
81
|
+
const act = async (
|
|
82
|
+
request: (client: ThreadAgentClient) => Promise<ThreadAgentState>,
|
|
83
|
+
): Promise<boolean> => {
|
|
84
|
+
if (!client) return false;
|
|
85
|
+
try {
|
|
86
|
+
const requested = ++revision.current;
|
|
87
|
+
const result = await request(client);
|
|
88
|
+
|
|
89
|
+
if (requested === revision.current) setState(result);
|
|
90
|
+
setError("");
|
|
91
|
+
|
|
92
|
+
return true;
|
|
93
|
+
} catch (error) {
|
|
94
|
+
setError(error instanceof Error ? error.message : String(error));
|
|
95
|
+
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return { state, client, error, setError, act };
|
|
101
|
+
}
|
|
@@ -34,6 +34,9 @@ export type DiffSurfaceProps = Pick<
|
|
|
34
34
|
| "onAnnotate"
|
|
35
35
|
| "onReply"
|
|
36
36
|
| "onUpdateAnnotation"
|
|
37
|
+
| "isAnnotationReadOnly"
|
|
38
|
+
| "annotationAction"
|
|
39
|
+
| "onInvoke"
|
|
37
40
|
| "resolveAuthorLabel"
|
|
38
41
|
| "onNavCommand"
|
|
39
42
|
| "onExit"
|
|
@@ -128,6 +131,9 @@ export function GridTabContent(props: {
|
|
|
128
131
|
onAddComment={(anchor, body) => props.onAddFileComment(filePath, anchor, body)}
|
|
129
132
|
onReply={props.surface.onReply}
|
|
130
133
|
onUpdateAnnotation={props.surface.onUpdateAnnotation}
|
|
134
|
+
isAnnotationReadOnly={props.surface.isAnnotationReadOnly}
|
|
135
|
+
annotationAction={props.surface.annotationAction}
|
|
136
|
+
onInvoke={props.surface.onInvoke}
|
|
131
137
|
resolveAuthorLabel={props.surface.resolveAuthorLabel}
|
|
132
138
|
onExit={props.surface.onExit}
|
|
133
139
|
theme={props.theme}
|