@signalcore/ui 1.0.0-beta.1 → 1.0.0-beta.3
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/README.md +55 -22
- package/dist/AgentAbout.js +11 -4
- package/dist/AgentAbout.js.map +1 -1
- package/dist/AgentChat.d.ts +7 -1
- package/dist/AgentChat.js +154 -2
- package/dist/AgentChat.js.map +1 -1
- package/dist/AgentSpace.d.ts +12 -3
- package/dist/AgentSpace.js +53 -11
- package/dist/AgentSpace.js.map +1 -1
- package/dist/AgentTasks.js +2 -1
- package/dist/AgentTasks.js.map +1 -1
- package/dist/Threads.d.ts +73 -0
- package/dist/Threads.js +140 -0
- package/dist/Threads.js.map +1 -0
- package/dist/VoiceCall.js +1 -1
- package/dist/VoiceCall.js.map +1 -1
- package/dist/about.d.ts +34 -144
- package/dist/about.js +6 -8
- package/dist/about.js.map +1 -1
- package/dist/automation/cron.d.ts +1 -1
- package/dist/automation/cron.js.map +1 -1
- package/dist/automation/marks.js +13 -5
- package/dist/automation/marks.js.map +1 -1
- package/dist/automation/messages.d.ts +6 -0
- package/dist/automation/messages.js +7 -1
- package/dist/automation/messages.js.map +1 -1
- package/dist/automation/types.d.ts +25 -128
- package/dist/automation/types.js +36 -0
- package/dist/automation/types.js.map +1 -0
- package/dist/automation/when.d.ts +1 -1
- package/dist/automation/when.js +13 -1
- package/dist/automation/when.js.map +1 -1
- package/dist/blocks.d.ts +23 -1
- package/dist/browser.js +2 -2
- package/dist/browser.js.map +1 -1
- package/dist/call.d.ts +1 -1
- package/dist/call.js.map +1 -1
- package/dist/client.d.ts +14 -4
- package/dist/client.js +7 -2
- package/dist/client.js.map +1 -1
- package/dist/contract.d.ts +267 -0
- package/dist/credentials.js.map +1 -1
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/es.d.ts +2 -0
- package/dist/es.js +31 -4
- package/dist/es.js.map +1 -1
- package/dist/frames.d.ts +7 -1
- package/dist/frames.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +6 -4
- package/dist/kit/AudioPlayer.js +1 -1
- package/dist/kit/AudioPlayer.js.map +1 -1
- package/dist/kit/Choices.js +1 -1
- package/dist/kit/Choices.js.map +1 -1
- package/dist/kit/FileField.js +1 -1
- package/dist/kit/FileField.js.map +1 -1
- package/dist/kit/Popover.js.map +1 -1
- package/dist/kit/Tile.d.ts +1 -1
- package/dist/kit/Tile.js +1 -1
- package/dist/kit/Tile.js.map +1 -1
- package/dist/kit/messages.d.ts +13 -0
- package/dist/kit/messages.js +7 -1
- package/dist/kit/messages.js.map +1 -1
- package/dist/kit/uploads.d.ts +2 -1
- package/dist/kit/uploads.js +1 -1
- package/dist/kit/uploads.js.map +1 -1
- package/dist/kit/waveform.js.map +1 -1
- package/dist/markdown.js.map +1 -1
- package/dist/marks.js +2 -3
- package/dist/marks.js.map +1 -1
- package/dist/surface/Form.js +1 -1
- package/dist/surface/Markdown.js +1 -1
- package/dist/surface/Markdown.js.map +1 -1
- package/dist/surface/Surface.js +43 -4
- package/dist/surface/Surface.js.map +1 -1
- package/dist/surface/scope.d.ts +1 -1
- package/dist/surface/scope.js.map +1 -1
- package/dist/surface/values.js +1 -1
- package/dist/surface/values.js.map +1 -1
- package/dist/tint.d.ts +1 -1
- package/dist/tint.js +1 -1
- package/dist/tint.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.js.map +1 -1
- package/dist/useConversation.d.ts +2 -0
- package/dist/useConversation.js +16 -0
- package/dist/useConversation.js.map +1 -1
- package/dist/usePolled.js +1 -1
- package/dist/usePolled.js.map +1 -1
- package/dist/voice/webgl.js +1 -1
- package/dist/voice/webgl.js.map +1 -1
- package/dist/widget.js +17 -16
- package/package.json +1 -1
- package/src/AgentAbout.tsx +14 -3
- package/src/AgentChat.tsx +203 -1
- package/src/AgentSpace.tsx +89 -13
- package/src/AgentTasks.tsx +2 -2
- package/src/Threads.tsx +218 -0
- package/src/VoiceCall.tsx +1 -1
- package/src/about.ts +42 -144
- package/src/automation/cron.ts +1 -1
- package/src/automation/marks.tsx +13 -2
- package/src/automation/messages.ts +12 -0
- package/src/automation/types.ts +58 -118
- package/src/automation/when.ts +7 -1
- package/src/blocks.ts +25 -0
- package/src/browser.ts +4 -4
- package/src/call.ts +1 -1
- package/src/client.ts +26 -10
- package/src/contract.ts +1934 -0
- package/src/credentials.ts +2 -2
- package/src/dev.ts +1 -1
- package/src/es.ts +29 -0
- package/src/frames.ts +3 -1
- package/src/index.ts +10 -1
- package/src/kit/AudioPlayer.tsx +1 -1
- package/src/kit/Choices.tsx +1 -1
- package/src/kit/FileField.tsx +1 -1
- package/src/kit/Popover.tsx +1 -1
- package/src/kit/Tile.tsx +1 -1
- package/src/kit/messages.ts +20 -0
- package/src/kit/uploads.ts +2 -2
- package/src/kit/waveform.ts +1 -1
- package/src/markdown.ts +1 -1
- package/src/marks.tsx +3 -123
- package/src/styles.css +206 -0
- package/src/surface/Markdown.tsx +1 -1
- package/src/surface/Surface.tsx +53 -4
- package/src/surface/scope.ts +3 -1
- package/src/surface/values.ts +5 -5
- package/src/tint.ts +1 -1
- package/src/types.ts +11 -0
- package/src/useConversation.ts +10 -0
- package/src/usePolled.ts +2 -2
- package/src/voice/webgl.ts +1 -1
- package/src/widget/element.tsx +13 -4
- package/src/widget/widget.css +13 -0
package/src/Threads.tsx
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { ArrowLeftIcon, PlusIcon } from "@phosphor-icons/react";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
|
|
4
|
+
import { AgentChat, type AgentChatProps } from "./AgentChat";
|
|
5
|
+
import { classes } from "./classes";
|
|
6
|
+
import type { Client } from "./client";
|
|
7
|
+
import { Button } from "./kit/Button";
|
|
8
|
+
import type { Conversation as Thread } from "./types";
|
|
9
|
+
|
|
10
|
+
/** What the person's threads say; a host gives its own, in its language. */
|
|
11
|
+
export interface ThreadMessages {
|
|
12
|
+
/** Over the chat, to open the list; and the list's title. */
|
|
13
|
+
open: string;
|
|
14
|
+
title: string;
|
|
15
|
+
back: string;
|
|
16
|
+
/** Starts another conversation with the agent. */
|
|
17
|
+
new: string;
|
|
18
|
+
/** A thread nothing names yet. */
|
|
19
|
+
untitled: string;
|
|
20
|
+
/** Beside a thread: how many of the agent's messages are unread; that it waits on them. */
|
|
21
|
+
unread: (count: number) => string;
|
|
22
|
+
waiting: string;
|
|
23
|
+
empty: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const THREAD_MESSAGES: ThreadMessages = {
|
|
27
|
+
open: "Conversations",
|
|
28
|
+
title: "Your conversations",
|
|
29
|
+
back: "Back to the conversation",
|
|
30
|
+
new: "New conversation",
|
|
31
|
+
untitled: "New conversation",
|
|
32
|
+
unread: (count) => (count === 1 ? "1 unread message" : `${count} unread messages`),
|
|
33
|
+
waiting: "Waiting for you",
|
|
34
|
+
empty: "Nothing here yet.",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type ThreadPart =
|
|
38
|
+
| "sc-threads"
|
|
39
|
+
| "sc-threads__head"
|
|
40
|
+
| "sc-threads__title"
|
|
41
|
+
| "sc-threads__list"
|
|
42
|
+
| "sc-threads__item"
|
|
43
|
+
| "sc-threads__item--current"
|
|
44
|
+
| "sc-threads__name"
|
|
45
|
+
| "sc-threads__badge"
|
|
46
|
+
| "sc-threads__dot"
|
|
47
|
+
| "sc-threads__empty";
|
|
48
|
+
|
|
49
|
+
/** How often the person's threads are read again, for what is unread. */
|
|
50
|
+
export const THREADS_POLL_MS = 20_000;
|
|
51
|
+
|
|
52
|
+
/** The person's threads with an agent, and what of them waits on the person. */
|
|
53
|
+
export interface Unread {
|
|
54
|
+
/** Newest first; null until read, and whenever they can't be. */
|
|
55
|
+
threads: Thread[] | null;
|
|
56
|
+
/** Every unread message of the agent's, across the threads. */
|
|
57
|
+
unread: number;
|
|
58
|
+
/** Whether a thread waits on the person (a question, their yes). */
|
|
59
|
+
waiting: boolean;
|
|
60
|
+
refresh: () => Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The threads the person the client speaks for has with the agent, read now, again every
|
|
65
|
+
* `THREADS_POLL_MS`, when the page comes back into sight, and on `refresh`: what draws a dot on
|
|
66
|
+
* a launcher, a count beside a tab. `enabled` off reads nothing.
|
|
67
|
+
*/
|
|
68
|
+
export function useUnread(client: Client, agentId: string, enabled = true): Unread {
|
|
69
|
+
const [threads, setThreads] = useState<Thread[] | null>(null);
|
|
70
|
+
const live = useRef(true);
|
|
71
|
+
const refresh = useCallback(async () => {
|
|
72
|
+
try {
|
|
73
|
+
const read = await client.conversations.list(agentId);
|
|
74
|
+
if (live.current) setThreads(read);
|
|
75
|
+
} catch {
|
|
76
|
+
if (live.current) setThreads(null);
|
|
77
|
+
}
|
|
78
|
+
}, [client, agentId]);
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
live.current = true;
|
|
81
|
+
if (!enabled) return undefined;
|
|
82
|
+
void refresh();
|
|
83
|
+
const timer = setInterval(() => void refresh(), THREADS_POLL_MS);
|
|
84
|
+
const shown = () => {
|
|
85
|
+
if (document.visibilityState === "visible") void refresh();
|
|
86
|
+
};
|
|
87
|
+
document.addEventListener("visibilitychange", shown);
|
|
88
|
+
return () => {
|
|
89
|
+
live.current = false;
|
|
90
|
+
clearInterval(timer);
|
|
91
|
+
document.removeEventListener("visibilitychange", shown);
|
|
92
|
+
};
|
|
93
|
+
}, [enabled, refresh]);
|
|
94
|
+
const read = enabled ? threads : null;
|
|
95
|
+
return {
|
|
96
|
+
threads: read,
|
|
97
|
+
unread: (read ?? []).reduce((sum, thread) => sum + (thread.unread ?? 0), 0),
|
|
98
|
+
waiting: (read ?? []).some((thread) => thread.waiting_on_person === true),
|
|
99
|
+
refresh,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface ThreadsProps {
|
|
104
|
+
/** The threads, newest first (`useUnread`'s). */
|
|
105
|
+
threads: readonly Thread[];
|
|
106
|
+
/** The one open now, marked. */
|
|
107
|
+
current?: string | null | undefined;
|
|
108
|
+
onSelect: (id: string) => void;
|
|
109
|
+
/** Starts another; without it, no button for it. */
|
|
110
|
+
onNew?: (() => void) | undefined;
|
|
111
|
+
/** The way back to the open conversation; without it, none. */
|
|
112
|
+
onBack?: (() => void) | undefined;
|
|
113
|
+
messages?: Partial<ThreadMessages> | undefined;
|
|
114
|
+
classNames?: Partial<Record<ThreadPart, string>> | undefined;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The person's threads with the agent: each by its title, how many of the agent's messages in
|
|
119
|
+
* it are unread, a dot when it waits on them; the open one marked; another to start.
|
|
120
|
+
*/
|
|
121
|
+
export function Threads({
|
|
122
|
+
threads,
|
|
123
|
+
current = null,
|
|
124
|
+
onSelect,
|
|
125
|
+
onNew,
|
|
126
|
+
onBack,
|
|
127
|
+
messages,
|
|
128
|
+
classNames,
|
|
129
|
+
}: ThreadsProps) {
|
|
130
|
+
const words = { ...THREAD_MESSAGES, ...messages };
|
|
131
|
+
return (
|
|
132
|
+
<section aria-label={words.title} part="threads" className={classes(classNames, "sc-threads")}>
|
|
133
|
+
<header className={classes(classNames, "sc-threads__head")}>
|
|
134
|
+
{onBack && (
|
|
135
|
+
<Button
|
|
136
|
+
tone="ghost"
|
|
137
|
+
size="sm"
|
|
138
|
+
icon={ArrowLeftIcon}
|
|
139
|
+
aria-label={words.back}
|
|
140
|
+
title={words.back}
|
|
141
|
+
onClick={onBack}
|
|
142
|
+
/>
|
|
143
|
+
)}
|
|
144
|
+
<h3 className={classes(classNames, "sc-threads__title")}>{words.title}</h3>
|
|
145
|
+
{onNew && (
|
|
146
|
+
<Button tone="ghost" size="sm" icon={PlusIcon} onClick={onNew}>
|
|
147
|
+
{words.new}
|
|
148
|
+
</Button>
|
|
149
|
+
)}
|
|
150
|
+
</header>
|
|
151
|
+
{threads.length === 0 ? (
|
|
152
|
+
<p className={classes(classNames, "sc-threads__empty")}>{words.empty}</p>
|
|
153
|
+
) : (
|
|
154
|
+
<ul className={classes(classNames, "sc-threads__list")}>
|
|
155
|
+
{threads.map((thread) => {
|
|
156
|
+
const unread = thread.unread ?? 0;
|
|
157
|
+
const open = thread.id === current;
|
|
158
|
+
return (
|
|
159
|
+
<li key={thread.id}>
|
|
160
|
+
<button
|
|
161
|
+
type="button"
|
|
162
|
+
aria-current={open || undefined}
|
|
163
|
+
className={classes(
|
|
164
|
+
classNames,
|
|
165
|
+
"sc-threads__item",
|
|
166
|
+
...(open ? (["sc-threads__item--current"] as const) : []),
|
|
167
|
+
)}
|
|
168
|
+
onClick={() => {
|
|
169
|
+
onSelect(thread.id);
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<span className={classes(classNames, "sc-threads__name")}>
|
|
173
|
+
{thread.title ?? words.untitled}
|
|
174
|
+
</span>
|
|
175
|
+
{unread > 0 ? (
|
|
176
|
+
<span
|
|
177
|
+
aria-label={words.unread(unread)}
|
|
178
|
+
className={classes(classNames, "sc-threads__badge")}
|
|
179
|
+
>
|
|
180
|
+
{unread}
|
|
181
|
+
</span>
|
|
182
|
+
) : (
|
|
183
|
+
thread.waiting_on_person === true && (
|
|
184
|
+
<span
|
|
185
|
+
role="img"
|
|
186
|
+
aria-label={words.waiting}
|
|
187
|
+
className={classes(classNames, "sc-threads__dot")}
|
|
188
|
+
/>
|
|
189
|
+
)
|
|
190
|
+
)}
|
|
191
|
+
</button>
|
|
192
|
+
</li>
|
|
193
|
+
);
|
|
194
|
+
})}
|
|
195
|
+
</ul>
|
|
196
|
+
)}
|
|
197
|
+
</section>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* A conversation between a person and one agent, as the API reads it (`types.ts`): one name for
|
|
203
|
+
* the shape and for the component that shows one.
|
|
204
|
+
*/
|
|
205
|
+
export type Conversation = Thread;
|
|
206
|
+
|
|
207
|
+
export type ConversationProps = Omit<AgentChatProps, "conversationId"> & {
|
|
208
|
+
/** The conversation to show, by its id. */
|
|
209
|
+
id: string;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* One conversation, for a host that lays out its own threads: the chat (`AgentChat`), which reads
|
|
214
|
+
* what comes as it shows it on a person's page, so their `unread` follows.
|
|
215
|
+
*/
|
|
216
|
+
export function Conversation({ id, ...chat }: ConversationProps) {
|
|
217
|
+
return <AgentChat conversationId={id} {...chat} />;
|
|
218
|
+
}
|
package/src/VoiceCall.tsx
CHANGED
|
@@ -92,7 +92,7 @@ export const VOICE_CALL_MESSAGES: VoiceCallMessages = {
|
|
|
92
92
|
},
|
|
93
93
|
builder: {
|
|
94
94
|
title: (name) => `${name} doesn't take calls`,
|
|
95
|
-
help: "
|
|
95
|
+
help: "The builder only writes. Call one of the agents.",
|
|
96
96
|
},
|
|
97
97
|
refused: {
|
|
98
98
|
title: (name) => `${name} can't take this call`,
|
package/src/about.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Qué puede: what an agent says about itself and the facts it rests on (`GET /agents/{id}/about`,
|
|
3
3
|
* `POST /agents/{id}/describe`). The words are the model's, written from the agent's folder and
|
|
4
|
-
* stale the moment it changes; the facts are the platform's, read each time.
|
|
4
|
+
* stale the moment it changes; the facts are the platform's, read each time. Their types are the
|
|
5
|
+
* contract's (`contract.ts`).
|
|
5
6
|
*/
|
|
6
7
|
|
|
8
|
+
import type * as C from "./contract";
|
|
9
|
+
|
|
7
10
|
/** The marks the package draws (a topic's, an automation's kind, a note's tone). */
|
|
8
11
|
export const ICONS = [
|
|
9
12
|
"message",
|
|
@@ -30,89 +33,33 @@ export const ICONS = [
|
|
|
30
33
|
|
|
31
34
|
export type Icon = (typeof ICONS)[number];
|
|
32
35
|
|
|
33
|
-
/** One automation as the agent tells it: what it does then, and when. */
|
|
34
|
-
export
|
|
35
|
-
/** The automation's id. */
|
|
36
|
-
automation: string;
|
|
37
|
-
text: string;
|
|
38
|
-
/** When it runs, the way a person says it: "Cada día a las 8:00". */
|
|
39
|
-
when: string;
|
|
40
|
-
}
|
|
36
|
+
/** One automation as the agent tells it: what it does then, and when ("Cada día a las 8:00"). */
|
|
37
|
+
export type Does = C.Does;
|
|
41
38
|
|
|
42
39
|
/** What the agent says about itself: a lead, what it does, what it asks leave for. */
|
|
43
|
-
export
|
|
44
|
-
/** Two or three sentences, first person, in the owner's language. */
|
|
45
|
-
summary: string;
|
|
46
|
-
does: Does[];
|
|
47
|
-
asks: string[];
|
|
48
|
-
}
|
|
40
|
+
export type About = C.About;
|
|
49
41
|
|
|
50
|
-
export type ActionSource = "
|
|
51
|
-
|
|
52
|
-
export interface ActionFact {
|
|
53
|
-
name: string;
|
|
54
|
-
description: string;
|
|
55
|
-
source: ActionSource;
|
|
56
|
-
on: boolean;
|
|
57
|
-
needs_approval: boolean;
|
|
58
|
-
destructive: boolean;
|
|
59
|
-
/** Its input as the model gets it (JSON Schema); left out by an API from before. */
|
|
60
|
-
input_schema?: Readonly<Record<string, unknown>> | undefined;
|
|
61
|
-
}
|
|
42
|
+
export type ActionSource = C.ActionRowOut["source"];
|
|
62
43
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
/** Something the agent does on its own: at a time, when another system calls, on an event. */
|
|
66
|
-
export interface AutomationFact {
|
|
67
|
-
id: string;
|
|
68
|
-
/** Its file's name, `automations/<name>.py`: how its page is reached. */
|
|
69
|
-
name: string;
|
|
70
|
-
kind: AutomationKind;
|
|
71
|
-
title: string;
|
|
72
|
-
/** What it does, in the owner's words. */
|
|
73
|
-
summary: string;
|
|
74
|
-
/** The same words, for a reader of the older shape. */
|
|
75
|
-
say: string;
|
|
76
|
-
/** A cron line and its time zone, for one that runs at a time. */
|
|
77
|
-
schedule?: string | null | undefined;
|
|
78
|
-
timezone?: string | null | undefined;
|
|
79
|
-
/** Where another system calls it, for a webhook (a path on the API). */
|
|
80
|
-
url?: string | null | undefined;
|
|
81
|
-
/** For one on an app's event: the app (the connection's name), the event as its provider
|
|
82
|
-
* names it, and the app as its mark is drawn (`composio:gmail`, the provider's logo). */
|
|
83
|
-
app?: string | null | undefined;
|
|
84
|
-
/** The app as people write it (`Google Calendar`). */
|
|
85
|
-
app_title?: string | null | undefined;
|
|
86
|
-
event?: string | null | undefined;
|
|
87
|
-
provider?: string | undefined;
|
|
88
|
-
icon?: string | null | undefined;
|
|
89
|
-
/** Off: declared, but it doesn't run. */
|
|
90
|
-
on: boolean;
|
|
91
|
-
next_run_at?: string | null | undefined;
|
|
92
|
-
}
|
|
44
|
+
/** One of its actions: where it comes from, whether it is on and asks first, its input. */
|
|
45
|
+
export type ActionFact = C.ActionRowOut;
|
|
93
46
|
|
|
47
|
+
export type AutomationKind = C.FactAutomation["kind"];
|
|
48
|
+
|
|
49
|
+
/** Something the agent does on its own: at a time, when another system calls, on an app's event
|
|
50
|
+
* (with the app's name and mark), on a message. */
|
|
51
|
+
export type AutomationFact = C.FactAutomation;
|
|
52
|
+
|
|
53
|
+
/** Who brings an app: one of the providers, an MCP server, the business's own API. */
|
|
94
54
|
export type Provider = "arcade" | "composio" | "mcp" | "api";
|
|
95
55
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/** The app, as the provider names it (`gmail`). */
|
|
100
|
-
toolkit?: string | undefined;
|
|
101
|
-
/** The app as people write it (`Google Calendar`). */
|
|
102
|
-
title?: string | undefined;
|
|
103
|
-
/** pending · active · error · disconnected */
|
|
104
|
-
status?: string | undefined;
|
|
105
|
-
/** The provider's names of what the agent may do in it (`Gmail.SendEmail`). */
|
|
106
|
-
actions: string[];
|
|
107
|
-
/** What the provider calls each of them for people (`List Events`), when it says. */
|
|
108
|
-
titles?: Readonly<Record<string, string>> | undefined;
|
|
109
|
-
/** A URL to the app's own mark, when the provider gives one. */
|
|
110
|
-
icon?: string | null | undefined;
|
|
111
|
-
}
|
|
56
|
+
/** An app it was given: its name and mark, and its tools, with their names for people
|
|
57
|
+
* (`titles`) and as the model calls them (`called`). */
|
|
58
|
+
export type ConnectionFact = C.FactConnection;
|
|
112
59
|
|
|
113
60
|
/** An app of the agent's as people write it: its provider's name, else its alias made words. */
|
|
114
61
|
export const appTitle = (connection: ConnectionFact): string =>
|
|
115
|
-
connection.title
|
|
62
|
+
connection.title || toolName(connection.name);
|
|
116
63
|
|
|
117
64
|
/** A tool of an app as people read it: its provider's name for it, else its own made words. */
|
|
118
65
|
export const toolTitle = (connection: ConnectionFact, action: string): string =>
|
|
@@ -143,7 +90,10 @@ export function actionWords(name: string): string {
|
|
|
143
90
|
/** The longest name the model takes for a tool (`app/connections` cuts there too). */
|
|
144
91
|
const MAX_TOOL_NAME = 64;
|
|
145
92
|
|
|
146
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* `gmail` + `Gmail.SendEmail` → `gmail__Gmail_SendEmail`: the tool the model is given.
|
|
95
|
+
* @deprecated The facts say it: `ConnectionFact.called`.
|
|
96
|
+
*/
|
|
147
97
|
export const generatedName = (alias: string, action: string): string =>
|
|
148
98
|
`${alias}__${action.replace(/[^A-Za-z0-9_]/g, "_")}`.slice(0, MAX_TOOL_NAME);
|
|
149
99
|
|
|
@@ -156,7 +106,7 @@ export function appSteps(connections: readonly ConnectionFact[]): Record<string,
|
|
|
156
106
|
return Object.fromEntries(
|
|
157
107
|
connections.flatMap((connection) =>
|
|
158
108
|
connection.actions.map((action) => [
|
|
159
|
-
generatedName(connection.name, action),
|
|
109
|
+
connection.called[action] ?? generatedName(connection.name, action),
|
|
160
110
|
`${toolTitle(connection, action)} (${appTitle(connection)})`,
|
|
161
111
|
]),
|
|
162
112
|
),
|
|
@@ -165,85 +115,33 @@ export function appSteps(connections: readonly ConnectionFact[]): Record<string,
|
|
|
165
115
|
|
|
166
116
|
export type ChannelKind = "whatsapp" | "instagram" | "email" | "sms" | "web" | "phone";
|
|
167
117
|
|
|
168
|
-
export
|
|
169
|
-
kind: ChannelKind;
|
|
170
|
-
name: string;
|
|
171
|
-
status: string;
|
|
172
|
-
}
|
|
118
|
+
export type ChannelFact = C.FactChannel;
|
|
173
119
|
|
|
174
120
|
/** A file the agent can read: its own, or one of the organization's, shared with every agent. */
|
|
175
|
-
export
|
|
176
|
-
path: string;
|
|
177
|
-
size: number;
|
|
178
|
-
/** Text, Markdown, JSON, YAML or PDF, read by `search_files`; anything else is only kept. */
|
|
179
|
-
searchable: boolean;
|
|
180
|
-
/** The organization's, not the agent's own. */
|
|
181
|
-
shared: boolean;
|
|
182
|
-
}
|
|
121
|
+
export type FileFact = C.FactFile;
|
|
183
122
|
|
|
184
|
-
/** A line the agent kept with `remember
|
|
185
|
-
export
|
|
186
|
-
id: string;
|
|
187
|
-
/** The agent that keeps it; the contact it is about, when it is about one. */
|
|
188
|
-
agent_id?: string | undefined;
|
|
189
|
-
contact_id?: string | null | undefined;
|
|
190
|
-
text: string;
|
|
191
|
-
created_at: string;
|
|
192
|
-
}
|
|
123
|
+
/** A line the agent kept with `remember`: its own, or about the contact it names. */
|
|
124
|
+
export type MemoryFact = C.MemoryOut;
|
|
193
125
|
|
|
194
|
-
/** A key the agent may use: its own, or one of the organization's
|
|
195
|
-
export
|
|
196
|
-
name: string;
|
|
197
|
-
/** The hosts it may be sent to. */
|
|
198
|
-
hosts?: string[] | undefined;
|
|
199
|
-
/** The organization's, not the agent's own. */
|
|
200
|
-
shared?: boolean | undefined;
|
|
201
|
-
}
|
|
126
|
+
/** A key the agent may use: its own, or one of the organization's its access gives it. */
|
|
127
|
+
export type VaultFact = C.FactKey;
|
|
202
128
|
|
|
203
129
|
/** A table of the organization's the agent may read or write (an agenda, the clients). */
|
|
204
|
-
export
|
|
205
|
-
table: string;
|
|
206
|
-
/** Its name for people, when it has one. */
|
|
207
|
-
title?: string | null | undefined;
|
|
208
|
-
can: string[];
|
|
209
|
-
}
|
|
130
|
+
export type DataFact = C.FactTable;
|
|
210
131
|
|
|
211
|
-
export
|
|
212
|
-
agent_id: string;
|
|
213
|
-
name: string;
|
|
214
|
-
}
|
|
132
|
+
export type AskFact = C.FactAsk;
|
|
215
133
|
|
|
216
|
-
export type DeviceKind = "
|
|
134
|
+
export type DeviceKind = C.FactDevice["kind"];
|
|
217
135
|
|
|
218
|
-
export
|
|
219
|
-
kind: DeviceKind;
|
|
220
|
-
name: string;
|
|
221
|
-
status: string;
|
|
222
|
-
}
|
|
136
|
+
export type DeviceFact = C.FactDevice;
|
|
223
137
|
|
|
224
|
-
/** What the agent has, every list present from day one; one whose phase has not come is empty
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
automations: AutomationFact[];
|
|
228
|
-
connections: ConnectionFact[];
|
|
229
|
-
channels: ChannelFact[];
|
|
230
|
-
/** Its own first, then the organization's shared. */
|
|
231
|
-
files: FileFact[];
|
|
232
|
-
/** Newest first. */
|
|
233
|
-
memories: MemoryFact[];
|
|
234
|
-
vault: VaultFact[];
|
|
235
|
-
data: DataFact[];
|
|
236
|
-
asks: AskFact[];
|
|
237
|
-
devices: DeviceFact[];
|
|
238
|
-
}
|
|
138
|
+
/** What the agent has, every list present from day one; one whose phase has not come is empty:
|
|
139
|
+
* its files its own first, its memories newest first. */
|
|
140
|
+
export type Facts = C.Facts;
|
|
239
141
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
/** When the words were written; null when the folder changed since, so they are stale. */
|
|
244
|
-
about_at: string | null;
|
|
245
|
-
facts: Facts;
|
|
246
|
-
}
|
|
142
|
+
/** What it says (null until written once; `about_at` null when the folder changed since, so the
|
|
143
|
+
* words are stale) and the facts. */
|
|
144
|
+
export type AboutOut = C.AboutOut;
|
|
247
145
|
|
|
248
146
|
/**
|
|
249
147
|
* What the panel lists of the facts beside what the agent does on its own, gathered into a few
|
package/src/automation/cron.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A schedule's cron line, read into what it fires at: the moments of a day (
|
|
2
|
+
* A schedule's cron line, read into what it fires at: the moments of a day (the agents' day, an
|
|
3
3
|
* automation's next runs) and the sentence that says it (`whenOf`). Five fields (minute, hour,
|
|
4
4
|
* day of the month, month, day of the week) with `*`, lists, ranges, steps and English names, as
|
|
5
5
|
* the API's croniter reads them; anything past that is not read (null).
|
package/src/automation/marks.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ArrowBendDownRightIcon,
|
|
2
3
|
BellIcon,
|
|
3
4
|
BrainIcon,
|
|
4
5
|
ChatCircleIcon,
|
|
@@ -8,7 +9,9 @@ import {
|
|
|
8
9
|
FileTextIcon,
|
|
9
10
|
FlaskIcon,
|
|
10
11
|
GlobeIcon,
|
|
12
|
+
HandTapIcon,
|
|
11
13
|
LightningIcon,
|
|
14
|
+
PlugsConnectedIcon,
|
|
12
15
|
SparkleIcon,
|
|
13
16
|
TableIcon,
|
|
14
17
|
WebhooksLogoIcon,
|
|
@@ -51,9 +54,13 @@ export function AppMark({
|
|
|
51
54
|
const KINDS: Readonly<Record<Exclude<Trigger["kind"], "event">, Icon>> = {
|
|
52
55
|
schedule: ClockIcon,
|
|
53
56
|
webhook: WebhooksLogoIcon,
|
|
57
|
+
platform: ChatCircleIcon,
|
|
58
|
+
manual: HandTapIcon,
|
|
59
|
+
after: ArrowBendDownRightIcon,
|
|
54
60
|
};
|
|
55
61
|
|
|
56
|
-
/** What starts an automation, as a mark: a clock, a webhook, the app whose event it
|
|
62
|
+
/** What starts an automation, as a mark: a clock, a webhook, a message, the app whose event it
|
|
63
|
+
* waits for. */
|
|
57
64
|
export function TriggerMark({
|
|
58
65
|
trigger,
|
|
59
66
|
size,
|
|
@@ -69,12 +76,16 @@ export function TriggerMark({
|
|
|
69
76
|
return <AppMark name={name} icon={trigger.icon} size={size} apps={apps} />;
|
|
70
77
|
}
|
|
71
78
|
|
|
72
|
-
/** What started a run: its time, a call, its app's event, a chat with the agent, a
|
|
79
|
+
/** What started a run: its time, a call, its app's event, a message, a chat with the agent, a
|
|
80
|
+
* test. */
|
|
73
81
|
const BY: Readonly<Record<Exclude<RunBy, "event">, Icon>> = {
|
|
74
82
|
schedule: ClockIcon,
|
|
75
83
|
webhook: WebhooksLogoIcon,
|
|
84
|
+
platform: ChatCircleIcon,
|
|
76
85
|
agent: ChatCircleIcon,
|
|
77
86
|
test: FlaskIcon,
|
|
87
|
+
api: PlugsConnectedIcon,
|
|
88
|
+
after: ArrowBendDownRightIcon,
|
|
78
89
|
};
|
|
79
90
|
|
|
80
91
|
export function ByMark({
|
|
@@ -66,6 +66,12 @@ export interface AutomationMessages {
|
|
|
66
66
|
/** What another kind of trigger waits for. */
|
|
67
67
|
webhook: string;
|
|
68
68
|
event: (app: string | null, event: string | null) => string;
|
|
69
|
+
/** One of the platform's events: a contact's message stored on a channel. */
|
|
70
|
+
platform: string;
|
|
71
|
+
/** Only started by hand: the agent, the business's app, a button. */
|
|
72
|
+
manual: string;
|
|
73
|
+
/** When another of the agent's automations ends well, by its name. */
|
|
74
|
+
after: (automation: string | null) => string;
|
|
69
75
|
/** When it runs next, after when it runs: the day, and the time when the line doesn't say it. */
|
|
70
76
|
next: (day: DayRef, time: string | null) => string;
|
|
71
77
|
/** How it stands, on its pill. */
|
|
@@ -124,6 +130,9 @@ export const AUTOMATION_MESSAGES: AutomationMessages = {
|
|
|
124
130
|
on: (often, days) => `${often}, ${days.charAt(0).toLowerCase()}${days.slice(1)}`,
|
|
125
131
|
custom: "On a schedule of its own",
|
|
126
132
|
webhook: "When another system calls it",
|
|
133
|
+
platform: "When a message arrives",
|
|
134
|
+
manual: "When someone starts it",
|
|
135
|
+
after: (automation) => (automation ? `After “${automation}”` : "After another automation"),
|
|
127
136
|
event: (app, event) =>
|
|
128
137
|
event ? `When ${event} in ${app ?? "an app"}` : `On an event in ${app ?? "an app"}`,
|
|
129
138
|
next: (day, time) => {
|
|
@@ -171,8 +180,11 @@ export const AUTOMATION_MESSAGES: AutomationMessages = {
|
|
|
171
180
|
schedule: "scheduled",
|
|
172
181
|
webhook: "webhook",
|
|
173
182
|
event: app ? `${app} event` : "event",
|
|
183
|
+
platform: "a message",
|
|
174
184
|
agent: "you asked in the chat",
|
|
175
185
|
test: "test",
|
|
186
|
+
api: "your app",
|
|
187
|
+
after: "after another",
|
|
176
188
|
})[by],
|
|
177
189
|
statuses: {
|
|
178
190
|
running: "Running",
|