@workbench-kit/shell-react 0.0.2-prototype.0.2.6 → 0.0.2-prototype.0.2.8
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 +41 -0
- package/package.json +9 -9
- package/src/{chat-ai-mock-proposals.ts → chat/ai-mock-proposals.ts} +39 -39
- package/src/{chat-command-input.ts → chat/command-input.ts} +52 -52
- package/src/{chat-command-policy.ts → chat/command-policy.ts} +54 -54
- package/src/{chat-command-surface.tsx → chat/command-surface.tsx} +155 -155
- package/src/{use-workbench-chat-command-proposals.ts → chat/use-chat-command-proposals.ts} +194 -194
- package/src/{chat-view-data.ts → chat/view-data.ts} +20 -20
- package/src/{chat-view.tsx → chat/view.tsx} +220 -220
- package/src/{command-inspector-surface.tsx → commands/inspector-surface.tsx} +46 -46
- package/src/{use-workbench-command-descriptors.ts → commands/use-command-descriptors.ts} +41 -41
- package/src/{use-context-key-revision.ts → commands/use-context-key-revision.ts} +18 -18
- package/src/{commands-view-data.ts → commands/view-data.ts} +17 -17
- package/src/{commands-view.tsx → commands/view.tsx} +43 -43
- package/src/devtools/WorkbenchDevtoolsPanel.tsx +124 -124
- package/src/devtools/WorkbenchDevtoolsShell.tsx +17 -17
- package/src/devtools/index.ts +11 -11
- package/src/devtools/use-workbench-devtools-snapshot.ts +84 -84
- package/src/devtools/workbench-devtools-snapshot.ts +140 -140
- package/src/devtools/workbench-devtools.css +82 -82
- package/src/{editor-area-dnd.ts → editor/area-dnd.ts} +69 -69
- package/src/{editor-area-model.ts → editor/area-model.ts} +71 -71
- package/src/{editor-area.css → editor/area.css} +454 -454
- package/src/{editor-area.tsx → editor/area.tsx} +676 -676
- package/src/{editor-host-surface.tsx → editor/host-surface.tsx} +631 -634
- package/src/{editor-pane-visibility.ts → editor/pane-visibility.ts} +130 -130
- package/src/{editor-resource.ts → editor/resource.ts} +36 -36
- package/src/{editor-state-storage.ts → editor/state-storage.ts} +182 -193
- package/src/{editor-tab-context-menu.ts → editor/tab-context-menu.ts} +118 -118
- package/src/{use-editor.ts → editor/use-editor.ts} +114 -107
- package/src/{editor-view-providers.tsx → editor/view-providers.tsx} +552 -552
- package/src/{editor-workspace-file-availability.ts → editor/workspace-file-availability.ts} +15 -15
- package/src/{editor-workspace-reconcile.tsx → editor/workspace-reconcile.tsx} +31 -28
- package/src/{explorer-context-menu.ts → explorer/context-menu.ts} +114 -114
- package/src/{createCommandWorkspaceExplorerPort.ts → explorer/create-command-workspace-explorer-port.ts} +86 -86
- package/src/{explorer-reveal.ts → explorer/reveal.ts} +112 -112
- package/src/{search-view-data.ts → explorer/search-view-data.ts} +15 -15
- package/src/{search-view.tsx → explorer/search-view.tsx} +65 -62
- package/src/{use-active-workspace-path.ts → explorer/use-active-workspace-path.ts} +15 -15
- package/src/{explorer-view-data.ts → explorer/view-data.ts} +58 -58
- package/src/{explorer-view.tsx → explorer/view.tsx} +227 -224
- package/src/{extension-context-menu.ts → extensions/context-menu.ts} +52 -52
- package/src/{extension-management-model.ts → extensions/management-model.ts} +313 -313
- package/src/{use-extension-management.ts → extensions/use-extension-management.ts} +241 -193
- package/src/{extensions-view-data.ts → extensions/view-data.ts} +19 -19
- package/src/{extensions-view.tsx → extensions/view.tsx} +63 -38
- package/src/{field-remap-demo.tsx → field-remap/demo.tsx} +18 -18
- package/src/{field-remap-editor-surface.tsx → field-remap/editor-surface.tsx} +36 -36
- package/src/{field-remap-flow-adapter.ts → field-remap/flow-adapter.ts} +240 -240
- package/src/{field-remap-flow.tsx → field-remap/flow.tsx} +369 -369
- package/src/{field-remap-graph.tsx → field-remap/graph.tsx} +559 -559
- package/src/field-remap/jsonata-transform.ts +166 -0
- package/src/{field-remap-panel.tsx → field-remap/panel.tsx} +193 -175
- package/src/{field-remap-samples.ts → field-remap/samples.ts} +352 -352
- package/src/{table-mapping-adapter.ts → field-remap/table-mapping-adapter.ts} +59 -59
- package/src/{field-remap-tree.tsx → field-remap/tree.tsx} +404 -404
- package/src/{field-remap-view-data.ts → field-remap/view-data.ts} +16 -16
- package/src/{field-remap-view.css → field-remap/view.css} +676 -676
- package/src/{field-remap-view.tsx → field-remap/view.tsx} +86 -86
- package/src/index.ts +212 -199
- package/src/{json-form-source-patch.ts → jdw/json-form-source-patch.ts} +323 -323
- package/src/{jdw-lab-view-data.ts → jdw/lab-view-data.ts} +25 -25
- package/src/{jdw-lab-view.css → jdw/lab-view.css} +21 -21
- package/src/{jdw-lab-view.tsx → jdw/lab-view.tsx} +79 -79
- package/src/{jdw-widget-form-view.tsx → jdw/widget-form-view.tsx} +68 -65
- package/src/{jdw-widget-preview-view.tsx → jdw/widget-preview-view.tsx} +54 -51
- package/src/{keybinding-overrides-storage.ts → management/keybinding-overrides-storage.ts} +49 -57
- package/src/{keybinding-management-settings.tsx → management/keybinding-settings.tsx} +16 -16
- package/src/{management-palette-commands.ts → management/palette-commands.ts} +38 -38
- package/src/{preference-settings-storage.ts → management/preference-settings-storage.ts} +50 -58
- package/src/{management-settings-ids.ts → management/settings-ids.ts} +12 -12
- package/src/{management-settings.tsx → management/settings.tsx} +96 -75
- package/src/{use-command-management.ts → management/use-command-management.ts} +191 -191
- package/src/{use-keybinding-management.ts → management/use-keybinding-management.ts} +130 -130
- package/src/{shell-model.tsx → shell/model.tsx} +149 -149
- package/src/{provider.tsx → shell/provider.tsx} +603 -573
- package/src/{shell-secondary-actions.tsx → shell/secondary-actions.tsx} +59 -59
- package/src/{shell-settings-constants.ts → shell/settings-constants.ts} +9 -9
- package/src/{shell-settings.tsx → shell/settings.tsx} +599 -599
- package/src/{shell.tsx → shell/shell.tsx} +680 -649
- package/src/{shell-titlebar-layout-controls.tsx → shell/titlebar-layout-controls.tsx} +4 -4
- package/src/{shell-view-host.tsx → shell/view-host.tsx} +212 -199
- package/src/{workbench-appearance-storage.ts → workbench/appearance-storage.ts} +107 -115
- package/src/{workbench-command-host.tsx → workbench/command-host.tsx} +243 -243
- package/src/{workbench-command-palette.ts → workbench/command-palette.ts} +208 -208
- package/src/{workbench-keybinding-bridge.ts → workbench/keybinding-bridge.ts} +54 -54
- package/src/{workbench-layout-storage.ts → workbench/layout-storage.ts} +134 -145
- package/src/{workbench-profile-modal.tsx → workbench/profile-modal.tsx} +118 -118
- package/src/{workbench-shell-command-registration.ts → workbench/shell-command-registration.ts} +58 -58
- package/src/{workbench-startup-gate.tsx → workbench/startup-gate.tsx} +136 -136
- package/src/{workbench-status-sections.ts → workbench/status-sections.ts} +43 -43
- package/src/{use-persisted-workbench-appearance.ts → workbench/use-persisted-appearance.ts} +33 -33
- package/src/{workbench-user-commands.ts → workbench/user-commands.ts} +46 -46
- package/src/{workspace-view-state.ts → workbench/workspace-view-state.ts} +35 -35
- package/src/jsonata-transform.ts +0 -36
|
@@ -1,220 +1,220 @@
|
|
|
1
|
-
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
-
import { ChatPanel, type ChatMessage } from '@workbench-kit/react/workbench/chat';
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
createMockAiChatCommandProposals,
|
|
6
|
-
createMockAiChatResponseContent,
|
|
7
|
-
} from './
|
|
8
|
-
import {
|
|
9
|
-
readWorkbenchAiChatCommandPolicyInput,
|
|
10
|
-
mergeWorkbenchAiChatCommandPolicyInput,
|
|
11
|
-
} from './
|
|
12
|
-
import {
|
|
13
|
-
useWorkbenchChatCommandSurface,
|
|
14
|
-
type WorkbenchChatCommandRunResult,
|
|
15
|
-
} from './
|
|
16
|
-
import { type BuiltinChatViewMode, type BuiltinChatViewRenderData } from './
|
|
17
|
-
import { useWorkbenchChatCommandProposals } from './use-
|
|
18
|
-
import { useWorkbenchCommandDescriptors } from '
|
|
19
|
-
|
|
20
|
-
export type { BuiltinChatViewMode, BuiltinChatViewRenderData };
|
|
21
|
-
export { BUILTIN_CHAT_VIEW_RENDER_KIND, isBuiltinChatViewRenderData } from './
|
|
22
|
-
|
|
23
|
-
type BuiltinChatRuntimeStatus = 'idle' | 'running' | 'error';
|
|
24
|
-
|
|
25
|
-
const initialChattingMessages: readonly ChatMessage[] = [
|
|
26
|
-
{
|
|
27
|
-
content: 'Share updates here while working in the workspace.',
|
|
28
|
-
createdAt: '2026-06-18T14:29:00.000Z',
|
|
29
|
-
id: 'workbench-chatting-intro',
|
|
30
|
-
label: 'Alex',
|
|
31
|
-
source: 'assistant',
|
|
32
|
-
},
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
const initialAiChatMessages: readonly ChatMessage[] = [
|
|
36
|
-
{
|
|
37
|
-
content: 'Ask about the workspace or run a command with `/command.id`.',
|
|
38
|
-
createdAt: '2026-06-18T14:29:00.000Z',
|
|
39
|
-
id: 'workbench-ai-chat-intro',
|
|
40
|
-
label: 'Assistant',
|
|
41
|
-
source: 'assistant',
|
|
42
|
-
},
|
|
43
|
-
];
|
|
44
|
-
|
|
45
|
-
export function BuiltinChatView({ mode }: { mode: BuiltinChatViewMode }) {
|
|
46
|
-
if (mode === 'aiChat') {
|
|
47
|
-
return <BuiltinAiChatView />;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return <BuiltinChattingView />;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function createChatCommandFeedbackMessage(result: WorkbenchChatCommandRunResult): ChatMessage {
|
|
54
|
-
const title = result.label ?? result.commandId;
|
|
55
|
-
const status =
|
|
56
|
-
result.status === 'success' ? `Ran command \`${title}\`.` : `Command failed: \`${title}\`.`;
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
content: result.message ? `${status}\n\n${result.message}` : status,
|
|
60
|
-
createdAt: new Date().toISOString(),
|
|
61
|
-
id: `chat-command-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
62
|
-
label: 'Workbench',
|
|
63
|
-
source: 'assistant',
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function createChatMessageId(prefix: string) {
|
|
68
|
-
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function BuiltinChattingView() {
|
|
72
|
-
const [draft, setDraft] = useState('');
|
|
73
|
-
const [messages, setMessages] = useState<ChatMessage[]>(() => [...initialChattingMessages]);
|
|
74
|
-
const appendCommandResult = useCallback((result: WorkbenchChatCommandRunResult) => {
|
|
75
|
-
setMessages((currentMessages) => [
|
|
76
|
-
...currentMessages,
|
|
77
|
-
createChatCommandFeedbackMessage(result),
|
|
78
|
-
]);
|
|
79
|
-
}, []);
|
|
80
|
-
const chatCommands = useWorkbenchChatCommandSurface({
|
|
81
|
-
onCommandResult: appendCommandResult,
|
|
82
|
-
onValueChange: setDraft,
|
|
83
|
-
value: draft,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
return (
|
|
87
|
-
<div className="workbench-chat-view">
|
|
88
|
-
<ChatPanel
|
|
89
|
-
assistantLabel="Alex"
|
|
90
|
-
commandLabel="Show commands"
|
|
91
|
-
commandSuggestPopover={chatCommands.commandSuggestPopover}
|
|
92
|
-
composerRef={chatCommands.composerRef}
|
|
93
|
-
emptyLabel="Start a conversation with your team."
|
|
94
|
-
messageLayout="peer"
|
|
95
|
-
messages={messages}
|
|
96
|
-
placeholder="Message your team"
|
|
97
|
-
title="Chat"
|
|
98
|
-
userLabel="Jay"
|
|
99
|
-
value={draft}
|
|
100
|
-
onCommandClick={chatCommands.onCommandClick}
|
|
101
|
-
onKeyDown={chatCommands.onKeyDown}
|
|
102
|
-
onSubmit={(message) => {
|
|
103
|
-
if (chatCommands.runInputAsCommand(message)) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
setDraft('');
|
|
108
|
-
setMessages((currentMessages) => [
|
|
109
|
-
...currentMessages,
|
|
110
|
-
{
|
|
111
|
-
content: message,
|
|
112
|
-
createdAt: new Date().toISOString(),
|
|
113
|
-
id: createChatMessageId('chatting-user'),
|
|
114
|
-
source: 'user',
|
|
115
|
-
},
|
|
116
|
-
]);
|
|
117
|
-
}}
|
|
118
|
-
onValueChange={setDraft}
|
|
119
|
-
/>
|
|
120
|
-
</div>
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function BuiltinAiChatView() {
|
|
125
|
-
const [draft, setDraft] = useState('');
|
|
126
|
-
const [messages, setMessages] = useState<ChatMessage[]>(() => [...initialAiChatMessages]);
|
|
127
|
-
const [runtimeStatus, setRuntimeStatus] = useState<BuiltinChatRuntimeStatus>('idle');
|
|
128
|
-
const commands = useWorkbenchCommandDescriptors();
|
|
129
|
-
const policyInput = useMemo(
|
|
130
|
-
() =>
|
|
131
|
-
mergeWorkbenchAiChatCommandPolicyInput(readWorkbenchAiChatCommandPolicyInput(), {
|
|
132
|
-
policyByCommandId: {
|
|
133
|
-
'workbench.togglePrimarySidebar': 'approval-required',
|
|
134
|
-
},
|
|
135
|
-
}),
|
|
136
|
-
[],
|
|
137
|
-
);
|
|
138
|
-
const appendCommandResult = useCallback((result: WorkbenchChatCommandRunResult) => {
|
|
139
|
-
setMessages((currentMessages) => [
|
|
140
|
-
...currentMessages,
|
|
141
|
-
createChatCommandFeedbackMessage(result),
|
|
142
|
-
]);
|
|
143
|
-
}, []);
|
|
144
|
-
const chatCommands = useWorkbenchChatCommandSurface({
|
|
145
|
-
onCommandResult: appendCommandResult,
|
|
146
|
-
onValueChange: setDraft,
|
|
147
|
-
value: draft,
|
|
148
|
-
});
|
|
149
|
-
const { createProposalHandlers, enrichMessageProposals, processAutoPolicies } =
|
|
150
|
-
useWorkbenchChatCommandProposals({
|
|
151
|
-
commands,
|
|
152
|
-
onCommandResult: appendCommandResult,
|
|
153
|
-
policyInput,
|
|
154
|
-
});
|
|
155
|
-
const proposalHandlers = useMemo(
|
|
156
|
-
() => createProposalHandlers(setMessages),
|
|
157
|
-
[createProposalHandlers],
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
return (
|
|
161
|
-
<div className="workbench-chat-view">
|
|
162
|
-
<ChatPanel
|
|
163
|
-
assistantLabel="Assistant"
|
|
164
|
-
commandLabel="Show commands"
|
|
165
|
-
commandSuggestPopover={chatCommands.commandSuggestPopover}
|
|
166
|
-
composerRef={chatCommands.composerRef}
|
|
167
|
-
disabled={runtimeStatus === 'error'}
|
|
168
|
-
emptyLabel="Ask about this workspace."
|
|
169
|
-
isRunning={runtimeStatus === 'running'}
|
|
170
|
-
messageLayout="assistant"
|
|
171
|
-
messages={messages}
|
|
172
|
-
placeholder="Ask about this workspace"
|
|
173
|
-
showTools
|
|
174
|
-
title="AI Chat"
|
|
175
|
-
value={draft}
|
|
176
|
-
onCancel={() => setRuntimeStatus('idle')}
|
|
177
|
-
onCommandClick={chatCommands.onCommandClick}
|
|
178
|
-
onCommandProposalAllow={proposalHandlers.onProposalAllow}
|
|
179
|
-
onCommandProposalDeny={proposalHandlers.onProposalDeny}
|
|
180
|
-
onKeyDown={chatCommands.onKeyDown}
|
|
181
|
-
onSubmit={(message) => {
|
|
182
|
-
if (chatCommands.runInputAsCommand(message)) {
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
setDraft('');
|
|
187
|
-
setRuntimeStatus('running');
|
|
188
|
-
|
|
189
|
-
const assistantMessageId = createChatMessageId('ai-chat-assistant');
|
|
190
|
-
const rawProposals = createMockAiChatCommandProposals(message);
|
|
191
|
-
const commandProposalsForMessage = enrichMessageProposals(rawProposals);
|
|
192
|
-
const assistantMessage: ChatMessage = {
|
|
193
|
-
commandProposals: commandProposalsForMessage.length
|
|
194
|
-
? commandProposalsForMessage
|
|
195
|
-
: undefined,
|
|
196
|
-
content: createMockAiChatResponseContent(message),
|
|
197
|
-
createdAt: new Date().toISOString(),
|
|
198
|
-
id: assistantMessageId,
|
|
199
|
-
label: 'Assistant',
|
|
200
|
-
source: 'assistant',
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
setMessages((currentMessages) => [
|
|
204
|
-
...currentMessages,
|
|
205
|
-
{
|
|
206
|
-
content: message,
|
|
207
|
-
createdAt: new Date().toISOString(),
|
|
208
|
-
id: createChatMessageId('ai-chat-user'),
|
|
209
|
-
source: 'user',
|
|
210
|
-
},
|
|
211
|
-
assistantMessage,
|
|
212
|
-
]);
|
|
213
|
-
processAutoPolicies(setMessages, assistantMessageId, commandProposalsForMessage);
|
|
214
|
-
setRuntimeStatus('idle');
|
|
215
|
-
}}
|
|
216
|
-
onValueChange={setDraft}
|
|
217
|
-
/>
|
|
218
|
-
</div>
|
|
219
|
-
);
|
|
220
|
-
}
|
|
1
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
2
|
+
import { ChatPanel, type ChatMessage } from '@workbench-kit/react/workbench/chat';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createMockAiChatCommandProposals,
|
|
6
|
+
createMockAiChatResponseContent,
|
|
7
|
+
} from './ai-mock-proposals.js';
|
|
8
|
+
import {
|
|
9
|
+
readWorkbenchAiChatCommandPolicyInput,
|
|
10
|
+
mergeWorkbenchAiChatCommandPolicyInput,
|
|
11
|
+
} from './command-policy.js';
|
|
12
|
+
import {
|
|
13
|
+
useWorkbenchChatCommandSurface,
|
|
14
|
+
type WorkbenchChatCommandRunResult,
|
|
15
|
+
} from './command-surface.js';
|
|
16
|
+
import { type BuiltinChatViewMode, type BuiltinChatViewRenderData } from './view-data.js';
|
|
17
|
+
import { useWorkbenchChatCommandProposals } from './use-chat-command-proposals.js';
|
|
18
|
+
import { useWorkbenchCommandDescriptors } from '../commands/use-command-descriptors.js';
|
|
19
|
+
|
|
20
|
+
export type { BuiltinChatViewMode, BuiltinChatViewRenderData };
|
|
21
|
+
export { BUILTIN_CHAT_VIEW_RENDER_KIND, isBuiltinChatViewRenderData } from './view-data.js';
|
|
22
|
+
|
|
23
|
+
type BuiltinChatRuntimeStatus = 'idle' | 'running' | 'error';
|
|
24
|
+
|
|
25
|
+
const initialChattingMessages: readonly ChatMessage[] = [
|
|
26
|
+
{
|
|
27
|
+
content: 'Share updates here while working in the workspace.',
|
|
28
|
+
createdAt: '2026-06-18T14:29:00.000Z',
|
|
29
|
+
id: 'workbench-chatting-intro',
|
|
30
|
+
label: 'Alex',
|
|
31
|
+
source: 'assistant',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const initialAiChatMessages: readonly ChatMessage[] = [
|
|
36
|
+
{
|
|
37
|
+
content: 'Ask about the workspace or run a command with `/command.id`.',
|
|
38
|
+
createdAt: '2026-06-18T14:29:00.000Z',
|
|
39
|
+
id: 'workbench-ai-chat-intro',
|
|
40
|
+
label: 'Assistant',
|
|
41
|
+
source: 'assistant',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
export function BuiltinChatView({ mode }: { mode: BuiltinChatViewMode }) {
|
|
46
|
+
if (mode === 'aiChat') {
|
|
47
|
+
return <BuiltinAiChatView />;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return <BuiltinChattingView />;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function createChatCommandFeedbackMessage(result: WorkbenchChatCommandRunResult): ChatMessage {
|
|
54
|
+
const title = result.label ?? result.commandId;
|
|
55
|
+
const status =
|
|
56
|
+
result.status === 'success' ? `Ran command \`${title}\`.` : `Command failed: \`${title}\`.`;
|
|
57
|
+
|
|
58
|
+
return {
|
|
59
|
+
content: result.message ? `${status}\n\n${result.message}` : status,
|
|
60
|
+
createdAt: new Date().toISOString(),
|
|
61
|
+
id: `chat-command-${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
62
|
+
label: 'Workbench',
|
|
63
|
+
source: 'assistant',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function createChatMessageId(prefix: string) {
|
|
68
|
+
return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function BuiltinChattingView() {
|
|
72
|
+
const [draft, setDraft] = useState('');
|
|
73
|
+
const [messages, setMessages] = useState<ChatMessage[]>(() => [...initialChattingMessages]);
|
|
74
|
+
const appendCommandResult = useCallback((result: WorkbenchChatCommandRunResult) => {
|
|
75
|
+
setMessages((currentMessages) => [
|
|
76
|
+
...currentMessages,
|
|
77
|
+
createChatCommandFeedbackMessage(result),
|
|
78
|
+
]);
|
|
79
|
+
}, []);
|
|
80
|
+
const chatCommands = useWorkbenchChatCommandSurface({
|
|
81
|
+
onCommandResult: appendCommandResult,
|
|
82
|
+
onValueChange: setDraft,
|
|
83
|
+
value: draft,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<div className="workbench-chat-view">
|
|
88
|
+
<ChatPanel
|
|
89
|
+
assistantLabel="Alex"
|
|
90
|
+
commandLabel="Show commands"
|
|
91
|
+
commandSuggestPopover={chatCommands.commandSuggestPopover}
|
|
92
|
+
composerRef={chatCommands.composerRef}
|
|
93
|
+
emptyLabel="Start a conversation with your team."
|
|
94
|
+
messageLayout="peer"
|
|
95
|
+
messages={messages}
|
|
96
|
+
placeholder="Message your team"
|
|
97
|
+
title="Chat"
|
|
98
|
+
userLabel="Jay"
|
|
99
|
+
value={draft}
|
|
100
|
+
onCommandClick={chatCommands.onCommandClick}
|
|
101
|
+
onKeyDown={chatCommands.onKeyDown}
|
|
102
|
+
onSubmit={(message) => {
|
|
103
|
+
if (chatCommands.runInputAsCommand(message)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
setDraft('');
|
|
108
|
+
setMessages((currentMessages) => [
|
|
109
|
+
...currentMessages,
|
|
110
|
+
{
|
|
111
|
+
content: message,
|
|
112
|
+
createdAt: new Date().toISOString(),
|
|
113
|
+
id: createChatMessageId('chatting-user'),
|
|
114
|
+
source: 'user',
|
|
115
|
+
},
|
|
116
|
+
]);
|
|
117
|
+
}}
|
|
118
|
+
onValueChange={setDraft}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function BuiltinAiChatView() {
|
|
125
|
+
const [draft, setDraft] = useState('');
|
|
126
|
+
const [messages, setMessages] = useState<ChatMessage[]>(() => [...initialAiChatMessages]);
|
|
127
|
+
const [runtimeStatus, setRuntimeStatus] = useState<BuiltinChatRuntimeStatus>('idle');
|
|
128
|
+
const commands = useWorkbenchCommandDescriptors();
|
|
129
|
+
const policyInput = useMemo(
|
|
130
|
+
() =>
|
|
131
|
+
mergeWorkbenchAiChatCommandPolicyInput(readWorkbenchAiChatCommandPolicyInput(), {
|
|
132
|
+
policyByCommandId: {
|
|
133
|
+
'workbench.togglePrimarySidebar': 'approval-required',
|
|
134
|
+
},
|
|
135
|
+
}),
|
|
136
|
+
[],
|
|
137
|
+
);
|
|
138
|
+
const appendCommandResult = useCallback((result: WorkbenchChatCommandRunResult) => {
|
|
139
|
+
setMessages((currentMessages) => [
|
|
140
|
+
...currentMessages,
|
|
141
|
+
createChatCommandFeedbackMessage(result),
|
|
142
|
+
]);
|
|
143
|
+
}, []);
|
|
144
|
+
const chatCommands = useWorkbenchChatCommandSurface({
|
|
145
|
+
onCommandResult: appendCommandResult,
|
|
146
|
+
onValueChange: setDraft,
|
|
147
|
+
value: draft,
|
|
148
|
+
});
|
|
149
|
+
const { createProposalHandlers, enrichMessageProposals, processAutoPolicies } =
|
|
150
|
+
useWorkbenchChatCommandProposals({
|
|
151
|
+
commands,
|
|
152
|
+
onCommandResult: appendCommandResult,
|
|
153
|
+
policyInput,
|
|
154
|
+
});
|
|
155
|
+
const proposalHandlers = useMemo(
|
|
156
|
+
() => createProposalHandlers(setMessages),
|
|
157
|
+
[createProposalHandlers],
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<div className="workbench-chat-view">
|
|
162
|
+
<ChatPanel
|
|
163
|
+
assistantLabel="Assistant"
|
|
164
|
+
commandLabel="Show commands"
|
|
165
|
+
commandSuggestPopover={chatCommands.commandSuggestPopover}
|
|
166
|
+
composerRef={chatCommands.composerRef}
|
|
167
|
+
disabled={runtimeStatus === 'error'}
|
|
168
|
+
emptyLabel="Ask about this workspace."
|
|
169
|
+
isRunning={runtimeStatus === 'running'}
|
|
170
|
+
messageLayout="assistant"
|
|
171
|
+
messages={messages}
|
|
172
|
+
placeholder="Ask about this workspace"
|
|
173
|
+
showTools
|
|
174
|
+
title="AI Chat"
|
|
175
|
+
value={draft}
|
|
176
|
+
onCancel={() => setRuntimeStatus('idle')}
|
|
177
|
+
onCommandClick={chatCommands.onCommandClick}
|
|
178
|
+
onCommandProposalAllow={proposalHandlers.onProposalAllow}
|
|
179
|
+
onCommandProposalDeny={proposalHandlers.onProposalDeny}
|
|
180
|
+
onKeyDown={chatCommands.onKeyDown}
|
|
181
|
+
onSubmit={(message) => {
|
|
182
|
+
if (chatCommands.runInputAsCommand(message)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
setDraft('');
|
|
187
|
+
setRuntimeStatus('running');
|
|
188
|
+
|
|
189
|
+
const assistantMessageId = createChatMessageId('ai-chat-assistant');
|
|
190
|
+
const rawProposals = createMockAiChatCommandProposals(message);
|
|
191
|
+
const commandProposalsForMessage = enrichMessageProposals(rawProposals);
|
|
192
|
+
const assistantMessage: ChatMessage = {
|
|
193
|
+
commandProposals: commandProposalsForMessage.length
|
|
194
|
+
? commandProposalsForMessage
|
|
195
|
+
: undefined,
|
|
196
|
+
content: createMockAiChatResponseContent(message),
|
|
197
|
+
createdAt: new Date().toISOString(),
|
|
198
|
+
id: assistantMessageId,
|
|
199
|
+
label: 'Assistant',
|
|
200
|
+
source: 'assistant',
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
setMessages((currentMessages) => [
|
|
204
|
+
...currentMessages,
|
|
205
|
+
{
|
|
206
|
+
content: message,
|
|
207
|
+
createdAt: new Date().toISOString(),
|
|
208
|
+
id: createChatMessageId('ai-chat-user'),
|
|
209
|
+
source: 'user',
|
|
210
|
+
},
|
|
211
|
+
assistantMessage,
|
|
212
|
+
]);
|
|
213
|
+
processAutoPolicies(setMessages, assistantMessageId, commandProposalsForMessage);
|
|
214
|
+
setRuntimeStatus('idle');
|
|
215
|
+
}}
|
|
216
|
+
onValueChange={setDraft}
|
|
217
|
+
/>
|
|
218
|
+
</div>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import { ScrollArea } from '@workbench-kit/react/primitives';
|
|
2
|
-
import {
|
|
3
|
-
CommandInspectorPanel,
|
|
4
|
-
findCommandManagementEntry,
|
|
5
|
-
} from '@workbench-kit/react/workbench/management';
|
|
6
|
-
|
|
7
|
-
import { useCommandManagementModel } from '
|
|
8
|
-
|
|
9
|
-
export interface CommandInspectorSurfaceProps {
|
|
10
|
-
commandId: string;
|
|
11
|
-
resourceUri: string;
|
|
12
|
-
tabId: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function CommandInspectorSurface({
|
|
16
|
-
commandId,
|
|
17
|
-
resourceUri,
|
|
18
|
-
tabId,
|
|
19
|
-
}: CommandInspectorSurfaceProps) {
|
|
20
|
-
const { groups, lastRun, runCommand } = useCommandManagementModel();
|
|
21
|
-
const entry = findCommandManagementEntry(groups, commandId);
|
|
22
|
-
|
|
23
|
-
if (!entry) {
|
|
24
|
-
return (
|
|
25
|
-
<section
|
|
26
|
-
aria-label="Command inspector"
|
|
27
|
-
className="workbench-command-inspector-surface"
|
|
28
|
-
data-editor-host-id={tabId}
|
|
29
|
-
data-resource-uri={resourceUri}
|
|
30
|
-
>
|
|
31
|
-
<div className="workbench-command-inspector-surface__missing" role="alert">
|
|
32
|
-
<p className="workbench-command-inspector-surface__missing-title">Command not found</p>
|
|
33
|
-
<p className="workbench-command-inspector-surface__missing-message">
|
|
34
|
-
No registry entry matches <code>{commandId}</code>.
|
|
35
|
-
</p>
|
|
36
|
-
</div>
|
|
37
|
-
</section>
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
return (
|
|
42
|
-
<ScrollArea className="workbench-command-inspector-surface" orientation="vertical">
|
|
43
|
-
<CommandInspectorPanel entry={entry} lastRun={lastRun} onRunCommand={runCommand} />
|
|
44
|
-
</ScrollArea>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
1
|
+
import { ScrollArea } from '@workbench-kit/react/primitives';
|
|
2
|
+
import {
|
|
3
|
+
CommandInspectorPanel,
|
|
4
|
+
findCommandManagementEntry,
|
|
5
|
+
} from '@workbench-kit/react/workbench/management';
|
|
6
|
+
|
|
7
|
+
import { useCommandManagementModel } from '../management/use-command-management.js';
|
|
8
|
+
|
|
9
|
+
export interface CommandInspectorSurfaceProps {
|
|
10
|
+
commandId: string;
|
|
11
|
+
resourceUri: string;
|
|
12
|
+
tabId: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function CommandInspectorSurface({
|
|
16
|
+
commandId,
|
|
17
|
+
resourceUri,
|
|
18
|
+
tabId,
|
|
19
|
+
}: CommandInspectorSurfaceProps) {
|
|
20
|
+
const { groups, lastRun, runCommand } = useCommandManagementModel();
|
|
21
|
+
const entry = findCommandManagementEntry(groups, commandId);
|
|
22
|
+
|
|
23
|
+
if (!entry) {
|
|
24
|
+
return (
|
|
25
|
+
<section
|
|
26
|
+
aria-label="Command inspector"
|
|
27
|
+
className="workbench-command-inspector-surface"
|
|
28
|
+
data-editor-host-id={tabId}
|
|
29
|
+
data-resource-uri={resourceUri}
|
|
30
|
+
>
|
|
31
|
+
<div className="workbench-command-inspector-surface__missing" role="alert">
|
|
32
|
+
<p className="workbench-command-inspector-surface__missing-title">Command not found</p>
|
|
33
|
+
<p className="workbench-command-inspector-surface__missing-message">
|
|
34
|
+
No registry entry matches <code>{commandId}</code>.
|
|
35
|
+
</p>
|
|
36
|
+
</div>
|
|
37
|
+
</section>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<ScrollArea className="workbench-command-inspector-surface" orientation="vertical">
|
|
43
|
+
<CommandInspectorPanel entry={entry} lastRun={lastRun} onRunCommand={runCommand} />
|
|
44
|
+
</ScrollArea>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import { useEffect, useMemo, useReducer } from 'react';
|
|
2
|
-
import type { WorkbenchCommandDescriptor } from '@workbench-kit/react/workbench';
|
|
3
|
-
|
|
4
|
-
import { useWorkbench } from '
|
|
5
|
-
import {
|
|
6
|
-
collectExtensionCommandFeaturesById,
|
|
7
|
-
extensionCommandToDescriptor,
|
|
8
|
-
mergeWorkbenchCommandDescriptors,
|
|
9
|
-
} from '
|
|
10
|
-
|
|
11
|
-
const EMPTY_COMMAND_DESCRIPTORS: readonly WorkbenchCommandDescriptor[] = [];
|
|
12
|
-
|
|
13
|
-
export function useWorkbenchCommandDescriptors(
|
|
14
|
-
additionalCommands: readonly WorkbenchCommandDescriptor[] = EMPTY_COMMAND_DESCRIPTORS,
|
|
15
|
-
) {
|
|
16
|
-
const { extensionRegistry } = useWorkbench();
|
|
17
|
-
const [refreshToken, refreshCommands] = useReducer((count: number) => count + 1, 0);
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
const disposable = extensionRegistry.commands.onDidRegisterCommand(() => {
|
|
21
|
-
refreshCommands();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
return () => {
|
|
25
|
-
disposable.dispose();
|
|
26
|
-
};
|
|
27
|
-
}, [extensionRegistry.commands]);
|
|
28
|
-
|
|
29
|
-
return useMemo(() => {
|
|
30
|
-
const commandFeaturesById = collectExtensionCommandFeaturesById(extensionRegistry);
|
|
31
|
-
|
|
32
|
-
return mergeWorkbenchCommandDescriptors(
|
|
33
|
-
extensionRegistry.commands
|
|
34
|
-
.getCommands()
|
|
35
|
-
.map((command) =>
|
|
36
|
-
extensionCommandToDescriptor(command, commandFeaturesById.get(command.id)),
|
|
37
|
-
),
|
|
38
|
-
[...additionalCommands],
|
|
39
|
-
);
|
|
40
|
-
}, [additionalCommands, extensionRegistry, refreshToken]);
|
|
41
|
-
}
|
|
1
|
+
import { useEffect, useMemo, useReducer } from 'react';
|
|
2
|
+
import type { WorkbenchCommandDescriptor } from '@workbench-kit/react/workbench';
|
|
3
|
+
|
|
4
|
+
import { useWorkbench } from '../shell/provider.js';
|
|
5
|
+
import {
|
|
6
|
+
collectExtensionCommandFeaturesById,
|
|
7
|
+
extensionCommandToDescriptor,
|
|
8
|
+
mergeWorkbenchCommandDescriptors,
|
|
9
|
+
} from '../workbench/command-palette.js';
|
|
10
|
+
|
|
11
|
+
const EMPTY_COMMAND_DESCRIPTORS: readonly WorkbenchCommandDescriptor[] = [];
|
|
12
|
+
|
|
13
|
+
export function useWorkbenchCommandDescriptors(
|
|
14
|
+
additionalCommands: readonly WorkbenchCommandDescriptor[] = EMPTY_COMMAND_DESCRIPTORS,
|
|
15
|
+
) {
|
|
16
|
+
const { extensionRegistry } = useWorkbench();
|
|
17
|
+
const [refreshToken, refreshCommands] = useReducer((count: number) => count + 1, 0);
|
|
18
|
+
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
const disposable = extensionRegistry.commands.onDidRegisterCommand(() => {
|
|
21
|
+
refreshCommands();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
disposable.dispose();
|
|
26
|
+
};
|
|
27
|
+
}, [extensionRegistry.commands]);
|
|
28
|
+
|
|
29
|
+
return useMemo(() => {
|
|
30
|
+
const commandFeaturesById = collectExtensionCommandFeaturesById(extensionRegistry);
|
|
31
|
+
|
|
32
|
+
return mergeWorkbenchCommandDescriptors(
|
|
33
|
+
extensionRegistry.commands
|
|
34
|
+
.getCommands()
|
|
35
|
+
.map((command) =>
|
|
36
|
+
extensionCommandToDescriptor(command, commandFeaturesById.get(command.id)),
|
|
37
|
+
),
|
|
38
|
+
[...additionalCommands],
|
|
39
|
+
);
|
|
40
|
+
}, [additionalCommands, extensionRegistry, refreshToken]);
|
|
41
|
+
}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import type { ContextKeyService } from '@workbench-kit/platform';
|
|
3
|
-
|
|
4
|
-
export function useContextKeyRevision(contextKeyService: ContextKeyService): number {
|
|
5
|
-
const [revision, setRevision] = useState(0);
|
|
6
|
-
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
const disposable = contextKeyService.onDidChangeContext(() => {
|
|
9
|
-
setRevision((current) => current + 1);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
return () => {
|
|
13
|
-
disposable.dispose();
|
|
14
|
-
};
|
|
15
|
-
}, [contextKeyService]);
|
|
16
|
-
|
|
17
|
-
return revision;
|
|
18
|
-
}
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import type { ContextKeyService } from '@workbench-kit/platform';
|
|
3
|
+
|
|
4
|
+
export function useContextKeyRevision(contextKeyService: ContextKeyService): number {
|
|
5
|
+
const [revision, setRevision] = useState(0);
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const disposable = contextKeyService.onDidChangeContext(() => {
|
|
9
|
+
setRevision((current) => current + 1);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
return () => {
|
|
13
|
+
disposable.dispose();
|
|
14
|
+
};
|
|
15
|
+
}, [contextKeyService]);
|
|
16
|
+
|
|
17
|
+
return revision;
|
|
18
|
+
}
|