@agentshouse/mdruntime 0.1.0-c2aaa9c0e3ca4 → 0.1.0-c2c52158b7381
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/AGENTS.md +285 -276
- package/README.md +9 -8
- package/dist/adapter.d.ts +80 -21
- package/dist/adapter.d.ts.map +1 -1
- package/dist/attached-model.d.ts +4 -1
- package/dist/attached-model.d.ts.map +1 -1
- package/dist/attached-model.js +13 -3
- package/dist/attempt.d.ts.map +1 -1
- package/dist/attempt.js +14 -1
- package/dist/bootstrap.d.ts +3 -2
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +83 -26
- package/dist/change-set.d.ts +7 -2
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +37 -10
- package/dist/change.d.ts +31 -1
- package/dist/change.d.ts.map +1 -1
- package/dist/change.js +10 -1
- package/dist/chat/acts.d.ts +3 -4
- package/dist/chat/acts.d.ts.map +1 -1
- package/dist/chat/acts.js +10 -10
- package/dist/chat/earlier.d.ts +10 -0
- package/dist/chat/earlier.d.ts.map +1 -0
- package/dist/chat/earlier.js +54 -0
- package/dist/chat/house.d.ts +25 -0
- package/dist/chat/house.d.ts.map +1 -0
- package/dist/chat/house.js +38 -0
- package/dist/chat/input.d.ts +3 -1
- package/dist/chat/input.d.ts.map +1 -1
- package/dist/chat/input.js +11 -18
- package/dist/chat/kit.d.ts +2 -1
- package/dist/chat/kit.d.ts.map +1 -1
- package/dist/chat/kit.js +3 -3
- package/dist/chat/list.d.ts +9 -1
- package/dist/chat/list.d.ts.map +1 -1
- package/dist/chat/list.js +53 -9
- package/dist/chat/markdown.d.ts +3 -1
- package/dist/chat/markdown.d.ts.map +1 -1
- package/dist/chat/markdown.js +85 -26
- package/dist/chat/message.d.ts +1 -0
- package/dist/chat/message.d.ts.map +1 -1
- package/dist/chat/message.js +57 -12
- package/dist/chat/messages.d.ts +9 -1
- package/dist/chat/messages.d.ts.map +1 -1
- package/dist/chat/messages.js +67 -28
- package/dist/chat/name.d.ts +1 -0
- package/dist/chat/name.d.ts.map +1 -1
- package/dist/chat/name.js +1 -1
- package/dist/chat/opened.d.ts +1 -0
- package/dist/chat/opened.d.ts.map +1 -1
- package/dist/chat/opened.js +2 -0
- package/dist/chat/overlay.d.ts +1 -0
- package/dist/chat/overlay.d.ts.map +1 -1
- package/dist/chat/overlay.js +11 -5
- package/dist/chat/parts.d.ts +1 -0
- package/dist/chat/parts.d.ts.map +1 -1
- package/dist/chat/parts.js +3 -2
- package/dist/chat/pieces.d.ts +62 -0
- package/dist/chat/pieces.d.ts.map +1 -0
- package/dist/chat/pieces.js +1110 -0
- package/dist/chat/provider.d.ts +7 -2
- package/dist/chat/provider.d.ts.map +1 -1
- package/dist/chat/provider.js +129 -155
- package/dist/chat/question.d.ts +1 -1
- package/dist/chat/question.d.ts.map +1 -1
- package/dist/chat/question.js +7 -18
- package/dist/chat/ready.d.ts +5 -1
- package/dist/chat/ready.d.ts.map +1 -1
- package/dist/chat/ready.js +9 -7
- package/dist/chat/room-file.d.ts +8 -0
- package/dist/chat/room-file.d.ts.map +1 -0
- package/dist/chat/room-file.js +72 -0
- package/dist/chat/steady.d.ts +3 -0
- package/dist/chat/steady.d.ts.map +1 -0
- package/dist/chat/steady.js +26 -0
- package/dist/chat/style.d.ts.map +1 -1
- package/dist/chat/style.js +8 -4
- package/dist/chat.d.ts +3 -2
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/client.d.ts +21 -9
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +47 -8
- package/dist/collection.d.ts +21 -6
- package/dist/collection.d.ts.map +1 -1
- package/dist/collection.js +332 -40
- package/dist/connection.d.ts +39 -11
- package/dist/connection.d.ts.map +1 -1
- package/dist/connection.js +2294 -492
- package/dist/conversation.d.ts +28 -9
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +500 -165
- package/dist/digest.d.ts +7 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +113 -0
- package/dist/durability.d.ts +8 -1
- package/dist/durability.d.ts.map +1 -1
- package/dist/entry.d.ts +18 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +157 -0
- package/dist/fence.d.ts +6 -0
- package/dist/fence.d.ts.map +1 -0
- package/dist/fence.js +10 -0
- package/dist/file.d.ts +2 -10
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js +3 -120
- package/dist/host.d.ts +15 -3
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +103 -13
- package/dist/identity.d.ts +2 -0
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +6 -0
- package/dist/index.d.ts +15 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/memory.d.ts +8 -2
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +43 -12
- package/dist/model.d.ts +4 -2
- package/dist/model.d.ts.map +1 -1
- package/dist/model.js +10 -1
- package/dist/name.d.ts +4 -0
- package/dist/name.d.ts.map +1 -0
- package/dist/name.js +122 -0
- package/dist/observation.d.ts +7 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +29 -12
- package/dist/opened.d.ts +22 -0
- package/dist/opened.d.ts.map +1 -0
- package/dist/opened.js +107 -0
- package/dist/outcome.d.ts +39 -4
- package/dist/outcome.d.ts.map +1 -1
- package/dist/outcome.js +29 -0
- package/dist/overlay.d.ts +6 -4
- package/dist/overlay.d.ts.map +1 -1
- package/dist/overlay.js +229 -161
- package/dist/query.d.ts +57 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +37 -7
- package/dist/reach.d.ts +11 -4
- package/dist/reach.d.ts.map +1 -1
- package/dist/reach.js +192 -41
- package/dist/react.d.ts +8 -6
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +7 -17
- package/dist/read-side.d.ts +18 -9
- package/dist/read-side.d.ts.map +1 -1
- package/dist/read-side.js +894 -155
- package/dist/readiness.d.ts +53 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +33 -0
- package/dist/reads.d.ts +11 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +98 -0
- package/dist/recovery.d.ts +25 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +198 -0
- package/dist/refresh.d.ts +4 -4
- package/dist/refresh.d.ts.map +1 -1
- package/dist/refresh.js +46 -20
- package/dist/replica.d.ts +12 -7
- package/dist/replica.d.ts.map +1 -1
- package/dist/replica.js +151 -64
- package/dist/room-draft.d.ts +16 -2
- package/dist/room-draft.d.ts.map +1 -1
- package/dist/room-draft.js +32 -25
- package/dist/rows.d.ts +6 -13
- package/dist/rows.d.ts.map +1 -1
- package/dist/rows.js +10 -13
- package/dist/save.d.ts +52 -10
- package/dist/save.d.ts.map +1 -1
- package/dist/save.js +519 -159
- package/dist/search.d.ts +49 -6
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +242 -46
- package/dist/seed.d.ts +16 -0
- package/dist/seed.d.ts.map +1 -0
- package/dist/seed.js +75 -0
- package/dist/shared.d.ts +19 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +461 -0
- package/dist/status.d.ts +4 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/store.d.ts +61 -17
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +581 -310
- package/dist/tables.d.ts +242 -0
- package/dist/tables.d.ts.map +1 -0
- package/dist/tables.js +406 -0
- package/dist/turn.d.ts +9 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +67 -0
- package/dist/windows.d.ts +21 -0
- package/dist/windows.d.ts.map +1 -0
- package/dist/windows.js +84 -0
- package/dist/wire.d.ts +168 -32
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +56 -31
- package/package.json +10 -2
package/dist/chat/provider.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type ReactElement, type ReactNode } from 'react';
|
|
2
2
|
import type { TurnContext } from '../adapter.js';
|
|
3
3
|
import type { MdRuntimeClient } from '../client.js';
|
|
4
|
-
import type
|
|
4
|
+
import { type ChatDraft, type ConversationAgent, type ConversationEntry, type ConversationView } from '../conversation.js';
|
|
5
5
|
import { type ChatOutcome } from './acts.js';
|
|
6
|
+
import type { ChatRequest } from './house.js';
|
|
6
7
|
import { type ChatCommand, type ChatOption } from './process.js';
|
|
7
8
|
import { type ChatLone, type ChatQuestion } from './questions.js';
|
|
8
9
|
export type ChatOpened = {
|
|
@@ -21,6 +22,7 @@ export type ChatState = ChatOpened & {
|
|
|
21
22
|
readonly conversations: readonly ConversationEntry[];
|
|
22
23
|
readonly agents: readonly ConversationAgent[];
|
|
23
24
|
readonly view: ConversationView | null;
|
|
25
|
+
readonly waiting: ChatRequest | null;
|
|
24
26
|
readonly running: boolean;
|
|
25
27
|
readonly questions: readonly ChatQuestion[];
|
|
26
28
|
readonly lone: ChatLone | null;
|
|
@@ -35,10 +37,12 @@ export type ChatState = ChatOpened & {
|
|
|
35
37
|
open(conversation: string): void;
|
|
36
38
|
start(agent: string): void;
|
|
37
39
|
send(draft: ChatDraft): void;
|
|
40
|
+
attach: ((files: readonly File[]) => Promise<boolean>) | null;
|
|
38
41
|
answer(question: ChatQuestion, response: unknown): Promise<boolean>;
|
|
39
42
|
choose(option: string, value: string): Promise<boolean>;
|
|
40
43
|
stop(): Promise<boolean>;
|
|
41
44
|
kill(): Promise<boolean>;
|
|
45
|
+
retry(message: string): Promise<boolean>;
|
|
42
46
|
done(): Promise<boolean>;
|
|
43
47
|
rename(name: string): Promise<boolean>;
|
|
44
48
|
remove(): Promise<boolean>;
|
|
@@ -49,6 +53,7 @@ export type ChatProviderProps = {
|
|
|
49
53
|
readonly client: MdRuntimeClient;
|
|
50
54
|
readonly conversation?: string | null;
|
|
51
55
|
readonly agent?: string | null;
|
|
56
|
+
readonly attachTo?: string | null;
|
|
52
57
|
readonly onOpen?: (opened: ChatOpened) => void;
|
|
53
58
|
readonly children?: ReactNode;
|
|
54
59
|
};
|
|
@@ -58,6 +63,6 @@ type Scope = {
|
|
|
58
63
|
};
|
|
59
64
|
export declare function useChatScope(): Scope;
|
|
60
65
|
export declare function useChat(): ChatState;
|
|
61
|
-
export declare function ChatProvider({ client, conversation, agent, onOpen, children, }: ChatProviderProps): ReactElement;
|
|
66
|
+
export declare function ChatProvider({ client, conversation, agent, attachTo, onOpen, children, }: ChatProviderProps): ReactElement;
|
|
62
67
|
export {};
|
|
63
68
|
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/chat/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/provider.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore, } from 'react';
|
|
2
|
-
import { AssistantRuntimeProvider, createMessageQueue,
|
|
2
|
+
import { AssistantRuntimeProvider, createMessageQueue, useExternalStoreRuntime, } from '@assistant-ui/react';
|
|
3
3
|
import { attempts } from '../attempt.js';
|
|
4
|
+
import { newChat, } from '../conversation.js';
|
|
4
5
|
import { expectedList } from '../expectation.js';
|
|
5
6
|
import { chatDraftRevision } from '../identity.js';
|
|
6
7
|
import { useObserve } from '../react.js';
|
|
7
8
|
import { accepted, answeredOf, outcomeOf, sender, unanswered, } from './acts.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
9
|
+
import { CHAT_WINDOW, useEarlier } from './earlier.js';
|
|
10
|
+
import { askedBefore, chatMessages, contextOf, requestIn } from './messages.js';
|
|
11
|
+
import { useSteady } from './steady.js';
|
|
12
|
+
import { conversationChanged, conversationGone, conversationListed, deliveryRetried, optionChosen, overlay, questionAnswered, sentMessage, } from './overlay.js';
|
|
10
13
|
import { commandIn, commandsOf, optionsOf } from './process.js';
|
|
11
14
|
import { loneOf, questionsOf } from './questions.js';
|
|
12
15
|
import { record, text } from './read.js';
|
|
13
16
|
const SHARED = new WeakMap();
|
|
17
|
+
const LATEST = { limit: CHAT_WINDOW };
|
|
14
18
|
function sharedOf(client) {
|
|
15
19
|
const held = SHARED.get(client);
|
|
16
20
|
if (held !== undefined)
|
|
@@ -19,53 +23,18 @@ function sharedOf(client) {
|
|
|
19
23
|
SHARED.set(client, fresh);
|
|
20
24
|
return fresh;
|
|
21
25
|
}
|
|
22
|
-
function newChat(agent) {
|
|
23
|
-
return `new:${agent}`;
|
|
24
|
-
}
|
|
25
26
|
function ready(observed) {
|
|
26
27
|
return observed.state === 'ready' ? observed.value : null;
|
|
27
28
|
}
|
|
28
|
-
async function alike(one, other) {
|
|
29
|
-
if (one.type !== other.type || one.size !== other.size)
|
|
30
|
-
return false;
|
|
31
|
-
const [mine, theirs] = await Promise.all([one.arrayBuffer(), other.arrayBuffer()]);
|
|
32
|
-
const bytes = new Uint8Array(theirs);
|
|
33
|
-
return new Uint8Array(mine).every((byte, at) => byte === bytes[at]);
|
|
34
|
-
}
|
|
35
|
-
async function same(one, other) {
|
|
36
|
-
if (one.text !== other.text || one.files.length !== other.files.length)
|
|
37
|
-
return false;
|
|
38
|
-
const files = await Promise.all(one.files.map(async (file, at) => {
|
|
39
|
-
const twin = other.files[at];
|
|
40
|
-
return twin !== undefined && file.name === twin.name && (await alike(file.blob, twin.blob));
|
|
41
|
-
}));
|
|
42
|
-
return files.every(Boolean);
|
|
43
|
-
}
|
|
44
29
|
function turnOf(result) {
|
|
45
30
|
return accepted(result) ? text(record(result.result), 'turn') : null;
|
|
46
31
|
}
|
|
47
|
-
async function deliver(client, send, conversation, said, key,
|
|
48
|
-
const
|
|
49
|
-
const kept = chatDraftRevision();
|
|
50
|
-
noted(conversation, kept);
|
|
51
|
-
await client.chatDraft.write(conversation, said, kept);
|
|
52
|
-
const result = await send.carried('conversation.send', { conversation, key }, () => {
|
|
53
|
-
noted(conversation, null);
|
|
54
|
-
noted(conversation, kept);
|
|
55
|
-
return client.conversation.send(conversation);
|
|
56
|
-
});
|
|
57
|
-
if (typed !== null && !(await same(typed, said))) {
|
|
58
|
-
const now = (await client.conversation.read(conversation)).chatDraft;
|
|
59
|
-
if (now === null || now.revision === kept) {
|
|
60
|
-
const back = chatDraftRevision();
|
|
61
|
-
noted(conversation, back);
|
|
62
|
-
await client.chatDraft.write(conversation, typed, back);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
32
|
+
async function deliver(client, send, conversation, said, key, idle) {
|
|
33
|
+
const result = await send.numbered('conversation.send', { conversation, key }, (operation) => client.conversation.send(conversation, operation, said));
|
|
65
34
|
if (accepted(result))
|
|
66
35
|
send.expect(sentMessage(key, [conversation], said, turnOf(result)));
|
|
67
36
|
else if (!unanswered(result))
|
|
68
|
-
|
|
37
|
+
idle();
|
|
69
38
|
return result;
|
|
70
39
|
}
|
|
71
40
|
const IDLE = { busy: false, outcome: null };
|
|
@@ -122,46 +91,21 @@ function useActs(overlay, online) {
|
|
|
122
91
|
}, [overlay, online, tried]);
|
|
123
92
|
return { ...running, call, clear };
|
|
124
93
|
}
|
|
125
|
-
const
|
|
126
|
-
accept: '*',
|
|
127
|
-
add: ({ file }) => Promise.resolve({
|
|
128
|
-
id: generateId(),
|
|
129
|
-
type: 'file',
|
|
130
|
-
name: file.name,
|
|
131
|
-
contentType: file.type,
|
|
132
|
-
file,
|
|
133
|
-
status: { type: 'requires-action', reason: 'composer-send' },
|
|
134
|
-
}),
|
|
135
|
-
send: (attachment) => Promise.resolve({ ...attachment, status: { type: 'complete' }, content: [] }),
|
|
136
|
-
remove: () => Promise.resolve(),
|
|
137
|
-
};
|
|
138
|
-
function filesOf(attachments) {
|
|
139
|
-
return attachments.flatMap((one) => one.file === undefined ? [] : [{ name: one.name, blob: one.file }]);
|
|
140
|
-
}
|
|
141
|
-
function fileOf(file) {
|
|
142
|
-
return file.blob instanceof File && file.blob.name === file.name
|
|
143
|
-
? file.blob
|
|
144
|
-
: new File([file.blob], file.name, { type: file.blob.type });
|
|
145
|
-
}
|
|
94
|
+
const AS_IT_IS = (message) => message;
|
|
146
95
|
function textOf(parts) {
|
|
147
96
|
return parts.map((part) => (part.type === 'text' ? (part.text ?? '') : '')).join('');
|
|
148
97
|
}
|
|
149
98
|
function draftOf(message) {
|
|
150
|
-
return { text: textOf(message.content)
|
|
99
|
+
return { text: textOf(message.content) };
|
|
100
|
+
}
|
|
101
|
+
function linkOf(path) {
|
|
102
|
+
return `[${path.slice(path.lastIndexOf('/') + 1)}](${path})`;
|
|
151
103
|
}
|
|
152
104
|
function appended(draft) {
|
|
153
105
|
return {
|
|
154
106
|
role: 'user',
|
|
155
107
|
content: [{ type: 'text', text: draft.text }],
|
|
156
|
-
attachments:
|
|
157
|
-
id: generateId(),
|
|
158
|
-
type: 'file',
|
|
159
|
-
name: file.name,
|
|
160
|
-
contentType: file.blob.type,
|
|
161
|
-
file: fileOf(file),
|
|
162
|
-
status: { type: 'complete' },
|
|
163
|
-
content: [],
|
|
164
|
-
})),
|
|
108
|
+
attachments: [],
|
|
165
109
|
metadata: { custom: {} },
|
|
166
110
|
createdAt: new Date(),
|
|
167
111
|
parentId: null,
|
|
@@ -169,9 +113,6 @@ function appended(draft) {
|
|
|
169
113
|
runConfig: undefined,
|
|
170
114
|
};
|
|
171
115
|
}
|
|
172
|
-
function composed(state) {
|
|
173
|
-
return JSON.stringify([state.text, state.attachments.map((one) => one.id)]);
|
|
174
|
-
}
|
|
175
116
|
const ChatContext = createContext(null);
|
|
176
117
|
const ScopeContext = createContext(null);
|
|
177
118
|
export function useChatScope() {
|
|
@@ -186,7 +127,7 @@ export function useChat() {
|
|
|
186
127
|
throw new Error('useChat is called outside a ChatProvider');
|
|
187
128
|
return chat;
|
|
188
129
|
}
|
|
189
|
-
export function ChatProvider({ client, conversation = null, agent = null, onOpen, children, }) {
|
|
130
|
+
export function ChatProvider({ client, conversation = null, agent = null, attachTo = null, onOpen, children, }) {
|
|
190
131
|
const shared = sharedOf(client);
|
|
191
132
|
const asked = JSON.stringify([conversation, agent]);
|
|
192
133
|
const [followed, setFollowed] = useState(asked);
|
|
@@ -206,11 +147,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
206
147
|
}, []);
|
|
207
148
|
const listedHeld = ready(useObserve(client, 'conversations'));
|
|
208
149
|
const agentsHeld = ready(useObserve(client, 'agents'));
|
|
209
|
-
const
|
|
150
|
+
const readiness = ready(useObserve(client, 'readiness'));
|
|
210
151
|
const refusal = ready(useObserve(client, 'connection-refusal'));
|
|
211
|
-
const online =
|
|
212
|
-
const thread = open.conversation ??
|
|
213
|
-
|
|
152
|
+
const online = readiness?.connection !== 'unreachable' && refusal === null;
|
|
153
|
+
const thread = open.conversation ??
|
|
154
|
+
(open.agent === null ? null : (shared.created.get(open.agent) ?? newChat(open.agent)));
|
|
155
|
+
const observed = ready(useObserve(thread === null ? null : client, 'conversation', thread ?? '', LATEST));
|
|
156
|
+
const held = observed !== null && observed.conversation === thread ? observed : null;
|
|
157
|
+
const paged = useEarlier(client, thread, useSteady(held));
|
|
214
158
|
const version = useSyncExternalStore(shared.overlay.subscribe, shared.overlay.version);
|
|
215
159
|
useEffect(() => {
|
|
216
160
|
if (listedHeld !== null)
|
|
@@ -221,7 +165,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
221
165
|
shared.overlay.heard(held);
|
|
222
166
|
}, [shared, held, version]);
|
|
223
167
|
const conversations = useMemo(() => shared.overlay.conversations(listedHeld ?? []), [shared, listedHeld, version]);
|
|
224
|
-
const view = useMemo(() =>
|
|
168
|
+
const view = useMemo(() => (paged.view === null ? null : shared.overlay.conversation(paged.view)), [shared, paged.view, version]);
|
|
225
169
|
const agents = agentsHeld ?? [];
|
|
226
170
|
const known = useRef(agents);
|
|
227
171
|
known.current = agents;
|
|
@@ -231,6 +175,10 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
231
175
|
const lone = loneOf(questions);
|
|
232
176
|
const commands = useMemo(() => commandsOf(view), [view]);
|
|
233
177
|
const messages = useMemo(() => chatMessages(view), [view]);
|
|
178
|
+
const awaiting = useMemo(() => {
|
|
179
|
+
const held = requestIn(view);
|
|
180
|
+
return held?.waiting === true ? held.request : null;
|
|
181
|
+
}, [view]);
|
|
234
182
|
const sending = useActs(shared.overlay, online);
|
|
235
183
|
const behind = useActs(shared.overlay, online);
|
|
236
184
|
const acting = useActs(shared.overlay, online);
|
|
@@ -238,6 +186,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
238
186
|
const current = useRef(thread);
|
|
239
187
|
current.current = thread;
|
|
240
188
|
const seeding = useRef(false);
|
|
189
|
+
const mounted = useRef(true);
|
|
190
|
+
useEffect(() => {
|
|
191
|
+
mounted.current = true;
|
|
192
|
+
return () => {
|
|
193
|
+
mounted.current = false;
|
|
194
|
+
};
|
|
195
|
+
}, []);
|
|
196
|
+
const was = useRef(null);
|
|
241
197
|
const heard = useRef('');
|
|
242
198
|
const shown = useRef('');
|
|
243
199
|
const own = useRef([]);
|
|
@@ -245,7 +201,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
245
201
|
own.current = [...own.current, `${to}\u0000${revision ?? ''}`];
|
|
246
202
|
}, []);
|
|
247
203
|
const keep = useCallback((to, draft) => {
|
|
248
|
-
const revision = draft.text === ''
|
|
204
|
+
const revision = draft.text === '' ? null : chatDraftRevision();
|
|
249
205
|
noted(to, revision);
|
|
250
206
|
void (revision === null
|
|
251
207
|
? client.chatDraft.discard(to)
|
|
@@ -255,21 +211,26 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
255
211
|
heard.current = '';
|
|
256
212
|
shown.current = '';
|
|
257
213
|
own.current = own.current.filter((one) => one.startsWith(`${thread}\u0000`));
|
|
214
|
+
const created = was.current === open;
|
|
215
|
+
was.current = open;
|
|
216
|
+
if (created)
|
|
217
|
+
return;
|
|
258
218
|
sending.clear();
|
|
259
219
|
acting.clear();
|
|
260
220
|
setAgain(null);
|
|
261
221
|
}, [thread, sending.clear, acting.clear]);
|
|
262
|
-
const sendTo = (to, said, key,
|
|
263
|
-
const first = (to, said, key,
|
|
222
|
+
const sendTo = (to, said, key, idle, acts = sending) => acts.call((send) => deliver(client, send, to, said, key, idle), sentMessage(key, [to], said, null));
|
|
223
|
+
const first = (to, said, key, returning, idle) => {
|
|
264
224
|
const drafted = [newChat(to)];
|
|
265
|
-
let made = null;
|
|
266
225
|
return sending.call(async (send) => {
|
|
267
226
|
let conversation = shared.created.get(to);
|
|
268
227
|
if (conversation === undefined) {
|
|
269
228
|
const answer = await send.carried('conversation.create', { agent: to }, (operation) => client.conversation.create({ agent_id: to, operation_id: operation }));
|
|
270
229
|
if (!accepted(answer)) {
|
|
271
|
-
if (!unanswered(answer))
|
|
272
|
-
|
|
230
|
+
if (!unanswered(answer)) {
|
|
231
|
+
returning();
|
|
232
|
+
idle();
|
|
233
|
+
}
|
|
273
234
|
return answer;
|
|
274
235
|
}
|
|
275
236
|
const named = text(record(answer.result), 'conversation');
|
|
@@ -285,43 +246,34 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
285
246
|
created: new Date().toISOString(),
|
|
286
247
|
finished: null,
|
|
287
248
|
outcome: null,
|
|
249
|
+
waiting: false,
|
|
288
250
|
state: 'idle',
|
|
289
251
|
started: null,
|
|
290
252
|
}));
|
|
291
253
|
}
|
|
292
|
-
made = conversation;
|
|
293
254
|
send.draw(sentMessage(key, [...drafted, conversation], said, null));
|
|
294
|
-
const result = await deliver(client, send, conversation, said, key,
|
|
295
|
-
if (accepted(result))
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}, sentMessage(key, drafted, said, null), () => {
|
|
299
|
-
if (made === null)
|
|
300
|
-
return;
|
|
301
|
-
void client.chatDraft.discard(newChat(to));
|
|
255
|
+
const result = await deliver(client, send, conversation, said, key, idle);
|
|
256
|
+
if (!accepted(result))
|
|
257
|
+
return result;
|
|
258
|
+
shared.created.delete(to);
|
|
302
259
|
const now = opened.current;
|
|
303
|
-
if (now.conversation === null && now.agent === to)
|
|
304
|
-
go({ conversation
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const now = (await client.conversation.read(to)).chatDraft;
|
|
309
|
-
await client.chatDraft.write(to, {
|
|
310
|
-
text: now === null || now.text === '' ? one.text : `${one.text}\n${now.text}`,
|
|
311
|
-
files: [...one.files, ...(now?.files ?? [])],
|
|
312
|
-
});
|
|
260
|
+
if (mounted.current && now.conversation === null && now.agent === to) {
|
|
261
|
+
go({ conversation, agent: to });
|
|
262
|
+
}
|
|
263
|
+
return result;
|
|
264
|
+
}, sentMessage(key, drafted, said, null));
|
|
313
265
|
};
|
|
314
266
|
const sent = () => {
|
|
315
267
|
shared.sends += 1;
|
|
316
268
|
return `sent ${shared.sends}`;
|
|
317
269
|
};
|
|
318
|
-
const deliverDraft = (said,
|
|
270
|
+
const deliverDraft = (said, returning, idle) => {
|
|
319
271
|
const key = sent();
|
|
320
272
|
const { conversation: to, agent: by } = opened.current;
|
|
321
273
|
const attempt = to !== null
|
|
322
|
-
? () => void sendTo(to, said, key,
|
|
274
|
+
? () => void sendTo(to, said, key, idle)
|
|
323
275
|
: by !== null
|
|
324
|
-
? () => void first(by, said, key,
|
|
276
|
+
? () => void first(by, said, key, returning, idle)
|
|
325
277
|
: null;
|
|
326
278
|
if (attempt === null)
|
|
327
279
|
return;
|
|
@@ -349,6 +301,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
349
301
|
return Promise.resolve(false);
|
|
350
302
|
return control('conversation.setOption', { conversation_id: to, option, value }, optionChosen(to, option, value));
|
|
351
303
|
};
|
|
304
|
+
const retry = (message) => {
|
|
305
|
+
const to = opened.current.conversation;
|
|
306
|
+
if (to === null)
|
|
307
|
+
return Promise.resolve(false);
|
|
308
|
+
return control('conversation.retry', { conversation_id: to, message_id: message }, deliveryRetried(to, message));
|
|
309
|
+
};
|
|
352
310
|
const done = (to = opened.current.conversation) => to === null
|
|
353
311
|
? Promise.resolve(false)
|
|
354
312
|
: control('conversation.markDone', { conversation_id: to }, conversationChanged(to, { finished: new Date().toISOString() }, (one) => one.finished !== null));
|
|
@@ -424,7 +382,9 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
424
382
|
const aui = useExternalStoreRuntime({
|
|
425
383
|
messages,
|
|
426
384
|
isRunning: running,
|
|
427
|
-
|
|
385
|
+
hasEarlier: paged.hasEarlier,
|
|
386
|
+
onLoadEarlier: paged.loadEarlier,
|
|
387
|
+
convertMessage: AS_IT_IS,
|
|
428
388
|
queue: lined(),
|
|
429
389
|
onNew: async (message) => lined().enqueue(message),
|
|
430
390
|
onCancel: async () => {
|
|
@@ -436,12 +396,11 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
436
396
|
const said = askedBefore(view, parent);
|
|
437
397
|
if (said === null)
|
|
438
398
|
return;
|
|
439
|
-
const draft = { text: said
|
|
399
|
+
const draft = { text: said };
|
|
440
400
|
const into = thread;
|
|
441
|
-
deliverDraft(draft, () => back(draft, into));
|
|
401
|
+
deliverDraft(draft, () => back(draft, into), () => undefined);
|
|
442
402
|
},
|
|
443
403
|
adapters: {
|
|
444
|
-
attachments: ATTACHMENTS,
|
|
445
404
|
threadList: {
|
|
446
405
|
...(thread === null ? {} : { threadId: thread }),
|
|
447
406
|
threads: threads.regular,
|
|
@@ -466,15 +425,39 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
466
425
|
});
|
|
467
426
|
function back(one, into) {
|
|
468
427
|
if (current.current !== into) {
|
|
469
|
-
void
|
|
428
|
+
void client.chatDraft.prepend(into, one);
|
|
470
429
|
return;
|
|
471
430
|
}
|
|
472
431
|
const composer = aui.thread.composer;
|
|
473
432
|
const now = composer.getState().text;
|
|
474
433
|
composer.setText(now === '' ? one.text : `${one.text}\n${now}`);
|
|
475
|
-
for (const file of one.files)
|
|
476
|
-
void composer.addAttachment(fileOf(file));
|
|
477
434
|
}
|
|
435
|
+
function linked(path, into) {
|
|
436
|
+
if (current.current !== into) {
|
|
437
|
+
void client.chatDraft.prepend(into, { text: linkOf(path) });
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const composer = aui.thread.composer;
|
|
441
|
+
const now = composer.getState().text;
|
|
442
|
+
composer.setText(now === '' ? linkOf(path) : `${now}\n${linkOf(path)}`);
|
|
443
|
+
}
|
|
444
|
+
const attach = (room, files) => {
|
|
445
|
+
const into = thread;
|
|
446
|
+
if (into === null || files.length === 0)
|
|
447
|
+
return Promise.resolve(false);
|
|
448
|
+
return acting.call(async (send) => {
|
|
449
|
+
let result = { kind: 'offline' };
|
|
450
|
+
for (const file of files) {
|
|
451
|
+
result = await send.numbered('conversation.attach', { room, name: file.name }, () => client.conversation.attach(room, { name: file.name, blob: file }));
|
|
452
|
+
if (!accepted(result))
|
|
453
|
+
return result;
|
|
454
|
+
const path = text(record(result.result), 'path');
|
|
455
|
+
if (path !== null)
|
|
456
|
+
linked(path, into);
|
|
457
|
+
}
|
|
458
|
+
return result;
|
|
459
|
+
});
|
|
460
|
+
};
|
|
478
461
|
function taken(message) {
|
|
479
462
|
const said = textOf(message.content);
|
|
480
463
|
if (lone === null || commandIn(said, commands))
|
|
@@ -486,6 +469,15 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
486
469
|
const holding = (put) => (message) => {
|
|
487
470
|
if (taken(message))
|
|
488
471
|
return;
|
|
472
|
+
if (!online) {
|
|
473
|
+
const draft = draftOf(message);
|
|
474
|
+
const at = current.current;
|
|
475
|
+
deliverDraft(draft, () => {
|
|
476
|
+
if (at !== null)
|
|
477
|
+
back(draft, at);
|
|
478
|
+
}, () => undefined);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
489
481
|
const known = new Set(lanes().map((one) => one.id));
|
|
490
482
|
if (!lane.running)
|
|
491
483
|
queue.notifyIdle();
|
|
@@ -513,18 +505,14 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
513
505
|
const draft = draftOf(message);
|
|
514
506
|
const idle = () => queues.current.get(key)?.queue.notifyIdle();
|
|
515
507
|
if (key !== (current.current ?? '')) {
|
|
516
|
-
void sendTo(key, draft, sent(),
|
|
517
|
-
back(draft, key);
|
|
518
|
-
idle();
|
|
519
|
-
}, behind);
|
|
508
|
+
void sendTo(key, draft, sent(), idle, behind);
|
|
520
509
|
return;
|
|
521
510
|
}
|
|
522
511
|
const into = current.current;
|
|
523
512
|
deliverDraft(draft, () => {
|
|
524
513
|
if (into !== null)
|
|
525
514
|
back(draft, into);
|
|
526
|
-
|
|
527
|
-
});
|
|
515
|
+
}, idle);
|
|
528
516
|
};
|
|
529
517
|
const unqueue = (id) => {
|
|
530
518
|
const message = waiting.current.get(id);
|
|
@@ -537,7 +525,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
537
525
|
const message = unqueue(id);
|
|
538
526
|
if (thread === null || item === undefined)
|
|
539
527
|
return;
|
|
540
|
-
back(message === undefined ? { text: textOf(item.parts)
|
|
528
|
+
back(message === undefined ? { text: textOf(item.parts) } : draftOf(message), thread);
|
|
541
529
|
};
|
|
542
530
|
const reconcile = useRef(() => undefined);
|
|
543
531
|
reconcile.current = () => {
|
|
@@ -556,42 +544,25 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
556
544
|
}
|
|
557
545
|
own.current = own.current.filter((one) => !one.startsWith(at));
|
|
558
546
|
const composer = aui.thread.composer;
|
|
559
|
-
const
|
|
547
|
+
const typed = composer.getState().text;
|
|
560
548
|
const stored = view.chatDraft;
|
|
561
|
-
const
|
|
562
|
-
const kept = !known && (typed.text !== '' || typed.files.length > 0);
|
|
549
|
+
const kept = !known && typed !== '';
|
|
563
550
|
if (kept && stored === null) {
|
|
564
|
-
shown.current = `${at}${
|
|
565
|
-
keep(thread, typed);
|
|
551
|
+
shown.current = `${at}${typed}`;
|
|
552
|
+
keep(thread, { text: typed });
|
|
566
553
|
return;
|
|
567
554
|
}
|
|
568
555
|
const draft = kept
|
|
569
|
-
?
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
: stored;
|
|
574
|
-
if (state.text === (draft?.text ?? '') &&
|
|
575
|
-
state.attachments.length === 0 &&
|
|
576
|
-
(draft?.files.length ?? 0) === 0) {
|
|
577
|
-
shown.current = `${at}${composed(state)}`;
|
|
556
|
+
? [stored?.text ?? '', typed].filter((one) => one !== '').join('\n')
|
|
557
|
+
: (stored?.text ?? '');
|
|
558
|
+
shown.current = `${at}${draft}`;
|
|
559
|
+
if (typed === draft)
|
|
578
560
|
return;
|
|
579
|
-
}
|
|
580
561
|
seeding.current = true;
|
|
581
|
-
composer.setText(draft
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
.finally(() => {
|
|
586
|
-
seeding.current = false;
|
|
587
|
-
if (current.current !== thread)
|
|
588
|
-
return;
|
|
589
|
-
const seeded = composer.getState();
|
|
590
|
-
shown.current = `${at}${composed(seeded)}`;
|
|
591
|
-
if (kept)
|
|
592
|
-
keep(thread, { text: seeded.text, files: filesOf(seeded.attachments) });
|
|
593
|
-
reconcile.current();
|
|
594
|
-
});
|
|
562
|
+
composer.setText(draft);
|
|
563
|
+
seeding.current = false;
|
|
564
|
+
if (kept)
|
|
565
|
+
keep(thread, { text: draft });
|
|
595
566
|
};
|
|
596
567
|
useEffect(() => reconcile.current(), [aui, thread, view]);
|
|
597
568
|
useEffect(() => {
|
|
@@ -602,12 +573,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
602
573
|
return composer.subscribe(() => {
|
|
603
574
|
if (seeding.current || !heard.current.startsWith(at))
|
|
604
575
|
return;
|
|
605
|
-
const
|
|
606
|
-
const next = `${at}${
|
|
576
|
+
const typed = composer.getState().text;
|
|
577
|
+
const next = `${at}${typed}`;
|
|
607
578
|
if (next === shown.current)
|
|
608
579
|
return;
|
|
609
580
|
shown.current = next;
|
|
610
|
-
keep(thread, { text:
|
|
581
|
+
keep(thread, { text: typed });
|
|
611
582
|
});
|
|
612
583
|
}, [aui, thread, keep]);
|
|
613
584
|
const queued = lanes().map((item) => ({ id: item.id, text: textOf(item.parts) }));
|
|
@@ -616,6 +587,7 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
616
587
|
conversations,
|
|
617
588
|
agents,
|
|
618
589
|
view,
|
|
590
|
+
waiting: awaiting,
|
|
619
591
|
running,
|
|
620
592
|
questions,
|
|
621
593
|
lone,
|
|
@@ -628,10 +600,12 @@ export function ChatProvider({ client, conversation = null, agent = null, onOpen
|
|
|
628
600
|
open: openConversation,
|
|
629
601
|
start,
|
|
630
602
|
send: (draft) => lined().enqueue(appended(draft)),
|
|
603
|
+
attach: attachTo === null ? null : (files) => attach(attachTo, files),
|
|
631
604
|
answer,
|
|
632
605
|
choose,
|
|
633
606
|
stop,
|
|
634
607
|
kill,
|
|
608
|
+
retry,
|
|
635
609
|
done: () => done(),
|
|
636
610
|
rename: (name) => rename(name),
|
|
637
611
|
remove: () => remove(),
|
package/dist/chat/question.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactElement } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import type { MdRuntimeClient } from '../client.js';
|
|
3
3
|
import type { ChatQuestion } from './questions.js';
|
|
4
4
|
export declare function forgetAnswers(client: MdRuntimeClient, conversation: string, interaction?: string): Promise<void>;
|
|
5
5
|
export type ChatQuestionCardProps = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/chat/question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGhE,OAAO,
|
|
1
|
+
{"version":3,"file":"question.d.ts","sourceRoot":"","sources":["../../src/chat/question.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAwB,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAGhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAMpD,OAAO,KAAK,EAAa,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9D,wBAAsB,aAAa,CACjC,MAAM,EAAE,eAAe,EACvB,YAAY,EAAE,MAAM,EACpB,WAAW,SAAK,GACf,OAAO,CAAC,IAAI,CAAC,CAOf;AAeD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;CACjC,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAmHlF"}
|
package/dist/chat/question.js
CHANGED
|
@@ -2,41 +2,30 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
import { useContext, useState } from 'react';
|
|
3
3
|
import Check from 'lucide-react/dist/esm/icons/check.mjs';
|
|
4
4
|
import CircleHelp from 'lucide-react/dist/esm/icons/circle-help.mjs';
|
|
5
|
-
import { inTurn } from '../client.js';
|
|
6
5
|
import { useObserve } from '../react.js';
|
|
7
6
|
import { Button, Scoped } from './kit.js';
|
|
8
7
|
import { Markdown } from './markdown.js';
|
|
9
8
|
import { Linked, Undelivered } from './message.js';
|
|
10
9
|
import { useChat, useChatScope } from './provider.js';
|
|
11
10
|
import { record, text } from './read.js';
|
|
12
|
-
const TYPED = 'typed';
|
|
13
11
|
function answerKey(conversation, interaction) {
|
|
14
|
-
return `answer:${conversation}:${interaction}`;
|
|
12
|
+
return `typed:answer:${conversation}:${interaction}`;
|
|
15
13
|
}
|
|
16
|
-
function
|
|
17
|
-
return inTurn(client, async () => {
|
|
18
|
-
const held = record(await client.presentation.read());
|
|
19
|
-
const typed = update(record(held[TYPED]));
|
|
20
|
-
if (typed !== null)
|
|
21
|
-
await client.presentation.write({ ...held, [TYPED]: typed });
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
export function forgetAnswers(client, conversation, interaction = '') {
|
|
14
|
+
export async function forgetAnswers(client, conversation, interaction = '') {
|
|
25
15
|
const at = answerKey(conversation, interaction);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
});
|
|
16
|
+
const gone = Object.keys(record(await client.presentation.read())).filter((key) => interaction === '' ? key.startsWith(at) : key === at);
|
|
17
|
+
if (gone.length > 0)
|
|
18
|
+
await client.presentation.edit(Object.fromEntries(gone.map((key) => [key, null])));
|
|
30
19
|
}
|
|
31
20
|
function useTyped(client, key) {
|
|
32
21
|
const held = useObserve(client, 'presentation');
|
|
33
|
-
const kept = record(record(
|
|
22
|
+
const kept = record(record(held.state === 'ready' ? held.value : null)[key]);
|
|
34
23
|
const [local, setLocal] = useState(null);
|
|
35
24
|
return [
|
|
36
25
|
local !== null && local.key === key ? local.value : kept,
|
|
37
26
|
(next) => {
|
|
38
27
|
setLocal({ key, value: next });
|
|
39
|
-
void
|
|
28
|
+
void client.presentation.edit({ [key]: next });
|
|
40
29
|
},
|
|
41
30
|
];
|
|
42
31
|
}
|