@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.
Files changed (32) hide show
  1. package/package.json +5 -5
  2. package/src/annotations/components/AnnotationCards.test.tsx +42 -0
  3. package/src/annotations/components/AnnotationCards.tsx +29 -6
  4. package/src/annotations/use-annotation-surface.tsx +245 -30
  5. package/src/app/App.thread-agent.test.ts +12 -0
  6. package/src/app/App.tsx +217 -97
  7. package/src/app/app-screens.tsx +2 -0
  8. package/src/app/components/AppShell.zoom.test.tsx +4 -3
  9. package/src/app/intent-dispatch.test.ts +1 -0
  10. package/src/diff/components/AnnotatableFileView.tsx +6 -0
  11. package/src/diff/components/DiffContentView.tsx +9 -0
  12. package/src/markdown/components/ThreadView.tsx +60 -16
  13. package/src/settings/config.test.ts +15 -0
  14. package/src/settings/config.ts +14 -4
  15. package/src/stories/__snapshots__/stories.test.tsx.snap +74 -0
  16. package/src/thread/agent-continuation.test.ts +32 -0
  17. package/src/thread/agent-continuation.ts +13 -0
  18. package/src/thread/agent-transcript.test.ts +161 -0
  19. package/src/thread/agent-transcript.ts +332 -0
  20. package/src/thread/components/AgentConfigControls.stories.tsx +39 -0
  21. package/src/thread/components/AgentConfigControls.test.tsx +110 -0
  22. package/src/thread/components/AgentConfigControls.tsx +114 -0
  23. package/src/thread/components/AgentThreadPane.stories.tsx +105 -0
  24. package/src/thread/components/AgentThreadPane.test.tsx +780 -0
  25. package/src/thread/components/AgentThreadPane.tsx +356 -0
  26. package/src/thread/components/ThreadFooter.tsx +3 -0
  27. package/src/thread/components/ThreadTree.test.tsx +41 -0
  28. package/src/thread/components/ThreadTree.tsx +25 -5
  29. package/src/thread/thread-controller.ts +34 -0
  30. package/src/thread/use-thread-agent.test.tsx +65 -0
  31. package/src/thread/use-thread-agent.ts +101 -0
  32. 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}