@stigmer/react 0.5.0 → 0.5.1

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.
Files changed (94) hide show
  1. package/composer/ContextChip.d.ts +7 -2
  2. package/composer/ContextChip.d.ts.map +1 -1
  3. package/composer/ContextChip.js +2 -1
  4. package/composer/ContextChip.js.map +1 -1
  5. package/composer/SessionComposer.d.ts +11 -0
  6. package/composer/SessionComposer.d.ts.map +1 -1
  7. package/composer/SessionComposer.js +33 -4
  8. package/composer/SessionComposer.js.map +1 -1
  9. package/environment/usePersonalEnvironment.d.ts.map +1 -1
  10. package/environment/usePersonalEnvironment.js +1 -0
  11. package/environment/usePersonalEnvironment.js.map +1 -1
  12. package/index.d.ts +2 -2
  13. package/index.d.ts.map +1 -1
  14. package/index.js +1 -1
  15. package/index.js.map +1 -1
  16. package/inline-edit/InlineEditKeyValue.d.ts +5 -1
  17. package/inline-edit/InlineEditKeyValue.d.ts.map +1 -1
  18. package/inline-edit/InlineEditKeyValue.js +3 -3
  19. package/inline-edit/InlineEditKeyValue.js.map +1 -1
  20. package/internal/useFetch.js +2 -2
  21. package/internal/useFetch.js.map +1 -1
  22. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  23. package/mcp-server/McpServerDetailView.js +145 -46
  24. package/mcp-server/McpServerDetailView.js.map +1 -1
  25. package/models/ModelRegistryContext.d.ts +2 -0
  26. package/models/ModelRegistryContext.d.ts.map +1 -1
  27. package/models/ModelRegistryContext.js +1 -0
  28. package/models/ModelRegistryContext.js.map +1 -1
  29. package/models/ModelSelector.d.ts.map +1 -1
  30. package/models/ModelSelector.js +2 -2
  31. package/models/ModelSelector.js.map +1 -1
  32. package/models/__tests__/useModelRegistry.test.js +4 -3
  33. package/models/__tests__/useModelRegistry.test.js.map +1 -1
  34. package/models/useModelRegistry.d.ts +2 -0
  35. package/models/useModelRegistry.d.ts.map +1 -1
  36. package/models/useModelRegistry.js +3 -2
  37. package/models/useModelRegistry.js.map +1 -1
  38. package/package.json +4 -4
  39. package/provider.d.ts.map +1 -1
  40. package/provider.js +69 -22
  41. package/provider.js.map +1 -1
  42. package/session/__tests__/session-spec-converters.test.d.ts +2 -0
  43. package/session/__tests__/session-spec-converters.test.d.ts.map +1 -0
  44. package/session/__tests__/session-spec-converters.test.js +162 -0
  45. package/session/__tests__/session-spec-converters.test.js.map +1 -0
  46. package/session/__tests__/useNewSessionFlow.test.js +2 -2
  47. package/session/__tests__/useNewSessionFlow.test.js.map +1 -1
  48. package/session/__tests__/usePersistedModel.test.js +1 -1
  49. package/session/__tests__/usePersistedModel.test.js.map +1 -1
  50. package/session/group-sessions.d.ts +17 -0
  51. package/session/group-sessions.d.ts.map +1 -1
  52. package/session/group-sessions.js +46 -0
  53. package/session/group-sessions.js.map +1 -1
  54. package/session/index.d.ts +4 -2
  55. package/session/index.d.ts.map +1 -1
  56. package/session/index.js +2 -1
  57. package/session/index.js.map +1 -1
  58. package/session/session-spec-converters.d.ts +24 -0
  59. package/session/session-spec-converters.d.ts.map +1 -0
  60. package/session/session-spec-converters.js +72 -0
  61. package/session/session-spec-converters.js.map +1 -0
  62. package/session/useSessionConversation.d.ts.map +1 -1
  63. package/session/useSessionConversation.js +1 -56
  64. package/session/useSessionConversation.js.map +1 -1
  65. package/session/useSessionPageFlow.d.ts +5 -0
  66. package/session/useSessionPageFlow.d.ts.map +1 -1
  67. package/session/useSessionPageFlow.js +20 -6
  68. package/session/useSessionPageFlow.js.map +1 -1
  69. package/session/useSessionSearch.d.ts +57 -0
  70. package/session/useSessionSearch.d.ts.map +1 -0
  71. package/session/useSessionSearch.js +94 -0
  72. package/session/useSessionSearch.js.map +1 -0
  73. package/src/composer/ContextChip.tsx +20 -11
  74. package/src/composer/SessionComposer.tsx +52 -3
  75. package/src/environment/usePersonalEnvironment.ts +1 -0
  76. package/src/index.ts +5 -0
  77. package/src/inline-edit/InlineEditKeyValue.tsx +23 -0
  78. package/src/internal/useFetch.ts +2 -2
  79. package/src/mcp-server/McpServerDetailView.tsx +429 -55
  80. package/src/models/ModelRegistryContext.ts +3 -0
  81. package/src/models/ModelSelector.tsx +25 -2
  82. package/src/models/__tests__/useModelRegistry.test.tsx +5 -3
  83. package/src/models/useModelRegistry.ts +5 -2
  84. package/src/provider.tsx +69 -18
  85. package/src/session/__tests__/session-spec-converters.test.ts +185 -0
  86. package/src/session/__tests__/useNewSessionFlow.test.tsx +2 -2
  87. package/src/session/__tests__/usePersistedModel.test.tsx +1 -1
  88. package/src/session/group-sessions.ts +65 -0
  89. package/src/session/index.ts +8 -2
  90. package/src/session/session-spec-converters.ts +86 -0
  91. package/src/session/useSessionConversation.ts +5 -64
  92. package/src/session/useSessionPageFlow.ts +28 -7
  93. package/src/session/useSessionSearch.ts +149 -0
  94. package/styles.css +1 -1
@@ -203,6 +203,18 @@ export interface SessionComposerProps {
203
203
  */
204
204
  readonly initialAgentRef?: ResourceRef;
205
205
 
206
+ /**
207
+ * When `true`, the agent chip renders without an X (remove) button.
208
+ *
209
+ * Used on the session page to indicate the session's default agent,
210
+ * where removing it would just re-select the same agent (a
211
+ * confusing no-op). The user can still switch agents via the
212
+ * Configure menu.
213
+ *
214
+ * @default false
215
+ */
216
+ readonly isDefaultAgent?: boolean;
217
+
206
218
  /**
207
219
  * Currently selected MCP server usages.
208
220
  * When `onMcpServerUsagesChange` is provided, a MCP server trigger
@@ -392,6 +404,7 @@ export const SessionComposer = memo(function SessionComposer({
392
404
  onAgentRefChange,
393
405
  onAgentResolutionChange,
394
406
  initialAgentRef,
407
+ isDefaultAgent = false,
395
408
  mcpServerUsages,
396
409
  onMcpServerUsagesChange,
397
410
  skillRefs,
@@ -868,14 +881,49 @@ export const SessionComposer = memo(function SessionComposer({
868
881
  }
869
882
  }, [initialAttachments, enableAttachments, attachments]);
870
883
 
884
+ // ---------------------------------------------------------------------------
885
+ // Initial MCP: seed useMcpServerSetup from mcpServerUsages prop on mount
886
+ // ---------------------------------------------------------------------------
887
+
888
+ const initialMcpSeeded = useRef(false);
889
+ const mcpSetupAddServerRef = useRef(mcpSetup.addServer);
890
+ mcpSetupAddServerRef.current = mcpSetup.addServer;
891
+ const mcpSetupSetEnabledToolsRef = useRef(mcpSetup.setEnabledTools);
892
+ mcpSetupSetEnabledToolsRef.current = mcpSetup.setEnabledTools;
893
+
894
+ useEffect(() => {
895
+ if (!showMcp || initialMcpSeeded.current || !mcpServerUsages?.length) return;
896
+ initialMcpSeeded.current = true;
897
+
898
+ for (const usage of mcpServerUsages) {
899
+ const ref = usage.mcpServerRef;
900
+ if (!ref) continue;
901
+ const savedTools = usage.enabledTools;
902
+
903
+ mcpSetupAddServerRef.current(ref).then(() => {
904
+ if (savedTools?.length) {
905
+ mcpSetupSetEnabledToolsRef.current(ref, savedTools);
906
+ }
907
+ }).catch(() => {
908
+ // Non-fatal: server may have been deleted or become inaccessible.
909
+ // The user can re-add it via the MCP picker.
910
+ });
911
+ }
912
+ }, [showMcp, mcpServerUsages]);
913
+
871
914
  // ---------------------------------------------------------------------------
872
915
  // MCP server setup: sync usageInputs to consumer
873
916
  // ---------------------------------------------------------------------------
874
917
 
918
+ const hasLoadingMcpEntries = useMemo(
919
+ () => Object.values(mcpSetup.entries).some(e => e.status === "loading"),
920
+ [mcpSetup.entries],
921
+ );
922
+
875
923
  useEffect(() => {
876
- if (!showMcp) return;
924
+ if (!showMcp || hasLoadingMcpEntries) return;
877
925
  onMcpServerUsagesChange?.(mcpSetup.usageInputs);
878
- }, [showMcp, mcpSetup.usageInputs, onMcpServerUsagesChange]);
926
+ }, [showMcp, mcpSetup.usageInputs, onMcpServerUsagesChange, hasLoadingMcpEntries]);
879
927
 
880
928
  // ---------------------------------------------------------------------------
881
929
  // Submission blocking: MCP servers must be fully configured before send
@@ -908,7 +956,7 @@ export const SessionComposer = memo(function SessionComposer({
908
956
  key: `agent:${refStr}`,
909
957
  label: displayNames.get(refStr) ?? agentRef.slug,
910
958
  type: "agent",
911
- onRemove: handleAgentChipRemove,
959
+ onRemove: isDefaultAgent ? undefined : handleAgentChipRemove,
912
960
  });
913
961
  } else if (
914
962
  agentSetup.state.status === "needsEnvVars" ||
@@ -1012,6 +1060,7 @@ export const SessionComposer = memo(function SessionComposer({
1012
1060
  return items;
1013
1061
  }, [
1014
1062
  agentRef,
1063
+ isDefaultAgent,
1015
1064
  agentSetup.state,
1016
1065
  handleAgentChipRemove,
1017
1066
  handlePendingAgentChipRemove,
@@ -184,6 +184,7 @@ export function usePersonalEnvironment(
184
184
  data,
185
185
  });
186
186
 
187
+ environmentRef.current = created;
187
188
  refetch();
188
189
  return created;
189
190
  } catch (err) {
package/src/index.ts CHANGED
@@ -89,6 +89,8 @@ export {
89
89
  parseDraftType,
90
90
  parseDraftParams,
91
91
  groupSessionsByTime,
92
+ groupSearchResultsByTime,
93
+ useSessionSearch,
92
94
  PENDING_SUBJECT,
93
95
  resolvedSubject,
94
96
  } from "./session";
@@ -101,6 +103,8 @@ export type {
101
103
  UseSessionReturn,
102
104
  UseSessionListOptions,
103
105
  UseSessionListReturn,
106
+ UseSessionSearchOptions,
107
+ UseSessionSearchReturn,
104
108
  UseSessionExecutionsReturn,
105
109
  SendFollowUpOptions,
106
110
  UseSessionConversationReturn,
@@ -121,6 +125,7 @@ export type {
121
125
  DraftResourceType,
122
126
  DraftParams,
123
127
  SessionGroup,
128
+ SearchResultGroup,
124
129
  } from "./session";
125
130
 
126
131
  // Execution — behavior hooks, styled components, and utilities (AgentExecution aggregate)
@@ -12,6 +12,10 @@ export interface InlineEditKeyValueProps extends InlineEditBaseProps {
12
12
  readonly onSave: (rows: KeyValueRow[]) => Promise<boolean>;
13
13
  /** Label for the "key" column. @default "Key" */
14
14
  readonly keyLabel?: string;
15
+ /** Show the value alongside the key in read mode and provide a value input in edit mode. @default false */
16
+ readonly showValue?: boolean;
17
+ /** Label for the "value" column (only relevant when showValue is true). @default "Value" */
18
+ readonly valueLabel?: string;
15
19
  /** Show the "secret" toggle per row. @default false */
16
20
  readonly showSecretToggle?: boolean;
17
21
  /** Show the "optional" toggle per row. @default false */
@@ -35,6 +39,8 @@ export function InlineEditKeyValue({
35
39
  value,
36
40
  onSave,
37
41
  keyLabel = "Key",
42
+ showValue = false,
43
+ valueLabel = "Value",
38
44
  showSecretToggle = false,
39
45
  showOptionalToggle = false,
40
46
  showDescription = false,
@@ -99,6 +105,11 @@ export function InlineEditKeyValue({
99
105
  <code className="shrink-0 font-mono text-sm font-medium text-foreground">
100
106
  {row.key}
101
107
  </code>
108
+ {showValue && (
109
+ <span className="min-w-0 break-all font-mono text-xs text-muted-foreground">
110
+ {row.value}
111
+ </span>
112
+ )}
102
113
  {showSecretToggle && (
103
114
  <span className="shrink-0 rounded bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
104
115
  {row.isSecret ? "secret" : "config"}
@@ -137,6 +148,18 @@ export function InlineEditKeyValue({
137
148
  "focus:outline-none focus:ring-2 focus:ring-ring",
138
149
  )}
139
150
  />
151
+ {showValue && (
152
+ <input
153
+ type="text"
154
+ value={row.value}
155
+ onChange={(e) => updateRow(i, { value: e.target.value })}
156
+ placeholder={valueLabel}
157
+ className={cn(
158
+ "rounded-md border border-border bg-input-bg px-2 py-1 font-mono text-sm text-foreground",
159
+ "focus:outline-none focus:ring-2 focus:ring-ring",
160
+ )}
161
+ />
162
+ )}
140
163
  {showDescription && (
141
164
  <input
142
165
  type="text"
@@ -94,8 +94,8 @@ export function useFetch<T>(
94
94
  const hasDataRef = useRef(
95
95
  cacheKey && cache ? cache.has(cacheKey) : false,
96
96
  );
97
- const isFetchingRef = useRef(false);
98
- const [isFetching, setIsFetching] = useState(false);
97
+ const isFetchingRef = useRef(fetchFn !== null);
98
+ const [isFetching, setIsFetching] = useState(fetchFn !== null);
99
99
 
100
100
  // Stable ref for cache — avoids adding cache to effect deps while
101
101
  // still letting the effect body access the current instance.