@tetherto/mdk-ui-agent 0.0.0 → 0.12.1
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/LICENSE +202 -0
- package/README.md +310 -0
- package/dist/branding.d.ts +36 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +37 -0
- package/dist/branding.js.map +1 -0
- package/dist/components/approval-card.d.ts +46 -0
- package/dist/components/approval-card.d.ts.map +1 -0
- package/dist/components/approval-card.js +84 -0
- package/dist/components/approval-card.js.map +1 -0
- package/dist/components/assistant-message.d.ts +25 -0
- package/dist/components/assistant-message.d.ts.map +1 -0
- package/dist/components/assistant-message.js +49 -0
- package/dist/components/assistant-message.js.map +1 -0
- package/dist/components/co-pilot-panel.d.ts +17 -0
- package/dist/components/co-pilot-panel.d.ts.map +1 -0
- package/dist/components/co-pilot-panel.js +33 -0
- package/dist/components/co-pilot-panel.js.map +1 -0
- package/dist/components/code-block.d.ts +17 -0
- package/dist/components/code-block.d.ts.map +1 -0
- package/dist/components/code-block.js +40 -0
- package/dist/components/code-block.js.map +1 -0
- package/dist/components/collapsible-answer.d.ts +26 -0
- package/dist/components/collapsible-answer.d.ts.map +1 -0
- package/dist/components/collapsible-answer.js +30 -0
- package/dist/components/collapsible-answer.js.map +1 -0
- package/dist/components/composer.d.ts +31 -0
- package/dist/components/composer.d.ts.map +1 -0
- package/dist/components/composer.js +82 -0
- package/dist/components/composer.js.map +1 -0
- package/dist/components/conversation-list.d.ts +21 -0
- package/dist/components/conversation-list.d.ts.map +1 -0
- package/dist/components/conversation-list.js +42 -0
- package/dist/components/conversation-list.js.map +1 -0
- package/dist/components/icons.d.ts +88 -0
- package/dist/components/icons.d.ts.map +1 -0
- package/dist/components/icons.js +112 -0
- package/dist/components/icons.js.map +1 -0
- package/dist/components/launcher-fab.d.ts +8 -0
- package/dist/components/launcher-fab.d.ts.map +1 -0
- package/dist/components/launcher-fab.js +6 -0
- package/dist/components/launcher-fab.js.map +1 -0
- package/dist/components/leaked-tool-call-notice.d.ts +18 -0
- package/dist/components/leaked-tool-call-notice.d.ts.map +1 -0
- package/dist/components/leaked-tool-call-notice.js +14 -0
- package/dist/components/leaked-tool-call-notice.js.map +1 -0
- package/dist/components/markdown-link.d.ts +17 -0
- package/dist/components/markdown-link.d.ts.map +1 -0
- package/dist/components/markdown-link.js +18 -0
- package/dist/components/markdown-link.js.map +1 -0
- package/dist/components/markdown-text.d.ts +26 -0
- package/dist/components/markdown-text.d.ts.map +1 -0
- package/dist/components/markdown-text.js +32 -0
- package/dist/components/markdown-text.js.map +1 -0
- package/dist/components/message-list.d.ts +24 -0
- package/dist/components/message-list.d.ts.map +1 -0
- package/dist/components/message-list.js +92 -0
- package/dist/components/message-list.js.map +1 -0
- package/dist/components/no-tools-note.d.ts +26 -0
- package/dist/components/no-tools-note.d.ts.map +1 -0
- package/dist/components/no-tools-note.js +27 -0
- package/dist/components/no-tools-note.js.map +1 -0
- package/dist/components/panel-header.d.ts +26 -0
- package/dist/components/panel-header.d.ts.map +1 -0
- package/dist/components/panel-header.js +13 -0
- package/dist/components/panel-header.js.map +1 -0
- package/dist/components/rehype-highlight-subset.d.ts +17 -0
- package/dist/components/rehype-highlight-subset.d.ts.map +1 -0
- package/dist/components/rehype-highlight-subset.js +77 -0
- package/dist/components/rehype-highlight-subset.js.map +1 -0
- package/dist/components/system-message.d.ts +15 -0
- package/dist/components/system-message.d.ts.map +1 -0
- package/dist/components/system-message.js +12 -0
- package/dist/components/system-message.js.map +1 -0
- package/dist/components/tool-chip.d.ts +19 -0
- package/dist/components/tool-chip.d.ts.map +1 -0
- package/dist/components/tool-chip.js +32 -0
- package/dist/components/tool-chip.js.map +1 -0
- package/dist/components/user-message.d.ts +9 -0
- package/dist/components/user-message.d.ts.map +1 -0
- package/dist/components/user-message.js +7 -0
- package/dist/components/user-message.js.map +1 -0
- package/dist/core/conversation-store.d.ts +107 -0
- package/dist/core/conversation-store.d.ts.map +1 -0
- package/dist/core/conversation-store.js +254 -0
- package/dist/core/conversation-store.js.map +1 -0
- package/dist/core/error-text.d.ts +19 -0
- package/dist/core/error-text.d.ts.map +1 -0
- package/dist/core/error-text.js +35 -0
- package/dist/core/error-text.js.map +1 -0
- package/dist/core/events.d.ts +98 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +50 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/format.d.ts +23 -0
- package/dist/core/format.d.ts.map +1 -0
- package/dist/core/format.js +49 -0
- package/dist/core/format.js.map +1 -0
- package/dist/core/index.d.ts +27 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +20 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/markdown.d.ts +26 -0
- package/dist/core/markdown.d.ts.map +1 -0
- package/dist/core/markdown.js +49 -0
- package/dist/core/markdown.js.map +1 -0
- package/dist/core/prose.d.ts +27 -0
- package/dist/core/prose.d.ts.map +1 -0
- package/dist/core/prose.js +79 -0
- package/dist/core/prose.js.map +1 -0
- package/dist/core/small-talk.d.ts +15 -0
- package/dist/core/small-talk.d.ts.map +1 -0
- package/dist/core/small-talk.js +42 -0
- package/dist/core/small-talk.js.map +1 -0
- package/dist/core/sse.d.ts +108 -0
- package/dist/core/sse.d.ts.map +1 -0
- package/dist/core/sse.js +236 -0
- package/dist/core/sse.js.map +1 -0
- package/dist/core/tool-label.d.ts +16 -0
- package/dist/core/tool-label.d.ts.map +1 -0
- package/dist/core/tool-label.js +31 -0
- package/dist/core/tool-label.js.map +1 -0
- package/dist/core/transport.d.ts +71 -0
- package/dist/core/transport.d.ts.map +1 -0
- package/dist/core/transport.js +147 -0
- package/dist/core/transport.js.map +1 -0
- package/dist/core/turn.d.ts +87 -0
- package/dist/core/turn.d.ts.map +1 -0
- package/dist/core/turn.js +232 -0
- package/dist/core/turn.js.map +1 -0
- package/dist/core/uuid.d.ts +21 -0
- package/dist/core/uuid.d.ts.map +1 -0
- package/dist/core/uuid.js +54 -0
- package/dist/core/uuid.js.map +1 -0
- package/dist/entries/chat-page.d.ts +28 -0
- package/dist/entries/chat-page.d.ts.map +1 -0
- package/dist/entries/chat-page.js +25 -0
- package/dist/entries/chat-page.js.map +1 -0
- package/dist/entries/co-pilot.d.ts +41 -0
- package/dist/entries/co-pilot.d.ts.map +1 -0
- package/dist/entries/co-pilot.js +39 -0
- package/dist/entries/co-pilot.js.map +1 -0
- package/dist/entries/lazy-panel.d.ts +15 -0
- package/dist/entries/lazy-panel.d.ts.map +1 -0
- package/dist/entries/lazy-panel.js +19 -0
- package/dist/entries/lazy-panel.js.map +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use-agent-chat.d.ts +46 -0
- package/dist/hooks/use-agent-chat.d.ts.map +1 -0
- package/dist/hooks/use-agent-chat.js +288 -0
- package/dist/hooks/use-agent-chat.js.map +1 -0
- package/dist/hooks/use-agent-config.d.ts +29 -0
- package/dist/hooks/use-agent-config.d.ts.map +1 -0
- package/dist/hooks/use-agent-config.js +45 -0
- package/dist/hooks/use-agent-config.js.map +1 -0
- package/dist/hooks/use-conversations.d.ts +19 -0
- package/dist/hooks/use-conversations.d.ts.map +1 -0
- package/dist/hooks/use-conversations.js +19 -0
- package/dist/hooks/use-conversations.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +1 -0
- package/package.json +105 -1
- package/src/branding.ts +40 -0
- package/src/components/approval-card.tsx +141 -0
- package/src/components/assistant-message.tsx +140 -0
- package/src/components/co-pilot-panel.tsx +109 -0
- package/src/components/code-block.tsx +63 -0
- package/src/components/collapsible-answer.tsx +55 -0
- package/src/components/composer.tsx +147 -0
- package/src/components/conversation-list.tsx +141 -0
- package/src/components/icons.tsx +189 -0
- package/src/components/launcher-fab.tsx +16 -0
- package/src/components/leaked-tool-call-notice.tsx +29 -0
- package/src/components/markdown-link.tsx +30 -0
- package/src/components/markdown-text.tsx +58 -0
- package/src/components/message-list.tsx +164 -0
- package/src/components/no-tools-note.tsx +33 -0
- package/src/components/panel-header.tsx +86 -0
- package/src/components/rehype-highlight-subset.ts +84 -0
- package/src/components/system-message.tsx +19 -0
- package/src/components/tool-chip.tsx +58 -0
- package/src/components/user-message.tsx +18 -0
- package/src/core/conversation-store.ts +342 -0
- package/src/core/error-text.ts +36 -0
- package/src/core/events.ts +127 -0
- package/src/core/format.ts +59 -0
- package/src/core/index.ts +115 -0
- package/src/core/markdown.ts +52 -0
- package/src/core/prose.ts +78 -0
- package/src/core/small-talk.ts +45 -0
- package/src/core/sse.ts +269 -0
- package/src/core/tool-label.ts +33 -0
- package/src/core/transport.ts +208 -0
- package/src/core/turn.ts +299 -0
- package/src/core/uuid.ts +59 -0
- package/src/entries/chat-page.tsx +56 -0
- package/src/entries/co-pilot.tsx +84 -0
- package/src/entries/lazy-panel.tsx +19 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/use-agent-chat.ts +387 -0
- package/src/hooks/use-agent-config.ts +70 -0
- package/src/hooks/use-conversations.ts +39 -0
- package/src/index.ts +30 -0
- package/src/styles/_approval.scss +68 -0
- package/src/styles/_composer.scss +45 -0
- package/src/styles/_conversations.scss +160 -0
- package/src/styles/_messages.scss +444 -0
- package/src/styles/_mixins.scss +27 -0
- package/src/styles/_panel.scss +147 -0
- package/src/styles/_tokens.scss +30 -0
- package/src/styles.scss +16 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one stateful hook: owns the session, the live turn, and persistence.
|
|
3
|
+
*
|
|
4
|
+
* Components below this are presentational — they receive already-shaped props
|
|
5
|
+
* and render them, per the repo's separation-of-concerns rule.
|
|
6
|
+
*/
|
|
7
|
+
import type { StoreApi } from 'zustand/vanilla';
|
|
8
|
+
import type { ChatMessage, Conversation, ConversationStore } from '../core/conversation-store';
|
|
9
|
+
import type { AgentTurnState, PendingApproval } from '../core/turn';
|
|
10
|
+
import type { AgentConfigOptions } from './use-agent-config';
|
|
11
|
+
export type UseAgentChatOptions = AgentConfigOptions & {
|
|
12
|
+
/** Isolated store for tests and the catalog demo; defaults to the singleton. */
|
|
13
|
+
store?: StoreApi<ConversationStore>;
|
|
14
|
+
/**
|
|
15
|
+
* The three silences a turn is allowed, all defaulted in `core/sse`: between
|
|
16
|
+
* events, while an approval is outstanding, and before the first event. Raise
|
|
17
|
+
* the second if your gateway's `agent.approvalTimeoutMs` is longer than five
|
|
18
|
+
* minutes, and the third if its model is slower to route than two minutes.
|
|
19
|
+
*/
|
|
20
|
+
idleTimeoutMs?: number;
|
|
21
|
+
approvalIdleTimeoutMs?: number;
|
|
22
|
+
firstEventIdleTimeoutMs?: number;
|
|
23
|
+
};
|
|
24
|
+
export type UseAgentChatResult = {
|
|
25
|
+
conversations: Conversation[];
|
|
26
|
+
active: Conversation | null;
|
|
27
|
+
/** Persisted transcript of the active conversation. */
|
|
28
|
+
messages: ChatMessage[];
|
|
29
|
+
/** The turn currently streaming, rendered after `messages`. Null when idle. */
|
|
30
|
+
live: AgentTurnState | null;
|
|
31
|
+
isStreaming: boolean;
|
|
32
|
+
pendingApproval: PendingApproval | null;
|
|
33
|
+
/** A decision has been POSTed and the stream has not resumed yet. */
|
|
34
|
+
isDecisionPending: boolean;
|
|
35
|
+
canSend: boolean;
|
|
36
|
+
send: (text: string) => void;
|
|
37
|
+
decide: (approved: boolean) => void;
|
|
38
|
+
abort: VoidFunction;
|
|
39
|
+
/** Re-sends the last question, for a turn that failed. */
|
|
40
|
+
retry: VoidFunction;
|
|
41
|
+
newConversation: VoidFunction;
|
|
42
|
+
selectConversation: (id: string) => void;
|
|
43
|
+
removeConversation: (id: string) => void;
|
|
44
|
+
};
|
|
45
|
+
export declare function useAgentChat(options?: UseAgentChatOptions): UseAgentChatResult;
|
|
46
|
+
//# sourceMappingURL=use-agent-chat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-chat.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-chat.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAG/C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9F,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAoC5D,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,GAAG;IACrD,gFAAgF;IAChF,KAAK,CAAC,EAAE,QAAQ,CAAC,iBAAiB,CAAC,CAAA;IACnC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,uDAAuD;IACvD,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,+EAA+E;IAC/E,IAAI,EAAE,cAAc,GAAG,IAAI,CAAA;IAC3B,WAAW,EAAE,OAAO,CAAA;IACpB,eAAe,EAAE,eAAe,GAAG,IAAI,CAAA;IACvC,qEAAqE;IACrE,iBAAiB,EAAE,OAAO,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,MAAM,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAA;IACnC,KAAK,EAAE,YAAY,CAAA;IACnB,0DAA0D;IAC1D,KAAK,EAAE,YAAY,CAAA;IACnB,eAAe,EAAE,YAAY,CAAA;IAC7B,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC,CAAA;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,kBAAkB,CA8SlF"}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one stateful hook: owns the session, the live turn, and persistence.
|
|
3
|
+
*
|
|
4
|
+
* Components below this are presentational — they receive already-shaped props
|
|
5
|
+
* and render them, per the repo's separation-of-concerns rule.
|
|
6
|
+
*/
|
|
7
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
8
|
+
import { conversationStore as defaultStore, MESSAGE_ROLE } from '../core/conversation-store';
|
|
9
|
+
import { describeAgentError, GENERIC_TURN_ERROR } from '../core/error-text';
|
|
10
|
+
import { AGENT_ERROR, AgentApiError, createSession, decideApproval, deleteSession, streamTurn, } from '../core/transport';
|
|
11
|
+
import { abortTurn, createTurnState, failTurn, isTurnSettled, reduceTurn } from '../core/turn';
|
|
12
|
+
import { uuid } from '../core/uuid';
|
|
13
|
+
import { useAgentConfig } from './use-agent-config';
|
|
14
|
+
import { useConversations } from './use-conversations';
|
|
15
|
+
/**
|
|
16
|
+
* Said in the transcript when a turn had to open a new gateway session.
|
|
17
|
+
*
|
|
18
|
+
* Sessions live in the gateway's memory, so a restart or the agent's own TTL makes
|
|
19
|
+
* a stored id a 404 and the next message starts a session with no history. The
|
|
20
|
+
* transcript above it still reads as one conversation, so without this the operator
|
|
21
|
+
* asks a follow-up about "that container" and the agent has never heard of it.
|
|
22
|
+
*/
|
|
23
|
+
const SESSION_RESET_NOTICE = 'New session — the agent does not remember the messages above this line.';
|
|
24
|
+
function describeError(error) {
|
|
25
|
+
if (error instanceof AgentApiError)
|
|
26
|
+
return describeAgentError(error.code) ?? error.message;
|
|
27
|
+
return GENERIC_TURN_ERROR;
|
|
28
|
+
}
|
|
29
|
+
function isAbort(error) {
|
|
30
|
+
return error instanceof DOMException && error.name === 'AbortError';
|
|
31
|
+
}
|
|
32
|
+
export function useAgentChat(options = {}) {
|
|
33
|
+
const { store = defaultStore, idleTimeoutMs, approvalIdleTimeoutMs, firstEventIdleTimeoutMs, ...configOptions } = options;
|
|
34
|
+
const config = useAgentConfig(configOptions);
|
|
35
|
+
const { conversations, active, create, select, remove } = useConversations(store);
|
|
36
|
+
const [live, setLive] = useState(null);
|
|
37
|
+
const [isBusy, setIsBusy] = useState(false);
|
|
38
|
+
const [decidedApprovalId, setDecidedApprovalId] = useState(null);
|
|
39
|
+
// Read inside async callbacks, where the rendered value would be stale.
|
|
40
|
+
const liveRef = useRef(null);
|
|
41
|
+
const abortRef = useRef(null);
|
|
42
|
+
const busyRef = useRef(false);
|
|
43
|
+
const frameRef = useRef(null);
|
|
44
|
+
/**
|
|
45
|
+
* Records the live turn, and commits it to React at most once per frame.
|
|
46
|
+
*
|
|
47
|
+
* One `setState` per SSE event means the whole panel re-renders 30–60 times a
|
|
48
|
+
* second at token rate, for a transcript whose settled half never changed. The
|
|
49
|
+
* ref is updated synchronously — callbacks and the next reduce read it — and the
|
|
50
|
+
* scheduled commit always publishes the latest value, so no event is skipped,
|
|
51
|
+
* only the intermediate paints. Clearing the turn commits immediately: it is the
|
|
52
|
+
* end of the turn, not a frame of it.
|
|
53
|
+
*/
|
|
54
|
+
const publish = useCallback((next) => {
|
|
55
|
+
liveRef.current = next;
|
|
56
|
+
if (next === null) {
|
|
57
|
+
if (frameRef.current !== null)
|
|
58
|
+
cancelAnimationFrame(frameRef.current);
|
|
59
|
+
frameRef.current = null;
|
|
60
|
+
setLive(null);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (frameRef.current !== null)
|
|
64
|
+
return;
|
|
65
|
+
frameRef.current = requestAnimationFrame(() => {
|
|
66
|
+
frameRef.current = null;
|
|
67
|
+
setLive(liveRef.current);
|
|
68
|
+
});
|
|
69
|
+
}, []);
|
|
70
|
+
useEffect(() => () => {
|
|
71
|
+
if (frameRef.current !== null)
|
|
72
|
+
cancelAnimationFrame(frameRef.current);
|
|
73
|
+
abortRef.current?.abort();
|
|
74
|
+
}, []);
|
|
75
|
+
/**
|
|
76
|
+
* A stored `sessionId` outlives the session it names — the gateway holds
|
|
77
|
+
* sessions in memory per process, so a restart or the agent's own TTL makes it
|
|
78
|
+
* a 404. `force` mints a replacement.
|
|
79
|
+
*/
|
|
80
|
+
const resolveSessionId = useCallback(async (conversationId, force) => {
|
|
81
|
+
const conversation = store
|
|
82
|
+
.getState()
|
|
83
|
+
.conversations.find((candidate) => candidate.id === conversationId);
|
|
84
|
+
if (!force && conversation?.sessionId)
|
|
85
|
+
return conversation.sessionId;
|
|
86
|
+
const sessionId = await createSession(config);
|
|
87
|
+
store.getState().setSessionId(conversationId, sessionId);
|
|
88
|
+
// Only a break if there was something to lose. A conversation whose only
|
|
89
|
+
// message is the question now being sent has no context to carry over, so
|
|
90
|
+
// the first session of a conversation is not announced.
|
|
91
|
+
const hadContext = conversation?.messages.some((message) => message.role === MESSAGE_ROLE.ASSISTANT) ?? false;
|
|
92
|
+
if (hadContext) {
|
|
93
|
+
store.getState().appendMessage(conversationId, {
|
|
94
|
+
id: uuid(),
|
|
95
|
+
role: MESSAGE_ROLE.SYSTEM,
|
|
96
|
+
text: SESSION_RESET_NOTICE,
|
|
97
|
+
at: Date.now(),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return sessionId;
|
|
101
|
+
}, [config, store]);
|
|
102
|
+
/**
|
|
103
|
+
* Opens the stream, retrying once against a fresh session if the stored one is
|
|
104
|
+
* gone. The first `next()` is what performs the fetch — an async generator's
|
|
105
|
+
* body does not run until then — so the status check happens here, not later
|
|
106
|
+
* in the consume loop.
|
|
107
|
+
*/
|
|
108
|
+
const openStream = useCallback(async (conversationId, text, signal) => {
|
|
109
|
+
const start = async (force) => {
|
|
110
|
+
const sessionId = await resolveSessionId(conversationId, force);
|
|
111
|
+
const iterator = streamTurn(sessionId, text, {
|
|
112
|
+
...config,
|
|
113
|
+
...(idleTimeoutMs === undefined ? {} : { idleTimeoutMs }),
|
|
114
|
+
...(approvalIdleTimeoutMs === undefined ? {} : { approvalIdleTimeoutMs }),
|
|
115
|
+
...(firstEventIdleTimeoutMs === undefined ? {} : { firstEventIdleTimeoutMs }),
|
|
116
|
+
signal,
|
|
117
|
+
});
|
|
118
|
+
return { iterator, first: await iterator.next() };
|
|
119
|
+
};
|
|
120
|
+
try {
|
|
121
|
+
return await start(false);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (error instanceof AgentApiError && error.is(AGENT_ERROR.SESSION_NOT_FOUND)) {
|
|
125
|
+
return await start(true);
|
|
126
|
+
}
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
}, [approvalIdleTimeoutMs, config, firstEventIdleTimeoutMs, idleTimeoutMs, resolveSessionId]);
|
|
130
|
+
const runTurn = useCallback(async (text) => {
|
|
131
|
+
busyRef.current = true;
|
|
132
|
+
setIsBusy(true);
|
|
133
|
+
setDecidedApprovalId(null);
|
|
134
|
+
const conversationId = store.getState().activeId ?? store.getState().create();
|
|
135
|
+
store.getState().appendMessage(conversationId, {
|
|
136
|
+
id: uuid(),
|
|
137
|
+
role: MESSAGE_ROLE.USER,
|
|
138
|
+
text,
|
|
139
|
+
at: Date.now(),
|
|
140
|
+
});
|
|
141
|
+
const controller = new AbortController();
|
|
142
|
+
abortRef.current = controller;
|
|
143
|
+
let state = createTurnState();
|
|
144
|
+
publish(state);
|
|
145
|
+
try {
|
|
146
|
+
const { iterator, first } = await openStream(conversationId, text, controller.signal);
|
|
147
|
+
let result = first;
|
|
148
|
+
while (!result.done) {
|
|
149
|
+
state = reduceTurn(state, result.value);
|
|
150
|
+
publish(state);
|
|
151
|
+
result = await iterator.next();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
// An abort is the operator's own doing: keep whatever streamed, add no
|
|
156
|
+
// error. Anything else becomes the turn's error. Either way a tool call
|
|
157
|
+
// still outstanding is closed — it will never report back now.
|
|
158
|
+
state = isAbort(error) ? abortTurn(state) : failTurn(state, describeError(error));
|
|
159
|
+
}
|
|
160
|
+
finally {
|
|
161
|
+
// An abort cancels the reader rather than rejecting the read, so it
|
|
162
|
+
// usually ends the loop normally and never reaches the catch above. The
|
|
163
|
+
// closing-down a stopped turn needs therefore happens here.
|
|
164
|
+
const interrupted = controller.signal.aborted && !isTurnSettled(state);
|
|
165
|
+
if (interrupted)
|
|
166
|
+
state = abortTurn(state);
|
|
167
|
+
store.getState().appendMessage(conversationId, {
|
|
168
|
+
id: uuid(),
|
|
169
|
+
role: MESSAGE_ROLE.ASSISTANT,
|
|
170
|
+
text: state.text,
|
|
171
|
+
at: Date.now(),
|
|
172
|
+
tools: state.tools,
|
|
173
|
+
error: state.error,
|
|
174
|
+
// Half an answer must not read back later as the agent's full statement.
|
|
175
|
+
...(interrupted ? { interrupted: true } : {}),
|
|
176
|
+
});
|
|
177
|
+
publish(null);
|
|
178
|
+
abortRef.current = null;
|
|
179
|
+
busyRef.current = false;
|
|
180
|
+
setIsBusy(false);
|
|
181
|
+
setDecidedApprovalId(null);
|
|
182
|
+
}
|
|
183
|
+
}, [openStream, publish, store]);
|
|
184
|
+
const send = useCallback((raw) => {
|
|
185
|
+
const text = raw.trim();
|
|
186
|
+
// Guarded on the ref rather than the rendered flag: two submits inside one
|
|
187
|
+
// frame would both see the old state and provoke a 409.
|
|
188
|
+
if (!text || busyRef.current)
|
|
189
|
+
return;
|
|
190
|
+
void runTurn(text);
|
|
191
|
+
}, [runTurn]);
|
|
192
|
+
const decide = useCallback((approved) => {
|
|
193
|
+
const pending = liveRef.current?.pendingApproval;
|
|
194
|
+
const conversationId = store.getState().activeId;
|
|
195
|
+
if (!pending || !conversationId)
|
|
196
|
+
return;
|
|
197
|
+
const sessionId = store
|
|
198
|
+
.getState()
|
|
199
|
+
.conversations.find((conversation) => conversation.id === conversationId)?.sessionId;
|
|
200
|
+
if (!sessionId)
|
|
201
|
+
return;
|
|
202
|
+
setDecidedApprovalId(pending.approvalId);
|
|
203
|
+
void decideApproval(sessionId, pending.approvalId, approved, config).catch((error) => {
|
|
204
|
+
// A 404 means the approval already settled — it timed out server-side, or
|
|
205
|
+
// this is a second decision. Both are indistinguishable by design, and
|
|
206
|
+
// the stream resumes either way, so there is nothing to report.
|
|
207
|
+
if (error instanceof AgentApiError && error.is(AGENT_ERROR.APPROVAL_NOT_FOUND))
|
|
208
|
+
return;
|
|
209
|
+
setDecidedApprovalId(null);
|
|
210
|
+
});
|
|
211
|
+
}, [config, store]);
|
|
212
|
+
const abort = useCallback(() => {
|
|
213
|
+
abortRef.current?.abort();
|
|
214
|
+
}, []);
|
|
215
|
+
/**
|
|
216
|
+
* Re-asks the last question after a failed turn.
|
|
217
|
+
*
|
|
218
|
+
* The question is re-sent as a new message rather than the failed turn being
|
|
219
|
+
* resumed — the gateway has no notion of resuming one — so the transcript shows
|
|
220
|
+
* it asked twice, which is what happened.
|
|
221
|
+
*/
|
|
222
|
+
const retry = useCallback(() => {
|
|
223
|
+
if (busyRef.current)
|
|
224
|
+
return;
|
|
225
|
+
const conversationId = store.getState().activeId;
|
|
226
|
+
if (!conversationId)
|
|
227
|
+
return;
|
|
228
|
+
const messages = store
|
|
229
|
+
.getState()
|
|
230
|
+
.conversations.find((conversation) => conversation.id === conversationId)?.messages ?? [];
|
|
231
|
+
const lastQuestion = [...messages].reverse().find((message) => message.role === MESSAGE_ROLE.USER);
|
|
232
|
+
if (!lastQuestion)
|
|
233
|
+
return;
|
|
234
|
+
void runTurn(lastQuestion.text);
|
|
235
|
+
}, [runTurn, store]);
|
|
236
|
+
const newConversation = useCallback(() => {
|
|
237
|
+
if (busyRef.current)
|
|
238
|
+
return;
|
|
239
|
+
create();
|
|
240
|
+
}, [create]);
|
|
241
|
+
const selectConversation = useCallback((id) => {
|
|
242
|
+
if (busyRef.current)
|
|
243
|
+
return;
|
|
244
|
+
select(id);
|
|
245
|
+
}, [select]);
|
|
246
|
+
/**
|
|
247
|
+
* Drops the conversation locally and releases its gateway session.
|
|
248
|
+
*
|
|
249
|
+
* The DELETE is best-effort and deliberately unawaited: the session may
|
|
250
|
+
* already be gone (a restart, or the agent's own TTL) and the gateway refuses
|
|
251
|
+
* to delete one with a turn in flight. Neither should block removing the local
|
|
252
|
+
* record, which is the only copy the operator can see.
|
|
253
|
+
*/
|
|
254
|
+
const removeConversation = useCallback((id) => {
|
|
255
|
+
if (busyRef.current && store.getState().activeId === id)
|
|
256
|
+
return;
|
|
257
|
+
const sessionId = store
|
|
258
|
+
.getState()
|
|
259
|
+
.conversations.find((conversation) => conversation.id === id)?.sessionId;
|
|
260
|
+
remove(id);
|
|
261
|
+
if (sessionId) {
|
|
262
|
+
void deleteSession(sessionId, config).catch(() => {
|
|
263
|
+
// Already collected, or still busy. The gateway reaps it either way.
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}, [config, remove, store]);
|
|
267
|
+
const pendingApproval = live?.pendingApproval ?? null;
|
|
268
|
+
return {
|
|
269
|
+
conversations,
|
|
270
|
+
active,
|
|
271
|
+
messages: active?.messages ?? [],
|
|
272
|
+
live,
|
|
273
|
+
isStreaming: isBusy,
|
|
274
|
+
pendingApproval,
|
|
275
|
+
isDecisionPending: pendingApproval !== null && decidedApprovalId === pendingApproval.approvalId,
|
|
276
|
+
// A turn paused on an approval still holds the session busy, so this stays
|
|
277
|
+
// false through the approval too — sending now would be a 409.
|
|
278
|
+
canSend: !isBusy,
|
|
279
|
+
send,
|
|
280
|
+
decide,
|
|
281
|
+
abort,
|
|
282
|
+
retry,
|
|
283
|
+
newConversation,
|
|
284
|
+
selectConversation,
|
|
285
|
+
removeConversation,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
//# sourceMappingURL=use-agent-chat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-chat.js","sourceRoot":"","sources":["../../src/hooks/use-agent-chat.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AgentTransportOptions, TokenSource } from '../core/transport';
|
|
2
|
+
export type AgentConfigOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Gateway origin. Defaults to whatever the app already configured on
|
|
5
|
+
* `MdkProvider`, so a host that set its API base once does not set it again
|
|
6
|
+
* here — and to `''` outside one, meaning relative URLs, which is what the
|
|
7
|
+
* generated shell wants: it proxies `/agent` in dev and is served same-origin
|
|
8
|
+
* in production. Set it only to override that, and remember the gateway sends
|
|
9
|
+
* no CORS headers if you point it at another origin.
|
|
10
|
+
*/
|
|
11
|
+
apiBaseUrl?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Bearer token source. Defaults to the `MdkProvider`'s auth provider, and to
|
|
14
|
+
* no token at all outside one — which is correct for a gateway running without
|
|
15
|
+
* an auth plugin, where every caller is the single local operator.
|
|
16
|
+
*/
|
|
17
|
+
getToken?: TokenSource;
|
|
18
|
+
/** Injected in tests and by the catalog demo. */
|
|
19
|
+
fetchImpl?: typeof fetch;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Resolves transport options from explicit props, falling back to the MDK
|
|
23
|
+
* provider.
|
|
24
|
+
*
|
|
25
|
+
* `useMdkAuth` deliberately does not throw outside an `MdkProvider`, which is
|
|
26
|
+
* what lets the panel be dropped into a non-MDK app with just an `apiBaseUrl`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useAgentConfig(options?: AgentConfigOptions): AgentTransportOptions;
|
|
29
|
+
//# sourceMappingURL=use-agent-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-config.d.ts","sourceRoot":"","sources":["../../src/hooks/use-agent-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAK3E,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,WAAW,CAAA;IACtB,iDAAiD;IACjD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,CAAA;AA0BD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,GAAE,kBAAuB,GAAG,qBAAqB,CAatF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { useMdkAuth, useQueryClient } from '@tetherto/mdk-react-adapter';
|
|
2
|
+
import { getFetcher, getMdkRuntime } from '@tetherto/mdk-ui-foundation';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
/**
|
|
5
|
+
* The base URL the app already configured on `MdkProvider`, or undefined.
|
|
6
|
+
*
|
|
7
|
+
* Two things make this narrower than a plain `getApiBaseUrl`. It has to survive
|
|
8
|
+
* having no provider at all, since the panel is meant to drop into a non-MDK
|
|
9
|
+
* app — `useQueryClient` throws there, and the context read happens before the
|
|
10
|
+
* throw, so guarding it leaves hook order intact. And `getApiBaseUrl` answers
|
|
11
|
+
* `http://localhost:3000` for a client MDK did not build, which would quietly
|
|
12
|
+
* point the panel at an origin nobody chose. A fetcher in the meta is what says
|
|
13
|
+
* the client came from `createMdkQueryClient`, so its base URL — including the
|
|
14
|
+
* empty string the shell sets deliberately — is meant rather than defaulted.
|
|
15
|
+
*/
|
|
16
|
+
function useConfiguredBaseUrl() {
|
|
17
|
+
// Neither MDK package re-exports the QueryClient type, and @tanstack/react-query is not a
|
|
18
|
+
// dependency here — so the type comes from the hook that returns it.
|
|
19
|
+
let client;
|
|
20
|
+
try {
|
|
21
|
+
client = useQueryClient();
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
return getFetcher(client) ? getMdkRuntime(client).baseUrl : undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolves transport options from explicit props, falling back to the MDK
|
|
30
|
+
* provider.
|
|
31
|
+
*
|
|
32
|
+
* `useMdkAuth` deliberately does not throw outside an `MdkProvider`, which is
|
|
33
|
+
* what lets the panel be dropped into a non-MDK app with just an `apiBaseUrl`.
|
|
34
|
+
*/
|
|
35
|
+
export function useAgentConfig(options = {}) {
|
|
36
|
+
const auth = useMdkAuth();
|
|
37
|
+
const configuredBaseUrl = useConfiguredBaseUrl();
|
|
38
|
+
const { apiBaseUrl, getToken, fetchImpl } = options;
|
|
39
|
+
return useMemo(() => ({
|
|
40
|
+
baseUrl: apiBaseUrl ?? configuredBaseUrl ?? '',
|
|
41
|
+
getToken: getToken ?? (() => auth.getToken()),
|
|
42
|
+
...(fetchImpl ? { fetchImpl } : {}),
|
|
43
|
+
}), [apiBaseUrl, configuredBaseUrl, getToken, fetchImpl, auth]);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=use-agent-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent-config.js","sourceRoot":"","sources":["../../src/hooks/use-agent-config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAsB/B;;;;;;;;;;;GAWG;AACH,SAAS,oBAAoB;IAC3B,0FAA0F;IAC1F,qEAAqE;IACrE,IAAI,MAAyC,CAAA;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,cAAc,EAAE,CAAA;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;IACD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AACvE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,OAAO,GAAuB,EAAE;IAC7D,MAAM,IAAI,GAAG,UAAU,EAAE,CAAA;IACzB,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAA;IAChD,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAA;IAEnD,OAAO,OAAO,CACZ,GAAG,EAAE,CAAC,CAAC;QACL,OAAO,EAAE,UAAU,IAAI,iBAAiB,IAAI,EAAE;QAC9C,QAAQ,EAAE,QAAQ,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC7C,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpC,CAAC,EACF,CAAC,UAAU,EAAE,iBAAiB,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,CAC3D,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StoreApi } from 'zustand/vanilla';
|
|
2
|
+
import type { Conversation, ConversationStore } from '../core/conversation-store';
|
|
3
|
+
export type UseConversationsResult = {
|
|
4
|
+
/** Newest first — the order the Conversations view renders. */
|
|
5
|
+
conversations: Conversation[];
|
|
6
|
+
active: Conversation | null;
|
|
7
|
+
activeId: string | null;
|
|
8
|
+
create: ConversationStore['create'];
|
|
9
|
+
select: ConversationStore['select'];
|
|
10
|
+
remove: ConversationStore['remove'];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Binds the conversation store to React.
|
|
14
|
+
*
|
|
15
|
+
* Takes a store instance so tests and the catalog demo can run against an
|
|
16
|
+
* isolated one; runtime callers get the module singleton.
|
|
17
|
+
*/
|
|
18
|
+
export declare function useConversations(store?: StoreApi<ConversationStore>): UseConversationsResult;
|
|
19
|
+
//# sourceMappingURL=use-conversations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-conversations.d.ts","sourceRoot":"","sources":["../../src/hooks/use-conversations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAI/C,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAGjF,MAAM,MAAM,sBAAsB,GAAG;IACnC,+DAA+D;IAC/D,aAAa,EAAE,YAAY,EAAE,CAAA;IAC7B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACnC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACnC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;CACpC,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,GAAE,QAAQ,CAAC,iBAAiB,CAAgB,GAChD,sBAAsB,CAaxB"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useStore } from 'zustand';
|
|
3
|
+
import { conversationStore as defaultStore } from '../core/conversation-store';
|
|
4
|
+
/**
|
|
5
|
+
* Binds the conversation store to React.
|
|
6
|
+
*
|
|
7
|
+
* Takes a store instance so tests and the catalog demo can run against an
|
|
8
|
+
* isolated one; runtime callers get the module singleton.
|
|
9
|
+
*/
|
|
10
|
+
export function useConversations(store = defaultStore) {
|
|
11
|
+
const conversations = useStore(store, (state) => state.conversations);
|
|
12
|
+
const activeId = useStore(store, (state) => state.activeId);
|
|
13
|
+
const create = useStore(store, (state) => state.create);
|
|
14
|
+
const select = useStore(store, (state) => state.select);
|
|
15
|
+
const remove = useStore(store, (state) => state.remove);
|
|
16
|
+
const active = useMemo(() => conversations.find((conversation) => conversation.id === activeId) ?? null, [conversations, activeId]);
|
|
17
|
+
return { conversations, active, activeId, create, select, remove };
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=use-conversations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-conversations.js","sourceRoot":"","sources":["../../src/hooks/use-conversations.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlC,OAAO,EAAE,iBAAiB,IAAI,YAAY,EAAE,MAAM,4BAA4B,CAAA;AAY9E;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAK,GAAgC,YAAY;IAEjD,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAA;IACrE,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAEvD,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,KAAK,QAAQ,CAAC,IAAI,IAAI,EAChF,CAAC,aAAa,EAAE,QAAQ,CAAC,CAC1B,CAAA;IAED,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAA;AACpE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tetherto/mdk-ui-agent
|
|
3
|
+
*
|
|
4
|
+
* The operator Co-pilot, as a drop-in for any MDK UI shell. Talks to the agent
|
|
5
|
+
* gateway plugin (`@tetherto/mdk-app-agent`) over SSE and renders its
|
|
6
|
+
* six-event contract as a conversation.
|
|
7
|
+
*
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { CoPilot } from '@tetherto/mdk-ui-agent'
|
|
10
|
+
* import '@tetherto/mdk-ui-agent/styles.css'
|
|
11
|
+
*
|
|
12
|
+
* <CoPilot />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* `CoPilotPanel` is deliberately NOT exported here — it is reachable from
|
|
16
|
+
* `@tetherto/mdk-ui-agent/panel`. Both entries load it through a lazy boundary
|
|
17
|
+
* so the markdown renderer and syntax highlighter stay out of the host's first
|
|
18
|
+
* paint, and a single static import from this barrel would collapse that split
|
|
19
|
+
* for every consumer.
|
|
20
|
+
*/
|
|
21
|
+
export { AGENT_LABELS, AGENT_NAME, OPERATOR_NAME } from './branding';
|
|
22
|
+
export * from './core';
|
|
23
|
+
export type { ChatUIEntryProps } from './entries/chat-page';
|
|
24
|
+
export { ChatUIEntry } from './entries/chat-page';
|
|
25
|
+
export type { CoPilotPosition, CoPilotProps } from './entries/co-pilot';
|
|
26
|
+
export { CoPilot, COPILOT_POSITION } from './entries/co-pilot';
|
|
27
|
+
export * from './hooks';
|
|
28
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACpE,cAAc,QAAQ,CAAA;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACjD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEvE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,cAAc,SAAS,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tetherto/mdk-ui-agent
|
|
3
|
+
*
|
|
4
|
+
* The operator Co-pilot, as a drop-in for any MDK UI shell. Talks to the agent
|
|
5
|
+
* gateway plugin (`@tetherto/mdk-app-agent`) over SSE and renders its
|
|
6
|
+
* six-event contract as a conversation.
|
|
7
|
+
*
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { CoPilot } from '@tetherto/mdk-ui-agent'
|
|
10
|
+
* import '@tetherto/mdk-ui-agent/styles.css'
|
|
11
|
+
*
|
|
12
|
+
* <CoPilot />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* `CoPilotPanel` is deliberately NOT exported here — it is reachable from
|
|
16
|
+
* `@tetherto/mdk-ui-agent/panel`. Both entries load it through a lazy boundary
|
|
17
|
+
* so the markdown renderer and syntax highlighter stay out of the host's first
|
|
18
|
+
* paint, and a single static import from this barrel would collapse that split
|
|
19
|
+
* for every consumer.
|
|
20
|
+
*/
|
|
21
|
+
export { AGENT_LABELS, AGENT_NAME, OPERATOR_NAME } from './branding';
|
|
22
|
+
export * from './core';
|
|
23
|
+
export { ChatUIEntry } from './entries/chat-page';
|
|
24
|
+
export { CoPilot, COPILOT_POSITION } from './entries/co-pilot';
|
|
25
|
+
export * from './hooks';
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACpE,cAAc,QAAQ,CAAA;AAGtB,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAGjD,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC9D,cAAc,SAAS,CAAA"}
|
package/dist/styles.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer base{:root{--mdk-agent-surface:var(--mdk-color-obsidian,#161514);--mdk-agent-surface-raised:var(--mdk-color-gray-900,#1a1815);--mdk-agent-border:var(--mdk-color-white-alpha-024,#ffffff24);--mdk-agent-border-strong:var(--mdk-color-white-alpha-04,#ffffff40);--mdk-agent-text:var(--mdk-color-text-secondary,#ffffffd9);--mdk-agent-text-muted:var(--mdk-color-gray-400,#8e8e8e);--mdk-agent-accent:var(--mdk-color-primary,#f7931a);--mdk-agent-accent-contrast:var(--mdk-color-dark-black,#10100f);--mdk-agent-success:var(--mdk-color-brick-green,#34c759);--mdk-agent-danger:var(--mdk-color-brick-red,#ff3b30);--mdk-agent-panel-width:420px;--mdk-agent-panel-height:640px;--mdk-agent-panel-inset:24px;--mdk-agent-radius:var(--mdk-radius,0px);--mdk-agent-font:var(--font-mono,ui-monospace, "SF Mono", monospace);--mdk-agent-z:900}}@layer mdk{.mdk-agent-root{bottom:var(--mdk-agent-panel-inset);z-index:var(--mdk-agent-z);font-family:var(--mdk-agent-font);position:fixed}.mdk-agent-root--bottom-right{right:var(--mdk-agent-panel-inset)}.mdk-agent-root--bottom-left{left:var(--mdk-agent-panel-inset)}.mdk-agent-fab{background:var(--mdk-agent-accent);width:48px;height:48px;color:var(--mdk-agent-accent-contrast);cursor:pointer;clip-path:polygon(25% 0,100% 0,100% 75%,75% 100%,0 100%,0 25%);border:none;justify-content:center;align-items:center;padding:0;display:flex}.mdk-agent-fab:hover{background:var(--mdk-color-primary-button-hover,#f8a348)}.mdk-agent-fab:focus-visible{box-shadow:inset 0 0 0 2px var(--mdk-agent-accent-contrast);outline:none}.mdk-agent-panel{border:1px solid var(--mdk-agent-border);border-radius:var(--mdk-agent-radius);background:var(--mdk-agent-surface);min-height:0;color:var(--mdk-agent-text);font-family:var(--mdk-agent-font);flex-direction:column;font-size:13px;line-height:19px;display:flex}.mdk-agent-panel--docked{width:var(--mdk-agent-panel-width);height:var(--mdk-agent-panel-height);max-width:calc(100vw - var(--mdk-agent-panel-inset) * 2);max-height:calc(100vh - var(--mdk-agent-panel-inset) * 2);box-shadow:0 18px 48px #0000008c}.mdk-agent-panel--page{width:100%;height:100%;min-height:480px}.mdk-agent-header{border-bottom:1px solid var(--mdk-agent-border);justify-content:space-between;align-items:flex-start;gap:12px;padding:10px 12px 10px 16px;display:flex}.mdk-agent-header__titles{flex-direction:column;gap:4px;min-width:0;display:flex}.mdk-agent-header__title{color:var(--mdk-color-white,#fff);align-items:center;gap:4px;margin:0;font-size:15px;font-weight:600;line-height:20px;display:flex}.mdk-agent-header__back{margin-left:-8px}.mdk-agent-header__status{color:var(--mdk-agent-text-muted);margin:0;font-size:11px;line-height:13px}.mdk-agent-header__actions{flex:none;align-items:center;gap:2px;display:flex}.mdk-agent-header__actions button,.mdk-agent-header__back{width:28px;height:28px;color:var(--mdk-agent-text-muted);background:0 0;border:none;padding:0}.mdk-agent-header__actions button:hover:not(:disabled),.mdk-agent-header__back:hover:not(:disabled){background:var(--mdk-agent-surface-raised);color:var(--mdk-color-white,#fff)}.mdk-agent-header__actions button:disabled,.mdk-agent-header__back:disabled{opacity:.4}.mdk-agent-header__actions button svg,.mdk-agent-header__back svg{width:16px;height:16px}.mdk-agent-messages{overscroll-behavior:contain;flex-direction:column;flex:auto;gap:20px;min-height:0;padding:16px;display:flex;overflow-y:auto}.mdk-agent-messages__empty{color:var(--mdk-agent-text-muted);text-align:center;margin:auto 0}.mdk-agent-message{flex-direction:column;gap:6px;min-width:0;display:flex}.mdk-agent-message__role{color:var(--mdk-agent-text-muted);letter-spacing:.08em;text-transform:uppercase;margin:0;font-size:10px}.mdk-agent-message__dot{background:var(--mdk-agent-accent);width:6px;height:6px;margin-right:6px;display:inline-block}.mdk-agent-message__bubble{border:1px solid var(--mdk-agent-border-strong);border-radius:var(--mdk-agent-radius);white-space:pre-wrap;overflow-wrap:anywhere;padding:9px 12px}.mdk-agent-message__tools{flex-wrap:wrap;gap:6px;display:flex}.mdk-agent-message__intent{margin:0}.mdk-agent-message__error{color:var(--mdk-agent-danger);align-items:baseline;gap:8px;margin:0;display:flex}.mdk-agent-message__retry{color:inherit;font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:none;flex:none;padding:0;text-decoration:underline}.mdk-agent-message__note{color:var(--mdk-agent-text-muted);margin:0;font-size:11px}.mdk-agent-message--user{align-items:flex-end}.mdk-agent-message--user .mdk-agent-message__role,.mdk-agent-message--user .mdk-agent-message__bubble{max-width:85%}.mdk-agent-tool-chip{border:1px solid var(--mdk-agent-border-strong);border-radius:var(--mdk-agent-radius);color:var(--mdk-agent-text-muted);align-items:center;gap:6px;padding:3px 8px;font-size:11px;line-height:13px;display:inline-flex}.mdk-agent-tool-chip__icon:empty{display:none}.mdk-agent-tool-chip__icon{display:inline-flex}.mdk-agent-tool-chip--ok{color:var(--mdk-agent-success);border-color:color-mix(in srgb, var(--mdk-agent-success) 45%, transparent)}.mdk-agent-tool-chip--running,.mdk-agent-tool-chip--awaiting-approval{color:var(--mdk-agent-accent);border-color:color-mix(in srgb, var(--mdk-agent-accent) 45%, transparent)}.mdk-agent-tool-chip--rejected{color:var(--mdk-agent-text-muted);border-color:var(--mdk-agent-border-strong);text-decoration:line-through}.mdk-agent-tool-chip--error{color:var(--mdk-agent-danger);border-color:color-mix(in srgb, var(--mdk-agent-danger) 45%, transparent)}.mdk-agent-tool-chip--interrupted{color:var(--mdk-agent-text-muted);border-color:var(--mdk-agent-border-strong);border-style:dashed}.mdk-agent-system{border-top:1px dashed var(--mdk-agent-border);color:var(--mdk-agent-text-muted);text-align:center;margin:0;padding:6px 0;font-size:11px}.mdk-agent-markdown{overflow-wrap:anywhere;min-width:0}.mdk-agent-markdown--streaming{white-space:pre-wrap}.mdk-agent-markdown>:first-child{margin-top:0}.mdk-agent-markdown>:last-child{margin-bottom:0}.mdk-agent-markdown p,.mdk-agent-markdown ul,.mdk-agent-markdown ol,.mdk-agent-markdown pre,.mdk-agent-markdown table,.mdk-agent-markdown blockquote,.mdk-agent-markdown hr,.mdk-agent-markdown .mdk-agent-code{margin:0 0 10px}.mdk-agent-markdown ul,.mdk-agent-markdown ol{padding-left:20px}.mdk-agent-markdown h1,.mdk-agent-markdown h2,.mdk-agent-markdown h3,.mdk-agent-markdown h4,.mdk-agent-markdown h5,.mdk-agent-markdown h6{margin:14px 0 6px;font-weight:600;line-height:1.3}.mdk-agent-markdown h1{font-size:15px}.mdk-agent-markdown h2{font-size:14px}.mdk-agent-markdown h3,.mdk-agent-markdown h4,.mdk-agent-markdown h5,.mdk-agent-markdown h6{font-size:13px}.mdk-agent-markdown blockquote{border-left:2px solid var(--mdk-agent-border-strong);color:var(--mdk-agent-text-muted);padding-left:10px}.mdk-agent-markdown hr{border:none;border-top:1px solid var(--mdk-agent-border);height:0}.mdk-agent-markdown img{max-width:100%;height:auto}.mdk-agent-markdown code{background:var(--mdk-agent-surface-raised);padding:1px 4px;font-size:12px}.mdk-agent-markdown pre{background:var(--mdk-agent-surface-raised);border:1px solid var(--mdk-agent-border);padding:10px;overflow-x:auto}.mdk-agent-markdown pre code{background:0 0;padding:0}.mdk-agent-markdown table{border-collapse:collapse;width:max-content;max-width:100%;display:block;overflow-x:auto}.mdk-agent-markdown th,.mdk-agent-markdown td{text-align:left;padding:4px 10px 4px 0}.mdk-agent-markdown th{color:var(--mdk-agent-text-muted);font-weight:600}.mdk-agent-markdown li:has(>input[type=checkbox]){margin-left:-20px;list-style:none}.mdk-agent-markdown input[type=checkbox]{vertical-align:baseline;accent-color:var(--mdk-agent-accent);margin-right:6px}.mdk-agent-markdown .footnotes{border-top:1px solid var(--mdk-agent-border);color:var(--mdk-agent-text-muted);margin-top:12px;padding-top:6px;font-size:11px}.mdk-agent-markdown .footnotes h2{clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}.mdk-agent-markdown a{color:var(--mdk-agent-accent)}.mdk-agent-markdown__more{color:var(--mdk-agent-accent);font:inherit;cursor:pointer;background:0 0;border:none;align-self:flex-start;padding:0;font-size:11px;text-decoration:underline}.mdk-agent-code{position:relative}.mdk-agent-code pre{margin:0}.mdk-agent-code__copy{border:1px solid var(--mdk-agent-border-strong);background:var(--mdk-agent-surface);color:var(--mdk-agent-text-muted);font:inherit;cursor:pointer;opacity:0;padding:2px 6px;font-size:10px;position:absolute;top:4px;right:4px}.mdk-agent-code:hover .mdk-agent-code__copy,.mdk-agent-code__copy:focus-visible{opacity:1}.mdk-agent-markdown pre code.hljs .hljs-keyword,.mdk-agent-markdown pre code.hljs .hljs-built_in,.mdk-agent-markdown pre code.hljs .hljs-section{color:var(--mdk-agent-accent)}.mdk-agent-markdown pre code.hljs .hljs-string,.mdk-agent-markdown pre code.hljs .hljs-symbol{color:var(--mdk-agent-success)}.mdk-agent-markdown pre code.hljs .hljs-attr,.mdk-agent-markdown pre code.hljs .hljs-attribute{color:color-mix(in srgb, var(--mdk-agent-accent) 60%, var(--mdk-agent-text))}.mdk-agent-markdown pre code.hljs .hljs-number,.mdk-agent-markdown pre code.hljs .hljs-literal,.mdk-agent-markdown pre code.hljs .hljs-bullet{color:color-mix(in srgb, var(--mdk-agent-success) 55%, var(--mdk-agent-text))}.mdk-agent-markdown pre code.hljs .hljs-variable,.mdk-agent-markdown pre code.hljs .hljs-template-variable,.mdk-agent-markdown pre code.hljs .hljs-meta{color:var(--mdk-agent-text)}.mdk-agent-markdown pre code.hljs .hljs-comment,.mdk-agent-markdown pre code.hljs .hljs-quote{color:var(--mdk-agent-text-muted);font-style:italic}.mdk-agent-no-tools{color:var(--mdk-agent-text-muted);letter-spacing:0;text-transform:none;opacity:.75;align-items:center;gap:4px;margin-left:8px;display:inline-flex}.mdk-agent-no-tools svg{flex:none}.mdk-agent-leaked{border:1px dashed color-mix(in srgb, var(--mdk-agent-accent) 55%, transparent);border-radius:var(--mdk-agent-radius);padding:10px 12px}.mdk-agent-leaked__title{color:var(--mdk-agent-accent);margin:0 0 4px}.mdk-agent-leaked__body{color:var(--mdk-agent-text-muted);margin:0}.mdk-agent-leaked__tool{color:var(--mdk-agent-text)}.mdk-agent-approval{border:1px dashed color-mix(in srgb, var(--mdk-agent-accent) 60%, transparent);border-radius:var(--mdk-agent-radius);background:color-mix(in srgb, var(--mdk-agent-accent) 6%, var(--mdk-agent-surface));padding:12px 14px 14px}.mdk-agent-approval__title{color:var(--mdk-agent-accent);letter-spacing:.08em;text-transform:uppercase;margin:0 0 12px;font-size:10px;font-weight:600}.mdk-agent-approval__details{margin:0 0 14px}.mdk-agent-approval__row{align-items:baseline;gap:12px;display:flex}.mdk-agent-approval__row+.mdk-agent-approval__row{margin-top:6px}.mdk-agent-approval__label{width:90px;color:var(--mdk-agent-text-muted);text-transform:capitalize;flex:none;font-size:11px}.mdk-agent-approval__value{overflow-wrap:anywhere;min-width:0;margin:0}.mdk-agent-approval__actions{justify-content:flex-end;gap:8px;display:flex}.mdk-agent-approval__actions button:first-child{border:1px solid var(--mdk-agent-border-strong);color:var(--mdk-agent-text);background:0 0}.mdk-agent-approval__actions button:first-child:hover:not(:disabled){border-color:var(--mdk-agent-danger);color:var(--mdk-agent-danger)}.mdk-agent-composer{border-top:1px solid var(--mdk-agent-border);flex:none;align-items:flex-end;gap:8px;padding:12px;display:flex}.mdk-agent-composer__input{border:1px solid var(--mdk-agent-border-strong);border-radius:var(--mdk-agent-radius);min-width:0;color:var(--mdk-agent-text);resize:none;background:0 0;flex:auto;padding:10px 12px;font-family:inherit;font-size:13px;line-height:19px}.mdk-agent-composer__input::placeholder{color:var(--mdk-agent-text-muted)}.mdk-agent-composer__input:focus-visible{border-color:var(--mdk-agent-accent);outline:none}.mdk-agent-composer__input:disabled{cursor:not-allowed;opacity:.5}.mdk-agent-composer__send{flex:none;width:40px;height:40px;padding:0}.mdk-agent-conversations{flex-direction:column;flex:auto;min-height:0;display:flex}.mdk-agent-conversations__scroll{overscroll-behavior:contain;flex-direction:column;flex:auto;min-height:0;display:flex;overflow-y:auto}.mdk-agent-conversations__empty{color:var(--mdk-agent-text-muted);text-align:center;margin:auto 0}.mdk-agent-conversations__row{border-bottom:1px solid var(--mdk-agent-border);align-items:center;gap:12px;padding:12px 16px;display:flex}.mdk-agent-conversations__row:hover{background:var(--mdk-agent-surface-raised)}.mdk-agent-conversations__row--active{background:var(--mdk-agent-surface-raised);box-shadow:inset 2px 0 0 var(--mdk-agent-accent)}.mdk-agent-conversations__open{min-width:0;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;flex-direction:column;flex:auto;gap:2px;padding:0;display:flex}.mdk-agent-conversations__title{white-space:nowrap;text-overflow:ellipsis;color:var(--mdk-color-white,#fff);overflow:hidden}.mdk-agent-conversations__meta{color:var(--mdk-agent-text-muted);font-size:11px}.mdk-agent-conversations__badge{color:var(--mdk-agent-text-muted);letter-spacing:.08em;text-transform:uppercase;flex:none;align-items:center;gap:6px;font-size:10px;display:flex}.mdk-agent-conversations__badge:before{content:"";background:currentColor;width:6px;height:6px}.mdk-agent-conversations__badge--running{color:var(--mdk-agent-accent)}.mdk-agent-conversations__delete{width:24px;height:24px;color:var(--mdk-agent-text-muted);cursor:pointer;opacity:0;background:0 0;border:none;flex:none;justify-content:center;align-items:center;padding:0;display:flex}.mdk-agent-conversations__delete:hover:not(:disabled){color:var(--mdk-agent-danger)}.mdk-agent-conversations__delete:disabled{cursor:not-allowed}.mdk-agent-conversations__row:hover .mdk-agent-conversations__delete,.mdk-agent-conversations__delete:focus-visible{opacity:1}.mdk-agent-conversations__confirm{flex:none;align-items:center;gap:6px;display:flex}.mdk-agent-conversations__confirm button{border:1px solid var(--mdk-agent-border-strong);color:var(--mdk-agent-text);font:inherit;cursor:pointer;background:0 0;padding:3px 8px;font-size:11px}.mdk-agent-conversations__confirm .mdk-agent-conversations__confirm-yes{border-color:color-mix(in srgb, var(--mdk-agent-danger) 60%, transparent);color:var(--mdk-agent-danger)}.mdk-agent-conversations__footer{border-top:1px solid var(--mdk-agent-border);flex:none;padding:12px}.mdk-agent-conversations__footer button{border:1px solid var(--mdk-agent-border-strong);color:var(--mdk-agent-text);background:0 0}.mdk-agent-conversations__footer button:hover:not(:disabled){border-color:var(--mdk-agent-accent);background:var(--mdk-agent-surface-raised);color:var(--mdk-color-white,#fff)}}@layer app;
|