@parhelia/core 0.1.12169 → 0.1.12181

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.
@@ -1,10 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import React, { useEffect, useState, useRef, useCallback, useLayoutEffect, useMemo, } from "react";
3
- import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, ArrowLeft, DollarSign, } from "lucide-react";
4
- import { getAgent, startAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, } from "../services/agentService";
3
+ import { Send, AlertCircle, Loader2, User, Wand2, Square, Mic, MicOff, ChevronDown, ChevronUp, ListTodo, ArrowLeft, DollarSign, ExternalLink, Settings2, Target, Plus, X, } from "lucide-react";
4
+ import { getAgent, startAgent, updateAgentSettings, updateAgentCostLimit, updateAgentContext, getAgentSkills, cancelAgent, canonicalizeAgentMetadata, getPendingPrompts, } from "../services/agentService";
5
5
  import { useEditContext, useFieldsEditContext } from "../client/editContext";
6
6
  import { Textarea } from "../../components/ui/textarea";
7
7
  import { Button } from "../../components/ui/button";
8
+ import { Input } from "../../components/ui/input";
8
9
  import { PlaceholderInput, } from "../../components/ui/PlaceholderInput";
9
10
  import { AiResponseMessage } from "./AiResponseMessage";
10
11
  import { ContextInfoBar } from "./ContextInfoBar";
@@ -771,6 +772,11 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
771
772
  const [contextPanelsActiveTab, setContextPanelsActiveTab] = useState(0);
772
773
  const [hiddenContextPanelTabIds, setHiddenContextPanelTabIds] = useState(new Set());
773
774
  const [showCostAndAgent, setShowCostAndAgent] = useState(false);
775
+ const [showAgentSettings, setShowAgentSettings] = useState(false);
776
+ const [skillSearchTerm, setSkillSearchTerm] = useState("");
777
+ const [availableSkills, setAvailableSkills] = useState([]);
778
+ const [skillsLoading, setSkillsLoading] = useState(false);
779
+ const [skillsError, setSkillsError] = useState(null);
774
780
  const hasSpawnedAgents = useMemo(() => {
775
781
  if (!agentMetadata)
776
782
  return false;
@@ -865,6 +871,33 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
865
871
  });
866
872
  return () => unsubscribe();
867
873
  }, [agent?.id, editContext?.addSocketMessageListener]);
874
+ useEffect(() => {
875
+ let active = true;
876
+ const loadSkills = async () => {
877
+ try {
878
+ setSkillsLoading(true);
879
+ setSkillsError(null);
880
+ const skills = await getAgentSkills(false);
881
+ if (active) {
882
+ setAvailableSkills(skills.filter((s) => !s.disabled));
883
+ }
884
+ }
885
+ catch (e) {
886
+ if (active) {
887
+ setSkillsError(e?.message || "Failed to load skills");
888
+ }
889
+ }
890
+ finally {
891
+ if (active) {
892
+ setSkillsLoading(false);
893
+ }
894
+ }
895
+ };
896
+ void loadSkills();
897
+ return () => {
898
+ active = false;
899
+ };
900
+ }, []);
868
901
  const modeOptions = useMemo(() => [
869
902
  {
870
903
  value: "supervised",
@@ -899,6 +932,70 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
899
932
  value: m.id,
900
933
  label: m.name,
901
934
  })) || []).sort((a, b) => a.label.localeCompare(b.label)), [activeProfile]);
935
+ const metadataSelectedSkillIds = useMemo(() => {
936
+ const rawSkillIds = agentMetadata?.additionalData?.skillIds ??
937
+ agentMetadata?.AdditionalData?.skillIds ??
938
+ agentMetadata?.skillIds ??
939
+ agentMetadata?.SkillIds ??
940
+ [];
941
+ if (!Array.isArray(rawSkillIds)) {
942
+ return [];
943
+ }
944
+ return rawSkillIds
945
+ .map((x) => String(x || "").trim())
946
+ .filter((x) => x.length > 0);
947
+ }, [agentMetadata]);
948
+ const backendAssignedSkillIds = useMemo(() => {
949
+ const rawSkillIds = agent?.assignedSkillIds ?? agent?.AssignedSkillIds ?? [];
950
+ if (!Array.isArray(rawSkillIds)) {
951
+ return [];
952
+ }
953
+ return rawSkillIds
954
+ .map((x) => String(x || "").trim())
955
+ .filter((x) => x.length > 0);
956
+ }, [agent]);
957
+ const selectedSkillIds = useMemo(() => {
958
+ const all = [...backendAssignedSkillIds, ...metadataSelectedSkillIds];
959
+ const seen = new Set();
960
+ const unique = [];
961
+ for (const id of all) {
962
+ const key = id.toLowerCase();
963
+ if (seen.has(key))
964
+ continue;
965
+ seen.add(key);
966
+ unique.push(id);
967
+ }
968
+ return unique;
969
+ }, [backendAssignedSkillIds, metadataSelectedSkillIds]);
970
+ const allowedProfileSkillIdSet = useMemo(() => {
971
+ const ids = activeProfile?.allowedSkills
972
+ ?.map((skill) => String(skill?.id || "").toLowerCase())
973
+ .filter((id) => id.length > 0) || [];
974
+ return new Set(ids);
975
+ }, [activeProfile?.allowedSkills]);
976
+ const profileFilteredSkills = useMemo(() => {
977
+ if (allowedProfileSkillIdSet.size === 0) {
978
+ return availableSkills;
979
+ }
980
+ return availableSkills.filter((skill) => allowedProfileSkillIdSet.has(skill.id.toLowerCase()));
981
+ }, [availableSkills, allowedProfileSkillIdSet]);
982
+ const selectedSkills = useMemo(() => selectedSkillIds
983
+ .map((id) => profileFilteredSkills.find((s) => s.id.toLowerCase() === id.toLowerCase()))
984
+ .filter((s) => !!s), [profileFilteredSkills, selectedSkillIds]);
985
+ const selectedSkillSet = useMemo(() => new Set(selectedSkillIds.map((id) => id.toLowerCase())), [selectedSkillIds]);
986
+ const backendAssignedSkillSet = useMemo(() => new Set(backendAssignedSkillIds.map((id) => id.toLowerCase())), [backendAssignedSkillIds]);
987
+ const selectableSkills = useMemo(() => profileFilteredSkills.filter((skill) => !selectedSkillSet.has(skill.id.toLowerCase())), [profileFilteredSkills, selectedSkillSet]);
988
+ const filteredSelectableSkills = useMemo(() => {
989
+ const q = skillSearchTerm.trim().toLowerCase();
990
+ if (!q)
991
+ return selectableSkills;
992
+ return selectableSkills.filter((skill) => {
993
+ const name = (skill.name || "").toLowerCase();
994
+ const description = (skill.description || "").toLowerCase();
995
+ const id = (skill.id || "").toLowerCase();
996
+ return name.includes(q) || description.includes(q) || id.includes(q);
997
+ });
998
+ }, [selectableSkills, skillSearchTerm]);
902
999
  // Remove deprecated cost limit fields from metadata to avoid confusion with agent/profile settings
903
1000
  const sanitizeAgentMetadata = useCallback((meta) => {
904
1001
  try {
@@ -923,6 +1020,65 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
923
1020
  return meta;
924
1021
  }
925
1022
  }, []);
1023
+ const updateSelectedSkillIds = useCallback(async (skillIds) => {
1024
+ if (!agent?.id)
1025
+ return;
1026
+ const current = agentMetadata || {};
1027
+ const currentAdditionalData = current.additionalData ||
1028
+ current.AdditionalData ||
1029
+ {};
1030
+ const nextAdditionalData = {
1031
+ ...currentAdditionalData,
1032
+ };
1033
+ if (skillIds.length > 0) {
1034
+ nextAdditionalData.skillIds = skillIds;
1035
+ }
1036
+ else {
1037
+ delete nextAdditionalData.skillIds;
1038
+ }
1039
+ const next = {
1040
+ ...current,
1041
+ };
1042
+ if (Object.keys(nextAdditionalData).length > 0) {
1043
+ next.additionalData = nextAdditionalData;
1044
+ delete next.AdditionalData;
1045
+ }
1046
+ else {
1047
+ delete next.additionalData;
1048
+ delete next.AdditionalData;
1049
+ }
1050
+ try {
1051
+ if (agent.status === "new") {
1052
+ setAgentMetadata(next);
1053
+ return;
1054
+ }
1055
+ await updateAgentContext(agent.id, next);
1056
+ setAgentMetadata(next);
1057
+ setAgent((prev) => prev ? { ...prev, agentContext: JSON.stringify(next) } : prev);
1058
+ }
1059
+ catch (e) {
1060
+ console.error("Failed to update selected skills", e);
1061
+ }
1062
+ }, [agent?.id, agent?.status, agentMetadata, setAgent, setAgentMetadata]);
1063
+ const handleAddSkill = useCallback(async (skillId) => {
1064
+ if (selectedSkillSet.has(skillId.toLowerCase()))
1065
+ return;
1066
+ await updateSelectedSkillIds([...metadataSelectedSkillIds, skillId]);
1067
+ }, [metadataSelectedSkillIds, selectedSkillSet, updateSelectedSkillIds]);
1068
+ const handleRemoveSkill = useCallback(async (skillId) => {
1069
+ await updateSelectedSkillIds(metadataSelectedSkillIds.filter((id) => id.toLowerCase() !== skillId.toLowerCase()));
1070
+ }, [metadataSelectedSkillIds, updateSelectedSkillIds]);
1071
+ const handleOpenProfileSettings = useCallback(async () => {
1072
+ if (!editContext || !activeProfile?.id)
1073
+ return;
1074
+ const lang = editContext.currentItemDescriptor?.language || "en";
1075
+ await editContext.loadItem({
1076
+ id: activeProfile.id,
1077
+ language: lang,
1078
+ version: 0,
1079
+ });
1080
+ editContext.switchWorkspace("editor");
1081
+ }, [editContext, activeProfile?.id]);
926
1082
  // Read deterministic flags from query string once
927
1083
  let deterministicFlags;
928
1084
  try {
@@ -4139,7 +4295,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4139
4295
  if (isLoading && !activeInlineDialog) {
4140
4296
  return (_jsx("div", { className: "flex h-full items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-[11px] text-gray-500", children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin", strokeWidth: 1 }), "Loading agent..."] }) }));
4141
4297
  }
4142
- const renderContextInfoBar = () => (_jsx(ContextInfoBar, { agent: agent, agentMetadata: agentMetadata, setAgentMetadata: setAgentMetadata, setAgent: setAgent, resolvedPageName: resolvedPageName, resolvedComponentName: resolvedComponentName, resolvedFieldName: resolvedFieldName, isLiveEditorContextMode: isLiveEditorContextMode, activeProfile: activeProfile, onRefreshContext: handleRefreshContext }));
4298
+ const renderContextInfoBar = () => (_jsx(ContextInfoBar, { agent: agent, agentMetadata: agentMetadata, setAgentMetadata: setAgentMetadata, setAgent: setAgent, resolvedPageName: resolvedPageName, resolvedComponentName: resolvedComponentName, resolvedFieldName: resolvedFieldName, isLiveEditorContextMode: isLiveEditorContextMode, onRefreshContext: handleRefreshContext }));
4143
4299
  const renderCostLimitBanner = () => {
4144
4300
  if (!costLimitExceeded)
4145
4301
  return null;
@@ -4424,7 +4580,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4424
4580
  ? "border-amber-300 bg-amber-50! text-amber-700 hover:bg-amber-100!"
4425
4581
  : "border-red-300 bg-red-50! text-red-700 hover:bg-red-100!"), value: mode, options: modeOptions, onValueChange: async (val) => {
4426
4582
  const nextMode = val || "supervised";
4427
- // Optimistic UI update
4428
4583
  setMode(nextMode);
4429
4584
  const current = agentMetadata || {};
4430
4585
  const nextMeta = {
@@ -4434,7 +4589,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4434
4589
  try {
4435
4590
  if (!agent?.id || agent.status === "new") {
4436
4591
  setAgentMetadata(nextMeta);
4437
- // Cache until first start when agent is persisted
4438
4592
  pendingSettingsRef.current = {
4439
4593
  ...(pendingSettingsRef.current || {}),
4440
4594
  mode: nextMode,
@@ -4445,87 +4599,108 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4445
4599
  mode: nextMode,
4446
4600
  });
4447
4601
  setAgentMetadata(nextMeta);
4448
- setAgent((prev) => prev
4449
- ? { ...prev, metadata: JSON.stringify(nextMeta) }
4450
- : prev);
4451
- }
4452
- catch (e2) {
4453
- console.error("Failed to persist mode change", e2);
4454
- }
4455
- } }), profiles?.length > 0 && (_jsx(Select, { size: "xs", maxWidth: 200, searchable: profiles.length > 5, searchPlaceholder: "Filter profiles...", className: "h-5 w-auto min-w-[120px] rounded border px-1.5 text-[11px] text-gray-500", value: activeProfile?.id || "", options: profileOptions, "data-testid": "agent-profile-selector", onValueChange: async (val) => {
4456
- const nextProfile = profiles.find((x) => x.id === val);
4457
- if (!nextProfile)
4458
- return;
4459
- setActiveProfile(nextProfile);
4460
- try {
4461
- if (agent?.id && agent.status !== "new") {
4462
- await updateAgentSettings(agent.id, {
4463
- profileId: nextProfile.id,
4464
- profileName: nextProfile.name,
4465
- });
4466
- }
4467
- else {
4468
- // cache until first start
4469
- pendingSettingsRef.current = {
4470
- ...(pendingSettingsRef.current || {}),
4471
- // we cache profile by updating local metadata
4472
- };
4473
- setAgentMetadata((current) => {
4474
- const next = { ...(current || {}) };
4475
- next.profile = nextProfile.name;
4476
- next.additionalData = {
4477
- ...(next.additionalData || {}),
4478
- profileId: nextProfile.id,
4479
- profileName: nextProfile.name,
4480
- };
4481
- return next;
4482
- });
4483
- }
4484
- // reflect in local agent stub so tabs and titles can use it if needed
4485
4602
  setAgent((prev) => prev
4486
4603
  ? {
4487
4604
  ...prev,
4488
- metadata: JSON.stringify({
4489
- ...(agentMetadata || {}),
4490
- profile: nextProfile.name,
4491
- additionalData: {
4492
- ...(agentMetadata
4493
- ?.additionalData || {}),
4494
- profileId: nextProfile.id,
4495
- profileName: nextProfile.name,
4496
- },
4497
- }),
4605
+ metadata: JSON.stringify(nextMeta),
4498
4606
  }
4499
4607
  : prev);
4500
4608
  }
4501
- catch (err) {
4502
- console.error("Failed to persist agent profile", err);
4503
- }
4504
- } })), activeProfile?.models?.length ? (_jsx(Select, { size: "xs", maxWidth: 300, searchable: activeProfile.models.length > 5, searchPlaceholder: "Filter models...", className: "h-5 w-auto min-w-[120px] rounded border px-1.5 text-[11px] text-gray-500", value: selectedModelId || "", options: modelOptions, onValueChange: async (val) => {
4505
- const nextId = val;
4506
- setSelectedModelId(nextId);
4507
- const modelName = activeProfile?.models?.find((m) => m.id === nextId)
4508
- ?.name || "";
4509
- // Update local agent state immediately for UX and to reflect in streaming stub
4510
- setAgent((prev) => prev ? { ...prev, model: modelName } : prev);
4511
- // Persist only for existing agents; otherwise cache until first start
4512
- try {
4513
- if (agent?.id && agent.status !== "new") {
4514
- await updateAgentSettings(agent.id, {
4515
- model: modelName,
4516
- });
4517
- }
4518
- else {
4519
- pendingSettingsRef.current = {
4520
- ...(pendingSettingsRef.current || {}),
4521
- modelName,
4522
- };
4523
- }
4524
- }
4525
- catch (err) {
4526
- console.error("Failed to persist agent model", err);
4609
+ catch (e2) {
4610
+ console.error("Failed to persist mode change", e2);
4527
4611
  }
4528
- } })) : null, activeProfile?.prompts?.length ? (_jsxs(Popover, { open: showPredefined, onOpenChange: setShowPredefined, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "rounded p-1 hover:bg-gray-100", onClick: () => { }, title: "Predefined prompts", "aria-label": "Predefined prompts", type: "button", children: _jsx(Wand2, { className: "h-3 w-3", strokeWidth: 1 }) }) }), _jsx(PopoverContent, { className: "w-64 p-0", align: "start", children: _jsx("div", { className: "max-h-56 overflow-y-auto p-2", children: activeProfile.prompts.map((p, index) => (_jsx("div", { className: "cursor-pointer rounded p-1.5 text-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4612
+ } }), _jsxs(Popover, { open: showAgentSettings, onOpenChange: (open) => {
4613
+ setShowAgentSettings(open);
4614
+ if (!open)
4615
+ setSkillSearchTerm("");
4616
+ }, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { size: "xs", variant: "outline", className: "h-5 rounded border px-1.5 text-[11px] text-gray-600", "data-testid": "agent-settings-popover-trigger", children: [_jsx(Settings2, { className: "mr-1 h-3 w-3", strokeWidth: 1 }), "Agent settings"] }) }), _jsx(PopoverContent, { className: "w-80 p-3", align: "start", children: _jsxs("div", { className: "space-y-3", children: [profiles?.length > 0 && (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-[11px] font-medium text-gray-700", children: "Agent profile" }), _jsx(Select, { size: "xs", maxWidth: 300, searchable: profiles.length > 5, searchPlaceholder: "Filter profiles...", className: "h-6 w-full rounded border px-1.5 text-[11px] text-gray-500", value: activeProfile?.id || "", options: profileOptions, "data-testid": "agent-profile-selector", onValueChange: async (val) => {
4617
+ const nextProfile = profiles.find((x) => x.id === val);
4618
+ if (!nextProfile)
4619
+ return;
4620
+ setActiveProfile(nextProfile);
4621
+ try {
4622
+ if (agent?.id && agent.status !== "new") {
4623
+ await updateAgentSettings(agent.id, {
4624
+ profileId: nextProfile.id,
4625
+ profileName: nextProfile.name,
4626
+ });
4627
+ }
4628
+ else {
4629
+ pendingSettingsRef.current = {
4630
+ ...(pendingSettingsRef.current || {}),
4631
+ };
4632
+ setAgentMetadata((current) => {
4633
+ const next = { ...(current || {}) };
4634
+ next.profile = nextProfile.name;
4635
+ next.additionalData = {
4636
+ ...(next.additionalData || {}),
4637
+ profileId: nextProfile.id,
4638
+ profileName: nextProfile.name,
4639
+ };
4640
+ return next;
4641
+ });
4642
+ }
4643
+ setAgent((prev) => prev
4644
+ ? {
4645
+ ...prev,
4646
+ metadata: JSON.stringify({
4647
+ ...(agentMetadata || {}),
4648
+ profile: nextProfile.name,
4649
+ additionalData: {
4650
+ ...(agentMetadata
4651
+ ?.additionalData || {}),
4652
+ profileId: nextProfile.id,
4653
+ profileName: nextProfile.name,
4654
+ },
4655
+ }),
4656
+ }
4657
+ : prev);
4658
+ }
4659
+ catch (err) {
4660
+ console.error("Failed to persist agent profile", err);
4661
+ }
4662
+ } }), activeProfile && (_jsxs("button", { type: "button", className: "mt-1 inline-flex items-center gap-1 text-[10px] text-gray-500 hover:text-gray-700", onClick: () => {
4663
+ void handleOpenProfileSettings();
4664
+ setShowAgentSettings(false);
4665
+ }, children: ["Open profile settings", _jsx(ExternalLink, { className: "h-2.5 w-2.5", strokeWidth: 1.5 })] }))] })), activeProfile?.models?.length ? (_jsxs("div", { children: [_jsx("div", { className: "mb-1 text-[11px] font-medium text-gray-700", children: "Model" }), _jsx(Select, { size: "xs", maxWidth: 300, searchable: activeProfile.models.length > 5, searchPlaceholder: "Filter models...", className: "h-6 w-full rounded border px-1.5 text-[11px] text-gray-500", value: selectedModelId || "", options: modelOptions, onValueChange: async (val) => {
4666
+ const nextId = val;
4667
+ setSelectedModelId(nextId);
4668
+ const modelName = activeProfile?.models?.find((m) => m.id === nextId)
4669
+ ?.name || "";
4670
+ setAgent((prev) => prev ? { ...prev, model: modelName } : prev);
4671
+ try {
4672
+ if (agent?.id && agent.status !== "new") {
4673
+ await updateAgentSettings(agent.id, {
4674
+ model: modelName,
4675
+ });
4676
+ }
4677
+ else {
4678
+ pendingSettingsRef.current = {
4679
+ ...(pendingSettingsRef.current || {}),
4680
+ modelName,
4681
+ };
4682
+ }
4683
+ }
4684
+ catch (err) {
4685
+ console.error("Failed to persist agent model", err);
4686
+ }
4687
+ } })] })) : null, _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center gap-1 text-[11px] font-medium text-gray-700", children: [_jsx(Target, { className: "h-3 w-3", strokeWidth: 1 }), "Skills"] }), _jsx(Input, { value: skillSearchTerm, onChange: (e) => setSkillSearchTerm(e.target.value), placeholder: "Search skills...", className: "mb-2 h-6 px-2 text-[10px]" }), selectedSkillIds.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-1", children: selectedSkillIds.map((skillId) => {
4688
+ const skill = selectedSkills.find((s) => s.id === skillId);
4689
+ return (_jsxs("button", { type: "button", className: "inline-flex items-center gap-1 rounded-full border border-gray-200 bg-gray-100 px-1.5 py-0.5 text-[10px] text-gray-700 hover:bg-gray-200", onClick: () => {
4690
+ if (backendAssignedSkillSet.has(skillId.toLowerCase()))
4691
+ return;
4692
+ void handleRemoveSkill(skillId);
4693
+ }, disabled: backendAssignedSkillSet.has(skillId.toLowerCase()), title: backendAssignedSkillSet.has(skillId.toLowerCase())
4694
+ ? "Assigned by backend profile"
4695
+ : "Remove skill", children: [_jsx("span", { children: skill?.name || skillId }), backendAssignedSkillSet.has(skillId.toLowerCase()) ? (_jsx("span", { className: "text-[9px] text-gray-500", children: "auto" })) : (_jsx(X, { className: "h-2.5 w-2.5", strokeWidth: 1 }))] }, skillId));
4696
+ }) })), _jsx("div", { className: "max-h-40 space-y-1 overflow-y-auto rounded border border-gray-200 bg-gray-50 p-1.5", children: skillsLoading ? (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: "Loading skills..." })) : filteredSelectableSkills.length > 0 ? (filteredSelectableSkills.map((skill) => (_jsxs("button", { type: "button", className: "flex w-full items-start gap-1 rounded px-1.5 py-1 text-left text-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4697
+ void handleAddSkill(skill.id);
4698
+ setSkillSearchTerm("");
4699
+ }, children: [_jsx(Plus, { className: "mt-[1px] h-2.5 w-2.5 shrink-0", strokeWidth: 1 }), _jsxs("span", { className: "min-w-0", children: [_jsx("span", { className: "block truncate font-medium text-gray-900", children: skill.name }), skill.description && (_jsx("span", { className: "line-clamp-2 text-[10px] text-gray-500", children: skill.description }))] })] }, skill.id)))) : (_jsx("div", { className: "px-1 text-[10px] text-gray-500", children: selectableSkills.length === 0
4700
+ ? selectedSkillIds.length > 0
4701
+ ? "All allowed skills are selected"
4702
+ : "No skills available for this profile"
4703
+ : "No skills match your search" })) }), !skillsLoading && selectableSkills.length > 0 && (_jsxs("div", { className: "mt-1 text-[10px] text-gray-500", children: ["Showing ", filteredSelectableSkills.length, " of ", selectableSkills.length] })), skillsError && (_jsx("div", { className: "mt-1 text-[10px] text-red-600", children: skillsError }))] })] }) })] }), activeProfile?.prompts?.length ? (_jsxs(Popover, { open: showPredefined, onOpenChange: setShowPredefined, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx("button", { className: "rounded p-1 hover:bg-gray-100", onClick: () => { }, title: "Predefined prompts", "aria-label": "Predefined prompts", type: "button", children: _jsx(Wand2, { className: "h-3 w-3", strokeWidth: 1 }) }) }), _jsx(PopoverContent, { className: "w-64 p-0", align: "start", children: _jsx("div", { className: "max-h-56 overflow-y-auto p-2", children: activeProfile.prompts.map((p, index) => (_jsx("div", { className: "cursor-pointer rounded p-1.5 text-[10px] text-gray-700 hover:bg-gray-100", onClick: () => {
4529
4704
  setPrompt(p.prompt);
4530
4705
  setShowPredefined(false);
4531
4706
  if (textareaRef.current)
@@ -4545,7 +4720,7 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4545
4720
  cacheWriteCost: liveTotals.cacheWriteCost ?? 0,
4546
4721
  totalCost: liveTotals.totalCost,
4547
4722
  }
4548
- : totalTokens, effectiveCostLimit: effectiveCostLimit, messages: messages, activeProfile: activeProfile, showCompressionPopover: showCompressionPopover, setShowCompressionPopover: setShowCompressionPopover }) }) })] }))] })), _jsxs("div", { className: "flex items-center gap-1 self-end", children: [_jsx("span", { title: isVoiceDisabled
4723
+ : totalTokens, effectiveCostLimit: effectiveCostLimit, messages: messages, showCompressionPopover: showCompressionPopover, setShowCompressionPopover: setShowCompressionPopover }) }) })] }))] })), _jsxs("div", { className: "flex items-center gap-1 self-end", children: [_jsx("span", { title: isVoiceDisabled
4549
4724
  ? "Your browser does not support Speech Recognition"
4550
4725
  : isListening
4551
4726
  ? "Stop voice input"
@@ -4578,6 +4753,6 @@ export function AgentTerminal({ agentStub, initialMetadata, profiles, isActive =
4578
4753
  cacheWriteCost: liveTotals.cacheWriteCost ?? 0,
4579
4754
  totalCost: liveTotals.totalCost,
4580
4755
  }
4581
- : totalTokens, effectiveCostLimit: effectiveCostLimit, messages: messages, activeProfile: activeProfile, showCompressionPopover: showCompressionPopover, setShowCompressionPopover: setShowCompressionPopover }))] })] }));
4756
+ : totalTokens, effectiveCostLimit: effectiveCostLimit, messages: messages, showCompressionPopover: showCompressionPopover, setShowCompressionPopover: setShowCompressionPopover }))] })] }));
4582
4757
  }
4583
4758
  //# sourceMappingURL=AgentTerminal.js.map