@invergent/agent-chat-react 2.17.2 → 2.17.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/dist/index.cjs +75 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -1
- package/dist/index.d.ts +23 -1
- package/dist/index.js +76 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -962,7 +962,8 @@ interface AgentChatAdapter {
|
|
|
962
962
|
}): Promise<AgentChatThreadRow>;
|
|
963
963
|
/**
|
|
964
964
|
* Start a thread the master proposed for the user's computer, in Surogate Desktop only: in a
|
|
965
|
-
* folder its user confirms in the desktop's own sheet, which names the project and *title
|
|
965
|
+
* folder its user confirms in the desktop's own sheet, which names the project and *title*; or,
|
|
966
|
+
* in a project made on this computer, at once in a copy of the project's folder, asking nothing.
|
|
966
967
|
*/
|
|
967
968
|
startLocalThread?(input: {
|
|
968
969
|
projectId: string;
|
|
@@ -970,6 +971,19 @@ interface AgentChatAdapter {
|
|
|
970
971
|
key: string;
|
|
971
972
|
title: string;
|
|
972
973
|
}): Promise<AgentChatThreadRow>;
|
|
974
|
+
/**
|
|
975
|
+
* The id of the computer this client runs on, as Surogate Desktop added it to the agent; null in
|
|
976
|
+
* a browser, and where the app has added none. A project made on a computer starts its threads there alone.
|
|
977
|
+
*/
|
|
978
|
+
getLocalDeviceId?(): Promise<string | null>;
|
|
979
|
+
/**
|
|
980
|
+
* Whether a project made on a computer can no longer reach its folder there: that computer was removed from the
|
|
981
|
+
* user's computers or its access revoked, or it could not set the folder up. Its user then uses another computer
|
|
982
|
+
* for the project, in Surogate Desktop. Another adapter says none is.
|
|
983
|
+
*/
|
|
984
|
+
isProjectFolderLost?(input: {
|
|
985
|
+
projectId: string;
|
|
986
|
+
}): Promise<boolean>;
|
|
973
987
|
getArtifact(input: {
|
|
974
988
|
sessionId: string;
|
|
975
989
|
artifactId: string;
|
|
@@ -1435,6 +1449,14 @@ interface AgentChatAdapterContextValue {
|
|
|
1435
1449
|
onOpenSession?: (sessionId: string) => void;
|
|
1436
1450
|
/** The project whose master this conversation is, or null: its proposal cards start threads. */
|
|
1437
1451
|
projectId?: string | null;
|
|
1452
|
+
/**
|
|
1453
|
+
* The computer that project works on, by the name the server stamped, for a project made in
|
|
1454
|
+
* Surogate Desktop; null for a project in the cloud. Its cards start their threads there alone.
|
|
1455
|
+
*/
|
|
1456
|
+
projectComputer?: {
|
|
1457
|
+
deviceId: string;
|
|
1458
|
+
name: string;
|
|
1459
|
+
} | null;
|
|
1438
1460
|
/** That project's threads, live, by id: what their cards show. */
|
|
1439
1461
|
threadRows?: Record<string, AgentChatThreadRow>;
|
|
1440
1462
|
/** A chat the host only reads (AgentChat's ``disabled``): nothing in it answers the agent's questions. */
|
package/dist/index.d.ts
CHANGED
|
@@ -962,7 +962,8 @@ interface AgentChatAdapter {
|
|
|
962
962
|
}): Promise<AgentChatThreadRow>;
|
|
963
963
|
/**
|
|
964
964
|
* Start a thread the master proposed for the user's computer, in Surogate Desktop only: in a
|
|
965
|
-
* folder its user confirms in the desktop's own sheet, which names the project and *title
|
|
965
|
+
* folder its user confirms in the desktop's own sheet, which names the project and *title*; or,
|
|
966
|
+
* in a project made on this computer, at once in a copy of the project's folder, asking nothing.
|
|
966
967
|
*/
|
|
967
968
|
startLocalThread?(input: {
|
|
968
969
|
projectId: string;
|
|
@@ -970,6 +971,19 @@ interface AgentChatAdapter {
|
|
|
970
971
|
key: string;
|
|
971
972
|
title: string;
|
|
972
973
|
}): Promise<AgentChatThreadRow>;
|
|
974
|
+
/**
|
|
975
|
+
* The id of the computer this client runs on, as Surogate Desktop added it to the agent; null in
|
|
976
|
+
* a browser, and where the app has added none. A project made on a computer starts its threads there alone.
|
|
977
|
+
*/
|
|
978
|
+
getLocalDeviceId?(): Promise<string | null>;
|
|
979
|
+
/**
|
|
980
|
+
* Whether a project made on a computer can no longer reach its folder there: that computer was removed from the
|
|
981
|
+
* user's computers or its access revoked, or it could not set the folder up. Its user then uses another computer
|
|
982
|
+
* for the project, in Surogate Desktop. Another adapter says none is.
|
|
983
|
+
*/
|
|
984
|
+
isProjectFolderLost?(input: {
|
|
985
|
+
projectId: string;
|
|
986
|
+
}): Promise<boolean>;
|
|
973
987
|
getArtifact(input: {
|
|
974
988
|
sessionId: string;
|
|
975
989
|
artifactId: string;
|
|
@@ -1435,6 +1449,14 @@ interface AgentChatAdapterContextValue {
|
|
|
1435
1449
|
onOpenSession?: (sessionId: string) => void;
|
|
1436
1450
|
/** The project whose master this conversation is, or null: its proposal cards start threads. */
|
|
1437
1451
|
projectId?: string | null;
|
|
1452
|
+
/**
|
|
1453
|
+
* The computer that project works on, by the name the server stamped, for a project made in
|
|
1454
|
+
* Surogate Desktop; null for a project in the cloud. Its cards start their threads there alone.
|
|
1455
|
+
*/
|
|
1456
|
+
projectComputer?: {
|
|
1457
|
+
deviceId: string;
|
|
1458
|
+
name: string;
|
|
1459
|
+
} | null;
|
|
1438
1460
|
/** That project's threads, live, by id: what their cards show. */
|
|
1439
1461
|
threadRows?: Record<string, AgentChatThreadRow>;
|
|
1440
1462
|
/** A chat the host only reads (AgentChat's ``disabled``): nothing in it answers the agent's questions. */
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { cjk } from '@streamdown/cjk';
|
|
|
9
9
|
import { code } from '@streamdown/code';
|
|
10
10
|
import { math } from '@streamdown/math';
|
|
11
11
|
import { mermaid } from '@streamdown/mermaid';
|
|
12
|
-
import { Streamdown } from 'streamdown';
|
|
12
|
+
import { defaultRehypePlugins, Streamdown } from 'streamdown';
|
|
13
13
|
import { useControllableState } from '@radix-ui/react-use-controllable-state';
|
|
14
14
|
import { ThinkingOrb } from 'thinking-orbs';
|
|
15
15
|
import { createHighlighter } from 'shiki';
|
|
@@ -1134,6 +1134,11 @@ function TooltipContent({
|
|
|
1134
1134
|
}
|
|
1135
1135
|
) });
|
|
1136
1136
|
}
|
|
1137
|
+
var streamdownRehypePlugins = Object.entries(defaultRehypePlugins).map(([name, plugin]) => {
|
|
1138
|
+
if (name !== "harden" || !Array.isArray(plugin)) return plugin;
|
|
1139
|
+
const [harden, options] = plugin;
|
|
1140
|
+
return [harden, { ...options, linkBlockPolicy: "text-only" }];
|
|
1141
|
+
});
|
|
1137
1142
|
|
|
1138
1143
|
// src/lib/oauth-popup.ts
|
|
1139
1144
|
function openOAuthPopup(url) {
|
|
@@ -1253,6 +1258,7 @@ var MessageResponse = memo(
|
|
|
1253
1258
|
className
|
|
1254
1259
|
),
|
|
1255
1260
|
plugins: streamdownPlugins,
|
|
1261
|
+
rehypePlugins: streamdownRehypePlugins,
|
|
1256
1262
|
components: streamdownComponents,
|
|
1257
1263
|
...props
|
|
1258
1264
|
}
|
|
@@ -1451,6 +1457,7 @@ var ReasoningContent = memo(
|
|
|
1451
1457
|
{
|
|
1452
1458
|
className: "[&_ol]:list-outside [&_ol]:pl-5 [&_ul]:list-outside [&_ul]:pl-5",
|
|
1453
1459
|
plugins: streamdownPlugins2,
|
|
1460
|
+
rehypePlugins: streamdownRehypePlugins,
|
|
1454
1461
|
children
|
|
1455
1462
|
}
|
|
1456
1463
|
)
|
|
@@ -11959,6 +11966,36 @@ function useCardStarts(adapter) {
|
|
|
11959
11966
|
);
|
|
11960
11967
|
return cardStarts.get(adapter) ?? /* @__PURE__ */ new Map();
|
|
11961
11968
|
}
|
|
11969
|
+
function useLocalDevice(adapter, wanted) {
|
|
11970
|
+
const [found, setFound] = useState(null);
|
|
11971
|
+
useEffect(() => {
|
|
11972
|
+
if (!wanted || !adapter.getLocalDeviceId) return;
|
|
11973
|
+
let live = true;
|
|
11974
|
+
void adapter.getLocalDeviceId().catch(() => null).then((id) => {
|
|
11975
|
+
if (live) setFound({ adapter, id });
|
|
11976
|
+
});
|
|
11977
|
+
return () => {
|
|
11978
|
+
live = false;
|
|
11979
|
+
};
|
|
11980
|
+
}, [adapter, wanted]);
|
|
11981
|
+
if (!adapter.getLocalDeviceId) return null;
|
|
11982
|
+
return found?.adapter === adapter ? found.id : void 0;
|
|
11983
|
+
}
|
|
11984
|
+
function useFolderLost(adapter, projectId, wanted) {
|
|
11985
|
+
const [found, setFound] = useState(null);
|
|
11986
|
+
useEffect(() => {
|
|
11987
|
+
if (!wanted || !projectId || !adapter.isProjectFolderLost) return;
|
|
11988
|
+
let live = true;
|
|
11989
|
+
void adapter.isProjectFolderLost({ projectId }).catch(() => false).then((lost) => {
|
|
11990
|
+
if (live) setFound({ adapter, projectId, lost });
|
|
11991
|
+
});
|
|
11992
|
+
return () => {
|
|
11993
|
+
live = false;
|
|
11994
|
+
};
|
|
11995
|
+
}, [adapter, projectId, wanted]);
|
|
11996
|
+
if (!adapter.isProjectFolderLost) return false;
|
|
11997
|
+
return found?.adapter === adapter && found.projectId === projectId ? found.lost : void 0;
|
|
11998
|
+
}
|
|
11962
11999
|
function ThreadCards({ message }) {
|
|
11963
12000
|
if (message.worker) return /* @__PURE__ */ jsx(WorkerCard, { worker: message.worker });
|
|
11964
12001
|
if (message.proposal) return /* @__PURE__ */ jsx(ProposalCard, { proposal: message.proposal });
|
|
@@ -12045,7 +12082,7 @@ function WorkerCard({ worker }) {
|
|
|
12045
12082
|
] });
|
|
12046
12083
|
}
|
|
12047
12084
|
function ProposalCard({ proposal }) {
|
|
12048
|
-
const { adapter, projectId, onOpenSession } = useAgentChatAdapterContext();
|
|
12085
|
+
const { adapter, projectId, projectComputer, onOpenSession } = useAgentChatAdapterContext();
|
|
12049
12086
|
const starts = useCardStarts(adapter);
|
|
12050
12087
|
const startOf = (key) => starts.get(`${proposal.proposalId}:${key}`);
|
|
12051
12088
|
const told = (key, start2) => setCardStart(adapter, `${proposal.proposalId}:${key}`, start2);
|
|
@@ -12062,6 +12099,9 @@ function ProposalCard({ proposal }) {
|
|
|
12062
12099
|
const starting = (key) => startingAt(key) !== void 0;
|
|
12063
12100
|
const canStart = !!projectId && !!adapter.startProposedThread;
|
|
12064
12101
|
const canStartHere = !!projectId && !!adapter.startLocalThread;
|
|
12102
|
+
const here = useLocalDevice(adapter, !!projectComputer && canStartHere);
|
|
12103
|
+
const onItsComputer = !!projectComputer && canStartHere && here === projectComputer.deviceId;
|
|
12104
|
+
const lost = useFolderLost(adapter, projectId, !!projectComputer && !onItsComputer && !(canStartHere && here === void 0));
|
|
12065
12105
|
const viewButtons = useRef({});
|
|
12066
12106
|
useEffect(() => {
|
|
12067
12107
|
drawnCards.set(proposal.proposalId, (drawnCards.get(proposal.proposalId) ?? 0) + 1);
|
|
@@ -12090,16 +12130,16 @@ function ProposalCard({ proposal }) {
|
|
|
12090
12130
|
}
|
|
12091
12131
|
};
|
|
12092
12132
|
const startable = proposal.threads.filter(
|
|
12093
|
-
(thread) => thread.where === "cloud" && !started[thread.key] && !starting(thread.key)
|
|
12133
|
+
(thread) => (projectComputer ? onItsComputer : thread.where === "cloud") && !started[thread.key] && !starting(thread.key)
|
|
12094
12134
|
);
|
|
12095
|
-
const startAll = async (
|
|
12096
|
-
for (const key of
|
|
12097
|
-
for (const key of
|
|
12135
|
+
const startAll = async (threads) => {
|
|
12136
|
+
for (const { key } of threads) told(key, { state: "starting", where: projectComputer ? "device" : "cloud" });
|
|
12137
|
+
for (const { key, title } of threads) await start(key, projectComputer ? title : void 0);
|
|
12098
12138
|
};
|
|
12099
12139
|
return /* @__PURE__ */ jsxs("div", { "data-testid": "thread-proposal-card", className: "my-2 rounded-lg border border-border px-3 py-2 text-sm", children: [
|
|
12100
12140
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
12101
12141
|
/* @__PURE__ */ jsx("span", { className: "flex-1 font-medium text-foreground", children: "Proposed threads" }),
|
|
12102
|
-
canStart && startable.length > 1 && /* @__PURE__ */ jsx(Button, { size: "xs", onClick: () => void startAll(startable
|
|
12142
|
+
(projectComputer ? onItsComputer : canStart) && startable.length > 1 && /* @__PURE__ */ jsx(Button, { size: "xs", onClick: () => void startAll(startable), children: "Start all" })
|
|
12103
12143
|
] }),
|
|
12104
12144
|
/* @__PURE__ */ jsx("ul", { className: "mt-1 space-y-2", children: proposal.threads.map((thread) => {
|
|
12105
12145
|
const threadId = started[thread.key];
|
|
@@ -12121,7 +12161,29 @@ function ProposalCard({ proposal }) {
|
|
|
12121
12161
|
onClick: () => onOpenSession(threadId),
|
|
12122
12162
|
children: "View thread"
|
|
12123
12163
|
}
|
|
12124
|
-
) :
|
|
12164
|
+
) : projectComputer ? onItsComputer ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12165
|
+
/* @__PURE__ */ jsx("span", { children: "Works in its own copy of the project's folder" }),
|
|
12166
|
+
/* @__PURE__ */ jsx(
|
|
12167
|
+
Button,
|
|
12168
|
+
{
|
|
12169
|
+
size: "xs",
|
|
12170
|
+
variant: "outline",
|
|
12171
|
+
disabled: starting(thread.key),
|
|
12172
|
+
"aria-label": `${starting(thread.key) ? "Starting" : "Start"} ${thread.title}`,
|
|
12173
|
+
onClick: () => void start(thread.key, thread.title),
|
|
12174
|
+
children: starting(thread.key) ? "Starting\u2026" : "Start"
|
|
12175
|
+
}
|
|
12176
|
+
)
|
|
12177
|
+
] }) : canStartHere && here === void 0 || lost === void 0 ? null : lost ? /* @__PURE__ */ jsxs("span", { children: [
|
|
12178
|
+
"This project's folder can no longer be reached on ",
|
|
12179
|
+
/* @__PURE__ */ jsx("bdi", { children: projectComputer.name }),
|
|
12180
|
+
".",
|
|
12181
|
+
" ",
|
|
12182
|
+
canStartHere ? "Choose Use this computer for this project in its Overview to start its threads here." : "Open the project in Surogate Desktop and choose Use this computer for this project."
|
|
12183
|
+
] }) : /* @__PURE__ */ jsxs("span", { children: [
|
|
12184
|
+
"Start this thread in Surogate Desktop on ",
|
|
12185
|
+
/* @__PURE__ */ jsx("bdi", { children: projectComputer.name })
|
|
12186
|
+
] }) : thread.where === "device" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
12125
12187
|
/* @__PURE__ */ jsx("span", { children: canStartHere ? "Allow Surogate to work in a folder on your device" : "This works in a folder on your device, which needs Surogate Desktop" }),
|
|
12126
12188
|
canStartHere && /* @__PURE__ */ jsx(
|
|
12127
12189
|
Button,
|
|
@@ -20135,6 +20197,11 @@ function AgentChat({
|
|
|
20135
20197
|
});
|
|
20136
20198
|
const sessionConfig = runtime.session?.config;
|
|
20137
20199
|
const projectId = sessionConfig?.workstream_role === "coordinator" && typeof sessionConfig.workstream_id === "string" ? sessionConfig.workstream_id : null;
|
|
20200
|
+
const projectComputer = useMemo(() => {
|
|
20201
|
+
const execution = projectId ? sessionConfig?.execution : void 0;
|
|
20202
|
+
const name = sessionComputer(sessionConfig);
|
|
20203
|
+
return execution?.kind === "device" && typeof execution.device_id === "string" && name !== null ? { deviceId: execution.device_id, name } : null;
|
|
20204
|
+
}, [projectId, sessionConfig]);
|
|
20138
20205
|
const threadRows = useProjectThreads(adapter, projectId);
|
|
20139
20206
|
useEffect(() => {
|
|
20140
20207
|
setOpenPane(null);
|
|
@@ -20263,6 +20330,7 @@ function AgentChat({
|
|
|
20263
20330
|
onOpenBilling,
|
|
20264
20331
|
onOpenSession: onSessionChange,
|
|
20265
20332
|
projectId,
|
|
20333
|
+
projectComputer,
|
|
20266
20334
|
threadRows,
|
|
20267
20335
|
readOnly: disabled === true
|
|
20268
20336
|
},
|