@candor-ui/react 1.5.0 → 1.7.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/dist/adapters/ag-ui.d.ts +24 -24
- package/dist/adapters/ai-sdk.d.ts +6 -6
- package/dist/adapters/claude-agent-sdk.d.ts +34 -34
- package/dist/adapters/claude-agent-server.d.ts +34 -34
- package/dist/adapters/use-ag-ui.d.ts +6 -6
- package/dist/adapters/use-ag-ui.js +14 -2
- package/dist/adapters/use-candor-chat.d.ts +1 -1
- package/dist/adapters/use-candor-chat.js +1 -1
- package/dist/adapters/use-claude-agent.d.ts +10 -10
- package/dist/adapters/use-claude-agent.js +1 -1
- package/dist/blocks/copy-field.d.ts +1 -1
- package/dist/blocks/copy-field.js +1 -1
- package/dist/blocks/degraded-panel.d.ts +5 -5
- package/dist/blocks/locale.d.ts +6 -6
- package/dist/blocks/locked.d.ts +8 -8
- package/dist/blocks/relative-time.d.ts +6 -6
- package/dist/blocks/status-dot.d.ts +3 -3
- package/dist/blocks/step-list.d.ts +3 -3
- package/dist/blocks/streaming-text.d.ts +3 -3
- package/dist/chat/agent-avatar.d.ts +4 -4
- package/dist/chat/ai-disclosure.d.ts +5 -5
- package/dist/chat/ai-disclosure.js +1 -1
- package/dist/chat/attachment-preview.d.ts +6 -6
- package/dist/chat/attachment-preview.js +1 -1
- package/dist/chat/card-registry.js +1 -1
- package/dist/chat/citation.d.ts +3 -3
- package/dist/chat/citation.js +3 -3
- package/dist/chat/composer.d.ts +31 -20
- package/dist/chat/composer.js +10 -6
- package/dist/chat/context-meter.d.ts +1 -1
- package/dist/chat/context-meter.js +1 -1
- package/dist/chat/entity-chip.d.ts +3 -3
- package/dist/chat/entity-chip.js +1 -1
- package/dist/chat/folded-turns.d.ts +11 -6
- package/dist/chat/folded-turns.js +2 -2
- package/dist/chat/message-actions.d.ts +6 -6
- package/dist/chat/message-actions.js +1 -1
- package/dist/chat/message-content.d.ts +13 -7
- package/dist/chat/message-content.js +10 -5
- package/dist/chat/message.d.ts +64 -37
- package/dist/chat/message.js +17 -11
- package/dist/chat/payload.d.ts +4 -4
- package/dist/chat/payload.js +2 -2
- package/dist/chat/permission-prompt.d.ts +23 -23
- package/dist/chat/prompt-suggestions.d.ts +4 -4
- package/dist/chat/prompt-suggestions.js +1 -1
- package/dist/chat/reasoning.d.ts +3 -3
- package/dist/chat/reasoning.js +1 -1
- package/dist/chat/thread-divider.d.ts +3 -3
- package/dist/chat/thread-event.d.ts +10 -5
- package/dist/chat/thread-event.js +3 -2
- package/dist/chat/thread.d.ts +23 -7
- package/dist/chat/thread.js +28 -5
- package/dist/chat/tool-call.d.ts +2 -2
- package/dist/chat/tool-call.js +2 -2
- package/dist/lib/chat.d.ts +42 -42
- package/dist/lib/know.d.ts +14 -12
- package/dist/lib/render-prop.d.ts +4 -4
- package/dist/lib/safe-markdown.d.ts +1 -1
- package/dist/lib/status.d.ts +21 -0
- package/dist/lib/status.js +17 -0
- package/dist/lib/use-shortcut.d.ts +1 -1
- package/dist/lib/use-virtual-list.d.ts +6 -6
- package/dist/styles.css +4 -1
- package/dist/ui/button.d.ts +1 -1
- package/dist/ui/button.js +1 -1
- package/package.json +1 -1
package/dist/adapters/ag-ui.d.ts
CHANGED
|
@@ -8,14 +8,14 @@ export type CandorAgUiEvent =
|
|
|
8
8
|
type: "candor_user";
|
|
9
9
|
id: string;
|
|
10
10
|
text: string;
|
|
11
|
-
references?: EntityRef[];
|
|
11
|
+
references?: EntityRef[] | undefined;
|
|
12
12
|
}
|
|
13
13
|
/** A person answered an interrupt; the next run resumes with it. */
|
|
14
14
|
| {
|
|
15
15
|
type: "candor_answer";
|
|
16
16
|
interruptId: string;
|
|
17
17
|
approved: boolean;
|
|
18
|
-
reason?: string;
|
|
18
|
+
reason?: string | undefined;
|
|
19
19
|
}
|
|
20
20
|
/** The run failed outside the protocol's own events (the request, the stream). */
|
|
21
21
|
| {
|
|
@@ -30,38 +30,38 @@ export type AgUiApproval = {
|
|
|
30
30
|
/** The agent's machine-readable reason, e.g. "tool_approval". */
|
|
31
31
|
reason: string;
|
|
32
32
|
/** The agent's own sentence for the request, when it sent one. */
|
|
33
|
-
message?: string;
|
|
33
|
+
message?: string | undefined;
|
|
34
34
|
/** A sentence to show: the agent's message, or a plain one naming the tool. */
|
|
35
35
|
title: string;
|
|
36
36
|
/** Set when the interrupt asks to run a tool call. */
|
|
37
|
-
toolCallId?: string;
|
|
37
|
+
toolCallId?: string | undefined;
|
|
38
38
|
/** The tool's name, when the tool call is in the thread. */
|
|
39
|
-
tool?: string;
|
|
39
|
+
tool?: string | undefined;
|
|
40
40
|
/** The tool call's arguments, when they arrived and parse. */
|
|
41
41
|
input?: unknown;
|
|
42
42
|
/** When the agent stops waiting (ISO 8601). */
|
|
43
|
-
expiresAt?: string;
|
|
43
|
+
expiresAt?: string | undefined;
|
|
44
44
|
/** The shape the agent expects an answer in, when it says. */
|
|
45
|
-
responseSchema?: Record<string, unknown
|
|
45
|
+
responseSchema?: Record<string, unknown> | undefined;
|
|
46
46
|
};
|
|
47
47
|
/** Tokens the runs reported, summed. A count no run reported stays unknown. AG-UI reports no cost. */
|
|
48
48
|
export type AgUiUsage = {
|
|
49
|
-
inputTokens?: number;
|
|
50
|
-
outputTokens?: number;
|
|
49
|
+
inputTokens?: number | undefined;
|
|
50
|
+
outputTokens?: number | undefined;
|
|
51
51
|
};
|
|
52
52
|
export type FromAgUiOptions = {
|
|
53
53
|
/** Who the agent is. Candor always names the agent. */
|
|
54
54
|
agent: AgentIdentity;
|
|
55
55
|
/** A run is open now: the last reply is still streaming, and no interrupt can be answered yet. */
|
|
56
|
-
running?: boolean;
|
|
56
|
+
running?: boolean | undefined;
|
|
57
57
|
/** A plain-words title for a tool call: "Read notes.md". `input` is undefined until the arguments arrive. */
|
|
58
|
-
toolTitle?: (tool: string, input: unknown) => string | undefined;
|
|
58
|
+
toolTitle?: ((tool: string, input: unknown) => string | undefined) | undefined;
|
|
59
59
|
/** The time to judge interrupt expiry by. Defaults to now. */
|
|
60
|
-
now?: Date;
|
|
60
|
+
now?: Date | undefined;
|
|
61
61
|
/** The state the first run started with; the first STATE_DELTA patches it. Defaults to `{}`, as AG-UI clients send. */
|
|
62
62
|
initialState?: unknown;
|
|
63
63
|
/** Other agents the app knows, by id. An activity naming an agent id not here (or `agent`) isn't mapped to an agent entry. */
|
|
64
|
-
agents?: AgentIdentity[];
|
|
64
|
+
agents?: AgentIdentity[] | undefined;
|
|
65
65
|
};
|
|
66
66
|
/**
|
|
67
67
|
* A plan step read from an activity whose content has `steps: [{ title, status }]`.
|
|
@@ -72,9 +72,9 @@ export type AgUiPlanStep = {
|
|
|
72
72
|
title: string;
|
|
73
73
|
status: RunStatus;
|
|
74
74
|
/** The step's own summary, when it sent one as text. */
|
|
75
|
-
summary?: string;
|
|
75
|
+
summary?: string | undefined;
|
|
76
76
|
/** Why it failed: the agent's words, or a plain sentence saying it didn't say. Set only when status is "failed". */
|
|
77
|
-
failure?: string;
|
|
77
|
+
failure?: string | undefined;
|
|
78
78
|
};
|
|
79
79
|
/**
|
|
80
80
|
* What an agent is doing, read from an activity whose content has `status`
|
|
@@ -83,9 +83,9 @@ export type AgUiPlanStep = {
|
|
|
83
83
|
export type AgUiAgentActivityEntry = {
|
|
84
84
|
/** The app's own identity for the agent, never one taken from the content. */
|
|
85
85
|
agent: AgentIdentity;
|
|
86
|
-
doing?: string;
|
|
86
|
+
doing?: string | undefined;
|
|
87
87
|
status: RunStatus;
|
|
88
|
-
since?: string;
|
|
88
|
+
since?: string | undefined;
|
|
89
89
|
};
|
|
90
90
|
/** An activity the agent reported: structured progress that isn't part of a reply. */
|
|
91
91
|
export type AgUiActivity = {
|
|
@@ -96,25 +96,25 @@ export type AgUiActivity = {
|
|
|
96
96
|
/** Its content as the agent sent it, after any patches. Data, never markup. */
|
|
97
97
|
content: Record<string, unknown>;
|
|
98
98
|
/** Set when an update to it couldn't be applied: the content is the last good one, and may be behind. */
|
|
99
|
-
outOfDate?: string;
|
|
99
|
+
outOfDate?: string | undefined;
|
|
100
100
|
/** Its `steps` as plan steps, when every step has a title and a status Candor knows. */
|
|
101
|
-
plan?: AgUiPlanStep[];
|
|
101
|
+
plan?: AgUiPlanStep[] | undefined;
|
|
102
102
|
/** Its `status`/`doing` as an agent entry, when the status is one Candor knows and the agent is one the app named. */
|
|
103
|
-
agentActivity?: AgUiAgentActivityEntry;
|
|
103
|
+
agentActivity?: AgUiAgentActivityEntry | undefined;
|
|
104
104
|
};
|
|
105
105
|
export type AgUiState = {
|
|
106
106
|
messages: Message[];
|
|
107
107
|
/** Interrupts waiting on a person, oldest first. Empty while a run is open; expired ones are left out. */
|
|
108
108
|
approvals: AgUiApproval[];
|
|
109
109
|
/** The thread the runs belong to. Send it back to continue the conversation. */
|
|
110
|
-
threadId?: string;
|
|
111
|
-
usage?: AgUiUsage;
|
|
110
|
+
threadId?: string | undefined;
|
|
111
|
+
usage?: AgUiUsage | undefined;
|
|
112
112
|
/** Something the person should know that isn't part of a reply, such as an expired request. */
|
|
113
|
-
notice?: string;
|
|
113
|
+
notice?: string | undefined;
|
|
114
114
|
/** The agent's shared state from STATE_SNAPSHOT and STATE_DELTA; undefined until the agent sends one. */
|
|
115
115
|
state?: unknown;
|
|
116
116
|
/** Set when a state update couldn't be applied: `state` is the last good value and may be behind. Cleared by the next snapshot. */
|
|
117
|
-
stateOutOfDate?: string;
|
|
117
|
+
stateOutOfDate?: string | undefined;
|
|
118
118
|
/** The activities the agent reported, in the order they first arrived. */
|
|
119
119
|
activities: AgUiActivity[];
|
|
120
120
|
};
|
|
@@ -6,22 +6,22 @@ export type FromAiSdkOptions = {
|
|
|
6
6
|
/** Who the assistant is. Candor always names the agent. */
|
|
7
7
|
agent: AgentIdentity;
|
|
8
8
|
/** The chat's status from useChat, so the last reply can show as streaming or failed. */
|
|
9
|
-
chatStatus?: "submitted" | "streaming" | "ready" | "error";
|
|
9
|
+
chatStatus?: "submitted" | "streaming" | "ready" | "error" | undefined;
|
|
10
10
|
/** When a message was sent, if your metadata says. Without it, no time is shown. */
|
|
11
|
-
createdAt?: (message: UIMessage) => string | undefined;
|
|
11
|
+
createdAt?: ((message: UIMessage) => string | undefined) | undefined;
|
|
12
12
|
/** A plain-words title for a tool call: "Searched the docs for “region”". */
|
|
13
|
-
toolTitle?: (tool: string, input: unknown) => string | undefined;
|
|
13
|
+
toolTitle?: ((tool: string, input: unknown) => string | undefined) | undefined;
|
|
14
14
|
/** The text version of a data part, used when its card can't be shown. */
|
|
15
|
-
summarize?: (name: string, data: unknown) => string;
|
|
15
|
+
summarize?: ((name: string, data: unknown) => string) | undefined;
|
|
16
16
|
/**
|
|
17
17
|
* The sources a tool's result supports, added to the reply's sources after the SDK's own source parts:
|
|
18
18
|
* `(tool, input, output) => [{ kind: "document", label: "Refund policy v2" }]`. Read only from the tool's output.
|
|
19
19
|
*/
|
|
20
|
-
sourcesFrom?: (tool: string, input: unknown, output: unknown) => ToolSource[] | undefined;
|
|
20
|
+
sourcesFrom?: ((tool: string, input: unknown, output: unknown) => ToolSource[] | undefined) | undefined;
|
|
21
21
|
};
|
|
22
22
|
/** Convert a whole useChat message list. */
|
|
23
23
|
export declare function fromAiSdkMessages(messages: UIMessage[], options: FromAiSdkOptions): Message[];
|
|
24
24
|
/** Convert one message. `last` marks the reply the chat status applies to. */
|
|
25
25
|
export declare function fromAiSdkMessage(message: UIMessage, options: FromAiSdkOptions & {
|
|
26
|
-
last?: boolean;
|
|
26
|
+
last?: boolean | undefined;
|
|
27
27
|
}): Message;
|
|
@@ -13,11 +13,11 @@ export type ClaudeQuestion = {
|
|
|
13
13
|
kind: "choice";
|
|
14
14
|
prompt: string;
|
|
15
15
|
/** The SDK's short header ("Library", "Approach"). */
|
|
16
|
-
tag?: string;
|
|
16
|
+
tag?: string | undefined;
|
|
17
17
|
options: {
|
|
18
18
|
id: string;
|
|
19
19
|
label: string;
|
|
20
|
-
detail?: string;
|
|
20
|
+
detail?: string | undefined;
|
|
21
21
|
}[];
|
|
22
22
|
multiple: boolean;
|
|
23
23
|
/** The SDK always lets the person answer in their own words. */
|
|
@@ -26,20 +26,20 @@ export type ClaudeQuestion = {
|
|
|
26
26
|
/** A person's answer to one ClaudeQuestion: the chosen labels, their own words, or both. Same shape as ClarifyingAnswer. */
|
|
27
27
|
export type ClaudeQuestionAnswer = {
|
|
28
28
|
questionId: string;
|
|
29
|
-
choice?: string[];
|
|
30
|
-
text?: string;
|
|
29
|
+
choice?: string[] | undefined;
|
|
30
|
+
text?: string | undefined;
|
|
31
31
|
};
|
|
32
32
|
/** How a person answered a permission request. */
|
|
33
33
|
export type ClaudeApprovalAnswer = {
|
|
34
34
|
approved: boolean;
|
|
35
35
|
/** Why it was denied, sent to the agent. */
|
|
36
|
-
reason?: string;
|
|
36
|
+
reason?: string | undefined;
|
|
37
37
|
/** The tool's input as the person edited it before allowing it. The tool runs with exactly this. */
|
|
38
|
-
updatedInput?: Record<string, unknown
|
|
38
|
+
updatedInput?: Record<string, unknown> | undefined;
|
|
39
39
|
/** Answers to the agent's questions, when the request is one (`questions`). */
|
|
40
|
-
answers?: ClaudeQuestionAnswer[];
|
|
40
|
+
answers?: ClaudeQuestionAnswer[] | undefined;
|
|
41
41
|
/** Which of the request's `suggestions` the person chose to keep ("always allow"), by index. None unless they choose. */
|
|
42
|
-
alwaysAllow?: number[];
|
|
42
|
+
alwaysAllow?: number[] | undefined;
|
|
43
43
|
};
|
|
44
44
|
/** Events of Candor's own, mixed into the SDK's stream. */
|
|
45
45
|
export type CandorAgentEvent =
|
|
@@ -48,7 +48,7 @@ export type CandorAgentEvent =
|
|
|
48
48
|
type: "candor_user";
|
|
49
49
|
id: string;
|
|
50
50
|
text: string;
|
|
51
|
-
references?: EntityRef[];
|
|
51
|
+
references?: EntityRef[] | undefined;
|
|
52
52
|
}
|
|
53
53
|
/** A tool call is waiting for a person to allow or deny it. */
|
|
54
54
|
| {
|
|
@@ -58,50 +58,50 @@ export type CandorAgentEvent =
|
|
|
58
58
|
tool: string;
|
|
59
59
|
input: unknown;
|
|
60
60
|
/** The SDK's own sentence for the request, e.g. "Claude wants to edit notes.md". */
|
|
61
|
-
title?: string;
|
|
62
|
-
description?: string;
|
|
61
|
+
title?: string | undefined;
|
|
62
|
+
description?: string | undefined;
|
|
63
63
|
/** Why the SDK asked, when it says. */
|
|
64
|
-
reason?: string;
|
|
65
|
-
blockedPath?: string;
|
|
64
|
+
reason?: string | undefined;
|
|
65
|
+
blockedPath?: string | undefined;
|
|
66
66
|
/** Open on "Deny" and offer no one-key approve: the request grants more than it looks. */
|
|
67
|
-
defaultToNo?: boolean;
|
|
67
|
+
defaultToNo?: boolean | undefined;
|
|
68
68
|
/** A short name for the action: "Edit file". */
|
|
69
|
-
displayName?: string;
|
|
69
|
+
displayName?: string | undefined;
|
|
70
70
|
/**
|
|
71
71
|
* Rules the SDK suggests so this isn't asked again ("always allow"), as the SDK sends them. Offer them as a
|
|
72
72
|
* choice the person makes; never keep one unless they pick it.
|
|
73
73
|
*/
|
|
74
|
-
suggestions?: PermissionUpdate[];
|
|
74
|
+
suggestions?: PermissionUpdate[] | undefined;
|
|
75
75
|
/** Offer no "always allow" for this request: its rule would grant more than this one action. */
|
|
76
|
-
noAlwaysAllow?: boolean;
|
|
76
|
+
noAlwaysAllow?: boolean | undefined;
|
|
77
77
|
/** The permission mode the run was in when it asked. */
|
|
78
|
-
mode?: ClaudePermissionMode;
|
|
78
|
+
mode?: ClaudePermissionMode | undefined;
|
|
79
79
|
/** The agent's questions, when the tool is AskUserQuestion: answer them instead of allowing a tool. */
|
|
80
|
-
questions?: ClaudeQuestion[];
|
|
80
|
+
questions?: ClaudeQuestion[] | undefined;
|
|
81
81
|
/** Set when a subagent asked, with its id. */
|
|
82
|
-
agentId?: string;
|
|
82
|
+
agentId?: string | undefined;
|
|
83
83
|
/** For an MCP tool: its server's name and where that server was configured, as the SDK reports them. */
|
|
84
84
|
mcpServer?: {
|
|
85
85
|
name: string;
|
|
86
86
|
source: string;
|
|
87
|
-
};
|
|
87
|
+
} | undefined;
|
|
88
88
|
/** Whether the server lets a person edit this call's input before allowing it. False means no; left out means yes (1.5.0). */
|
|
89
|
-
editable?: boolean;
|
|
89
|
+
editable?: boolean | undefined;
|
|
90
90
|
}
|
|
91
91
|
/** The request was answered, or the run ended before anyone did. */
|
|
92
92
|
| {
|
|
93
93
|
type: "candor_approval_closed";
|
|
94
94
|
id: string;
|
|
95
95
|
approved: boolean;
|
|
96
|
-
reason?: string;
|
|
96
|
+
reason?: string | undefined;
|
|
97
97
|
/** The person changed the input before allowing it. */
|
|
98
|
-
edited?: boolean;
|
|
98
|
+
edited?: boolean | undefined;
|
|
99
99
|
/** The input the tool ran with, when the person edited it. */
|
|
100
100
|
input?: unknown;
|
|
101
101
|
/** Nobody answered in time (the server's `approvalTimeoutMs`). */
|
|
102
|
-
expired?: boolean;
|
|
102
|
+
expired?: boolean | undefined;
|
|
103
103
|
/** How many "always allow" rules the person kept. */
|
|
104
|
-
kept?: number;
|
|
104
|
+
kept?: number | undefined;
|
|
105
105
|
}
|
|
106
106
|
/** The run's permission mode changed, by the app (`setPermissionMode`). The SDK's own mode reports also count. */
|
|
107
107
|
| {
|
|
@@ -135,27 +135,27 @@ export type FromClaudeAgentOptions = {
|
|
|
135
135
|
/** Who the agent is. Candor always names the agent. */
|
|
136
136
|
agent: AgentIdentity;
|
|
137
137
|
/** A request is open now: the last reply is still streaming and its approvals can be answered. */
|
|
138
|
-
running?: boolean;
|
|
138
|
+
running?: boolean | undefined;
|
|
139
139
|
/** A plain-words title for a tool call: "Read notes.md". */
|
|
140
|
-
toolTitle?: (tool: string, input: unknown) => string | undefined;
|
|
140
|
+
toolTitle?: ((tool: string, input: unknown) => string | undefined) | undefined;
|
|
141
141
|
/**
|
|
142
142
|
* The sources a tool's result supports, for the reply's source list: `(tool, input, output) => [{ kind: "document",
|
|
143
143
|
* label: "Pricing policy v3" }]`. Read only from what the tool returned, never from numbers in the agent's text.
|
|
144
144
|
* Claude's own citations and web search results are read without it.
|
|
145
145
|
*/
|
|
146
|
-
sourcesFrom?: (tool: string, input: unknown, output: string) => ToolSource[] | undefined;
|
|
146
|
+
sourcesFrom?: ((tool: string, input: unknown, output: string) => ToolSource[] | undefined) | undefined;
|
|
147
147
|
};
|
|
148
148
|
export type ClaudeAgentState = {
|
|
149
149
|
messages: Message[];
|
|
150
150
|
/** Tool calls waiting on a person, oldest first. Empty once the request has ended. */
|
|
151
151
|
approvals: ClaudeApproval[];
|
|
152
152
|
/** Send it back with the next message to continue the same session (the SDK's `resume`). */
|
|
153
|
-
sessionId?: string;
|
|
154
|
-
usage?: ClaudeAgentUsage;
|
|
153
|
+
sessionId?: string | undefined;
|
|
154
|
+
usage?: ClaudeAgentUsage | undefined;
|
|
155
155
|
/** A passing problem the agent is handling itself, such as a retried API call. */
|
|
156
|
-
notice?: string;
|
|
156
|
+
notice?: string | undefined;
|
|
157
157
|
/** The permission mode last reported, by the SDK or the app. Absent until one is. */
|
|
158
|
-
permissionMode?: ClaudePermissionMode;
|
|
158
|
+
permissionMode?: ClaudePermissionMode | undefined;
|
|
159
159
|
};
|
|
160
160
|
/**
|
|
161
161
|
* Turns Claude Agent SDK events into Candor messages, waiting approvals and usage.
|
|
@@ -179,7 +179,7 @@ export declare function claudePermissionResult(request: Answerable, answer: Clau
|
|
|
179
179
|
export type ClaudeSuggestion = {
|
|
180
180
|
action: "allow" | "deny" | "ask" | "remove" | "mode" | "directories" | "other";
|
|
181
181
|
what: string;
|
|
182
|
-
scope?: string;
|
|
182
|
+
scope?: string | undefined;
|
|
183
183
|
};
|
|
184
184
|
/**
|
|
185
185
|
* The SDK's suggested permission updates as plain parts PermissionPrompt shows, in the same order, so the indexes a
|
|
@@ -5,20 +5,20 @@ import type { EntityRef } from "../lib/chat.js";
|
|
|
5
5
|
export type StoredApproval = {
|
|
6
6
|
id: string;
|
|
7
7
|
/** The run it belongs to, when the run has an id. */
|
|
8
|
-
runId?: string;
|
|
8
|
+
runId?: string | undefined;
|
|
9
9
|
/** Who may answer it; checked by answerClaudeApproval. */
|
|
10
|
-
owner?: string;
|
|
10
|
+
owner?: string | undefined;
|
|
11
11
|
request: ClaudeApproval;
|
|
12
12
|
createdAt: string;
|
|
13
13
|
/** Set once answered. Recorded, not necessarily used: a run that stopped at the same moment still denies the tool. */
|
|
14
14
|
answer?: ClaudeApprovalAnswer & {
|
|
15
15
|
at: string;
|
|
16
|
-
};
|
|
16
|
+
} | undefined;
|
|
17
17
|
/** Set when nobody can answer any more (the run ended or stopped), with why. */
|
|
18
18
|
closed?: {
|
|
19
19
|
at: string;
|
|
20
20
|
reason: string;
|
|
21
|
-
};
|
|
21
|
+
} | undefined;
|
|
22
22
|
};
|
|
23
23
|
/**
|
|
24
24
|
* Where waiting permission requests live. Answering and closing each happen once: whichever comes first wins, so a
|
|
@@ -47,33 +47,33 @@ export interface ApprovalStore {
|
|
|
47
47
|
* (10 minutes), so it doesn't grow without bound.
|
|
48
48
|
*/
|
|
49
49
|
export declare function memoryApprovalStore({ keepMs }?: {
|
|
50
|
-
keepMs?: number;
|
|
50
|
+
keepMs?: number | undefined;
|
|
51
51
|
}): ApprovalStore;
|
|
52
52
|
/** A `wait` for stores that can't push: reads the request every `intervalMs` (1s) until it's answered or closed. */
|
|
53
53
|
export declare function waitByPolling(get: (id: string) => Promise<StoredApproval | undefined>, id: string, signal: AbortSignal, intervalMs?: number): Promise<ClaudeApprovalAnswer | undefined>;
|
|
54
54
|
export type ClaudeCanUseToolOptions = {
|
|
55
55
|
/** Where requests wait. Defaults to this process's memory. */
|
|
56
|
-
approvals?: ApprovalStore;
|
|
56
|
+
approvals?: ApprovalStore | undefined;
|
|
57
57
|
/** Sends each request, and its closing, to whoever shows it (the browser, your event log). */
|
|
58
58
|
emit: (event: AgentEvent) => void;
|
|
59
59
|
/** Who may answer. */
|
|
60
|
-
owner?: string;
|
|
60
|
+
owner?: string | undefined;
|
|
61
61
|
/** The run's id, kept with each request. */
|
|
62
|
-
runId?: string;
|
|
62
|
+
runId?: string | undefined;
|
|
63
63
|
/** The run's permission mode now, recorded on each request. */
|
|
64
|
-
mode?: () => ClaudePermissionMode | undefined;
|
|
64
|
+
mode?: (() => ClaudePermissionMode | undefined) | undefined;
|
|
65
65
|
/** Called with each request's id as it starts waiting and once it's settled, e.g. to close the rest when the run ends. */
|
|
66
66
|
track?: {
|
|
67
67
|
add(id: string): void;
|
|
68
68
|
delete(id: string): void;
|
|
69
|
-
};
|
|
69
|
+
} | undefined;
|
|
70
70
|
/**
|
|
71
71
|
* Which tools' input a person may edit before allowing it (`updatedInput`). Every tool by default, as in 1.5.0;
|
|
72
72
|
* an answer that edits a tool this refuses is rejected by answerClaudeApproval, whatever the browser sends.
|
|
73
73
|
*/
|
|
74
|
-
editable?: (tool: string, input: unknown) => boolean;
|
|
74
|
+
editable?: ((tool: string, input: unknown) => boolean) | undefined;
|
|
75
75
|
/** Close a request nobody answered after this long, as expired: the tool is denied, never allowed. No limit by default. */
|
|
76
|
-
approvalTimeoutMs?: number;
|
|
76
|
+
approvalTimeoutMs?: number | undefined;
|
|
77
77
|
};
|
|
78
78
|
/**
|
|
79
79
|
* A canUseTool that keeps each request in an ApprovalStore and waits for its answer from wherever it's given: your
|
|
@@ -113,8 +113,8 @@ export interface ClaudeRunStore {
|
|
|
113
113
|
* browser sees text arrive a message at a time instead of as it streams.
|
|
114
114
|
*/
|
|
115
115
|
export declare function memoryRunStore({ maxRuns, maxEvents }?: {
|
|
116
|
-
maxRuns?: number;
|
|
117
|
-
maxEvents?: number;
|
|
116
|
+
maxRuns?: number | undefined;
|
|
117
|
+
maxEvents?: number | undefined;
|
|
118
118
|
}): ClaudeRunStore;
|
|
119
119
|
/** Which permission modes a run may be switched to: a list, or a test. */
|
|
120
120
|
export type ModePolicy = readonly PermissionMode[] | ((mode: PermissionMode) => boolean);
|
|
@@ -133,31 +133,31 @@ export type RunClaudeAgent = (tools: {
|
|
|
133
133
|
}) => Query;
|
|
134
134
|
export type StreamClaudeAgentOptions = {
|
|
135
135
|
/** The incoming request's signal (`request.signal`): the agent stops when the browser goes away, unless `detach`. */
|
|
136
|
-
signal?: AbortSignal;
|
|
136
|
+
signal?: AbortSignal | undefined;
|
|
137
137
|
/** Who may answer this run's permission requests, e.g. the signed-in user's id. Checked when they're answered. */
|
|
138
|
-
owner?: string;
|
|
138
|
+
owner?: string | undefined;
|
|
139
139
|
/** The sentence shown when the run fails. Defaults to a generic one, so server errors don't leak to the browser. */
|
|
140
|
-
describeError?: (error: unknown) => string;
|
|
140
|
+
describeError?: ((error: unknown) => string) | undefined;
|
|
141
141
|
/**
|
|
142
142
|
* Called with every SDK message just before it's sent to the browser, e.g. to record usage and cost from
|
|
143
143
|
* `assistant` and `result` messages. To stop the run from here, abort the run's abortController: the message
|
|
144
144
|
* in hand is still sent, and nothing after it.
|
|
145
145
|
*/
|
|
146
|
-
onMessage?: (message: SDKMessage) => void | Promise<void
|
|
146
|
+
onMessage?: ((message: SDKMessage) => void | Promise<void>) | undefined;
|
|
147
147
|
/** Called with every event the browser gets, in order, e.g. to keep the whole conversation for replay. */
|
|
148
|
-
onEvent?: (event: AgentEvent) => void | Promise<void
|
|
148
|
+
onEvent?: ((event: AgentEvent) => void | Promise<void>) | undefined;
|
|
149
149
|
/** Where permission requests wait. Defaults to this process's memory. */
|
|
150
|
-
approvals?: ApprovalStore;
|
|
150
|
+
approvals?: ApprovalStore | undefined;
|
|
151
151
|
/** Keeps the run's events so a browser can re-attach (attachClaudeAgentRun). Without it, a reload loses the run. */
|
|
152
|
-
runs?: ClaudeRunStore;
|
|
152
|
+
runs?: ClaudeRunStore | undefined;
|
|
153
153
|
/** The run's id; a new one by default. Sent back in the `x-candor-run-id` header. */
|
|
154
|
-
runId?: string;
|
|
154
|
+
runId?: string | undefined;
|
|
155
155
|
/**
|
|
156
156
|
* Keep running when the browser goes away (a reload, a closed tab), so it can re-attach. Stop it with
|
|
157
157
|
* stopClaudeAgentRun. Needs a process that outlives the response: not a serverless function that's frozen when
|
|
158
158
|
* the response ends.
|
|
159
159
|
*/
|
|
160
|
-
detach?: boolean;
|
|
160
|
+
detach?: boolean | undefined;
|
|
161
161
|
/**
|
|
162
162
|
* What the person sent, recorded as the run's first event in `runs`, so a re-attached browser shows it. Pass the
|
|
163
163
|
* `promptId` useClaudeAgent sends as `id`: a browser that re-attaches with `initialEvents` then replaces the run's
|
|
@@ -166,14 +166,14 @@ export type StreamClaudeAgentOptions = {
|
|
|
166
166
|
prompt?: {
|
|
167
167
|
id: string;
|
|
168
168
|
text: string;
|
|
169
|
-
references?: EntityRef[];
|
|
170
|
-
};
|
|
169
|
+
references?: EntityRef[] | undefined;
|
|
170
|
+
} | undefined;
|
|
171
171
|
/** Which tools' input a person may edit before allowing it. Every tool by default. See claudeCanUseTool. */
|
|
172
|
-
editable?: ClaudeCanUseToolOptions["editable"];
|
|
172
|
+
editable?: ClaudeCanUseToolOptions["editable"] | undefined;
|
|
173
173
|
/** Close a permission request nobody answered after this long, as expired (denied). No limit by default; set one with `detach`. */
|
|
174
|
-
approvalTimeoutMs?: number;
|
|
174
|
+
approvalTimeoutMs?: number | undefined;
|
|
175
175
|
/** The permission modes setClaudeAgentPermissionMode may switch this run to. Any mode by default. */
|
|
176
|
-
modes?: ModePolicy;
|
|
176
|
+
modes?: ModePolicy | undefined;
|
|
177
177
|
};
|
|
178
178
|
/**
|
|
179
179
|
* Run an agent and stream it to useClaudeAgent.
|
|
@@ -200,10 +200,10 @@ export declare function streamClaudeAgent(run: RunClaudeAgent, { signal, owner,
|
|
|
200
200
|
* }
|
|
201
201
|
*/
|
|
202
202
|
export declare function attachClaudeAgentRun(runs: ClaudeRunStore, runId: string, { from, owner, signal, pollMs }?: {
|
|
203
|
-
from?: number;
|
|
204
|
-
owner?: string;
|
|
205
|
-
signal?: AbortSignal;
|
|
206
|
-
pollMs?: number;
|
|
203
|
+
from?: number | undefined;
|
|
204
|
+
owner?: string | undefined;
|
|
205
|
+
signal?: AbortSignal | undefined;
|
|
206
|
+
pollMs?: number | undefined;
|
|
207
207
|
}): Promise<Response>;
|
|
208
208
|
/** Stop a run this process is running. False when it isn't running here, or `owner` didn't start it. */
|
|
209
209
|
export declare function stopClaudeAgentRun(runId: string, owner?: string): boolean;
|
|
@@ -214,7 +214,7 @@ export declare function stopClaudeAgentRun(runId: string, owner?: string): boole
|
|
|
214
214
|
* must be left out of `allowed` (or the run's `modes`) too, since anyone can post to the route directly.
|
|
215
215
|
*/
|
|
216
216
|
export declare function setClaudeAgentPermissionMode(runId: string, mode: PermissionMode, owner?: string, { allowed }?: {
|
|
217
|
-
allowed?: ModePolicy;
|
|
217
|
+
allowed?: ModePolicy | undefined;
|
|
218
218
|
}): Promise<boolean>;
|
|
219
219
|
/**
|
|
220
220
|
* Check an answer from the browser against the request it answers, and record it. False when there's no such
|
|
@@ -228,7 +228,7 @@ export declare function setClaudeAgentPermissionMode(runId: string, mode: Permis
|
|
|
228
228
|
* }
|
|
229
229
|
*/
|
|
230
230
|
export declare function answerClaudeApproval(approvals: ApprovalStore, id: string, answer: ClaudeApprovalAnswer, { owner }?: {
|
|
231
|
-
owner?: string;
|
|
231
|
+
owner?: string | undefined;
|
|
232
232
|
}): Promise<boolean>;
|
|
233
233
|
/**
|
|
234
234
|
* Answer a waiting permission request in the default, in-memory store. Kept from 1.4; answerClaudeApproval takes a
|
|
@@ -5,16 +5,16 @@ import { type FromAgUiOptions } from "./ag-ui.js";
|
|
|
5
5
|
export type UseAgUiOptions = Omit<FromAgUiOptions, "running" | "now"> & {
|
|
6
6
|
/** Your AG-UI endpoint (LangGraph, Mastra, CrewAI, Google ADK, Pydantic AI…). It receives a RunAgentInput and streams events back. */
|
|
7
7
|
url: string;
|
|
8
|
-
headers?: Record<string, string
|
|
8
|
+
headers?: Record<string, string> | undefined;
|
|
9
9
|
/** Replaces the global fetch, e.g. to add auth or to play a script in tests and demos. */
|
|
10
|
-
fetch?: typeof fetch;
|
|
10
|
+
fetch?: typeof fetch | undefined;
|
|
11
11
|
/** Continue an existing thread instead of starting a new one. */
|
|
12
|
-
threadId?: string;
|
|
12
|
+
threadId?: string | undefined;
|
|
13
13
|
/** Sent with every run as `forwardedProps`, next to the `references` the person mentioned. */
|
|
14
|
-
forwardedProps?: Record<string, unknown
|
|
14
|
+
forwardedProps?: Record<string, unknown> | undefined;
|
|
15
15
|
/** Tools and context for every run, as AG-UI defines them. Candor doesn't run frontend tools for you. */
|
|
16
|
-
tools?: RunAgentParameters["tools"];
|
|
17
|
-
context?: RunAgentParameters["context"];
|
|
16
|
+
tools?: RunAgentParameters["tools"] | undefined;
|
|
17
|
+
context?: RunAgentParameters["context"] | undefined;
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Wires an AG-UI agent to Candor: messages for <Thread>/<Message>, props for
|
|
@@ -42,7 +42,13 @@ export function useAgUi(options) {
|
|
|
42
42
|
React.useEffect(() => () => run.current?.abort(), []);
|
|
43
43
|
const getClient = React.useCallback(() => {
|
|
44
44
|
if (!client.current)
|
|
45
|
-
client.current = new HttpAgent({
|
|
45
|
+
client.current = new HttpAgent({
|
|
46
|
+
url,
|
|
47
|
+
...(headers && { headers }),
|
|
48
|
+
...(fetcher && { fetch: fetcher }),
|
|
49
|
+
...(threadId !== undefined && { threadId }),
|
|
50
|
+
...(initialState !== undefined && { initialState }),
|
|
51
|
+
});
|
|
46
52
|
const http = client.current;
|
|
47
53
|
// The latest options win, without losing the thread.
|
|
48
54
|
http.url = url;
|
|
@@ -66,7 +72,13 @@ export function useAgUi(options) {
|
|
|
66
72
|
setEvents((e) => [...e, ...batch]);
|
|
67
73
|
};
|
|
68
74
|
try {
|
|
69
|
-
await http.runAgent({
|
|
75
|
+
await http.runAgent({
|
|
76
|
+
...(params.resume && { resume: params.resume }),
|
|
77
|
+
...(tools && { tools }),
|
|
78
|
+
...(context && { context }),
|
|
79
|
+
forwardedProps: { ...forwardedProps, references: params.references ?? [] },
|
|
80
|
+
abortController: controller,
|
|
81
|
+
}, {
|
|
70
82
|
onEvent: ({ event }) => {
|
|
71
83
|
pending.events.push(event);
|
|
72
84
|
pending.frame ||= requestAnimationFrame(flush);
|
|
@@ -30,7 +30,7 @@ export function useCandorChat(chat, options) {
|
|
|
30
30
|
});
|
|
31
31
|
}, [chat.messages]);
|
|
32
32
|
const { sendMessage, stop, addToolApprovalResponse } = chat;
|
|
33
|
-
const respond = React.useCallback((approvalId, approved, reason) => addToolApprovalResponse({ id: approvalId, approved, reason }), [addToolApprovalResponse]);
|
|
33
|
+
const respond = React.useCallback((approvalId, approved, reason) => addToolApprovalResponse({ id: approvalId, approved, ...(reason !== undefined && { reason }) }), [addToolApprovalResponse]);
|
|
34
34
|
return {
|
|
35
35
|
messages,
|
|
36
36
|
approvals,
|
|
@@ -8,30 +8,30 @@ export type UseClaudeAgentOptions = Omit<FromClaudeAgentOptions, "running"> & {
|
|
|
8
8
|
* Your route that records an answer (answerClaudeApproval). It receives `{ id, approved, reason, updatedInput,
|
|
9
9
|
* answers, alwaysAllow }` and returns `{ ok }`. Not needed with `onRespond`.
|
|
10
10
|
*/
|
|
11
|
-
approveApi?: string;
|
|
11
|
+
approveApi?: string | undefined;
|
|
12
12
|
/**
|
|
13
13
|
* Answer through your own route instead, e.g. one that signals the workflow running the agent. Resolve true once
|
|
14
14
|
* the answer is recorded, false if it wasn't (the request had ended).
|
|
15
15
|
*/
|
|
16
|
-
onRespond?: (approvalId: string, answer: ClaudeApprovalAnswer) => Promise<boolean
|
|
16
|
+
onRespond?: ((approvalId: string, answer: ClaudeApprovalAnswer) => Promise<boolean>) | undefined;
|
|
17
17
|
/** Events you kept from earlier (onEvent, a run store): the conversation is folded from them, as it was. */
|
|
18
|
-
initialEvents?: AgentEvent[];
|
|
18
|
+
initialEvents?: AgentEvent[] | undefined;
|
|
19
19
|
/**
|
|
20
20
|
* Where to re-attach to a run after a reload: `(runId, from) => \`/api/agent/${runId}?from=${from}\``, a route that
|
|
21
21
|
* returns attachClaudeAgentRun. With `runId`, the hook re-attaches when it mounts.
|
|
22
22
|
*/
|
|
23
|
-
attachUrl?: (runId: string, from: number) => string;
|
|
23
|
+
attachUrl?: ((runId: string, from: number) => string) | undefined;
|
|
24
24
|
/** A run to re-attach to when the hook mounts, e.g. the one you saved from `runId` before the reload. */
|
|
25
|
-
runId?: string;
|
|
25
|
+
runId?: string | undefined;
|
|
26
26
|
/** Your route that calls stopClaudeAgentRun with `{ runId }`. Needed to stop a run that keeps going without the browser (`detach`). */
|
|
27
|
-
stopApi?: string;
|
|
27
|
+
stopApi?: string | undefined;
|
|
28
28
|
/** Your route that calls setClaudeAgentPermissionMode with `{ runId, mode }`. Enables `setPermissionMode`. */
|
|
29
|
-
modeApi?: string;
|
|
29
|
+
modeApi?: string | undefined;
|
|
30
30
|
/** Extra fields for every request, e.g. which project the agent works on. */
|
|
31
|
-
body?: Record<string, unknown
|
|
32
|
-
headers?: Record<string, string
|
|
31
|
+
body?: Record<string, unknown> | undefined;
|
|
32
|
+
headers?: Record<string, string> | undefined;
|
|
33
33
|
/** Replaces the global fetch, e.g. to add auth or to play a script in tests and demos. */
|
|
34
|
-
fetch?: typeof fetch;
|
|
34
|
+
fetch?: typeof fetch | undefined;
|
|
35
35
|
};
|
|
36
36
|
/**
|
|
37
37
|
* Wires a Claude Agent SDK server route to Candor: messages for <Thread>/<Message>,
|
|
@@ -97,7 +97,7 @@ export function useClaudeAgent(options) {
|
|
|
97
97
|
if (!attachUrl)
|
|
98
98
|
return Promise.resolve();
|
|
99
99
|
setRunId(id);
|
|
100
|
-
return stream((signal) => (fetcher ?? fetch)(attachUrl(id, from), { headers, signal }), undefined, from === 0);
|
|
100
|
+
return stream((signal) => (fetcher ?? fetch)(attachUrl(id, from), { ...(headers && { headers }), signal }), undefined, from === 0);
|
|
101
101
|
}, [attachUrl, fetcher, headers, stream]);
|
|
102
102
|
// Re-attach to the run named in options once, when the hook mounts.
|
|
103
103
|
const attachOnMount = React.useRef(options.runId);
|
|
@@ -18,6 +18,6 @@ export const copyFieldStrings = {
|
|
|
18
18
|
function CopyField({ label, value, className, }) {
|
|
19
19
|
const { state, copy } = useCopy();
|
|
20
20
|
const t = useStrings("copyField", copyFieldStrings);
|
|
21
|
-
return (_jsxs("div", { "data-slot": "copy-field", className: cn("flex flex-col gap-1", className), children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: label }), _jsxs("button", { type: "button", onClick: () => copy(value), className: "group/copy flex w-full items-center gap-2 rounded-lg border bg-sunken px-3 py-2 text-start outline-none transition-colors duration-150 hover:border-border-strong focus-visible:ring-[3px] focus-visible:ring-ring/
|
|
21
|
+
return (_jsxs("div", { "data-slot": "copy-field", className: cn("flex flex-col gap-1", className), children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: label }), _jsxs("button", { type: "button", onClick: () => copy(value), className: "group/copy flex w-full items-center gap-2 rounded-lg border bg-sunken px-3 py-2 text-start outline-none transition-colors duration-150 hover:border-border-strong focus-visible:ring-[3px] focus-visible:ring-ring/80", children: [_jsx("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: value }), _jsx("span", { "aria-live": "polite", className: "inline-flex shrink-0 items-center gap-1 text-xs text-muted-foreground group-hover/copy:text-foreground", children: state === "copied" ? (_jsxs(_Fragment, { children: [_jsx(Check, { className: "size-3 text-success-text" }), " ", t("copied")] })) : state === "failed" ? (_jsxs(_Fragment, { children: [_jsx(X, { className: "size-3 text-destructive-text" }), " ", t("failed")] })) : (_jsxs(_Fragment, { children: [_jsx(Copy, { className: "size-3" }), " ", t("copy")] })) })] })] }));
|
|
22
22
|
}
|
|
23
23
|
export { CopyField };
|