@burdenoff/microfe-vibecontrols 2026.528.8 → 2026.528.10
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/components/agent-manager/AgentManagerInputArea.js +70 -64
- package/dist/components/agent-manager/AgentManagerInputArea.js.map +1 -1
- package/dist/generated/wspace-operations.js +1533 -1512
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.js +15 -13
- package/dist/generated/wspace-types.js.map +1 -1
- package/dist/index.js +10 -10
- package/dist/pages/SessionDetailsPage.js +460 -404
- package/dist/pages/SessionDetailsPage.js.map +1 -1
- package/dist/services/schedulerApi.js +37 -15
- package/dist/services/schedulerApi.js.map +1 -1
- package/package.json +1 -1
|
@@ -56,7 +56,7 @@ var pe = [
|
|
|
56
56
|
command: "/help",
|
|
57
57
|
description: "Show available commands"
|
|
58
58
|
}
|
|
59
|
-
],
|
|
59
|
+
], h = [
|
|
60
60
|
"claude",
|
|
61
61
|
"codex",
|
|
62
62
|
"gemini",
|
|
@@ -73,18 +73,18 @@ var pe = [
|
|
|
73
73
|
"pi",
|
|
74
74
|
"aider",
|
|
75
75
|
"plandex"
|
|
76
|
-
],
|
|
77
|
-
function g({ agentId: g, sessionId: _, onSend: v, onCancel:
|
|
78
|
-
let [
|
|
76
|
+
], me = ["sdk", "cli"];
|
|
77
|
+
function g({ agentId: g, sessionId: _, onSend: v, onCancel: y, mcpServers: he = [], agentTunnelUrl: b, agentApiKey: x }) {
|
|
78
|
+
let [S, C] = f(""), [w, T] = f([]), [ge, E] = f(!1), [_e, ve] = f(""), [D, O] = f(!1), [k, A] = f(!1), [j, M] = f(""), [ye, N] = f([]), P = e(), F = d(null), I = d(null);
|
|
79
79
|
l(() => {
|
|
80
80
|
F.current?.focus({ preventScroll: !0 });
|
|
81
81
|
}, []);
|
|
82
82
|
let L = i((e) => e.sessionStates[_]), R = i((e) => e.setSessionModel), z = i((e) => e.setSessionSdk), B = i((e) => e.setSessionMode), be = i((e) => e.setSessionPermissionMode), xe = i((e) => e.toggleVoice), Se = i((e) => e.toggleThinking), Ce = i((e) => e.setSessionContextLevel), we = i((e) => e.setSessionVibe), Te = i((e) => e.setSessionRootPath), V = i((e) => e.openSession), H = i((e) => e.addMessage), { vibes: Ee, agents: U } = t(), { active: W } = n(u(() => U.find((e) => e.id === g) ?? null, [U, g])?.id ?? null), G = u(() => ({
|
|
83
83
|
id: g,
|
|
84
84
|
profile: W
|
|
85
|
-
}), [g, W]), { isListening: K, transcript: q, startListening: De, stopListening: Oe } = ee(), J = L?.status === "streaming", Y =
|
|
85
|
+
}), [g, W]), { isListening: K, transcript: q, startListening: De, stopListening: Oe } = ee(), J = L?.status === "streaming", Y = S.trim().length > 0 && !J;
|
|
86
86
|
l(() => {
|
|
87
|
-
q && K &&
|
|
87
|
+
q && K && C((e) => e + (e ? " " : "") + q);
|
|
88
88
|
}, [q, K]), l(() => {
|
|
89
89
|
let e = !1;
|
|
90
90
|
return r(G).then((t) => {
|
|
@@ -95,79 +95,85 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
95
95
|
e = !0;
|
|
96
96
|
};
|
|
97
97
|
}, [G]), l(() => {
|
|
98
|
-
|
|
99
|
-
}, [
|
|
100
|
-
let
|
|
98
|
+
S.startsWith("/") && !S.includes(" ") ? (E(!0), ve(S.slice(1))) : E(!1);
|
|
99
|
+
}, [S]);
|
|
100
|
+
let ke = u(() => pe.filter((e) => e.command.toLowerCase().includes(`/${_e.toLowerCase()}`)), [_e]);
|
|
101
101
|
l(() => {
|
|
102
102
|
let e = F.current;
|
|
103
103
|
e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, 200)}px`);
|
|
104
|
-
}, [
|
|
104
|
+
}, [S]), l(() => {
|
|
105
105
|
if (!D && !k) return;
|
|
106
106
|
let e = (e) => {
|
|
107
107
|
I.current && !I.current.contains(e.target) && (O(!1), A(!1));
|
|
108
108
|
};
|
|
109
109
|
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
110
110
|
}, [D, k]);
|
|
111
|
-
let
|
|
111
|
+
let X = c((e) => {
|
|
112
112
|
H(_, {
|
|
113
113
|
id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
114
114
|
role: "system",
|
|
115
115
|
content: e,
|
|
116
116
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
117
117
|
});
|
|
118
|
-
}, [H, _]),
|
|
119
|
-
if (!(!
|
|
118
|
+
}, [H, _]), Ae = c(async () => {
|
|
119
|
+
if (!(!S.trim() || !j || !b || !x)) try {
|
|
120
120
|
let e = await te({
|
|
121
121
|
sessionId: _,
|
|
122
|
-
agentTunnelUrl:
|
|
123
|
-
agentApiKey:
|
|
124
|
-
|
|
122
|
+
agentTunnelUrl: b,
|
|
123
|
+
agentApiKey: x,
|
|
124
|
+
agentRef: W ? {
|
|
125
|
+
agentId: g,
|
|
126
|
+
profile: W
|
|
127
|
+
} : void 0,
|
|
128
|
+
prompt: S.trim(),
|
|
125
129
|
scheduledAt: new Date(j).toISOString()
|
|
126
130
|
});
|
|
127
|
-
|
|
131
|
+
X(`Prompt scheduled for ${new Date(e.scheduledAt).toLocaleString()} (Job: ${e.jobId.slice(0, 8)})`), C(""), M(""), A(!1), O(!1);
|
|
128
132
|
} catch (e) {
|
|
129
|
-
|
|
133
|
+
X(`Failed to schedule: ${e instanceof Error ? e.message : "Unknown error"}`);
|
|
130
134
|
}
|
|
131
135
|
}, [
|
|
132
|
-
|
|
136
|
+
S,
|
|
133
137
|
j,
|
|
134
|
-
y,
|
|
135
138
|
b,
|
|
139
|
+
x,
|
|
136
140
|
_,
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
g,
|
|
142
|
+
W,
|
|
143
|
+
X
|
|
144
|
+
]), Z = c((e) => {
|
|
139
145
|
let t = e.trim().split(/\s+/), n = t[0].toLowerCase(), r = t.slice(1).join(" ");
|
|
140
146
|
switch (n) {
|
|
141
147
|
case "/new":
|
|
142
148
|
V(`session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`);
|
|
143
149
|
break;
|
|
144
150
|
case "/rename":
|
|
145
|
-
|
|
151
|
+
X(r ? `Session renamed to "${r}".` : "Usage: /rename <name>");
|
|
146
152
|
break;
|
|
147
153
|
case "/model":
|
|
148
|
-
r ? (R(_, r),
|
|
154
|
+
r ? (R(_, r), X(`Model switched to "${r}".`)) : X("Usage: /model <model-name>");
|
|
149
155
|
break;
|
|
150
156
|
case "/sdk":
|
|
151
|
-
if (r &&
|
|
157
|
+
if (r && h.includes(r)) {
|
|
152
158
|
let e = r;
|
|
153
|
-
z(_, e), s(G, e, L?.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L?.model ?? "default")),
|
|
154
|
-
} else
|
|
159
|
+
z(_, e), s(G, e, L?.model ?? "default").then((e) => R(_, e)).catch(() => R(_, L?.model ?? "default")), X(`SDK switched to "${r}".`);
|
|
160
|
+
} else X(`Usage: /sdk <${h.join("|")}>`);
|
|
155
161
|
break;
|
|
156
162
|
case "/mode":
|
|
157
|
-
r &&
|
|
163
|
+
r && me.includes(r) ? (B(_, r), X(`Mode switched to "${r}".`)) : X(`Usage: /mode <${me.join("|")}>`);
|
|
158
164
|
break;
|
|
159
165
|
case "/export": {
|
|
160
166
|
let e = r === "md" ? "md" : "json", t = L?.messages ?? [], n = e === "json" ? JSON.stringify(t, null, 2) : t.map((e) => `**${e.role}** (${e.timestamp ?? ""}):\n${e.content ?? ""}`).join("\n\n---\n\n"), i = new Blob([n], { type: e === "json" ? "application/json" : "text/markdown" }), a = URL.createObjectURL(i), o = document.createElement("a");
|
|
161
|
-
o.href = a, o.download = `conversation-${_}.${e}`, o.click(), URL.revokeObjectURL(a),
|
|
167
|
+
o.href = a, o.download = `conversation-${_}.${e}`, o.click(), URL.revokeObjectURL(a), X(`Conversation exported as ${e}.`);
|
|
162
168
|
break;
|
|
163
169
|
}
|
|
164
170
|
case "/clear":
|
|
165
|
-
|
|
171
|
+
X("Conversation cleared.");
|
|
166
172
|
break;
|
|
167
173
|
case "/help":
|
|
168
|
-
|
|
174
|
+
X(`Available commands:\n${pe.map((e) => ` ${e.command}${e.args ? " " + e.args : ""} - ${e.description}`).join("\n")}`);
|
|
169
175
|
break;
|
|
170
|
-
default:
|
|
176
|
+
default: X(`Unknown command: ${n}. Type /help for available commands.`);
|
|
171
177
|
}
|
|
172
178
|
}, [
|
|
173
179
|
_,
|
|
@@ -177,42 +183,42 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
177
183
|
R,
|
|
178
184
|
z,
|
|
179
185
|
B,
|
|
180
|
-
|
|
186
|
+
X,
|
|
181
187
|
G
|
|
182
|
-
]),
|
|
183
|
-
e.args ?
|
|
184
|
-
}, [
|
|
188
|
+
]), je = c((e) => {
|
|
189
|
+
e.args ? C(`${e.command} `) : (Z(e.command), C("")), E(!1), F.current?.focus();
|
|
190
|
+
}, [Z]), Q = c(() => {
|
|
185
191
|
if (!Y) return;
|
|
186
|
-
let e =
|
|
192
|
+
let e = S.trim();
|
|
187
193
|
if (e.startsWith("/")) {
|
|
188
|
-
|
|
194
|
+
Z(e), C(""), T([]);
|
|
189
195
|
return;
|
|
190
196
|
}
|
|
191
|
-
v(e,
|
|
197
|
+
v(e, w.length > 0 ? w : void 0), C(""), T([]);
|
|
192
198
|
}, [
|
|
193
199
|
Y,
|
|
194
|
-
|
|
195
|
-
|
|
200
|
+
S,
|
|
201
|
+
w,
|
|
196
202
|
v,
|
|
197
|
-
|
|
198
|
-
]),
|
|
199
|
-
e.key === "Enter" && !e.shiftKey && (e.preventDefault(),
|
|
200
|
-
}, [
|
|
201
|
-
|
|
202
|
-
}, [
|
|
203
|
-
|
|
203
|
+
Z
|
|
204
|
+
]), Me = c((e) => {
|
|
205
|
+
e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Q());
|
|
206
|
+
}, [Q]), Ne = c(() => {
|
|
207
|
+
y?.();
|
|
208
|
+
}, [y]), $ = c((e) => {
|
|
209
|
+
T((t) => [...t, ...e]);
|
|
204
210
|
}, []), Pe = c((e) => {
|
|
205
|
-
|
|
206
|
-
}, []), Fe = oe(
|
|
211
|
+
T((t) => t.filter((t, n) => n !== e));
|
|
212
|
+
}, []), Fe = oe($);
|
|
207
213
|
return L ? /* @__PURE__ */ m("div", {
|
|
208
214
|
className: "relative z-30 border-t border-border-default bg-bg-surface",
|
|
209
215
|
...Fe,
|
|
210
216
|
children: [
|
|
211
|
-
|
|
217
|
+
ge && ke.length > 0 && /* @__PURE__ */ p("div", {
|
|
212
218
|
className: "absolute bottom-full left-0 right-0 mb-1 mx-3 bg-bg-elevated border border-border-default rounded-lg shadow-lg max-h-48 overflow-y-auto z-50",
|
|
213
|
-
children:
|
|
219
|
+
children: ke.map((e) => /* @__PURE__ */ m("button", {
|
|
214
220
|
type: "button",
|
|
215
|
-
onClick: () =>
|
|
221
|
+
onClick: () => je(e),
|
|
216
222
|
className: "flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors",
|
|
217
223
|
children: [
|
|
218
224
|
/* @__PURE__ */ p("span", {
|
|
@@ -230,9 +236,9 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
230
236
|
]
|
|
231
237
|
}, e.command))
|
|
232
238
|
}),
|
|
233
|
-
|
|
239
|
+
w.length > 0 && /* @__PURE__ */ p("div", {
|
|
234
240
|
className: "flex items-center gap-2 px-3 pt-2 overflow-x-auto",
|
|
235
|
-
children:
|
|
241
|
+
children: w.map((e, t) => /* @__PURE__ */ m("div", {
|
|
236
242
|
className: "flex items-center gap-1.5 px-2 py-1 rounded-md bg-bg-elevated border border-border-default text-xs text-text-secondary",
|
|
237
243
|
children: [/* @__PURE__ */ p("span", {
|
|
238
244
|
className: "truncate max-w-[120px]",
|
|
@@ -270,7 +276,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
270
276
|
}),
|
|
271
277
|
/* @__PURE__ */ p(re, {
|
|
272
278
|
selected: L.mcpServers,
|
|
273
|
-
available:
|
|
279
|
+
available: he,
|
|
274
280
|
onChange: () => {}
|
|
275
281
|
}),
|
|
276
282
|
/* @__PURE__ */ p(se, {
|
|
@@ -324,7 +330,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
324
330
|
},
|
|
325
331
|
isListening: K
|
|
326
332
|
}),
|
|
327
|
-
/* @__PURE__ */ p(ae, { onFileSelect:
|
|
333
|
+
/* @__PURE__ */ p(ae, { onFileSelect: $ })
|
|
328
334
|
]
|
|
329
335
|
}),
|
|
330
336
|
/* @__PURE__ */ m("div", {
|
|
@@ -332,16 +338,16 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
332
338
|
children: [/* @__PURE__ */ p("textarea", {
|
|
333
339
|
"aria-label": "control",
|
|
334
340
|
ref: F,
|
|
335
|
-
value:
|
|
336
|
-
onChange: (e) =>
|
|
337
|
-
onKeyDown:
|
|
341
|
+
value: S,
|
|
342
|
+
onChange: (e) => C(e.target.value),
|
|
343
|
+
onKeyDown: Me,
|
|
338
344
|
placeholder: P("vibecontrols.agentManager.inputArea.placeholder", "Type a message or / for commands... (Enter to send)"),
|
|
339
345
|
rows: 1,
|
|
340
346
|
className: "flex-1 resize-none rounded-lg border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors",
|
|
341
347
|
disabled: J
|
|
342
348
|
}), J ? /* @__PURE__ */ p("button", {
|
|
343
349
|
type: "button",
|
|
344
|
-
onClick:
|
|
350
|
+
onClick: Ne,
|
|
345
351
|
className: "flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity",
|
|
346
352
|
title: P("vibecontrols.agentManager.inputArea.cancel", "Cancel"),
|
|
347
353
|
children: /* @__PURE__ */ p(de, { className: "size-4" })
|
|
@@ -351,7 +357,7 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
351
357
|
children: [
|
|
352
358
|
/* @__PURE__ */ p("button", {
|
|
353
359
|
type: "button",
|
|
354
|
-
onClick:
|
|
360
|
+
onClick: Q,
|
|
355
361
|
disabled: !Y,
|
|
356
362
|
className: "p-2 rounded-l-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors",
|
|
357
363
|
title: P("vibecontrols.agentManager.inputArea.send", "Send (Enter)"),
|
|
@@ -383,8 +389,8 @@ function g({ agentId: g, sessionId: _, onSend: v, onCancel: he, mcpServers: ge =
|
|
|
383
389
|
}),
|
|
384
390
|
/* @__PURE__ */ p("button", {
|
|
385
391
|
type: "button",
|
|
386
|
-
onClick: () => void
|
|
387
|
-
disabled: !j || !
|
|
392
|
+
onClick: () => void Ae(),
|
|
393
|
+
disabled: !j || !b || !x,
|
|
388
394
|
className: "w-full px-2 py-1.5 text-xs font-medium rounded bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors",
|
|
389
395
|
children: P("vibecontrols.agentManager.inputArea.schedule", "Schedule")
|
|
390
396
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentManagerInputArea.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerInputArea.tsx"],"sourcesContent":["/**\n * Rich input area for the Agent Manager chat.\n *\n * Sits at the bottom of the chat pane. Contains a toolbar row with\n * control selectors and a resizable textarea with send/cancel buttons.\n * Supports file attachment preview, keyboard shortcuts, and slash\n * commands for quick actions.\n */\n\nimport { useState, useRef, useCallback, useEffect, useMemo, type KeyboardEvent } from 'react';\nimport { ArrowUp, Square, X, ChevronDown, Clock } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useVoiceMode } from '@/hooks/useVoiceMode';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchProviders, type AIProvider } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { schedulePrompt } from '@/services/schedulerApi';\nimport { ModelSelector } from './controls/ModelSelector';\nimport { SdkSelector } from './controls/SdkSelector';\nimport { AutonomySelector } from './controls/AutonomySelector';\nimport { McpServerSelector } from './controls/McpServerSelector';\nimport { VoiceToggle } from './controls/VoiceToggle';\nimport { FileAttachButton } from './controls/FileAttachButton';\nimport { createDropHandlers } from './controls/createDropHandlers';\nimport { ContextLevelToggle } from './controls/ContextLevelToggle';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from './modelDefaults';\nimport type { AgentSdkType, McpServer, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Slash commands */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface SlashCommand {\n command: string;\n description: string;\n args?: string;\n}\n\nconst SLASH_COMMANDS: SlashCommand[] = [\n { command: '/new', description: 'Create new session' },\n { command: '/rename', description: 'Rename current session', args: '<name>' },\n { command: '/model', description: 'Switch model', args: '<model-name>' },\n {\n command: '/sdk',\n description: 'Switch SDK',\n args: '<claude|codex|gemini|opencode|openai-compat>',\n },\n { command: '/mode', description: 'Switch mode', args: '<sdk|cli>' },\n { command: '/export', description: 'Export conversation', args: '[json|md]' },\n { command: '/clear', description: 'Clear conversation' },\n { command: '/help', description: 'Show available commands' },\n];\n\nconst VALID_SDKS: AgentSdkType[] = [\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n];\nconst VALID_MODES: ProviderMode[] = ['sdk', 'cli'];\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Component */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface AgentManagerInputAreaProps {\n agentId: string;\n sessionId: string;\n onSend: (text: string, attachments?: File[]) => void;\n onCancel?: () => void;\n mcpServers?: McpServer[];\n agentTunnelUrl?: string;\n agentApiKey?: string;\n}\n\nexport function AgentManagerInputArea({\n agentId,\n sessionId,\n onSend,\n onCancel,\n mcpServers = [],\n agentTunnelUrl,\n agentApiKey,\n}: AgentManagerInputAreaProps) {\n const [text, setText] = useState('');\n const [pendingFiles, setPendingFiles] = useState<File[]>([]);\n const [showSlashMenu, setShowSlashMenu] = useState(false);\n const [slashFilter, setSlashFilter] = useState('');\n const [showScheduleMenu, setShowScheduleMenu] = useState(false);\n const [showSchedulePopup, setShowSchedulePopup] = useState(false);\n const [scheduleDateTime, setScheduleDateTime] = useState('');\n const [providers, setProviders] = useState<AIProvider[]>([]);\n const tr = useTr();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const scheduleMenuRef = useRef<HTMLDivElement>(null);\n\n // Auto-focus textarea when session is opened or switched\n useEffect(() => {\n textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const setSessionPermissionMode = useAgentManagerStore((s) => s.setSessionPermissionMode);\n const toggleVoice = useAgentManagerStore((s) => s.toggleVoice);\n const toggleThinking = useAgentManagerStore((s) => s.toggleThinking);\n const setSessionContextLevel = useAgentManagerStore((s) => s.setSessionContextLevel);\n const setSessionVibe = useAgentManagerStore((s) => s.setSessionVibe);\n const setSessionRootPath = useAgentManagerStore((s) => s.setSessionRootPath);\n const openSession = useAgentManagerStore((s) => s.openSession);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const { vibes, agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n\n const { isListening, transcript, startListening, stopListening } = useVoiceMode();\n\n const isStreaming = sessionState?.status === 'streaming';\n const canSend = text.trim().length > 0 && !isStreaming;\n\n // Append voice transcript to textarea\n useEffect(() => {\n if (transcript && isListening) {\n setText((prev) => prev + (prev ? ' ' : '') + transcript);\n }\n }, [transcript, isListening]);\n\n useEffect(() => {\n let cancelled = false;\n void fetchProviders(agentRef)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agentRef]);\n\n // ── Slash command filtering ──\n useEffect(() => {\n if (text.startsWith('/') && !text.includes(' ')) {\n setShowSlashMenu(true);\n setSlashFilter(text.slice(1));\n } else {\n setShowSlashMenu(false);\n }\n }, [text]);\n\n const filteredCommands = useMemo(\n () =>\n SLASH_COMMANDS.filter((cmd) =>\n cmd.command.toLowerCase().includes(`/${slashFilter.toLowerCase()}`)\n ),\n [slashFilter]\n );\n\n // Auto-resize textarea\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = 'auto';\n const maxRows = 10;\n const lineHeight = 20;\n const maxHeight = maxRows * lineHeight;\n el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;\n }, [text]);\n\n // Close schedule menu on outside click\n useEffect(() => {\n if (!showScheduleMenu && !showSchedulePopup) return;\n const handler = (e: MouseEvent) => {\n if (scheduleMenuRef.current && !scheduleMenuRef.current.contains(e.target as Node)) {\n setShowScheduleMenu(false);\n setShowSchedulePopup(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showScheduleMenu, showSchedulePopup]);\n\n const addSystemMessage = useCallback(\n (content: string) => {\n addMessage(sessionId, {\n id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n role: 'system',\n content,\n timestamp: new Date().toISOString(),\n });\n },\n [addMessage, sessionId]\n );\n\n const handleScheduleSend = useCallback(async () => {\n if (!text.trim() || !scheduleDateTime || !agentTunnelUrl || !agentApiKey) return;\n try {\n const result = await schedulePrompt({\n sessionId,\n agentTunnelUrl,\n agentApiKey,\n prompt: text.trim(),\n scheduledAt: new Date(scheduleDateTime).toISOString(),\n });\n addSystemMessage(\n `Prompt scheduled for ${new Date(result.scheduledAt).toLocaleString()} (Job: ${result.jobId.slice(0, 8)})`\n );\n setText('');\n setScheduleDateTime('');\n setShowSchedulePopup(false);\n setShowScheduleMenu(false);\n } catch (err) {\n addSystemMessage(\n `Failed to schedule: ${err instanceof Error ? err.message : 'Unknown error'}`\n );\n }\n }, [text, scheduleDateTime, agentTunnelUrl, agentApiKey, sessionId, addSystemMessage]);\n\n const executeSlashCommand = useCallback(\n (input: string) => {\n const parts = input.trim().split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n const arg = parts.slice(1).join(' ');\n\n switch (cmd) {\n case '/new': {\n const newId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n openSession(newId);\n break;\n }\n case '/rename':\n if (arg) {\n addSystemMessage(`Session renamed to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /rename <name>');\n }\n break;\n case '/model':\n if (arg) {\n setSessionModel(sessionId, arg);\n addSystemMessage(`Model switched to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /model <model-name>');\n }\n break;\n case '/sdk':\n if (arg && VALID_SDKS.includes(arg as AgentSdkType)) {\n const nextSdk = arg as AgentSdkType;\n setSessionSdk(sessionId, nextSdk);\n void resolveProviderDefaultModel(\n agentRef,\n nextSdk,\n sessionState?.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState?.model ?? GENERIC_MODEL_FALLBACK)\n );\n addSystemMessage(`SDK switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /sdk <${VALID_SDKS.join('|')}>`);\n }\n break;\n case '/mode':\n if (arg && VALID_MODES.includes(arg as ProviderMode)) {\n setSessionMode(sessionId, arg as ProviderMode);\n addSystemMessage(`Mode switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /mode <${VALID_MODES.join('|')}>`);\n }\n break;\n case '/export': {\n const format = arg === 'md' ? 'md' : 'json';\n const messages = sessionState?.messages ?? [];\n const exported =\n format === 'json'\n ? JSON.stringify(messages, null, 2)\n : messages\n .map((m) => `**${m.role}** (${m.timestamp ?? ''}):\\n${m.content ?? ''}`)\n .join('\\n\\n---\\n\\n');\n const blob = new Blob([exported], {\n type: format === 'json' ? 'application/json' : 'text/markdown',\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `conversation-${sessionId}.${format}`;\n a.click();\n URL.revokeObjectURL(url);\n addSystemMessage(`Conversation exported as ${format}.`);\n break;\n }\n case '/clear':\n addSystemMessage('Conversation cleared.');\n break;\n case '/help': {\n const helpText = SLASH_COMMANDS.map(\n (c) => ` ${c.command}${c.args ? ' ' + c.args : ''} - ${c.description}`\n ).join('\\n');\n addSystemMessage(`Available commands:\\n${helpText}`);\n break;\n }\n default:\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\n }\n },\n [\n sessionId,\n sessionState?.messages,\n sessionState?.model,\n openSession,\n setSessionModel,\n setSessionSdk,\n setSessionMode,\n addSystemMessage,\n agentRef,\n ]\n );\n\n const handleSlashSelect = useCallback(\n (cmd: SlashCommand) => {\n // If command takes args, fill the text and let user type args\n if (cmd.args) {\n setText(`${cmd.command} `);\n } else {\n executeSlashCommand(cmd.command);\n setText('');\n }\n setShowSlashMenu(false);\n textareaRef.current?.focus();\n },\n [executeSlashCommand]\n );\n\n const handleSend = useCallback(() => {\n if (!canSend) return;\n\n const trimmed = text.trim();\n\n // Handle slash commands locally\n if (trimmed.startsWith('/')) {\n executeSlashCommand(trimmed);\n setText('');\n setPendingFiles([]);\n return;\n }\n\n onSend(trimmed, pendingFiles.length > 0 ? pendingFiles : undefined);\n setText('');\n setPendingFiles([]);\n }, [canSend, text, pendingFiles, onSend, executeSlashCommand]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n // Enter sends, Shift+Enter inserts newline\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n const handleCancel = useCallback(() => {\n onCancel?.();\n }, [onCancel]);\n\n const handleFileSelect = useCallback((files: File[]) => {\n setPendingFiles((prev) => [...prev, ...files]);\n }, []);\n\n const removeFile = useCallback((index: number) => {\n setPendingFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const dropHandlers = createDropHandlers(handleFileSelect);\n\n if (!sessionState) return null;\n\n return (\n <div className=\"relative z-30 border-t border-border-default bg-bg-surface\" {...dropHandlers}>\n {/* Slash command popup */}\n {showSlashMenu && filteredCommands.length > 0 && (\n <div className=\"absolute bottom-full left-0 right-0 mb-1 mx-3 bg-bg-elevated border border-border-default rounded-lg shadow-lg max-h-48 overflow-y-auto z-50\">\n {filteredCommands.map((cmd) => (\n <button\n key={cmd.command}\n type=\"button\"\n onClick={() => handleSlashSelect(cmd)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors\"\n >\n <span className=\"font-mono text-xs text-text-primary\">{cmd.command}</span>\n {cmd.args && <span className=\"text-text-tertiary text-xs\">{cmd.args}</span>}\n <span className=\"text-text-secondary text-xs ml-auto\">{cmd.description}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* File attachment preview row */}\n {pendingFiles.length > 0 && (\n <div className=\"flex items-center gap-2 px-3 pt-2 overflow-x-auto\">\n {pendingFiles.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className=\"flex items-center gap-1.5 px-2 py-1 rounded-md bg-bg-elevated border border-border-default text-xs text-text-secondary\"\n >\n <span className=\"truncate max-w-[120px]\">{file.name}</span>\n <button\n type=\"button\"\n onClick={() => removeFile(index)}\n className=\"p-0.5 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n <X className=\"size-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Toolbar row */}\n <div className=\"flex flex-wrap items-center gap-1 px-3 pt-2 pb-1 overflow-x-auto\">\n <SdkSelector\n sdk={sessionState.sdk}\n mode={sessionState.mode}\n providers={providers}\n onSdkChange={(sdk) => {\n setSessionSdk(sessionId, sdk);\n void resolveProviderDefaultModel(\n agentRef,\n sdk,\n sessionState.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState.model ?? GENERIC_MODEL_FALLBACK)\n );\n }}\n onModeChange={(mode) => setSessionMode(sessionId, mode)}\n />\n <ModelSelector\n value={sessionState.model}\n onChange={(model) => setSessionModel(sessionId, model)}\n provider={sessionState.sdk}\n agentId={agentId}\n />\n <AutonomySelector\n value={sessionState.permissionMode}\n mode={sessionState.mode}\n onChange={(permissionMode) => setSessionPermissionMode(sessionId, permissionMode)}\n />\n <McpServerSelector\n selected={sessionState.mcpServers}\n available={mcpServers}\n onChange={() => {\n // Update via store -- MCP servers are part of session state\n // For now we store them directly\n }}\n />\n <ContextLevelToggle\n agentId=\"\"\n sessionId={sessionId}\n contextLevel={sessionState.contextLevel}\n rootPath={sessionState.rootPath}\n onChange={(level, rootPath, vibeId) => {\n setSessionContextLevel(sessionId, level);\n setSessionRootPath(sessionId, rootPath ?? null);\n setSessionVibe(sessionId, vibeId ?? null, rootPath ?? null);\n }}\n vibes={vibes.map((v) => ({ id: v.id, name: v.name, path: v.path }))}\n />\n\n <div className=\"flex-1\" />\n\n {/* Show Thinking toggle */}\n <button\n type=\"button\"\n onClick={() => toggleThinking(sessionId)}\n className={`p-1.5 rounded text-xs font-medium transition-colors ${\n sessionState.showThinking\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary'\n }`}\n title={\n sessionState.showThinking\n ? tr('vibecontrols.agentManager.inputArea.hideThinking', 'Hide thinking')\n : tr('vibecontrols.agentManager.inputArea.showThinking', 'Show thinking')\n }\n >\n Think\n </button>\n {/* Context history limit */}\n <button\n type=\"button\"\n onClick={() => {\n const val = window.prompt(\n 'Context history limit (messages sent with each prompt):',\n String(sessionState.contextHistoryLimit)\n );\n if (val !== null) {\n const num = parseInt(val, 10);\n if (!isNaN(num) && num >= 0) {\n const store = useAgentManagerStore.getState();\n const s = store.sessionStates[sessionId];\n if (s) {\n useAgentManagerStore.setState((prev) => ({\n sessionStates: {\n ...prev.sessionStates,\n [sessionId]: { ...s, contextHistoryLimit: num },\n },\n }));\n }\n }\n }\n }}\n className=\"p-1.5 rounded text-[10px] font-mono text-text-tertiary hover:text-text-secondary transition-colors\"\n title={`Context history: last ${sessionState.contextHistoryLimit} messages sent with each prompt`}\n >\n H:{sessionState.contextHistoryLimit}\n </button>\n <VoiceToggle\n enabled={sessionState.voiceEnabled}\n onToggle={() => {\n toggleVoice(sessionId);\n if (!sessionState.voiceEnabled) startListening();\n else stopListening();\n }}\n isListening={isListening}\n />\n <FileAttachButton onFileSelect={handleFileSelect} />\n </div>\n\n {/* Textarea + send/cancel */}\n <div className=\"flex items-end gap-2 px-3 pb-3 pt-1\">\n <textarea\n aria-label=\"control\"\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={tr(\n 'vibecontrols.agentManager.inputArea.placeholder',\n 'Type a message or / for commands... (Enter to send)'\n )}\n rows={1}\n className=\"flex-1 resize-none rounded-lg border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n disabled={isStreaming}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity\"\n title={tr('vibecontrols.agentManager.inputArea.cancel', 'Cancel')}\n >\n <Square className=\"size-4\" />\n </button>\n ) : (\n <div className=\"flex items-end flex-shrink-0 relative\" ref={scheduleMenuRef}>\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"p-2 rounded-l-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.send', 'Send (Enter)')}\n >\n <ArrowUp className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setShowScheduleMenu(!showScheduleMenu)}\n disabled={!canSend}\n className=\"ml-1 p-2 rounded-r-lg border-l border-action-primary-text/20 bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.scheduleSend', 'Schedule send')}\n >\n <ChevronDown className=\"size-3\" />\n </button>\n\n {/* Schedule dropdown */}\n {showScheduleMenu && (\n <div className=\"absolute bottom-full right-0 mb-1 w-56 bg-bg-surface border border-border-default rounded-md shadow-lg py-1 z-50\">\n {!showSchedulePopup ? (\n <button\n type=\"button\"\n onClick={() => setShowSchedulePopup(true)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left text-xs text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Clock className=\"size-3.5 text-text-secondary\" />\n {tr(\n 'vibecontrols.agentManager.inputArea.scheduleSendEllipsis',\n 'Schedule Send...'\n )}\n </button>\n ) : (\n <div className=\"px-3 py-2 space-y-2\">\n <label className=\"block text-[11px] font-medium text-text-secondary\">\n {tr('vibecontrols.agentManager.inputArea.sendAt', 'Send at:')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduleDateTime}\n onChange={(e) => setScheduleDateTime(e.target.value)}\n className=\"w-full px-2 py-1 text-xs rounded border border-border-default bg-bg-primary text-text-primary focus:outline-none focus:border-border-strong\"\n />\n <button\n type=\"button\"\n onClick={() => void handleScheduleSend()}\n disabled={!scheduleDateTime || !agentTunnelUrl || !agentApiKey}\n className=\"w-full px-2 py-1.5 text-xs font-medium rounded bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.agentManager.inputArea.schedule', 'Schedule')}\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AgentManagerInputArea.js","names":[],"sources":["../../../src/components/agent-manager/AgentManagerInputArea.tsx"],"sourcesContent":["/**\n * Rich input area for the Agent Manager chat.\n *\n * Sits at the bottom of the chat pane. Contains a toolbar row with\n * control selectors and a resizable textarea with send/cancel buttons.\n * Supports file attachment preview, keyboard shortcuts, and slash\n * commands for quick actions.\n */\n\nimport { useState, useRef, useCallback, useEffect, useMemo, type KeyboardEvent } from 'react';\nimport { ArrowUp, Square, X, ChevronDown, Clock } from 'lucide-react';\nimport { useAgentManagerStore } from '@/store/agentManagerStore';\nimport { useVoiceMode } from '@/hooks/useVoiceMode';\nimport { useCachedInitialData } from '@/hooks/useCachedInitialData';\nimport { fetchProviders, type AIProvider } from '@/services/aiApi';\nimport { useActiveAgentProfile } from '@/hooks/useActiveAgentProfile';\nimport { schedulePrompt } from '@/services/schedulerApi';\nimport { ModelSelector } from './controls/ModelSelector';\nimport { SdkSelector } from './controls/SdkSelector';\nimport { AutonomySelector } from './controls/AutonomySelector';\nimport { McpServerSelector } from './controls/McpServerSelector';\nimport { VoiceToggle } from './controls/VoiceToggle';\nimport { FileAttachButton } from './controls/FileAttachButton';\nimport { createDropHandlers } from './controls/createDropHandlers';\nimport { ContextLevelToggle } from './controls/ContextLevelToggle';\nimport { GENERIC_MODEL_FALLBACK, resolveProviderDefaultModel } from './modelDefaults';\nimport type { AgentSdkType, McpServer, ProviderMode } from '@/types/agentManager';\nimport { useTr } from '../../shared/hooks/useTr';\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Slash commands */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface SlashCommand {\n command: string;\n description: string;\n args?: string;\n}\n\nconst SLASH_COMMANDS: SlashCommand[] = [\n { command: '/new', description: 'Create new session' },\n { command: '/rename', description: 'Rename current session', args: '<name>' },\n { command: '/model', description: 'Switch model', args: '<model-name>' },\n {\n command: '/sdk',\n description: 'Switch SDK',\n args: '<claude|codex|gemini|opencode|openai-compat>',\n },\n { command: '/mode', description: 'Switch mode', args: '<sdk|cli>' },\n { command: '/export', description: 'Export conversation', args: '[json|md]' },\n { command: '/clear', description: 'Clear conversation' },\n { command: '/help', description: 'Show available commands' },\n];\n\nconst VALID_SDKS: AgentSdkType[] = [\n 'claude',\n 'codex',\n 'gemini',\n 'opencode',\n 'cursor',\n 'openrouter',\n 'minimax',\n 'ollama',\n 'openai-compat',\n 'goose',\n 'amp',\n 'copilot',\n 'crush',\n 'pi',\n 'aider',\n 'plandex',\n];\nconst VALID_MODES: ProviderMode[] = ['sdk', 'cli'];\n\n/* ────────────────────────────────────────────────────────────────────── */\n/* Component */\n/* ────────────────────────────────────────────────────────────────────── */\n\ninterface AgentManagerInputAreaProps {\n agentId: string;\n sessionId: string;\n onSend: (text: string, attachments?: File[]) => void;\n onCancel?: () => void;\n mcpServers?: McpServer[];\n agentTunnelUrl?: string;\n agentApiKey?: string;\n}\n\nexport function AgentManagerInputArea({\n agentId,\n sessionId,\n onSend,\n onCancel,\n mcpServers = [],\n agentTunnelUrl,\n agentApiKey,\n}: AgentManagerInputAreaProps) {\n const [text, setText] = useState('');\n const [pendingFiles, setPendingFiles] = useState<File[]>([]);\n const [showSlashMenu, setShowSlashMenu] = useState(false);\n const [slashFilter, setSlashFilter] = useState('');\n const [showScheduleMenu, setShowScheduleMenu] = useState(false);\n const [showSchedulePopup, setShowSchedulePopup] = useState(false);\n const [scheduleDateTime, setScheduleDateTime] = useState('');\n const [providers, setProviders] = useState<AIProvider[]>([]);\n const tr = useTr();\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const scheduleMenuRef = useRef<HTMLDivElement>(null);\n\n // Auto-focus textarea when session is opened or switched\n useEffect(() => {\n textareaRef.current?.focus({ preventScroll: true });\n }, []);\n\n const sessionState = useAgentManagerStore((s) => s.sessionStates[sessionId]);\n const setSessionModel = useAgentManagerStore((s) => s.setSessionModel);\n const setSessionSdk = useAgentManagerStore((s) => s.setSessionSdk);\n const setSessionMode = useAgentManagerStore((s) => s.setSessionMode);\n const setSessionPermissionMode = useAgentManagerStore((s) => s.setSessionPermissionMode);\n const toggleVoice = useAgentManagerStore((s) => s.toggleVoice);\n const toggleThinking = useAgentManagerStore((s) => s.toggleThinking);\n const setSessionContextLevel = useAgentManagerStore((s) => s.setSessionContextLevel);\n const setSessionVibe = useAgentManagerStore((s) => s.setSessionVibe);\n const setSessionRootPath = useAgentManagerStore((s) => s.setSessionRootPath);\n const openSession = useAgentManagerStore((s) => s.openSession);\n const addMessage = useAgentManagerStore((s) => s.addMessage);\n\n const { vibes, agents } = useCachedInitialData();\n const activeAgent = useMemo(\n () => agents.find((a) => a.id === agentId) ?? null,\n [agents, agentId]\n );\n const { active: activeProfile } = useActiveAgentProfile(activeAgent?.id ?? null);\n const agentRef = useMemo(\n () => ({ id: agentId, profile: activeProfile }),\n [agentId, activeProfile]\n );\n\n const { isListening, transcript, startListening, stopListening } = useVoiceMode();\n\n const isStreaming = sessionState?.status === 'streaming';\n const canSend = text.trim().length > 0 && !isStreaming;\n\n // Append voice transcript to textarea\n useEffect(() => {\n if (transcript && isListening) {\n setText((prev) => prev + (prev ? ' ' : '') + transcript);\n }\n }, [transcript, isListening]);\n\n useEffect(() => {\n let cancelled = false;\n void fetchProviders(agentRef)\n .then((items) => {\n if (!cancelled) setProviders(items);\n })\n .catch(() => {\n if (!cancelled) setProviders([]);\n });\n\n return () => {\n cancelled = true;\n };\n }, [agentRef]);\n\n // ── Slash command filtering ──\n useEffect(() => {\n if (text.startsWith('/') && !text.includes(' ')) {\n setShowSlashMenu(true);\n setSlashFilter(text.slice(1));\n } else {\n setShowSlashMenu(false);\n }\n }, [text]);\n\n const filteredCommands = useMemo(\n () =>\n SLASH_COMMANDS.filter((cmd) =>\n cmd.command.toLowerCase().includes(`/${slashFilter.toLowerCase()}`)\n ),\n [slashFilter]\n );\n\n // Auto-resize textarea\n useEffect(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.style.height = 'auto';\n const maxRows = 10;\n const lineHeight = 20;\n const maxHeight = maxRows * lineHeight;\n el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;\n }, [text]);\n\n // Close schedule menu on outside click\n useEffect(() => {\n if (!showScheduleMenu && !showSchedulePopup) return;\n const handler = (e: MouseEvent) => {\n if (scheduleMenuRef.current && !scheduleMenuRef.current.contains(e.target as Node)) {\n setShowScheduleMenu(false);\n setShowSchedulePopup(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [showScheduleMenu, showSchedulePopup]);\n\n const addSystemMessage = useCallback(\n (content: string) => {\n addMessage(sessionId, {\n id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,\n role: 'system',\n content,\n timestamp: new Date().toISOString(),\n });\n },\n [addMessage, sessionId]\n );\n\n const handleScheduleSend = useCallback(async () => {\n if (!text.trim() || !scheduleDateTime || !agentTunnelUrl || !agentApiKey) return;\n try {\n // SECURITY-F12: pass both `agentRef` (preferred, secret-free) and\n // legacy `agentApiKey` (fallback). `schedulerApi.schedulePrompt`\n // picks the secret-free GRAPHQL executor when\n // `VITE_SCHEDULER_AGENT_REF_ENABLED=true` and `agentRef` is set;\n // otherwise it falls back to the legacy WEBHOOK payload. See\n // ~/products/dev/platform/context/scheduler/SECURITY_F12.md.\n const result = await schedulePrompt({\n sessionId,\n agentTunnelUrl,\n agentApiKey,\n agentRef: activeProfile ? { agentId, profile: activeProfile } : undefined,\n prompt: text.trim(),\n scheduledAt: new Date(scheduleDateTime).toISOString(),\n });\n addSystemMessage(\n `Prompt scheduled for ${new Date(result.scheduledAt).toLocaleString()} (Job: ${result.jobId.slice(0, 8)})`\n );\n setText('');\n setScheduleDateTime('');\n setShowSchedulePopup(false);\n setShowScheduleMenu(false);\n } catch (err) {\n addSystemMessage(\n `Failed to schedule: ${err instanceof Error ? err.message : 'Unknown error'}`\n );\n }\n }, [\n text,\n scheduleDateTime,\n agentTunnelUrl,\n agentApiKey,\n sessionId,\n agentId,\n activeProfile,\n addSystemMessage,\n ]);\n\n const executeSlashCommand = useCallback(\n (input: string) => {\n const parts = input.trim().split(/\\s+/);\n const cmd = parts[0].toLowerCase();\n const arg = parts.slice(1).join(' ');\n\n switch (cmd) {\n case '/new': {\n const newId = `session-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n openSession(newId);\n break;\n }\n case '/rename':\n if (arg) {\n addSystemMessage(`Session renamed to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /rename <name>');\n }\n break;\n case '/model':\n if (arg) {\n setSessionModel(sessionId, arg);\n addSystemMessage(`Model switched to \"${arg}\".`);\n } else {\n addSystemMessage('Usage: /model <model-name>');\n }\n break;\n case '/sdk':\n if (arg && VALID_SDKS.includes(arg as AgentSdkType)) {\n const nextSdk = arg as AgentSdkType;\n setSessionSdk(sessionId, nextSdk);\n void resolveProviderDefaultModel(\n agentRef,\n nextSdk,\n sessionState?.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState?.model ?? GENERIC_MODEL_FALLBACK)\n );\n addSystemMessage(`SDK switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /sdk <${VALID_SDKS.join('|')}>`);\n }\n break;\n case '/mode':\n if (arg && VALID_MODES.includes(arg as ProviderMode)) {\n setSessionMode(sessionId, arg as ProviderMode);\n addSystemMessage(`Mode switched to \"${arg}\".`);\n } else {\n addSystemMessage(`Usage: /mode <${VALID_MODES.join('|')}>`);\n }\n break;\n case '/export': {\n const format = arg === 'md' ? 'md' : 'json';\n const messages = sessionState?.messages ?? [];\n const exported =\n format === 'json'\n ? JSON.stringify(messages, null, 2)\n : messages\n .map((m) => `**${m.role}** (${m.timestamp ?? ''}):\\n${m.content ?? ''}`)\n .join('\\n\\n---\\n\\n');\n const blob = new Blob([exported], {\n type: format === 'json' ? 'application/json' : 'text/markdown',\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `conversation-${sessionId}.${format}`;\n a.click();\n URL.revokeObjectURL(url);\n addSystemMessage(`Conversation exported as ${format}.`);\n break;\n }\n case '/clear':\n addSystemMessage('Conversation cleared.');\n break;\n case '/help': {\n const helpText = SLASH_COMMANDS.map(\n (c) => ` ${c.command}${c.args ? ' ' + c.args : ''} - ${c.description}`\n ).join('\\n');\n addSystemMessage(`Available commands:\\n${helpText}`);\n break;\n }\n default:\n addSystemMessage(`Unknown command: ${cmd}. Type /help for available commands.`);\n }\n },\n [\n sessionId,\n sessionState?.messages,\n sessionState?.model,\n openSession,\n setSessionModel,\n setSessionSdk,\n setSessionMode,\n addSystemMessage,\n agentRef,\n ]\n );\n\n const handleSlashSelect = useCallback(\n (cmd: SlashCommand) => {\n // If command takes args, fill the text and let user type args\n if (cmd.args) {\n setText(`${cmd.command} `);\n } else {\n executeSlashCommand(cmd.command);\n setText('');\n }\n setShowSlashMenu(false);\n textareaRef.current?.focus();\n },\n [executeSlashCommand]\n );\n\n const handleSend = useCallback(() => {\n if (!canSend) return;\n\n const trimmed = text.trim();\n\n // Handle slash commands locally\n if (trimmed.startsWith('/')) {\n executeSlashCommand(trimmed);\n setText('');\n setPendingFiles([]);\n return;\n }\n\n onSend(trimmed, pendingFiles.length > 0 ? pendingFiles : undefined);\n setText('');\n setPendingFiles([]);\n }, [canSend, text, pendingFiles, onSend, executeSlashCommand]);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>) => {\n // Enter sends, Shift+Enter inserts newline\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSend();\n }\n },\n [handleSend]\n );\n\n const handleCancel = useCallback(() => {\n onCancel?.();\n }, [onCancel]);\n\n const handleFileSelect = useCallback((files: File[]) => {\n setPendingFiles((prev) => [...prev, ...files]);\n }, []);\n\n const removeFile = useCallback((index: number) => {\n setPendingFiles((prev) => prev.filter((_, i) => i !== index));\n }, []);\n\n const dropHandlers = createDropHandlers(handleFileSelect);\n\n if (!sessionState) return null;\n\n return (\n <div className=\"relative z-30 border-t border-border-default bg-bg-surface\" {...dropHandlers}>\n {/* Slash command popup */}\n {showSlashMenu && filteredCommands.length > 0 && (\n <div className=\"absolute bottom-full left-0 right-0 mb-1 mx-3 bg-bg-elevated border border-border-default rounded-lg shadow-lg max-h-48 overflow-y-auto z-50\">\n {filteredCommands.map((cmd) => (\n <button\n key={cmd.command}\n type=\"button\"\n onClick={() => handleSlashSelect(cmd)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left hover:bg-bg-sunken transition-colors\"\n >\n <span className=\"font-mono text-xs text-text-primary\">{cmd.command}</span>\n {cmd.args && <span className=\"text-text-tertiary text-xs\">{cmd.args}</span>}\n <span className=\"text-text-secondary text-xs ml-auto\">{cmd.description}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* File attachment preview row */}\n {pendingFiles.length > 0 && (\n <div className=\"flex items-center gap-2 px-3 pt-2 overflow-x-auto\">\n {pendingFiles.map((file, index) => (\n <div\n key={`${file.name}-${index}`}\n className=\"flex items-center gap-1.5 px-2 py-1 rounded-md bg-bg-elevated border border-border-default text-xs text-text-secondary\"\n >\n <span className=\"truncate max-w-[120px]\">{file.name}</span>\n <button\n type=\"button\"\n onClick={() => removeFile(index)}\n className=\"p-0.5 rounded hover:bg-bg-sunken transition-colors flex-shrink-0\"\n >\n <X className=\"size-3\" />\n </button>\n </div>\n ))}\n </div>\n )}\n\n {/* Toolbar row */}\n <div className=\"flex flex-wrap items-center gap-1 px-3 pt-2 pb-1 overflow-x-auto\">\n <SdkSelector\n sdk={sessionState.sdk}\n mode={sessionState.mode}\n providers={providers}\n onSdkChange={(sdk) => {\n setSessionSdk(sessionId, sdk);\n void resolveProviderDefaultModel(\n agentRef,\n sdk,\n sessionState.model ?? GENERIC_MODEL_FALLBACK\n )\n .then((nextModel) => setSessionModel(sessionId, nextModel))\n .catch(() =>\n setSessionModel(sessionId, sessionState.model ?? GENERIC_MODEL_FALLBACK)\n );\n }}\n onModeChange={(mode) => setSessionMode(sessionId, mode)}\n />\n <ModelSelector\n value={sessionState.model}\n onChange={(model) => setSessionModel(sessionId, model)}\n provider={sessionState.sdk}\n agentId={agentId}\n />\n <AutonomySelector\n value={sessionState.permissionMode}\n mode={sessionState.mode}\n onChange={(permissionMode) => setSessionPermissionMode(sessionId, permissionMode)}\n />\n <McpServerSelector\n selected={sessionState.mcpServers}\n available={mcpServers}\n onChange={() => {\n // Update via store -- MCP servers are part of session state\n // For now we store them directly\n }}\n />\n <ContextLevelToggle\n agentId=\"\"\n sessionId={sessionId}\n contextLevel={sessionState.contextLevel}\n rootPath={sessionState.rootPath}\n onChange={(level, rootPath, vibeId) => {\n setSessionContextLevel(sessionId, level);\n setSessionRootPath(sessionId, rootPath ?? null);\n setSessionVibe(sessionId, vibeId ?? null, rootPath ?? null);\n }}\n vibes={vibes.map((v) => ({ id: v.id, name: v.name, path: v.path }))}\n />\n\n <div className=\"flex-1\" />\n\n {/* Show Thinking toggle */}\n <button\n type=\"button\"\n onClick={() => toggleThinking(sessionId)}\n className={`p-1.5 rounded text-xs font-medium transition-colors ${\n sessionState.showThinking\n ? 'bg-action-primary-bg/10 text-action-primary-text'\n : 'text-text-tertiary hover:text-text-secondary'\n }`}\n title={\n sessionState.showThinking\n ? tr('vibecontrols.agentManager.inputArea.hideThinking', 'Hide thinking')\n : tr('vibecontrols.agentManager.inputArea.showThinking', 'Show thinking')\n }\n >\n Think\n </button>\n {/* Context history limit */}\n <button\n type=\"button\"\n onClick={() => {\n const val = window.prompt(\n 'Context history limit (messages sent with each prompt):',\n String(sessionState.contextHistoryLimit)\n );\n if (val !== null) {\n const num = parseInt(val, 10);\n if (!isNaN(num) && num >= 0) {\n const store = useAgentManagerStore.getState();\n const s = store.sessionStates[sessionId];\n if (s) {\n useAgentManagerStore.setState((prev) => ({\n sessionStates: {\n ...prev.sessionStates,\n [sessionId]: { ...s, contextHistoryLimit: num },\n },\n }));\n }\n }\n }\n }}\n className=\"p-1.5 rounded text-[10px] font-mono text-text-tertiary hover:text-text-secondary transition-colors\"\n title={`Context history: last ${sessionState.contextHistoryLimit} messages sent with each prompt`}\n >\n H:{sessionState.contextHistoryLimit}\n </button>\n <VoiceToggle\n enabled={sessionState.voiceEnabled}\n onToggle={() => {\n toggleVoice(sessionId);\n if (!sessionState.voiceEnabled) startListening();\n else stopListening();\n }}\n isListening={isListening}\n />\n <FileAttachButton onFileSelect={handleFileSelect} />\n </div>\n\n {/* Textarea + send/cancel */}\n <div className=\"flex items-end gap-2 px-3 pb-3 pt-1\">\n <textarea\n aria-label=\"control\"\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={tr(\n 'vibecontrols.agentManager.inputArea.placeholder',\n 'Type a message or / for commands... (Enter to send)'\n )}\n rows={1}\n className=\"flex-1 resize-none rounded-lg border border-border-default bg-bg-primary px-3 py-2 text-sm text-text-primary placeholder:text-text-tertiary focus:outline-none focus:border-border-strong transition-colors\"\n disabled={isStreaming}\n />\n {isStreaming ? (\n <button\n type=\"button\"\n onClick={handleCancel}\n className=\"flex-shrink-0 p-2 rounded-lg bg-status-error-bg text-status-error-text hover:opacity-90 transition-opacity\"\n title={tr('vibecontrols.agentManager.inputArea.cancel', 'Cancel')}\n >\n <Square className=\"size-4\" />\n </button>\n ) : (\n <div className=\"flex items-end flex-shrink-0 relative\" ref={scheduleMenuRef}>\n <button\n type=\"button\"\n onClick={handleSend}\n disabled={!canSend}\n className=\"p-2 rounded-l-lg bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.send', 'Send (Enter)')}\n >\n <ArrowUp className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setShowScheduleMenu(!showScheduleMenu)}\n disabled={!canSend}\n className=\"ml-1 p-2 rounded-r-lg border-l border-action-primary-text/20 bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n title={tr('vibecontrols.agentManager.inputArea.scheduleSend', 'Schedule send')}\n >\n <ChevronDown className=\"size-3\" />\n </button>\n\n {/* Schedule dropdown */}\n {showScheduleMenu && (\n <div className=\"absolute bottom-full right-0 mb-1 w-56 bg-bg-surface border border-border-default rounded-md shadow-lg py-1 z-50\">\n {!showSchedulePopup ? (\n <button\n type=\"button\"\n onClick={() => setShowSchedulePopup(true)}\n className=\"flex items-center gap-2 w-full px-3 py-2 text-left text-xs text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n <Clock className=\"size-3.5 text-text-secondary\" />\n {tr(\n 'vibecontrols.agentManager.inputArea.scheduleSendEllipsis',\n 'Schedule Send...'\n )}\n </button>\n ) : (\n <div className=\"px-3 py-2 space-y-2\">\n <label className=\"block text-[11px] font-medium text-text-secondary\">\n {tr('vibecontrols.agentManager.inputArea.sendAt', 'Send at:')}\n </label>\n <input\n aria-label=\"control\"\n type=\"datetime-local\"\n value={scheduleDateTime}\n onChange={(e) => setScheduleDateTime(e.target.value)}\n className=\"w-full px-2 py-1 text-xs rounded border border-border-default bg-bg-primary text-text-primary focus:outline-none focus:border-border-strong\"\n />\n <button\n type=\"button\"\n onClick={() => void handleScheduleSend()}\n disabled={!scheduleDateTime || !agentTunnelUrl || !agentApiKey}\n className=\"w-full px-2 py-1.5 text-xs font-medium rounded bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bg-hover disabled:opacity-40 disabled:cursor-not-allowed transition-colors\"\n >\n {tr('vibecontrols.agentManager.inputArea.schedule', 'Schedule')}\n </button>\n </div>\n )}\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|