@synergenius/flow-weaver-pack-weaver 0.9.57 → 0.9.59
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/ai-chat-provider.d.ts.map +1 -1
- package/dist/ai-chat-provider.js +96 -4
- package/dist/ai-chat-provider.js.map +1 -1
- package/dist/bot/bot-registry.d.ts +33 -0
- package/dist/bot/bot-registry.d.ts.map +1 -0
- package/dist/bot/bot-registry.js +98 -0
- package/dist/bot/bot-registry.js.map +1 -0
- package/dist/bot/runner.d.ts.map +1 -1
- package/dist/bot/runner.js +11 -5
- package/dist/bot/runner.js.map +1 -1
- package/dist/ui/bot-panel.js +388 -0
- package/dist/ui/bot-workspace.js +76 -153
- package/dist/ui/chat-bot-result.js +71 -0
- package/flowweaver.manifest.json +128 -1
- package/package.json +1 -1
- package/src/ai-chat-provider.ts +101 -7
- package/src/bot/bot-registry.ts +116 -0
- package/src/bot/runner.ts +8 -5
- package/src/ui/bot-panel.tsx +382 -0
- package/src/ui/bot-workspace.tsx +42 -6
- package/src/ui/chat-bot-result.tsx +81 -0
package/src/ui/bot-workspace.tsx
CHANGED
|
@@ -28,7 +28,7 @@ import { SessionBar } from './session-bar';
|
|
|
28
28
|
import { SettingsSection } from './settings-section';
|
|
29
29
|
import { QueueInput } from './queue-input';
|
|
30
30
|
import { GenesisBlock } from './genesis-block';
|
|
31
|
-
|
|
31
|
+
// ApprovalCard no longer needed — TaskBlock handles approval UI natively
|
|
32
32
|
import { useStreamTimeline } from './use-stream-timeline';
|
|
33
33
|
import { traceToTimeline } from './trace-to-timeline';
|
|
34
34
|
import { sendSteerCommand } from './steer-api';
|
|
@@ -313,10 +313,43 @@ function BotWorkspace() {
|
|
|
313
313
|
return text;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
// Approval
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
316
|
+
// Approval state for running TaskBlock
|
|
317
|
+
const [approvalStatus, setApprovalStatus] = useState<'pending' | 'approved' | 'rejected' | null>(null);
|
|
318
|
+
const [approvalLoading, setApprovalLoading] = useState(false);
|
|
319
|
+
|
|
320
|
+
// Sync approval status with stream events
|
|
321
|
+
useEffect(() => {
|
|
322
|
+
if (awaitingApproval) setApprovalStatus('pending');
|
|
323
|
+
}, [awaitingApproval]);
|
|
324
|
+
|
|
325
|
+
// Reset approval when stream restarts (new run)
|
|
326
|
+
useEffect(() => {
|
|
327
|
+
if (stream.events.length === 0) setApprovalStatus(null);
|
|
328
|
+
}, [stream.events.length]);
|
|
329
|
+
|
|
330
|
+
const handleApprove = useCallback(async () => {
|
|
331
|
+
setApprovalLoading(true);
|
|
332
|
+
try {
|
|
333
|
+
await callTool('fw_weaver_approve', { approved: true });
|
|
334
|
+
setApprovalStatus('approved');
|
|
335
|
+
toast('Plan approved', { type: 'success' });
|
|
336
|
+
} catch (err: unknown) {
|
|
337
|
+
toast(err instanceof Error ? err.message : 'Failed to approve', { type: 'error' });
|
|
338
|
+
}
|
|
339
|
+
setApprovalLoading(false);
|
|
340
|
+
}, [callTool]);
|
|
341
|
+
|
|
342
|
+
const handleReject = useCallback(async () => {
|
|
343
|
+
setApprovalLoading(true);
|
|
344
|
+
try {
|
|
345
|
+
await callTool('fw_weaver_approve', { approved: false });
|
|
346
|
+
setApprovalStatus('rejected');
|
|
347
|
+
toast('Plan rejected', { type: 'info' });
|
|
348
|
+
} catch (err: unknown) {
|
|
349
|
+
toast(err instanceof Error ? err.message : 'Failed to reject', { type: 'error' });
|
|
350
|
+
}
|
|
351
|
+
setApprovalLoading(false);
|
|
352
|
+
}, [callTool]);
|
|
320
353
|
|
|
321
354
|
return React.createElement(Flex, {
|
|
322
355
|
variant: 'column-stretch-start-nowrap-0',
|
|
@@ -376,7 +409,10 @@ function BotWorkspace() {
|
|
|
376
409
|
cost,
|
|
377
410
|
plan,
|
|
378
411
|
error: stream.error,
|
|
379
|
-
|
|
412
|
+
approval: approvalStatus ?? undefined,
|
|
413
|
+
approvalLoading,
|
|
414
|
+
onApprove: handleApprove,
|
|
415
|
+
onReject: handleReject,
|
|
380
416
|
onPause: handlePause,
|
|
381
417
|
onStop: handleStop,
|
|
382
418
|
pauseLoading: pausing,
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat Bot Result — compact inline card for the AI chat thread.
|
|
3
|
+
*
|
|
4
|
+
* Renders when `fw_weaver_bot` returns a result. Shows task instruction,
|
|
5
|
+
* live status (polls fw_weaver_status), and an "Open" button to launch
|
|
6
|
+
* the full workspace.
|
|
7
|
+
*/
|
|
8
|
+
const React = require('react');
|
|
9
|
+
const { useState, useEffect, useCallback } = React;
|
|
10
|
+
const { Flex, Typography, StatusIcon, Button, toast } = require('@fw/plugin-ui-kit');
|
|
11
|
+
|
|
12
|
+
interface ChatBotResultProps {
|
|
13
|
+
result: unknown;
|
|
14
|
+
toolName: string;
|
|
15
|
+
args: Record<string, unknown>;
|
|
16
|
+
callTool: (tool: string, args?: Record<string, unknown>) => Promise<unknown>;
|
|
17
|
+
openWorkspace: (data: Record<string, unknown>) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function ChatBotResult({ result, args, callTool, openWorkspace }: ChatBotResultProps) {
|
|
21
|
+
const [status, setStatus] = useState<'running' | 'completed' | 'failed'>('running');
|
|
22
|
+
const [summary, setSummary] = useState<string | null>(null);
|
|
23
|
+
|
|
24
|
+
const parsed = typeof result === 'string' ? JSON.parse(result) : result;
|
|
25
|
+
const runId = parsed?.runId;
|
|
26
|
+
const instruction = parsed?.instruction || (args?.task as string) || 'Bot task';
|
|
27
|
+
|
|
28
|
+
// Poll status briefly
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (!runId || status !== 'running') return;
|
|
31
|
+
const poll = async () => {
|
|
32
|
+
try {
|
|
33
|
+
const s = await callTool('fw_weaver_status') as Record<string, unknown>;
|
|
34
|
+
if (s?.currentRunId !== runId) {
|
|
35
|
+
// Run finished — check history
|
|
36
|
+
const history = await callTool('fw_weaver_history', { id: runId }) as unknown[];
|
|
37
|
+
if (Array.isArray(history) && history.length > 0) {
|
|
38
|
+
const run = history[0] as Record<string, unknown>;
|
|
39
|
+
setStatus(run.success ? 'completed' : 'failed');
|
|
40
|
+
setSummary(run.summary as string || null);
|
|
41
|
+
} else {
|
|
42
|
+
setStatus('completed');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
} catch { /* non-fatal */ }
|
|
46
|
+
};
|
|
47
|
+
const interval = setInterval(poll, 3000);
|
|
48
|
+
poll();
|
|
49
|
+
return () => clearInterval(interval);
|
|
50
|
+
}, [runId, status, callTool]);
|
|
51
|
+
|
|
52
|
+
return React.createElement(Flex, {
|
|
53
|
+
variant: 'row-center-start-nowrap-10',
|
|
54
|
+
style: {
|
|
55
|
+
padding: '8px 12px',
|
|
56
|
+
borderRadius: 'var(--border-radius-regular)',
|
|
57
|
+
border: '1px solid var(--color-border-default)',
|
|
58
|
+
backgroundColor: 'var(--color-surface-low)',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
React.createElement(StatusIcon, {
|
|
62
|
+
status: status === 'running' ? 'running' : status === 'completed' ? 'completed' : 'failed',
|
|
63
|
+
size: 'sm',
|
|
64
|
+
}),
|
|
65
|
+
React.createElement(Flex, { variant: 'column-start-start-nowrap-2', style: { flex: 1, minWidth: 0 } },
|
|
66
|
+
React.createElement(Typography, {
|
|
67
|
+
variant: 'caption-thick', color: 'color-text-high',
|
|
68
|
+
style: { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' },
|
|
69
|
+
}, instruction),
|
|
70
|
+
summary && React.createElement(Typography, {
|
|
71
|
+
variant: 'smallCaption-regular', color: 'color-text-medium',
|
|
72
|
+
}, summary),
|
|
73
|
+
),
|
|
74
|
+
React.createElement(Button, {
|
|
75
|
+
size: 'xs', variant: 'clear', color: 'secondary',
|
|
76
|
+
onClick: () => openWorkspace({ runId, packId: '@synergenius/flow-weaver-pack-weaver', live: status === 'running' }),
|
|
77
|
+
}, 'Open'),
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = ChatBotResult;
|