@datalayer/agent-runtimes 1.5.53 → 1.5.55
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-embed/chunks/ChatView-D4hFmYbm.js +32 -0
- package/dist-embed/chunks/{DeckComponent-C7AztSPA.js → DeckComponent-y0KZOMsH.js} +1 -1
- package/dist-embed/chunks/{DocumentView-DwpK2feQ.js → DocumentView-BKeO-v4k.js} +1 -1
- package/dist-embed/chunks/{EphemeralDocument-rusBlgBp.js → EphemeralDocument-BvbG68Jm.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawComponent-Qv9LHutW.js → ExcalidrawComponent-DeNgg0ms.js} +1 -1
- package/dist-embed/chunks/{ExcalidrawModal-D6Mb9nmf.js → ExcalidrawModal-X6Yh6FKI.js} +1 -1
- package/dist-embed/chunks/{JupyterLexicalExtension-r47Jyrrd.js → JupyterLexicalExtension-Ght2bbbp.js} +5 -5
- package/dist-embed/chunks/{YouTubePlugin-4pUBJORX.js → YouTubePlugin-BnaV5Sxl.js} +1 -1
- package/dist-embed/chunks/{ar-SA-G6X2FPQ2-CD4X_3wm.js → ar-SA-G6X2FPQ2-DFML-KO4.js} +1 -1
- package/dist-embed/chunks/{az-AZ-76LH7QW2-oMbKQcB-.js → az-AZ-76LH7QW2-DTzTpRpk.js} +1 -1
- package/dist-embed/chunks/{bg-BG-XCXSNQG7-lSIB5dDU.js → bg-BG-XCXSNQG7-DMTmzgtc.js} +1 -1
- package/dist-embed/chunks/{bn-BD-2XOGV67Q-B5PkHAFO.js → bn-BD-2XOGV67Q-D1xy-Djm.js} +1 -1
- package/dist-embed/chunks/{ca-ES-6MX7JW3Y-BPeavtUl.js → ca-ES-6MX7JW3Y-hTO_csy7.js} +1 -1
- package/dist-embed/chunks/{cs-CZ-2BRQDIVT-DrBOFpi4.js → cs-CZ-2BRQDIVT-DBcXv81g.js} +1 -1
- package/dist-embed/chunks/{da-DK-5WZEPLOC-G5bUTE3Z.js → da-DK-5WZEPLOC-Rp51nhJX.js} +1 -1
- package/dist-embed/chunks/{de-DE-XR44H4JA-Drpt3qDZ.js → de-DE-XR44H4JA-DIgLamrP.js} +1 -1
- package/dist-embed/chunks/{el-GR-BZB4AONW-D4taPxaF.js → el-GR-BZB4AONW-XWt7TL7f.js} +1 -1
- package/dist-embed/chunks/{es-ES-U4NZUMDT-BvIGVphk.js → es-ES-U4NZUMDT-Bh1eks-u.js} +1 -1
- package/dist-embed/chunks/{eu-ES-A7QVB2H4-B8nvrNDk.js → eu-ES-A7QVB2H4-Bslg2HDc.js} +1 -1
- package/dist-embed/chunks/{fa-IR-HGAKTJCU-hwisHoU4.js → fa-IR-HGAKTJCU-9fGOejth.js} +1 -1
- package/dist-embed/chunks/{fi-FI-Z5N7JZ37-DKrDvTXs.js → fi-FI-Z5N7JZ37-DctXrD-R.js} +1 -1
- package/dist-embed/chunks/{fr-FR-RHASNOE6-DPtlBK_j.js → fr-FR-RHASNOE6-PUSl_g5c.js} +1 -1
- package/dist-embed/chunks/{gl-ES-HMX3MZ6V-B1ngwQkd.js → gl-ES-HMX3MZ6V-C5hGec18.js} +1 -1
- package/dist-embed/chunks/{he-IL-6SHJWFNN-BaoAQZ3f.js → he-IL-6SHJWFNN-rdU3Uatf.js} +1 -1
- package/dist-embed/chunks/{hi-IN-IWLTKZ5I-DzPeRmLM.js → hi-IN-IWLTKZ5I-CbVBP2OS.js} +1 -1
- package/dist-embed/chunks/{hu-HU-A5ZG7DT2-BgLcm8oA.js → hu-HU-A5ZG7DT2-BqNM3HXj.js} +1 -1
- package/dist-embed/chunks/{id-ID-SAP4L64H-egIA8l8_.js → id-ID-SAP4L64H-Z7074d-A.js} +1 -1
- package/dist-embed/chunks/{index-cYM4KfdD.js → index-2ciQBsIP.js} +1 -1
- package/dist-embed/chunks/{index-CkQ6IAoY.js → index-BIbnsdGY.js} +1 -1
- package/dist-embed/chunks/{index-Z2pxzg3H.js → index-BP84Dsqq.js} +1 -1
- package/dist-embed/chunks/{index-BzMt3uYX.js → index-BdQdhGo5.js} +1 -1
- package/dist-embed/chunks/{index-BKB97UwL.js → index-BpX_2Evh.js} +1 -1
- package/dist-embed/chunks/{index-CEbnhuIo.js → index-BrPjTG8-.js} +1 -1
- package/dist-embed/chunks/{index-Di3aBGLV.js → index-CAPuT1O_.js} +1 -1
- package/dist-embed/chunks/{index-5N0EOEHV.js → index-CC3OzP1C.js} +1 -1
- package/dist-embed/chunks/{index-D9_026K2.js → index-COWwWw7v.js} +1 -1
- package/dist-embed/chunks/{index-BTdq_niO.js → index-C_IEokTU.js} +1 -1
- package/dist-embed/chunks/{index-_H5U6gal.js → index-CalzGdbU.js} +1 -1
- package/dist-embed/chunks/{index-DVaPKQyL.js → index-CynaHotU.js} +1 -1
- package/dist-embed/chunks/{index-Cd5CgKFr.js → index-D4zET-qQ.js} +1 -1
- package/dist-embed/chunks/{index-BKOQQ5Ku.js → index-DJq5Nwi9.js} +1 -1
- package/dist-embed/chunks/{index-CZB8DyUw.js → index-Dx_VgK3b.js} +1 -1
- package/dist-embed/chunks/{index-BN8Bbau-.js → index-Dzf9vro3.js} +2 -2
- package/dist-embed/chunks/{index-DWfzdTZo.js → index-IGJ-OsCO.js} +1 -1
- package/dist-embed/chunks/{index-b6e3y1R-.js → index-mjwdOWLk.js} +1 -1
- package/dist-embed/chunks/{index-Gngo0bXi.js → index-wuTQQ7uK.js} +1 -1
- package/dist-embed/chunks/{index-CCRwowMu.js → index-zOsAyJ2Z.js} +1 -1
- package/dist-embed/chunks/{it-IT-JPQ66NNP-DDwc6pzw.js → it-IT-JPQ66NNP-CMr44eTw.js} +1 -1
- package/dist-embed/chunks/{ja-JP-DBVTYXUO-TrA2khDT.js → ja-JP-DBVTYXUO-DT0NU6hE.js} +1 -1
- package/dist-embed/chunks/{kaa-6HZHGXH3-GwFnOAIz.js → kaa-6HZHGXH3-C7H2NR4A.js} +1 -1
- package/dist-embed/chunks/{kab-KAB-ZGHBKWFO-xYS1Kjfb.js → kab-KAB-ZGHBKWFO-CNMStwQY.js} +1 -1
- package/dist-embed/chunks/{kk-KZ-P5N5QNE5-BwDJRk5I.js → kk-KZ-P5N5QNE5-D6IFMubV.js} +1 -1
- package/dist-embed/chunks/{km-KH-HSX4SM5Z-Di9J-9zc.js → km-KH-HSX4SM5Z-sh4HcGEj.js} +1 -1
- package/dist-embed/chunks/{ko-KR-MTYHY66A-BxF1Locw.js → ko-KR-MTYHY66A-Bgk5LE7Q.js} +1 -1
- package/dist-embed/chunks/{ku-TR-6OUDTVRD-mGflwIcv.js → ku-TR-6OUDTVRD-CoM0o1jW.js} +1 -1
- package/dist-embed/chunks/{lt-LT-XHIRWOB4-DWluphZ2.js → lt-LT-XHIRWOB4-1uHPL6b-.js} +1 -1
- package/dist-embed/chunks/{lv-LV-5QDEKY6T-D9EEzVQ9.js → lv-LV-5QDEKY6T-DYKbCrq6.js} +1 -1
- package/dist-embed/chunks/{mr-IN-CRQNXWMA-DoMvP_Jp.js → mr-IN-CRQNXWMA-C7qlI0yH.js} +1 -1
- package/dist-embed/chunks/{my-MM-5M5IBNSE-CPPbx93K.js → my-MM-5M5IBNSE-BWSQ_5V3.js} +1 -1
- package/dist-embed/chunks/{nb-NO-T6EIAALU-m2hgNNww.js → nb-NO-T6EIAALU-BVQfX-Pe.js} +1 -1
- package/dist-embed/chunks/{nl-NL-IS3SIHDZ-B809T0Iy.js → nl-NL-IS3SIHDZ-BXjyEe9g.js} +1 -1
- package/dist-embed/chunks/{nn-NO-6E72VCQL-DcMxKEVg.js → nn-NO-6E72VCQL-3eaL8woM.js} +1 -1
- package/dist-embed/chunks/{oc-FR-POXYY2M6-BZTBaY64.js → oc-FR-POXYY2M6-CDqoITm8.js} +1 -1
- package/dist-embed/chunks/{pa-IN-N4M65BXN-Cs4i3fnS.js → pa-IN-N4M65BXN-CoKaIMNa.js} +1 -1
- package/dist-embed/chunks/{percentages-BXMCSKIN-D82iCuEy.js → percentages-BXMCSKIN-X4aF_7zv.js} +3 -3
- package/dist-embed/chunks/{pl-PL-T2D74RX3-B3jg7qOY.js → pl-PL-T2D74RX3-DDD5SgtT.js} +1 -1
- package/dist-embed/chunks/{pt-BR-5N22H2LF-aCJuloaY.js → pt-BR-5N22H2LF-BIIRVQqv.js} +1 -1
- package/dist-embed/chunks/{pt-PT-UZXXM6DQ-8ZZdQp1P.js → pt-PT-UZXXM6DQ-HB1n3nNc.js} +1 -1
- package/dist-embed/chunks/{ro-RO-JPDTUUEW-BmyO5zyl.js → ro-RO-JPDTUUEW-CDxFIF2P.js} +1 -1
- package/dist-embed/chunks/{ru-RU-B4JR7IUQ-BneR_2Bm.js → ru-RU-B4JR7IUQ-CM2wpzEh.js} +1 -1
- package/dist-embed/chunks/{si-LK-N5RQ5JYF-CDB0IyVm.js → si-LK-N5RQ5JYF-u_f-pZ4T.js} +1 -1
- package/dist-embed/chunks/{sk-SK-C5VTKIMK-ypZmPMe_.js → sk-SK-C5VTKIMK-1MdhriDY.js} +1 -1
- package/dist-embed/chunks/{sl-SI-NN7IZMDC-D9OrZXr7.js → sl-SI-NN7IZMDC-BtkaEwYy.js} +1 -1
- package/dist-embed/chunks/{subset-shared.chunk-cQajIUFT.js → subset-shared.chunk-Ca3xPoZL.js} +1 -1
- package/dist-embed/chunks/{subset-worker.chunk-DEC9qaDu.js → subset-worker.chunk-CEgJtfh9.js} +1 -1
- package/dist-embed/chunks/{sv-SE-XGPEYMSR-CXBRqMMZ.js → sv-SE-XGPEYMSR-CX9l-s8b.js} +1 -1
- package/dist-embed/chunks/{ta-IN-2NMHFXQM-BuB9HEjH.js → ta-IN-2NMHFXQM-Bs3QMZdy.js} +1 -1
- package/dist-embed/chunks/{th-TH-HPSO5L25-Ci7wR5dZ.js → th-TH-HPSO5L25-yCfu_zLh.js} +1 -1
- package/dist-embed/chunks/{tr-TR-DEFEU3FU-CEJUT8zN.js → tr-TR-DEFEU3FU-PnpIJqSm.js} +1 -1
- package/dist-embed/chunks/{uk-UA-QMV73CPH-Ceh5JIiD.js → uk-UA-QMV73CPH--aODafpt.js} +1 -1
- package/dist-embed/chunks/{url-DuKx0yk0.js → url-CzjbCo42.js} +1 -1
- package/dist-embed/chunks/{vi-VN-M7AON7JQ-8-R9Ohxp.js → vi-VN-M7AON7JQ-BruA8Fg-.js} +1 -1
- package/dist-embed/chunks/{zh-CN-LNUGB5OW-D4q5wqKm.js → zh-CN-LNUGB5OW-DtbH5pJi.js} +1 -1
- package/dist-embed/chunks/{zh-HK-E62DVLB3-_UiIVKpk.js → zh-HK-E62DVLB3-CPacR6Re.js} +1 -1
- package/dist-embed/chunks/{zh-TW-RAJ6MFWO-DyXZ-PXI.js → zh-TW-RAJ6MFWO-CImbtPSf.js} +1 -1
- package/dist-embed/datalayer-app-main.js +86 -86
- package/lib/apps/core/index.d.ts +11 -0
- package/lib/apps/plugins/app-rules/AppRulesCard.d.ts +6 -0
- package/lib/apps/plugins/app-rules/AppRulesCard.js +9 -1
- package/lib/apps/plugins/chat/ChatView.js +18 -3
- package/lib/apps/shell/LoopWorkspace.js +8 -0
- package/lib/portable/hosts/contracts.json +30 -0
- package/lib/specs/agents/agents.d.ts +6 -0
- package/lib/specs/agents/agents.js +294 -0
- package/lib/voice/HandsFree.js +11 -1
- package/lib/voice/VoiceInput.js +10 -2
- package/lib/voice/handsFree.d.ts +4 -2
- package/lib/voice/handsFree.js +4 -2
- package/package.json +1 -1
- package/dist-embed/chunks/ChatView-CRp8Mt57.js +0 -32
package/lib/apps/core/index.d.ts
CHANGED
|
@@ -144,6 +144,17 @@ export type LoopWorkspaceContext = {
|
|
|
144
144
|
setAgentId: (agentId: string) => void;
|
|
145
145
|
/** Conversation being continued, when there is one. */
|
|
146
146
|
conversationId?: string;
|
|
147
|
+
/**
|
|
148
|
+
* The thread the chat last sent on, once it has sent: an application's
|
|
149
|
+
* thread is its session on the runtime, so what reads a running session —
|
|
150
|
+
* the Rules card's *This session* (SH-54) — reads it here. Without it a
|
|
151
|
+
* workspace whose host named no conversation never knew its session, and
|
|
152
|
+
* the card said *Start a conversation* after one had started (16 October
|
|
153
|
+
* 2026).
|
|
154
|
+
*/
|
|
155
|
+
thread?: string;
|
|
156
|
+
/** For the chat to say which thread it sends on. */
|
|
157
|
+
setThread?: (thread: string) => void;
|
|
147
158
|
/**
|
|
148
159
|
* The id the notebook and the document on screen are addressed by.
|
|
149
160
|
*
|
|
@@ -61,6 +61,12 @@ export declare function SessionRules({ agentServerUrl, sessionUid, token, }: {
|
|
|
61
61
|
sessionUid: string;
|
|
62
62
|
token: string;
|
|
63
63
|
}): JSX.Element;
|
|
64
|
+
/**
|
|
65
|
+
* The running session the card tightens: the conversation the host
|
|
66
|
+
* continued, else the thread the chat sent on — an application's thread is
|
|
67
|
+
* its session on the runtime. None before a message is sent.
|
|
68
|
+
*/
|
|
69
|
+
export declare function sessionUidOf(workspace?: Pick<LoopWorkspaceContext, 'conversationId' | 'thread'>): string | undefined;
|
|
64
70
|
export declare function AppRulesCard({ app, workspace, }: {
|
|
65
71
|
app: AppSpec;
|
|
66
72
|
/** The workspace the card sits in, when the slot gives it: names the session running. */
|
|
@@ -107,13 +107,21 @@ export function SessionRules({ agentServerUrl, sessionUid, token, }) {
|
|
|
107
107
|
};
|
|
108
108
|
return (_jsxs(Box, { "data-testid": "session-rules", mt: 3, children: [_jsx(Heading, { as: "h4", sx: { fontSize: 1, mb: 1 }, children: SESSION_RULES_WORDS.title }), inForce?.unavailable ? (_jsx(Text, { as: "p", role: "alert", sx: { fontSize: 0, m: 0, mb: 1 }, children: SESSION_RULES_WORDS.unavailable(inForce.unavailable) })) : null, inForce && inForce.session_rules.length === 0 ? (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: SESSION_RULES_WORDS.none })) : (_jsx(Box, { as: "ul", listStyle: "none", p: 0, m: 0, children: (inForce?.session_rules ?? []).map(rule => (_jsxs(Box, { as: "li", py: 1, fontSize: 1, display: "flex", gap: 2, alignItems: "center", children: [_jsx(Text, { sx: { fontWeight: 'semibold' }, children: rule.name }), _jsx(Text, { sx: { color: 'fg.muted', fontSize: 0 }, children: sessionRuleInWords(rule) }), _jsx(Button, { size: "small", variant: "invisible", disabled: busy, onClick: () => void act(() => removeSessionRule(agentServerUrl, token, sessionUid, rule.name)), children: SESSION_RULES_WORDS.remove })] }, rule.name))) })), _jsxs(Box, { display: "flex", gap: 1, mt: 1, flexWrap: "wrap", alignItems: "center", children: [_jsx(TextInput, { size: "small", value: name, placeholder: SESSION_RULES_WORDS.namePlaceholder, "aria-label": "The rule's name", onChange: event => setName(event.target.value) }), _jsx(Select, { size: "small", value: kind, "aria-label": "What it covers", onChange: event => setKind(event.target.value), children: SESSION_RULE_CLASSES.map(item => (_jsx(Select.Option, { value: item, children: SESSION_RULES_WORDS.classes[item] }, item))) }), _jsx(Select, { size: "small", value: decision, "aria-label": "What it says", onChange: event => setDecision(event.target.value), children: SESSION_RULE_DECISIONS.map(item => (_jsx(Select.Option, { value: item, children: SESSION_RULES_WORDS.decisions[item] }, item))) }), _jsx(Button, { size: "small", disabled: busy, onClick: add, children: SESSION_RULES_WORDS.add })] }), _jsx(Box, { display: "flex", gap: 1, mt: 1, flexWrap: "wrap", "data-testid": "session-rules-file-and-shell", children: FILE_AND_SHELL_RULES.map(rule => (_jsx(Button, { size: "small", variant: "invisible", disabled: busy, title: sessionRuleInWords(rule), onClick: () => void act(() => addSessionRule(agentServerUrl, token, sessionUid, rule)), children: rule.name }, rule.name))) }), problem ? (_jsx(Text, { as: "p", role: "alert", sx: { fontSize: 0, m: 0, mt: 1 }, children: problem })) : null, _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1, mb: 0 }, children: SESSION_RULES_WORDS.goneWithSession })] }));
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The running session the card tightens: the conversation the host
|
|
112
|
+
* continued, else the thread the chat sent on — an application's thread is
|
|
113
|
+
* its session on the runtime. None before a message is sent.
|
|
114
|
+
*/
|
|
115
|
+
export function sessionUidOf(workspace) {
|
|
116
|
+
return workspace?.conversationId || workspace?.thread || undefined;
|
|
117
|
+
}
|
|
110
118
|
export function AppRulesCard({ app, workspace, }) {
|
|
111
119
|
const token = useIAMStore(state => state.token) ?? '';
|
|
112
120
|
const signedIn = Boolean(token);
|
|
113
121
|
const agentServerUrl = workspace
|
|
114
122
|
? agentServerOf(workspace.sandbox, workspace.serverUrl)
|
|
115
123
|
: undefined;
|
|
116
|
-
const sessionUid = workspace
|
|
124
|
+
const sessionUid = sessionUidOf(workspace);
|
|
117
125
|
return (_jsxs(Box, { "data-testid": "app-rules", mb: 4, children: [_jsx(Heading, { as: "h3", sx: { fontSize: 2, mb: 2 }, children: APP_RULES_WORDS.title }), app.rules.length === 0 ? (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', m: 0 }, children: APP_RULES_WORDS.none })) : (_jsx(Box, { as: "ul", listStyle: "none", p: 0, m: 0, children: app.rules.map(ruleInWords).map((rule, index) => (_jsxs(Box, { as: "li", py: 1, fontSize: 1, children: [_jsx(Text, { children: rule.action }), ' ', _jsx(Label, { title: rule.means, children: rule.says }), _jsx(Text, { as: "p", sx: { m: 0, color: 'fg.muted', fontSize: 0 }, children: rule.covers })] }, index))) })), _jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 1, mb: 0 }, children: APP_RULES_WORDS.byDefault }), signedIn ? (_jsx(Approvals, { app: app })) : (_jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', mt: 3, mb: 0 }, children: APP_RULES_WORDS.signedOut })), signedIn && agentServerUrl ? (sessionUid ? (_jsx(SessionRules, { agentServerUrl: agentServerUrl, sessionUid: sessionUid, token: token })) : (_jsx(Text, { as: "p", sx: { fontSize: 0, color: 'fg.muted', mt: 3, mb: 0 }, children: SESSION_RULES_WORDS.noSession }))) : null] }));
|
|
118
126
|
}
|
|
119
127
|
export default AppRulesCard;
|
|
@@ -80,6 +80,20 @@ export default function ChatView({ workspace }) {
|
|
|
80
80
|
const palette = useColorPalette();
|
|
81
81
|
const controlsRef = useRef(null);
|
|
82
82
|
const { setViewControls } = workspace;
|
|
83
|
+
/*
|
|
84
|
+
* Say the thread a message goes on to the workspace: an application's
|
|
85
|
+
* thread is its session on the runtime, which the Rules card's *This
|
|
86
|
+
* session* reads (SH-54). Through a ref, as the senders below are built once.
|
|
87
|
+
*/
|
|
88
|
+
const setThreadRef = useRef(workspace.setThread);
|
|
89
|
+
setThreadRef.current = workspace.setThread;
|
|
90
|
+
const sayThread = useCallback(() => {
|
|
91
|
+
const thread = controlsRef.current?.thread();
|
|
92
|
+
if (thread) {
|
|
93
|
+
setThreadRef.current?.(thread);
|
|
94
|
+
}
|
|
95
|
+
return thread;
|
|
96
|
+
}, []);
|
|
83
97
|
const [transient, setTransient] = useState(null);
|
|
84
98
|
// Read from the reactor rather than taken as a prop: the placeholder and the
|
|
85
99
|
// default editor are the chat plugin's own configuration, so a host sets them
|
|
@@ -440,14 +454,14 @@ export default function ChatView({ workspace }) {
|
|
|
440
454
|
return;
|
|
441
455
|
}
|
|
442
456
|
// A new turn: whatever the panel showed is gone, this message is it.
|
|
443
|
-
turnFeedRef.current?.begin(message,
|
|
457
|
+
turnFeedRef.current?.begin(message, sayThread());
|
|
444
458
|
const send = controlsRef.current?.send;
|
|
445
459
|
if (!send) {
|
|
446
460
|
heldForAdapter.current.push([message, forwardedProps]);
|
|
447
461
|
return;
|
|
448
462
|
}
|
|
449
463
|
send(message, forwardedProps);
|
|
450
|
-
}, []);
|
|
464
|
+
}, [sayThread]);
|
|
451
465
|
// One writer, so neither fact can erase the other.
|
|
452
466
|
useEffect(() => {
|
|
453
467
|
setViewControls(sendReady
|
|
@@ -481,9 +495,10 @@ export default function ChatView({ workspace }) {
|
|
|
481
495
|
}
|
|
482
496
|
const held = heldForAdapter.current.splice(0, heldForAdapter.current.length);
|
|
483
497
|
for (const [message, forwardedProps] of held) {
|
|
498
|
+
sayThread();
|
|
484
499
|
controlsRef.current?.send(message, forwardedProps);
|
|
485
500
|
}
|
|
486
|
-
}, [sendReady]);
|
|
501
|
+
}, [sendReady, sayThread]);
|
|
487
502
|
/*
|
|
488
503
|
* Fired once, on the first real send, for the life of this mounted chat —
|
|
489
504
|
* a ref rather than a signal, because nothing here needs to re-render when
|
|
@@ -45,6 +45,11 @@ function WorkspaceBody({ serverUrl, agentId: initialAgentId, conversationId, mod
|
|
|
45
45
|
useEffect(() => {
|
|
46
46
|
setAgentId(initialAgentId);
|
|
47
47
|
}, [initialAgentId]);
|
|
48
|
+
// The thread the chat sends on, said by the chat (its session, SH-54).
|
|
49
|
+
const [thread, setThreadState] = useState(undefined);
|
|
50
|
+
const setThread = useCallback((next) => {
|
|
51
|
+
setThreadState(current => (current === next ? current : next));
|
|
52
|
+
}, []);
|
|
48
53
|
const [activeViewType, setActiveViewType] = useState(initialViewType ?? '');
|
|
49
54
|
// Seeded by the host (a handoff carries what the terminal knew), then kept
|
|
50
55
|
// current by whichever plugin owns the sandbox.
|
|
@@ -109,6 +114,8 @@ function WorkspaceBody({ serverUrl, agentId: initialAgentId, conversationId, mod
|
|
|
109
114
|
surfaceId: surfaceIdRef.current,
|
|
110
115
|
setAgentId,
|
|
111
116
|
conversationId,
|
|
117
|
+
thread,
|
|
118
|
+
setThread,
|
|
112
119
|
model,
|
|
113
120
|
sandbox,
|
|
114
121
|
setSandbox,
|
|
@@ -124,6 +131,7 @@ function WorkspaceBody({ serverUrl, agentId: initialAgentId, conversationId, mod
|
|
|
124
131
|
serverUrl,
|
|
125
132
|
agentId,
|
|
126
133
|
conversationId,
|
|
134
|
+
thread,
|
|
127
135
|
model,
|
|
128
136
|
sandbox,
|
|
129
137
|
activeViewType,
|
|
@@ -125,6 +125,35 @@
|
|
|
125
125
|
"expires_in"
|
|
126
126
|
]
|
|
127
127
|
},
|
|
128
|
+
"bind_session": {
|
|
129
|
+
"about": "The host maps a session it opened to a place of its own, with the host token it opened it with and its host key: binding it again replaces the target. The target is opaque to ai-agents (a JSON object of at most target_limit characters) and is handed back with every delivery of that session.",
|
|
130
|
+
"request": {
|
|
131
|
+
"target": {
|
|
132
|
+
"appId": "A0",
|
|
133
|
+
"channelId": "C0",
|
|
134
|
+
"teamId": "T0",
|
|
135
|
+
"threadTs": "1700000000.000001",
|
|
136
|
+
"userId": "U0ALICE"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"session_uid_pattern": "^[A-Za-z0-9_-]{8,128}$",
|
|
140
|
+
"target_limit": 2048,
|
|
141
|
+
"response_keys": [
|
|
142
|
+
"success",
|
|
143
|
+
"binding"
|
|
144
|
+
],
|
|
145
|
+
"binding_keys": [
|
|
146
|
+
"uid",
|
|
147
|
+
"host_uid",
|
|
148
|
+
"session_uid",
|
|
149
|
+
"deployment_uid",
|
|
150
|
+
"agent_id",
|
|
151
|
+
"link_uid",
|
|
152
|
+
"principal_uid",
|
|
153
|
+
"target",
|
|
154
|
+
"state"
|
|
155
|
+
]
|
|
156
|
+
},
|
|
128
157
|
"external_turn": {
|
|
129
158
|
"start_request": {
|
|
130
159
|
"agent": "agent-desk",
|
|
@@ -142,6 +171,7 @@
|
|
|
142
171
|
"type": "CUSTOM",
|
|
143
172
|
"name": "loop.turn",
|
|
144
173
|
"value_keys": [
|
|
174
|
+
"session",
|
|
145
175
|
"turn",
|
|
146
176
|
"external_event_id",
|
|
147
177
|
"replayed",
|
|
@@ -42,6 +42,12 @@ export declare const EXAMPLE_GPT_AND_CLAUDE_COLLABORATE_AGENTSPEC_0_0_1: Agentsp
|
|
|
42
42
|
export declare const EXAMPLE_GUARDRAILS_AGENTSPEC_0_0_1: Agentspec;
|
|
43
43
|
export declare const EXAMPLE_HAIKU_GENERATIVE_UI_AGENTSPEC_0_0_1: Agentspec;
|
|
44
44
|
export declare const EXAMPLE_HARNESS_CLAUDE_CODE_AGENTSPEC_0_0_1: Agentspec;
|
|
45
|
+
export declare const EXAMPLE_HARNESS_CODEX_AGENTSPEC_0_0_1: Agentspec;
|
|
46
|
+
export declare const EXAMPLE_HARNESS_FAST_AGENT_SPEC_0_0_1: Agentspec;
|
|
47
|
+
export declare const EXAMPLE_HARNESS_GEMINI_CLI_AGENTSPEC_0_0_1: Agentspec;
|
|
48
|
+
export declare const EXAMPLE_HARNESS_GOOSE_AGENTSPEC_0_0_1: Agentspec;
|
|
49
|
+
export declare const EXAMPLE_HARNESS_OPENCODE_AGENTSPEC_0_0_1: Agentspec;
|
|
50
|
+
export declare const EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1: Agentspec;
|
|
45
51
|
export declare const EXAMPLE_HOOKS_AGENTSPEC_0_0_1: Agentspec;
|
|
46
52
|
export declare const EXAMPLE_HUMAN_APPROVED_AUTOMATION_AGENTSPEC_0_0_1: Agentspec;
|
|
47
53
|
export declare const EXAMPLE_HUMAN_IN_THE_LOOP_AGENTSPEC_0_0_1: Agentspec;
|
|
@@ -2630,6 +2630,294 @@ export const EXAMPLE_HARNESS_CLAUDE_CODE_AGENTSPEC_0_0_1 = {
|
|
|
2630
2630
|
parameters: undefined,
|
|
2631
2631
|
subagents: undefined,
|
|
2632
2632
|
};
|
|
2633
|
+
export const EXAMPLE_HARNESS_CODEX_AGENTSPEC_0_0_1 = {
|
|
2634
|
+
id: 'example-harness-codex',
|
|
2635
|
+
version: '0.0.1',
|
|
2636
|
+
name: 'A Codex Agent',
|
|
2637
|
+
description: `OpenAI's Codex as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's OPENAI_API_KEY.`,
|
|
2638
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2639
|
+
domain: undefined,
|
|
2640
|
+
enabled: false,
|
|
2641
|
+
model: undefined,
|
|
2642
|
+
mcpServers: [],
|
|
2643
|
+
skills: [].filter(Boolean),
|
|
2644
|
+
backendTools: [],
|
|
2645
|
+
frontendTools: [],
|
|
2646
|
+
environmentName: 'ai-agents-env',
|
|
2647
|
+
icon: undefined,
|
|
2648
|
+
emoji: undefined,
|
|
2649
|
+
color: undefined,
|
|
2650
|
+
suggestions: [],
|
|
2651
|
+
welcomeMessage: undefined,
|
|
2652
|
+
welcomeNotebook: undefined,
|
|
2653
|
+
welcomeDocument: undefined,
|
|
2654
|
+
sandboxVariant: 'jupyter-server',
|
|
2655
|
+
harness: 'codex',
|
|
2656
|
+
systemPrompt: undefined,
|
|
2657
|
+
systemPromptCodemodeAddons: undefined,
|
|
2658
|
+
goal: undefined,
|
|
2659
|
+
delegable: [],
|
|
2660
|
+
protocol: undefined,
|
|
2661
|
+
ui: [],
|
|
2662
|
+
protocols: [],
|
|
2663
|
+
trigger: undefined,
|
|
2664
|
+
modelConfig: undefined,
|
|
2665
|
+
mcpServerTools: undefined,
|
|
2666
|
+
guardrails: undefined,
|
|
2667
|
+
evals: undefined,
|
|
2668
|
+
codemode: undefined,
|
|
2669
|
+
output: undefined,
|
|
2670
|
+
advanced: undefined,
|
|
2671
|
+
checkpoints: undefined,
|
|
2672
|
+
authorizationPolicy: undefined,
|
|
2673
|
+
notifications: undefined,
|
|
2674
|
+
memory: 'ephemeral',
|
|
2675
|
+
preHooks: undefined,
|
|
2676
|
+
postHooks: undefined,
|
|
2677
|
+
toolHooks: undefined,
|
|
2678
|
+
parameters: undefined,
|
|
2679
|
+
subagents: undefined,
|
|
2680
|
+
};
|
|
2681
|
+
export const EXAMPLE_HARNESS_FAST_AGENT_SPEC_0_0_1 = {
|
|
2682
|
+
id: 'example-harness-fast-agent',
|
|
2683
|
+
version: '0.0.1',
|
|
2684
|
+
name: 'A fast-agent Agent',
|
|
2685
|
+
description: `fast-agent as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's ANTHROPIC_API_KEY.`,
|
|
2686
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2687
|
+
domain: undefined,
|
|
2688
|
+
enabled: false,
|
|
2689
|
+
model: undefined,
|
|
2690
|
+
mcpServers: [],
|
|
2691
|
+
skills: [].filter(Boolean),
|
|
2692
|
+
backendTools: [],
|
|
2693
|
+
frontendTools: [],
|
|
2694
|
+
environmentName: 'ai-agents-env',
|
|
2695
|
+
icon: undefined,
|
|
2696
|
+
emoji: undefined,
|
|
2697
|
+
color: undefined,
|
|
2698
|
+
suggestions: [],
|
|
2699
|
+
welcomeMessage: undefined,
|
|
2700
|
+
welcomeNotebook: undefined,
|
|
2701
|
+
welcomeDocument: undefined,
|
|
2702
|
+
sandboxVariant: 'jupyter-server',
|
|
2703
|
+
harness: 'fast-agent',
|
|
2704
|
+
systemPrompt: undefined,
|
|
2705
|
+
systemPromptCodemodeAddons: undefined,
|
|
2706
|
+
goal: undefined,
|
|
2707
|
+
delegable: [],
|
|
2708
|
+
protocol: undefined,
|
|
2709
|
+
ui: [],
|
|
2710
|
+
protocols: [],
|
|
2711
|
+
trigger: undefined,
|
|
2712
|
+
modelConfig: undefined,
|
|
2713
|
+
mcpServerTools: undefined,
|
|
2714
|
+
guardrails: undefined,
|
|
2715
|
+
evals: undefined,
|
|
2716
|
+
codemode: undefined,
|
|
2717
|
+
output: undefined,
|
|
2718
|
+
advanced: undefined,
|
|
2719
|
+
checkpoints: undefined,
|
|
2720
|
+
authorizationPolicy: undefined,
|
|
2721
|
+
notifications: undefined,
|
|
2722
|
+
memory: 'ephemeral',
|
|
2723
|
+
preHooks: undefined,
|
|
2724
|
+
postHooks: undefined,
|
|
2725
|
+
toolHooks: undefined,
|
|
2726
|
+
parameters: undefined,
|
|
2727
|
+
subagents: undefined,
|
|
2728
|
+
};
|
|
2729
|
+
export const EXAMPLE_HARNESS_GEMINI_CLI_AGENTSPEC_0_0_1 = {
|
|
2730
|
+
id: 'example-harness-gemini-cli',
|
|
2731
|
+
version: '0.0.1',
|
|
2732
|
+
name: 'A Gemini CLI Agent',
|
|
2733
|
+
description: `Google's Gemini CLI as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's GEMINI_API_KEY.`,
|
|
2734
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2735
|
+
domain: undefined,
|
|
2736
|
+
enabled: false,
|
|
2737
|
+
model: undefined,
|
|
2738
|
+
mcpServers: [],
|
|
2739
|
+
skills: [].filter(Boolean),
|
|
2740
|
+
backendTools: [],
|
|
2741
|
+
frontendTools: [],
|
|
2742
|
+
environmentName: 'ai-agents-env',
|
|
2743
|
+
icon: undefined,
|
|
2744
|
+
emoji: undefined,
|
|
2745
|
+
color: undefined,
|
|
2746
|
+
suggestions: [],
|
|
2747
|
+
welcomeMessage: undefined,
|
|
2748
|
+
welcomeNotebook: undefined,
|
|
2749
|
+
welcomeDocument: undefined,
|
|
2750
|
+
sandboxVariant: 'jupyter-server',
|
|
2751
|
+
harness: 'gemini-cli',
|
|
2752
|
+
systemPrompt: undefined,
|
|
2753
|
+
systemPromptCodemodeAddons: undefined,
|
|
2754
|
+
goal: undefined,
|
|
2755
|
+
delegable: [],
|
|
2756
|
+
protocol: undefined,
|
|
2757
|
+
ui: [],
|
|
2758
|
+
protocols: [],
|
|
2759
|
+
trigger: undefined,
|
|
2760
|
+
modelConfig: undefined,
|
|
2761
|
+
mcpServerTools: undefined,
|
|
2762
|
+
guardrails: undefined,
|
|
2763
|
+
evals: undefined,
|
|
2764
|
+
codemode: undefined,
|
|
2765
|
+
output: undefined,
|
|
2766
|
+
advanced: undefined,
|
|
2767
|
+
checkpoints: undefined,
|
|
2768
|
+
authorizationPolicy: undefined,
|
|
2769
|
+
notifications: undefined,
|
|
2770
|
+
memory: 'ephemeral',
|
|
2771
|
+
preHooks: undefined,
|
|
2772
|
+
postHooks: undefined,
|
|
2773
|
+
toolHooks: undefined,
|
|
2774
|
+
parameters: undefined,
|
|
2775
|
+
subagents: undefined,
|
|
2776
|
+
};
|
|
2777
|
+
export const EXAMPLE_HARNESS_GOOSE_AGENTSPEC_0_0_1 = {
|
|
2778
|
+
id: 'example-harness-goose',
|
|
2779
|
+
version: '0.0.1',
|
|
2780
|
+
name: 'A goose Agent',
|
|
2781
|
+
description: `goose as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's ANTHROPIC_API_KEY.`,
|
|
2782
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2783
|
+
domain: undefined,
|
|
2784
|
+
enabled: false,
|
|
2785
|
+
model: undefined,
|
|
2786
|
+
mcpServers: [],
|
|
2787
|
+
skills: [].filter(Boolean),
|
|
2788
|
+
backendTools: [],
|
|
2789
|
+
frontendTools: [],
|
|
2790
|
+
environmentName: 'ai-agents-env',
|
|
2791
|
+
icon: undefined,
|
|
2792
|
+
emoji: undefined,
|
|
2793
|
+
color: undefined,
|
|
2794
|
+
suggestions: [],
|
|
2795
|
+
welcomeMessage: undefined,
|
|
2796
|
+
welcomeNotebook: undefined,
|
|
2797
|
+
welcomeDocument: undefined,
|
|
2798
|
+
sandboxVariant: 'jupyter-server',
|
|
2799
|
+
harness: 'goose',
|
|
2800
|
+
systemPrompt: undefined,
|
|
2801
|
+
systemPromptCodemodeAddons: undefined,
|
|
2802
|
+
goal: undefined,
|
|
2803
|
+
delegable: [],
|
|
2804
|
+
protocol: undefined,
|
|
2805
|
+
ui: [],
|
|
2806
|
+
protocols: [],
|
|
2807
|
+
trigger: undefined,
|
|
2808
|
+
modelConfig: undefined,
|
|
2809
|
+
mcpServerTools: undefined,
|
|
2810
|
+
guardrails: undefined,
|
|
2811
|
+
evals: undefined,
|
|
2812
|
+
codemode: undefined,
|
|
2813
|
+
output: undefined,
|
|
2814
|
+
advanced: undefined,
|
|
2815
|
+
checkpoints: undefined,
|
|
2816
|
+
authorizationPolicy: undefined,
|
|
2817
|
+
notifications: undefined,
|
|
2818
|
+
memory: 'ephemeral',
|
|
2819
|
+
preHooks: undefined,
|
|
2820
|
+
postHooks: undefined,
|
|
2821
|
+
toolHooks: undefined,
|
|
2822
|
+
parameters: undefined,
|
|
2823
|
+
subagents: undefined,
|
|
2824
|
+
};
|
|
2825
|
+
export const EXAMPLE_HARNESS_OPENCODE_AGENTSPEC_0_0_1 = {
|
|
2826
|
+
id: 'example-harness-opencode',
|
|
2827
|
+
version: '0.0.1',
|
|
2828
|
+
name: 'An OpenCode Agent',
|
|
2829
|
+
description: `OpenCode as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's ANTHROPIC_API_KEY.`,
|
|
2830
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2831
|
+
domain: undefined,
|
|
2832
|
+
enabled: false,
|
|
2833
|
+
model: undefined,
|
|
2834
|
+
mcpServers: [],
|
|
2835
|
+
skills: [].filter(Boolean),
|
|
2836
|
+
backendTools: [],
|
|
2837
|
+
frontendTools: [],
|
|
2838
|
+
environmentName: 'ai-agents-env',
|
|
2839
|
+
icon: undefined,
|
|
2840
|
+
emoji: undefined,
|
|
2841
|
+
color: undefined,
|
|
2842
|
+
suggestions: [],
|
|
2843
|
+
welcomeMessage: undefined,
|
|
2844
|
+
welcomeNotebook: undefined,
|
|
2845
|
+
welcomeDocument: undefined,
|
|
2846
|
+
sandboxVariant: 'jupyter-server',
|
|
2847
|
+
harness: 'opencode',
|
|
2848
|
+
systemPrompt: undefined,
|
|
2849
|
+
systemPromptCodemodeAddons: undefined,
|
|
2850
|
+
goal: undefined,
|
|
2851
|
+
delegable: [],
|
|
2852
|
+
protocol: undefined,
|
|
2853
|
+
ui: [],
|
|
2854
|
+
protocols: [],
|
|
2855
|
+
trigger: undefined,
|
|
2856
|
+
modelConfig: undefined,
|
|
2857
|
+
mcpServerTools: undefined,
|
|
2858
|
+
guardrails: undefined,
|
|
2859
|
+
evals: undefined,
|
|
2860
|
+
codemode: undefined,
|
|
2861
|
+
output: undefined,
|
|
2862
|
+
advanced: undefined,
|
|
2863
|
+
checkpoints: undefined,
|
|
2864
|
+
authorizationPolicy: undefined,
|
|
2865
|
+
notifications: undefined,
|
|
2866
|
+
memory: 'ephemeral',
|
|
2867
|
+
preHooks: undefined,
|
|
2868
|
+
postHooks: undefined,
|
|
2869
|
+
toolHooks: undefined,
|
|
2870
|
+
parameters: undefined,
|
|
2871
|
+
subagents: undefined,
|
|
2872
|
+
};
|
|
2873
|
+
export const EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1 = {
|
|
2874
|
+
id: 'example-harness-openhands',
|
|
2875
|
+
version: '0.0.1',
|
|
2876
|
+
name: 'An OpenHands Agent',
|
|
2877
|
+
description: `The OpenHands CLI as a Datalayer agent: launched in the runtime over the Agent Client Protocol, its files, terminals and permissions decided by the Shield under the application's Rules, every action in the record. Needs the account's LLM_API_KEY.`,
|
|
2878
|
+
tags: ['coding', 'harness', 'acp'],
|
|
2879
|
+
domain: undefined,
|
|
2880
|
+
enabled: false,
|
|
2881
|
+
model: undefined,
|
|
2882
|
+
mcpServers: [],
|
|
2883
|
+
skills: [].filter(Boolean),
|
|
2884
|
+
backendTools: [],
|
|
2885
|
+
frontendTools: [],
|
|
2886
|
+
environmentName: 'ai-agents-env',
|
|
2887
|
+
icon: undefined,
|
|
2888
|
+
emoji: undefined,
|
|
2889
|
+
color: undefined,
|
|
2890
|
+
suggestions: [],
|
|
2891
|
+
welcomeMessage: undefined,
|
|
2892
|
+
welcomeNotebook: undefined,
|
|
2893
|
+
welcomeDocument: undefined,
|
|
2894
|
+
sandboxVariant: 'jupyter-server',
|
|
2895
|
+
harness: 'openhands',
|
|
2896
|
+
systemPrompt: undefined,
|
|
2897
|
+
systemPromptCodemodeAddons: undefined,
|
|
2898
|
+
goal: undefined,
|
|
2899
|
+
delegable: [],
|
|
2900
|
+
protocol: undefined,
|
|
2901
|
+
ui: [],
|
|
2902
|
+
protocols: [],
|
|
2903
|
+
trigger: undefined,
|
|
2904
|
+
modelConfig: undefined,
|
|
2905
|
+
mcpServerTools: undefined,
|
|
2906
|
+
guardrails: undefined,
|
|
2907
|
+
evals: undefined,
|
|
2908
|
+
codemode: undefined,
|
|
2909
|
+
output: undefined,
|
|
2910
|
+
advanced: undefined,
|
|
2911
|
+
checkpoints: undefined,
|
|
2912
|
+
authorizationPolicy: undefined,
|
|
2913
|
+
notifications: undefined,
|
|
2914
|
+
memory: 'ephemeral',
|
|
2915
|
+
preHooks: undefined,
|
|
2916
|
+
postHooks: undefined,
|
|
2917
|
+
toolHooks: undefined,
|
|
2918
|
+
parameters: undefined,
|
|
2919
|
+
subagents: undefined,
|
|
2920
|
+
};
|
|
2633
2921
|
export const EXAMPLE_HOOKS_AGENTSPEC_0_0_1 = {
|
|
2634
2922
|
id: 'example-hooks',
|
|
2635
2923
|
version: '0.0.1',
|
|
@@ -13563,6 +13851,12 @@ export const AGENTSPECS = {
|
|
|
13563
13851
|
'example-guardrails': EXAMPLE_GUARDRAILS_AGENTSPEC_0_0_1,
|
|
13564
13852
|
'example-haiku-generative-ui': EXAMPLE_HAIKU_GENERATIVE_UI_AGENTSPEC_0_0_1,
|
|
13565
13853
|
'example-harness-claude-code': EXAMPLE_HARNESS_CLAUDE_CODE_AGENTSPEC_0_0_1,
|
|
13854
|
+
'example-harness-codex': EXAMPLE_HARNESS_CODEX_AGENTSPEC_0_0_1,
|
|
13855
|
+
'example-harness-fast-agent': EXAMPLE_HARNESS_FAST_AGENT_SPEC_0_0_1,
|
|
13856
|
+
'example-harness-gemini-cli': EXAMPLE_HARNESS_GEMINI_CLI_AGENTSPEC_0_0_1,
|
|
13857
|
+
'example-harness-goose': EXAMPLE_HARNESS_GOOSE_AGENTSPEC_0_0_1,
|
|
13858
|
+
'example-harness-opencode': EXAMPLE_HARNESS_OPENCODE_AGENTSPEC_0_0_1,
|
|
13859
|
+
'example-harness-openhands': EXAMPLE_HARNESS_OPENHANDS_AGENTSPEC_0_0_1,
|
|
13566
13860
|
'example-hooks': EXAMPLE_HOOKS_AGENTSPEC_0_0_1,
|
|
13567
13861
|
'example-human-approved-automation': EXAMPLE_HUMAN_APPROVED_AUTOMATION_AGENTSPEC_0_0_1,
|
|
13568
13862
|
'example-human-in-the-loop': EXAMPLE_HUMAN_IN_THE_LOOP_AGENTSPEC_0_0_1,
|
package/lib/voice/HandsFree.js
CHANGED
|
@@ -198,7 +198,17 @@ export function HandsFree({ hearing, language, consentKey, microphoneId, turnSil
|
|
|
198
198
|
}, [on, paused]);
|
|
199
199
|
return (_jsxs(Box, { display: "inline-flex", alignItems: "center", sx: { gap: 1, position: 'relative' }, "data-hands-free": state, children: [_jsx(Tooltip, { text: on
|
|
200
200
|
? 'Stop talking with it'
|
|
201
|
-
: 'Talk with it: speak, it answers, and listens on (hands-free)', direction: "n", children: _jsx(Button, { size: "small", variant: on ? 'primary' : 'invisible', "aria-pressed": on, "aria-label": on ? 'Stop talking with it' : 'Talk with it',
|
|
201
|
+
: 'Talk with it: speak, it answers, and listens on (hands-free)', direction: "n", children: _jsx(Button, { size: "small", variant: on ? 'primary' : 'invisible', "aria-pressed": on, "aria-label": on ? 'Stop talking with it' : 'Talk with it', "aria-disabled": disabled || undefined, "data-hands-free-toggle": "", onClick: () => {
|
|
202
|
+
if (disabled) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (on) {
|
|
206
|
+
turnOff();
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
turnOn();
|
|
210
|
+
}
|
|
211
|
+
}, children: HANDS_FREE_WORDS.off }) }), on ? (_jsxs(_Fragment, { children: [_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, role: "status", "aria-live": "polite", "data-hands-free-state": state, children: HANDS_FREE_WORDS[state] }), paused ? (_jsx(IconButton, { icon: () => _jsx("span", { "aria-hidden": "true", children: "\u25B6" }), size: "small", variant: "invisible", "aria-label": "Resume listening", "data-hands-free-resume": "", onClick: () => setPaused(false) })) : (_jsx(IconButton, { icon: () => _jsx("span", { "aria-hidden": "true", children: "\u275A\u275A" }), size: "small", variant: "invisible", "aria-label": "Pause listening (Esc)", "data-hands-free-pause": "", onClick: () => {
|
|
202
212
|
setPaused(true);
|
|
203
213
|
capture.current?.cancel();
|
|
204
214
|
capture.current = undefined;
|
package/lib/voice/VoiceInput.js
CHANGED
|
@@ -239,13 +239,15 @@ export function VoiceInput({ hearing, language, onTranscript, onInterim, silence
|
|
|
239
239
|
// Never left open behind the page.
|
|
240
240
|
useEffect(() => () => capture.current?.cancel(), []);
|
|
241
241
|
const listening = state === 'listening';
|
|
242
|
+
// Not to be pressed: turned off, or the words still being heard.
|
|
243
|
+
const inert = disabled || state === 'hearing';
|
|
242
244
|
const label = listening
|
|
243
245
|
? clicked
|
|
244
246
|
? 'Listening — click to stop'
|
|
245
247
|
: 'Listening — let go to stop'
|
|
246
248
|
: 'Click to talk, or hold (Ctrl+Space)';
|
|
247
|
-
return (_jsxs(Box, { "data-voice-input": state, display: "inline-flex", alignItems: "center", gap: 1, position: "relative", children: [speaking && onStopSpeaking && (_jsx(Tooltip, { text: "Stop speaking (Esc)", direction: "n", children: _jsx(IconButton, { icon: MuteIcon, "aria-label": "Stop speaking", size: "small", variant: "invisible", "data-voice-stop": "", onClick: onStopSpeaking }) })), listening && (_jsx(Box, { "aria-hidden": "true", width: 40, height: 4, borderRadius: 2, bg: "neutral.muted", overflow: "hidden", children: _jsx(Box, { ref: meter, width: "100%", height: "100%", bg: "danger.emphasis", transformOrigin: "left", transform: prefersStill() ? 'scaleX(1)' : 'scaleX(0.04)' }) })), (state === 'loading' || state === 'hearing') && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-voice-progress": "", children: state === 'loading' && progress !== undefined ? `${progress}%` : '…' })), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(IconButton, { icon: () => _jsx(MicrophoneIcon, { size: 16 }), "aria-label": label, "aria-pressed": listening, size: "small", variant: listening ? 'danger' : 'invisible', disabled:
|
|
248
|
-
if (event.button !== 0) {
|
|
249
|
+
return (_jsxs(Box, { "data-voice-input": state, display: "inline-flex", alignItems: "center", gap: 1, position: "relative", children: [speaking && onStopSpeaking && (_jsx(Tooltip, { text: "Stop speaking (Esc)", direction: "n", children: _jsx(IconButton, { icon: MuteIcon, "aria-label": "Stop speaking", size: "small", variant: "invisible", "data-voice-stop": "", onClick: onStopSpeaking }) })), listening && (_jsx(Box, { "aria-hidden": "true", width: 40, height: 4, borderRadius: 2, bg: "neutral.muted", overflow: "hidden", children: _jsx(Box, { ref: meter, width: "100%", height: "100%", bg: "danger.emphasis", transformOrigin: "left", transform: prefersStill() ? 'scaleX(1)' : 'scaleX(0.04)' }) })), (state === 'loading' || state === 'hearing') && (_jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, "data-voice-progress": "", children: state === 'loading' && progress !== undefined ? `${progress}%` : '…' })), _jsx(Tooltip, { text: label, direction: "n", children: _jsx(IconButton, { icon: () => _jsx(MicrophoneIcon, { size: 16 }), "aria-label": label, "aria-pressed": listening, size: "small", variant: listening ? 'danger' : 'invisible', "aria-disabled": inert || undefined, "data-voice-mic": "", onPointerDown: event => {
|
|
250
|
+
if (inert || event.button !== 0) {
|
|
249
251
|
return;
|
|
250
252
|
}
|
|
251
253
|
pressedAt.current = Date.now();
|
|
@@ -255,6 +257,9 @@ export function VoiceInput({ hearing, language, onTranscript, onInterim, silence
|
|
|
255
257
|
void start();
|
|
256
258
|
}
|
|
257
259
|
}, onPointerUp: () => {
|
|
260
|
+
if (inert) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
258
263
|
// Held: letting go stops. A click: it goes on until the next
|
|
259
264
|
// one, or until the person stops speaking.
|
|
260
265
|
if (stopOnRelease.current ||
|
|
@@ -269,6 +274,9 @@ export function VoiceInput({ hearing, language, onTranscript, onInterim, silence
|
|
|
269
274
|
// Enter or Space on the focused button toggles, for the keyboard (VO-66).
|
|
270
275
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
271
276
|
event.preventDefault();
|
|
277
|
+
if (inert) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
272
280
|
if (stateRef.current === 'listening') {
|
|
273
281
|
void stop();
|
|
274
282
|
}
|
package/lib/voice/handsFree.d.ts
CHANGED
|
@@ -53,8 +53,10 @@ export declare function turnEnded(heard: HeardSoFarLike, turnSilenceMs?: number)
|
|
|
53
53
|
* At most this share of what plays is taken to come back into the
|
|
54
54
|
* microphone once the browser's echo cancellation has done its part (VO-13),
|
|
55
55
|
* on the meters' own scales (the microphone's `Capture.level`, the speaker's
|
|
56
|
-
* `level`).
|
|
57
|
-
*
|
|
56
|
+
* `level`). Measured on a laptop's own speakers in Chrome (VO-13): the echo
|
|
57
|
+
* left after cancellation was about 1% of the playback (0.055 at p95), and a
|
|
58
|
+
* voice over the answer passed this gate several times a second. 0.6 keeps
|
|
59
|
+
* a margin for worse speakers and rooms.
|
|
58
60
|
*/
|
|
59
61
|
export declare const ECHO_SHARE = 0.6;
|
|
60
62
|
/** How far above that echo the person's voice must be, on the meter's scale. */
|
package/lib/voice/handsFree.js
CHANGED
|
@@ -41,8 +41,10 @@ export function turnEnded(heard, turnSilenceMs = TURN_SILENCE_MS) {
|
|
|
41
41
|
* At most this share of what plays is taken to come back into the
|
|
42
42
|
* microphone once the browser's echo cancellation has done its part (VO-13),
|
|
43
43
|
* on the meters' own scales (the microphone's `Capture.level`, the speaker's
|
|
44
|
-
* `level`).
|
|
45
|
-
*
|
|
44
|
+
* `level`). Measured on a laptop's own speakers in Chrome (VO-13): the echo
|
|
45
|
+
* left after cancellation was about 1% of the playback (0.055 at p95), and a
|
|
46
|
+
* voice over the answer passed this gate several times a second. 0.6 keeps
|
|
47
|
+
* a margin for worse speakers and rooms.
|
|
46
48
|
*/
|
|
47
49
|
export const ECHO_SHARE = 0.6;
|
|
48
50
|
/** How far above that echo the person's voice must be, on the meter's scale. */
|