Skip to content

Commit 43b6c93

Browse files
committed
feat: enable WinRM terminal and AI foreground execution
1 parent fd0e546 commit 43b6c93

16 files changed

Lines changed: 87 additions & 26 deletions

‎ui/components/RightPanel/ai/AiRunStep.vue‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ const props = withDefaults(
2323
executionOverrides: ReadonlyMap<string, string>;
2424
executionMode: string;
2525
approvalMode: string;
26+
ptyExec?: boolean;
2627
backgroundExec: boolean;
2728
readOnly?: boolean;
2829
}>(),
29-
{ expanded: undefined }
30+
{ expanded: undefined, ptyExec: true }
3031
);
3132
3233
const emit = defineEmits<{
@@ -144,7 +145,7 @@ function statusIconClass() {
144145
}
145146
146147
function selectedExecution(data: TerminalAiEventData) {
147-
return terminalExecutionMode(props.executionOverrides.get(String(data.id)) || data.execution);
148+
return terminalExecutionMode(props.executionOverrides.get(String(data.id)) || data.execution, props);
148149
}
149150
150151
function executionLabel(value: unknown) {
@@ -247,6 +248,7 @@ function terminalRiskLabel(level: unknown) {
247248
@click="emit('setExecutionOverride', String(execution.command?.id), 'auto')"
248249
/>
249250
<UButton
251+
v-if="ptyExec"
250252
size="xs"
251253
color="neutral"
252254
class="exec-group-btn"

‎ui/components/RightPanel/ai/domains/terminal/TerminalAiTimelineItem.vue‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ function setExecutionOverride(id: string, value: string) {
4747
:execution-overrides="terminalSession.executionOverrides"
4848
:execution-mode="terminalSession.executionMode"
4949
:approval-mode="terminalSession.approvalMode"
50+
:pty-exec="terminalSession.ptyExec"
5051
:background-exec="terminalSession.backgroundExec"
5152
:read-only="readOnly"
5253
@decide="decide"

‎ui/components/RightPanel/ai/domains/terminal/adapter.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function handleDecision(session: KokoTerminalAiSession, action: Extract<AiTimeli
4545
if (!decisionId || session.decisions.has(decisionId)) return;
4646

4747
const override = session.executionOverrides.get(decisionId);
48-
const execution = terminalExecutionMode(override || action.data.execution);
48+
const execution = terminalExecutionMode(override || action.data.execution, session);
4949
const toolCallId = String(action.data.toolCallId || "");
5050
if (action.approved && toolCallId && (override || execution !== "auto")) {
5151
session.executionOverrides.set(toolCallId, execution);
@@ -174,7 +174,8 @@ export const terminalAiPanelDomain: AiPanelDomainAdapter = {
174174
{
175175
label: context.t("RightPanel.AIModePtyShort"),
176176
description: context.t("RightPanel.AIModePty"),
177-
value: "pty"
177+
value: "pty",
178+
disabled: !current.ptyExec
178179
},
179180
{
180181
label: context.t("RightPanel.AIModeBackgroundShort"),
@@ -253,8 +254,7 @@ export const terminalAiPanelDomain: AiPanelDomainAdapter = {
253254
updateExecutionMode(session, value) {
254255
const current = terminalSession(session);
255256
if (!current) return;
256-
const mode = String(value || "auto");
257-
current.executionMode = mode === "pty" || mode === "background" ? mode : "auto";
257+
current.executionMode = terminalExecutionMode(value, current);
258258
},
259259

260260
handleTimelineAction(session, action) {
@@ -265,7 +265,7 @@ export const terminalAiPanelDomain: AiPanelDomainAdapter = {
265265
return;
266266
}
267267
if (action.type === "set-execution-override") {
268-
current.executionOverrides.set(action.id, action.value);
268+
current.executionOverrides.set(action.id, terminalExecutionMode(action.value, current));
269269
return;
270270
}
271271
if (action.type === "set-step-expanded") {

‎ui/composables/useAssetAction.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,9 +1205,7 @@ export const useAssetAction = () => {
12051205
getAssetDetailRequest(assetId)
12061206
.then((assetDetail) => {
12071207
const permedAccounts = assetDetail.permed_accounts ?? [];
1208-
const permedProtocols = (assetDetail.permed_protocols ?? []).filter(
1209-
(protocol: PermedProtocol) => protocol?.name !== "winrm"
1210-
);
1208+
const permedProtocols = assetDetail.permed_protocols ?? [];
12111209

12121210
useEventBus().emit("assetDetailUpdated", {
12131211
assetId,

‎ui/composables/useConnectionFormState.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,9 +348,7 @@ export function useConnectionFormState() {
348348
return {
349349
...asset,
350350
permedAccounts: detail.permed_accounts ?? asset.permedAccounts ?? [],
351-
permedProtocols: (detail.permed_protocols ?? asset.permedProtocols ?? []).filter(
352-
(protocol: PermedProtocol) => protocol?.name !== "winrm"
353-
)
351+
permedProtocols: detail.permed_protocols ?? asset.permedProtocols ?? []
354352
};
355353
};
356354

‎ui/composables/useSessionWindowConnect.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export function toAdminAssetItem(
100100
const item = transformAssetDetail(assetId, {
101101
...asset,
102102
permed_protocols: (asset.permed_protocols || asset.protocols || []).filter(
103-
(protocol) => protocol?.name && protocol.name !== "winrm"
103+
(protocol) => protocol?.name
104104
) as AssetDetail["permed_protocols"],
105105
permed_accounts: [
106106
{

‎ui/composables/useSidebarAssetActions.ts‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,7 @@ export function useSidebarAssetActions() {
8888
return {
8989
...asset,
9090
permedAccounts: detail.permed_accounts ?? asset.permedAccounts ?? [],
91-
permedProtocols: (detail.permed_protocols ?? asset.permedProtocols ?? []).filter(
92-
(protocol: { name?: string }) => protocol?.name !== "winrm"
93-
)
91+
permedProtocols: detail.permed_protocols ?? asset.permedProtocols ?? []
9492
};
9593
};
9694

‎ui/composables/useWorkspaceAssistantSession.test.ts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ describe("Workspace Assistant capability", () => {
119119
expect(() => workspaceAssistantConnectionChoices(asset, "ssh", "missing")).toThrow("not authorized");
120120
});
121121

122+
it("offers an authorized WinRM connection to the assistant", () => {
123+
const asset = {
124+
permedProtocols: [{ name: "winrm", public: true }],
125+
permedAccounts: [{ ...manualAccount, id: "windows-admin" }]
126+
} as any;
127+
expect(workspaceAssistantConnectionChoices(asset, "winrm", "windows-admin")).toMatchObject({
128+
protocol: "winrm",
129+
account: { id: "windows-admin" }
130+
});
131+
});
132+
122133
it("notifies the timeline for every shallow AI SDK message update", () => {
123134
const message = {
124135
id: "assistant-1",

‎ui/composables/useWorkspaceAssistantSession.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ function normalizeCandidate(value: unknown) {
535535

536536
function uniqueProtocols(protocols: PermedProtocol[]) {
537537
const names = protocols
538-
.filter((protocol) => protocol?.name !== "winrm" && (isDesktopRuntime() || protocol?.public !== false))
538+
.filter((protocol) => isDesktopRuntime() || protocol?.public !== false)
539539
.map((protocol) => boundedString(protocol.name, 64).toLowerCase())
540540
.filter(Boolean);
541541
return [...new Set(names)];

‎ui/koko/composables/terminal/terminalCommandSuggestions.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ const CASE_INSENSITIVE_PROFILES = new Set<KokoTerminalCommandProfile>([
228228

229229
export function resolveTerminalCommandProfile(profile: ConnectorTerminalProfile = {}): KokoTerminalCommandProfile {
230230
const protocol = String(profile.protocol || "").toLowerCase();
231+
if (protocol === "winrm") return "windows";
231232
if (protocol === "mariadb" || protocol === "mysql") return "mysql";
232233
if (protocol === "pg" || protocol === "postgres" || protocol === "postgresql") return "postgresql";
233234
if (["redis", "mongodb", "oracle", "dameng", "sqlserver"].includes(protocol)) {

0 commit comments

Comments
 (0)