@stigmer/react 3.5.3 → 3.7.0

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 (283) hide show
  1. package/agent/AgentPicker.d.ts +10 -1
  2. package/agent/AgentPicker.d.ts.map +1 -1
  3. package/agent/AgentPicker.js +2 -2
  4. package/agent/AgentPicker.js.map +1 -1
  5. package/billing/CreditLedgerTable.d.ts.map +1 -1
  6. package/billing/CreditLedgerTable.js +2 -7
  7. package/billing/CreditLedgerTable.js.map +1 -1
  8. package/channel/AgentChannelsPanel.d.ts.map +1 -1
  9. package/channel/AgentChannelsPanel.js +22 -5
  10. package/channel/AgentChannelsPanel.js.map +1 -1
  11. package/channel/ChannelTemplatesDialog.d.ts +53 -0
  12. package/channel/ChannelTemplatesDialog.d.ts.map +1 -0
  13. package/channel/ChannelTemplatesDialog.js +150 -0
  14. package/channel/ChannelTemplatesDialog.js.map +1 -0
  15. package/channel/index.d.ts +8 -0
  16. package/channel/index.d.ts.map +1 -1
  17. package/channel/index.js +4 -0
  18. package/channel/index.js.map +1 -1
  19. package/channel/providers.d.ts +12 -0
  20. package/channel/providers.d.ts.map +1 -1
  21. package/channel/providers.js +14 -2
  22. package/channel/providers.js.map +1 -1
  23. package/channel/templatePresentation.d.ts +37 -0
  24. package/channel/templatePresentation.d.ts.map +1 -0
  25. package/channel/templatePresentation.js +69 -0
  26. package/channel/templatePresentation.js.map +1 -0
  27. package/channel/useChannelTemplateList.d.ts +64 -0
  28. package/channel/useChannelTemplateList.d.ts.map +1 -0
  29. package/channel/useChannelTemplateList.js +69 -0
  30. package/channel/useChannelTemplateList.js.map +1 -0
  31. package/channel/useChannelTemplateReadiness.d.ts +53 -0
  32. package/channel/useChannelTemplateReadiness.d.ts.map +1 -0
  33. package/channel/useChannelTemplateReadiness.js +42 -0
  34. package/channel/useChannelTemplateReadiness.js.map +1 -0
  35. package/composer/ComposerToolbar.d.ts +6 -1
  36. package/composer/ComposerToolbar.d.ts.map +1 -1
  37. package/composer/ComposerToolbar.js +2 -2
  38. package/composer/ComposerToolbar.js.map +1 -1
  39. package/composer/SessionComposer.d.ts +9 -0
  40. package/composer/SessionComposer.d.ts.map +1 -1
  41. package/composer/SessionComposer.js +13 -2
  42. package/composer/SessionComposer.js.map +1 -1
  43. package/dashboard/useDashboardFailedRuns.d.ts.map +1 -1
  44. package/dashboard/useDashboardFailedRuns.js +2 -0
  45. package/dashboard/useDashboardFailedRuns.js.map +1 -1
  46. package/execution/useCreateAgentExecution.d.ts +14 -0
  47. package/execution/useCreateAgentExecution.d.ts.map +1 -1
  48. package/execution/useCreateAgentExecution.js +5 -0
  49. package/execution/useCreateAgentExecution.js.map +1 -1
  50. package/index.d.ts +4 -2
  51. package/index.d.ts.map +1 -1
  52. package/index.js +10 -1
  53. package/index.js.map +1 -1
  54. package/internal/Pagination.d.ts +15 -0
  55. package/internal/Pagination.d.ts.map +1 -0
  56. package/internal/Pagination.js +20 -0
  57. package/internal/Pagination.js.map +1 -0
  58. package/library/useExportResource.d.ts +4 -3
  59. package/library/useExportResource.d.ts.map +1 -1
  60. package/library/useExportResource.js +1 -1
  61. package/library/useExportResource.js.map +1 -1
  62. package/models/ModelSelector.d.ts +26 -1
  63. package/models/ModelSelector.d.ts.map +1 -1
  64. package/models/ModelSelector.js +27 -6
  65. package/models/ModelSelector.js.map +1 -1
  66. package/models/index.d.ts +2 -0
  67. package/models/index.d.ts.map +1 -1
  68. package/models/index.js +1 -0
  69. package/models/index.js.map +1 -1
  70. package/models/registry.d.ts +10 -0
  71. package/models/registry.d.ts.map +1 -1
  72. package/models/registry.js +3 -0
  73. package/models/registry.js.map +1 -1
  74. package/models/service-tier.d.ts +27 -0
  75. package/models/service-tier.d.ts.map +1 -0
  76. package/models/service-tier.js +34 -0
  77. package/models/service-tier.js.map +1 -0
  78. package/organization/OrgProvider.d.ts +11 -4
  79. package/organization/OrgProvider.d.ts.map +1 -1
  80. package/organization/OrgProvider.js +28 -4
  81. package/organization/OrgProvider.js.map +1 -1
  82. package/package.json +4 -4
  83. package/resource-detail/useDeleteResource.d.ts +1 -1
  84. package/resource-detail/useDeleteResource.d.ts.map +1 -1
  85. package/resource-detail/useDeleteResource.js +5 -0
  86. package/resource-detail/useDeleteResource.js.map +1 -1
  87. package/resource-workbench/components/ResourceWorkbench.d.ts +10 -1
  88. package/resource-workbench/components/ResourceWorkbench.d.ts.map +1 -1
  89. package/resource-workbench/components/ResourceWorkbench.js +6 -2
  90. package/resource-workbench/components/ResourceWorkbench.js.map +1 -1
  91. package/resource-workbench/hooks/useResourceCollection.d.ts +8 -0
  92. package/resource-workbench/hooks/useResourceCollection.d.ts.map +1 -1
  93. package/resource-workbench/hooks/useResourceCollection.js +2 -2
  94. package/resource-workbench/hooks/useResourceCollection.js.map +1 -1
  95. package/schedule/CadenceField.d.ts +31 -0
  96. package/schedule/CadenceField.d.ts.map +1 -0
  97. package/schedule/CadenceField.js +116 -0
  98. package/schedule/CadenceField.js.map +1 -0
  99. package/schedule/ScheduleDetailView.d.ts +81 -0
  100. package/schedule/ScheduleDetailView.d.ts.map +1 -0
  101. package/schedule/ScheduleDetailView.js +648 -0
  102. package/schedule/ScheduleDetailView.js.map +1 -0
  103. package/schedule/ScheduleForm.d.ts +46 -0
  104. package/schedule/ScheduleForm.d.ts.map +1 -0
  105. package/schedule/ScheduleForm.js +214 -0
  106. package/schedule/ScheduleForm.js.map +1 -0
  107. package/schedule/ScheduleRowActions.d.ts +20 -0
  108. package/schedule/ScheduleRowActions.d.ts.map +1 -0
  109. package/schedule/ScheduleRowActions.js +54 -0
  110. package/schedule/ScheduleRowActions.js.map +1 -0
  111. package/schedule/ScheduleRunsTable.d.ts +72 -0
  112. package/schedule/ScheduleRunsTable.d.ts.map +1 -0
  113. package/schedule/ScheduleRunsTable.js +161 -0
  114. package/schedule/ScheduleRunsTable.js.map +1 -0
  115. package/schedule/TimeZoneField.d.ts +32 -0
  116. package/schedule/TimeZoneField.d.ts.map +1 -0
  117. package/schedule/TimeZoneField.js +104 -0
  118. package/schedule/TimeZoneField.js.map +1 -0
  119. package/schedule/cadence.d.ts +95 -0
  120. package/schedule/cadence.d.ts.map +1 -0
  121. package/schedule/cadence.js +242 -0
  122. package/schedule/cadence.js.map +1 -0
  123. package/schedule/index.d.ts +37 -0
  124. package/schedule/index.d.ts.map +1 -0
  125. package/schedule/index.js +19 -0
  126. package/schedule/index.js.map +1 -0
  127. package/schedule/scheduleColumns.d.ts +26 -0
  128. package/schedule/scheduleColumns.d.ts.map +1 -0
  129. package/schedule/scheduleColumns.js +77 -0
  130. package/schedule/scheduleColumns.js.map +1 -0
  131. package/schedule/scheduleListFn.d.ts +50 -0
  132. package/schedule/scheduleListFn.d.ts.map +1 -0
  133. package/schedule/scheduleListFn.js +65 -0
  134. package/schedule/scheduleListFn.js.map +1 -0
  135. package/schedule/scheduleState.d.ts +43 -0
  136. package/schedule/scheduleState.d.ts.map +1 -0
  137. package/schedule/scheduleState.js +67 -0
  138. package/schedule/scheduleState.js.map +1 -0
  139. package/schedule/useCreateSchedule.d.ts +57 -0
  140. package/schedule/useCreateSchedule.d.ts.map +1 -0
  141. package/schedule/useCreateSchedule.js +61 -0
  142. package/schedule/useCreateSchedule.js.map +1 -0
  143. package/schedule/useResumeSchedule.d.ts +30 -0
  144. package/schedule/useResumeSchedule.d.ts.map +1 -0
  145. package/schedule/useResumeSchedule.js +45 -0
  146. package/schedule/useResumeSchedule.js.map +1 -0
  147. package/schedule/useSchedule.d.ts +39 -0
  148. package/schedule/useSchedule.d.ts.map +1 -0
  149. package/schedule/useSchedule.js +44 -0
  150. package/schedule/useSchedule.js.map +1 -0
  151. package/schedule/useScheduleCount.d.ts +38 -0
  152. package/schedule/useScheduleCount.d.ts.map +1 -0
  153. package/schedule/useScheduleCount.js +30 -0
  154. package/schedule/useScheduleCount.js.map +1 -0
  155. package/schedule/useScheduleList.d.ts +48 -0
  156. package/schedule/useScheduleList.d.ts.map +1 -0
  157. package/schedule/useScheduleList.js +43 -0
  158. package/schedule/useScheduleList.js.map +1 -0
  159. package/schedule/useScheduleRuns.d.ts +44 -0
  160. package/schedule/useScheduleRuns.d.ts.map +1 -0
  161. package/schedule/useScheduleRuns.js +48 -0
  162. package/schedule/useScheduleRuns.js.map +1 -0
  163. package/schedule/useSetScheduleEnabled.d.ts +31 -0
  164. package/schedule/useSetScheduleEnabled.d.ts.map +1 -0
  165. package/schedule/useSetScheduleEnabled.js +53 -0
  166. package/schedule/useSetScheduleEnabled.js.map +1 -0
  167. package/schedule/useTriggerSchedule.d.ts +41 -0
  168. package/schedule/useTriggerSchedule.d.ts.map +1 -0
  169. package/schedule/useTriggerSchedule.js +62 -0
  170. package/schedule/useTriggerSchedule.js.map +1 -0
  171. package/schedule/useUpdateScheduleSpec.d.ts +49 -0
  172. package/schedule/useUpdateScheduleSpec.d.ts.map +1 -0
  173. package/schedule/useUpdateScheduleSpec.js +70 -0
  174. package/schedule/useUpdateScheduleSpec.js.map +1 -0
  175. package/search/useResourceCount.d.ts +2 -1
  176. package/search/useResourceCount.d.ts.map +1 -1
  177. package/search/useResourceCount.js +6 -1
  178. package/search/useResourceCount.js.map +1 -1
  179. package/session/useNewSessionFlow.d.ts.map +1 -1
  180. package/session/useNewSessionFlow.js +1 -0
  181. package/session/useNewSessionFlow.js.map +1 -1
  182. package/session/useSessionConversation.d.ts +11 -0
  183. package/session/useSessionConversation.d.ts.map +1 -1
  184. package/session/useSessionConversation.js +1 -0
  185. package/session/useSessionConversation.js.map +1 -1
  186. package/session/useSessionPageFlow.d.ts.map +1 -1
  187. package/session/useSessionPageFlow.js +1 -0
  188. package/session/useSessionPageFlow.js.map +1 -1
  189. package/src/agent/AgentPicker.tsx +13 -1
  190. package/src/billing/CreditLedgerTable.tsx +3 -42
  191. package/src/channel/AgentChannelsPanel.tsx +43 -1
  192. package/src/channel/ChannelTemplatesDialog.tsx +433 -0
  193. package/src/channel/__tests__/AgentChannelsPanel.test.tsx +73 -0
  194. package/src/channel/__tests__/ChannelTemplatesDialog.test.tsx +292 -0
  195. package/src/channel/__tests__/providers.test.ts +9 -0
  196. package/src/channel/__tests__/templatePresentation.test.ts +96 -0
  197. package/src/channel/__tests__/useChannelTemplateList.test.tsx +216 -0
  198. package/src/channel/__tests__/useChannelTemplateReadiness.test.tsx +124 -0
  199. package/src/channel/index.ts +15 -0
  200. package/src/channel/providers.ts +26 -2
  201. package/src/channel/templatePresentation.ts +82 -0
  202. package/src/channel/useChannelTemplateList.ts +123 -0
  203. package/src/channel/useChannelTemplateReadiness.ts +69 -0
  204. package/src/composer/ComposerToolbar.tsx +9 -0
  205. package/src/composer/SessionComposer.tsx +24 -1
  206. package/src/composer/__tests__/SessionComposer-serviceTier.test.tsx +156 -0
  207. package/src/dashboard/__tests__/useDashboardFailedRuns.test.tsx +106 -0
  208. package/src/dashboard/useDashboardFailedRuns.ts +2 -0
  209. package/src/execution/useCreateAgentExecution.ts +18 -0
  210. package/src/index.ts +70 -0
  211. package/src/internal/Pagination.tsx +72 -0
  212. package/src/library/useExportResource.ts +4 -3
  213. package/src/models/ModelSelector.tsx +100 -3
  214. package/src/models/__tests__/ModelSelector-serviceTier.test.tsx +172 -0
  215. package/src/models/__tests__/useModelRegistry.test.tsx +15 -0
  216. package/src/models/index.ts +2 -0
  217. package/src/models/registry.ts +16 -0
  218. package/src/models/service-tier.ts +49 -0
  219. package/src/organization/OrgProvider.tsx +29 -4
  220. package/src/organization/__tests__/OrgProvider.orgSwitch.test.tsx +89 -0
  221. package/src/resource-detail/useDeleteResource.ts +11 -1
  222. package/src/resource-workbench/__tests__/ResourceWorkbench.test.tsx +112 -0
  223. package/src/resource-workbench/components/ResourceWorkbench.tsx +32 -15
  224. package/src/resource-workbench/hooks/useResourceCollection.ts +11 -1
  225. package/src/schedule/CadenceField.tsx +365 -0
  226. package/src/schedule/ScheduleDetailView.tsx +1651 -0
  227. package/src/schedule/ScheduleForm.tsx +615 -0
  228. package/src/schedule/ScheduleRowActions.tsx +124 -0
  229. package/src/schedule/ScheduleRunsTable.tsx +424 -0
  230. package/src/schedule/TimeZoneField.tsx +199 -0
  231. package/src/schedule/__tests__/ScheduleDetailView.test.tsx +683 -0
  232. package/src/schedule/__tests__/cadence.test.ts +278 -0
  233. package/src/schedule/__tests__/scheduleColumnsRowActions.test.tsx +176 -0
  234. package/src/schedule/__tests__/scheduleCreation.test.tsx +537 -0
  235. package/src/schedule/__tests__/scheduleHooks.test.tsx +399 -0
  236. package/src/schedule/__tests__/scheduleListFn.test.ts +128 -0
  237. package/src/schedule/__tests__/scheduleState.test.ts +133 -0
  238. package/src/schedule/cadence.ts +298 -0
  239. package/src/schedule/index.ts +69 -0
  240. package/src/schedule/scheduleColumns.tsx +118 -0
  241. package/src/schedule/scheduleListFn.ts +108 -0
  242. package/src/schedule/scheduleState.ts +96 -0
  243. package/src/schedule/useCreateSchedule.ts +88 -0
  244. package/src/schedule/useResumeSchedule.ts +67 -0
  245. package/src/schedule/useSchedule.ts +67 -0
  246. package/src/schedule/useScheduleCount.ts +57 -0
  247. package/src/schedule/useScheduleList.ts +83 -0
  248. package/src/schedule/useScheduleRuns.ts +93 -0
  249. package/src/schedule/useSetScheduleEnabled.ts +84 -0
  250. package/src/schedule/useTriggerSchedule.ts +90 -0
  251. package/src/schedule/useUpdateScheduleSpec.ts +108 -0
  252. package/src/search/__tests__/useResourceCount.test.tsx +89 -0
  253. package/src/search/useResourceCount.ts +8 -2
  254. package/src/session/useNewSessionFlow.ts +1 -0
  255. package/src/session/useSessionConversation.ts +12 -0
  256. package/src/session/useSessionPageFlow.ts +1 -0
  257. package/src/workflow/WorkflowDashboard.tsx +1 -0
  258. package/src/workflow/__tests__/inspector-forms.test.tsx +119 -2
  259. package/src/workflow/inspector/forms/AgentCallForm.tsx +260 -37
  260. package/src/workflow/inspector/tabs/RuntimeTab.tsx +72 -33
  261. package/src/workflow/starter-workflow-yaml.ts +2 -1
  262. package/src/workflow/useWorkflowExecutionList.ts +13 -2
  263. package/styles.css +1 -1
  264. package/workflow/CanvasTransitionEdge.d.ts +1 -1
  265. package/workflow/WorkflowDashboard.d.ts.map +1 -1
  266. package/workflow/WorkflowDashboard.js +1 -0
  267. package/workflow/WorkflowDashboard.js.map +1 -1
  268. package/workflow/inspector/forms/AgentCallForm.d.ts +18 -2
  269. package/workflow/inspector/forms/AgentCallForm.d.ts.map +1 -1
  270. package/workflow/inspector/forms/AgentCallForm.js +87 -9
  271. package/workflow/inspector/forms/AgentCallForm.js.map +1 -1
  272. package/workflow/inspector/tabs/RuntimeTab.d.ts +2 -1
  273. package/workflow/inspector/tabs/RuntimeTab.d.ts.map +1 -1
  274. package/workflow/inspector/tabs/RuntimeTab.js +31 -5
  275. package/workflow/inspector/tabs/RuntimeTab.js.map +1 -1
  276. package/workflow/starter-workflow-yaml.d.ts +1 -1
  277. package/workflow/starter-workflow-yaml.d.ts.map +1 -1
  278. package/workflow/starter-workflow-yaml.js +2 -1
  279. package/workflow/starter-workflow-yaml.js.map +1 -1
  280. package/workflow/useWorkflowExecutionList.d.ts +10 -0
  281. package/workflow/useWorkflowExecutionList.d.ts.map +1 -1
  282. package/workflow/useWorkflowExecutionList.js +3 -2
  283. package/workflow/useWorkflowExecutionList.js.map +1 -1
@@ -0,0 +1,88 @@
1
+ "use client";
2
+
3
+ import { useCallback, useState } from "react";
4
+ import type { ScheduleInput } from "@stigmer/sdk";
5
+ import type { Schedule } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
6
+ import { useStigmer } from "../hooks.js";
7
+ import { toError } from "../internal/toError.js";
8
+
9
+ /** Return value of {@link useCreateSchedule}. */
10
+ export interface UseCreateScheduleReturn {
11
+ /**
12
+ * Submit a {@link ScheduleInput} to create (or upsert) a schedule.
13
+ *
14
+ * Uses `stigmer.schedule.apply()` — the idempotent upsert operation.
15
+ * Resolves with the server-created `Schedule` proto including
16
+ * populated metadata (id, slug, audit timestamps) and the
17
+ * platform-computed `status.next_fire_at`.
18
+ */
19
+ readonly create: (input: ScheduleInput) => Promise<Schedule>;
20
+ /** `true` while the apply request is in flight. */
21
+ readonly isCreating: boolean;
22
+ /** Error from the last failed create, or `null` when healthy. */
23
+ readonly error: Error | null;
24
+ /** Reset `error` to `null`. */
25
+ readonly clearError: () => void;
26
+ }
27
+
28
+ /**
29
+ * Behavior hook that wraps `schedule.apply()` with loading and error
30
+ * state.
31
+ *
32
+ * Creates a schedule from a {@link ScheduleInput}. Uses `apply()`
33
+ * (upsert) rather than `create()` so re-submissions are idempotent —
34
+ * matching the CLI's `stigmer apply` semantics and the established SDK
35
+ * mutation hook pattern (`isCreating` flag, `error` state, `clearError`
36
+ * reset, result returned from the promise, not stored in hook state).
37
+ *
38
+ * NOTE: this hook is for CREATION. Editing an existing schedule must
39
+ * NOT go through `ScheduleInput` — the input type cannot express every
40
+ * metadata field (tags, description), and the server replaces spec and
41
+ * mutable metadata wholesale on update, so a down-converting edit would
42
+ * silently wipe them. Edit flows use the full-proto path instead (see
43
+ * `useSetScheduleEnabled` for the pattern).
44
+ *
45
+ * @example
46
+ * ```tsx
47
+ * const { create, isCreating, error, clearError } = useCreateSchedule();
48
+ *
49
+ * const schedule = await create({
50
+ * name: "daily-fee-reminders",
51
+ * org: "acme",
52
+ * cron: "0 9 * * *",
53
+ * timeZone: "Asia/Kolkata",
54
+ * enabled: false,
55
+ * agent: {
56
+ * agentRef: { org: "acme", slug: "billing-assistant" },
57
+ * message: "Send today's fee reminders.",
58
+ * },
59
+ * });
60
+ * // schedule.metadata?.slug → "daily-fee-reminders"
61
+ * ```
62
+ */
63
+ export function useCreateSchedule(): UseCreateScheduleReturn {
64
+ const stigmer = useStigmer();
65
+ const [isCreating, setIsCreating] = useState(false);
66
+ const [error, setError] = useState<Error | null>(null);
67
+
68
+ const clearError = useCallback(() => setError(null), []);
69
+
70
+ const create = useCallback(
71
+ async (input: ScheduleInput): Promise<Schedule> => {
72
+ setIsCreating(true);
73
+ setError(null);
74
+
75
+ try {
76
+ return await stigmer.schedule.apply(input);
77
+ } catch (err) {
78
+ setError(toError(err));
79
+ throw err;
80
+ } finally {
81
+ setIsCreating(false);
82
+ }
83
+ },
84
+ [stigmer],
85
+ );
86
+
87
+ return { create, isCreating, error, clearError };
88
+ }
@@ -0,0 +1,67 @@
1
+ "use client";
2
+
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import type { Schedule } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
5
+ import { getUserMessage } from "@stigmer/sdk";
6
+ import { useStigmer } from "../hooks.js";
7
+ import { toast } from "../feedback/toast.js";
8
+ import { toError } from "../internal/toError.js";
9
+
10
+ /** Return value of {@link useResumeSchedule}. */
11
+ export interface UseResumeScheduleReturn {
12
+ /**
13
+ * Clear the platform's failure-streak pause and let the schedule fire
14
+ * again. Resolves with the post-resume schedule; the caller refetches
15
+ * or replaces its local copy from it.
16
+ */
17
+ readonly resumeSchedule: (scheduleId: string) => Promise<Schedule>;
18
+ /** `true` while the resume request is in flight. */
19
+ readonly isResuming: boolean;
20
+ /** Error from the last failed resume, or `null` when healthy. */
21
+ readonly error: Error | null;
22
+ }
23
+
24
+ /**
25
+ * Behavior hook that resumes a platform-paused schedule.
26
+ *
27
+ * Resume is the ONE path that clears `status.paused_reason` (and the
28
+ * failure streak with it) — re-applying the manifest deliberately does
29
+ * not, so a routine GitOps apply can never silently un-pause a failing
30
+ * schedule. Resuming a schedule that is not paused is a server-side
31
+ * no-op; resuming a disabled schedule clears the pause but the schedule
32
+ * stays disabled (the owner's lever is separate — see
33
+ * {@link useSetScheduleEnabled}).
34
+ *
35
+ * Error toasts relay the server's message verbatim: the copy is
36
+ * identical across editions and states the remedy.
37
+ */
38
+ export function useResumeSchedule(): UseResumeScheduleReturn {
39
+ const stigmer = useStigmer();
40
+ const [isResuming, setIsResuming] = useState(false);
41
+ const [error, setError] = useState<Error | null>(null);
42
+
43
+ const resumeSchedule = useCallback(
44
+ async (scheduleId: string): Promise<Schedule> => {
45
+ setIsResuming(true);
46
+ setError(null);
47
+ try {
48
+ const resumed = await stigmer.schedule.resume(scheduleId);
49
+ toast.success("Schedule resumed");
50
+ return resumed;
51
+ } catch (err) {
52
+ const wrapped = toError(err);
53
+ setError(wrapped);
54
+ toast.error(getUserMessage(err));
55
+ throw wrapped;
56
+ } finally {
57
+ setIsResuming(false);
58
+ }
59
+ },
60
+ [stigmer],
61
+ );
62
+
63
+ return useMemo(
64
+ () => ({ resumeSchedule, isResuming, error }),
65
+ [resumeSchedule, isResuming, error],
66
+ );
67
+ }
@@ -0,0 +1,67 @@
1
+ "use client";
2
+
3
+ import type { Schedule } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
4
+ import { isNotFound } from "@stigmer/sdk";
5
+ import { useStigmer } from "../hooks.js";
6
+ import { useFetch } from "../internal/useFetch.js";
7
+
8
+ /** Return value of {@link useSchedule}. */
9
+ export interface UseScheduleReturn {
10
+ /** The resolved schedule, or `null` while loading, on error, or when not found. */
11
+ readonly schedule: Schedule | null;
12
+ /** `true` while the initial fetch is in flight. */
13
+ readonly isLoading: boolean;
14
+ /** `true` while a background refetch is in flight. */
15
+ readonly isRefetching: boolean;
16
+ /** Error from the last failed request, or `null` when healthy. */
17
+ readonly error: Error | null;
18
+ /** Discard cached data and re-fetch the schedule from the server. */
19
+ readonly refetch: () => void;
20
+ }
21
+
22
+ /**
23
+ * Data hook that fetches a single Schedule by organization and slug.
24
+ *
25
+ * Wraps `stigmer.schedule.getByReference()` with loading, error, and
26
+ * not-found state management. The loaded resource carries the spec
27
+ * (cron, time zone, enabled, target) and the platform-written status
28
+ * (`next_fire_at`, `last_fire_at`, `last_execution_id`,
29
+ * `consecutive_failures`, `paused_reason`) — everything the detail view
30
+ * renders, including the disabled-vs-paused distinction (see
31
+ * {@link deriveScheduleState}).
32
+ *
33
+ * Pass `null` for either `org` or `slug` to skip fetching (stable
34
+ * no-op).
35
+ *
36
+ * **Not-found handling:** a NOT_FOUND response sets `schedule` to
37
+ * `null` without raising an error; `schedule === null && !isLoading
38
+ * && !error` means the resource does not exist.
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * const { schedule, isLoading, error, refetch } = useSchedule("isc", "daily-fee-reminders");
43
+ * ```
44
+ */
45
+ export function useSchedule(
46
+ org: string | null,
47
+ slug: string | null,
48
+ ): UseScheduleReturn {
49
+ const stigmer = useStigmer();
50
+
51
+ const { data: schedule, isLoading, isRefetching, error, refetch } = useFetch(
52
+ org && slug
53
+ ? async () => {
54
+ try {
55
+ return await stigmer.schedule.getByReference({ org, slug });
56
+ } catch (err) {
57
+ if (isNotFound(err)) return null;
58
+ throw err;
59
+ }
60
+ }
61
+ : null,
62
+ [org, slug, stigmer],
63
+ null,
64
+ );
65
+
66
+ return { schedule, isLoading, isRefetching, error, refetch };
67
+ }
@@ -0,0 +1,57 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import { useStigmer } from "../hooks.js";
5
+ import { useResourceCount } from "../search/index.js";
6
+ import { createScheduleListFn } from "./scheduleListFn.js";
7
+
8
+ /** Options for {@link useScheduleCount}. */
9
+ export interface UseScheduleCountOptions {
10
+ /** Opaque token that forces a recount when its value changes. */
11
+ readonly refetchToken?: unknown;
12
+ }
13
+
14
+ /** Return value of {@link useScheduleCount}. */
15
+ export interface UseScheduleCountReturn {
16
+ /**
17
+ * Total number of schedules in the organization. `undefined` until
18
+ * the first successful fetch completes.
19
+ */
20
+ readonly count: number | undefined;
21
+ /** `true` while the count fetch is in flight. */
22
+ readonly isLoading: boolean;
23
+ /** Error from the last failed request, or `null` when healthy. */
24
+ readonly error: Error | null;
25
+ /** Discard cached data and re-fetch the count from the server. */
26
+ readonly refetch: () => void;
27
+ }
28
+
29
+ /**
30
+ * Data hook that fetches the total count of an organization's schedules.
31
+ *
32
+ * Issues a minimal direct `listSchedules` call to retrieve only the
33
+ * total count. Useful for the Library landing card and dashboard
34
+ * widgets. There is no scope option: schedules are org-only.
35
+ *
36
+ * For the full paginated schedule list, use {@link useScheduleList}
37
+ * instead.
38
+ *
39
+ * Pass `null` as `org` to skip fetching (stable no-op).
40
+ *
41
+ * @example
42
+ * ```tsx
43
+ * const { count, isLoading } = useScheduleCount("isc");
44
+ * ```
45
+ */
46
+ export function useScheduleCount(
47
+ org: string | null,
48
+ options?: UseScheduleCountOptions,
49
+ ): UseScheduleCountReturn {
50
+ const stigmer = useStigmer();
51
+
52
+ const listFn = useMemo(() => createScheduleListFn(stigmer), [stigmer]);
53
+
54
+ return useResourceCount(listFn, org, {
55
+ refetchToken: options?.refetchToken,
56
+ });
57
+ }
@@ -0,0 +1,83 @@
1
+ "use client";
2
+
3
+ import type { Schedule } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
4
+ import { useStigmer } from "../hooks.js";
5
+ import { useFetch } from "../internal/useFetch.js";
6
+ import { listSchedulesPage, type SchedulePage } from "./scheduleListFn.js";
7
+
8
+ /** Options for {@link useScheduleList}. */
9
+ export interface UseScheduleListOptions {
10
+ /** Maximum schedules per page. @default 20 */
11
+ readonly pageSize?: number;
12
+ /** Page number (1-indexed). @default 1 */
13
+ readonly page?: number;
14
+ }
15
+
16
+ /** Return value of {@link useScheduleList}. */
17
+ export interface UseScheduleListReturn {
18
+ /** Full `Schedule` protos (spec + status) for the current page. */
19
+ readonly schedules: readonly Schedule[];
20
+ /** Total number of schedules in the organization. */
21
+ readonly totalCount: number;
22
+ /** Total pages available at the current page size. */
23
+ readonly totalPages: number;
24
+ /** The current page number (mirrors the `page` option). */
25
+ readonly currentPage: number;
26
+ /** `true` while the initial fetch is in flight. */
27
+ readonly isLoading: boolean;
28
+ /** `true` while a background refetch is in flight. */
29
+ readonly isRefetching: boolean;
30
+ /** Error from the last failed request, or `null` when healthy. */
31
+ readonly error: Error | null;
32
+ /** Discard cached data and re-fetch the current page from the server. */
33
+ readonly refetch: () => void;
34
+ }
35
+
36
+ const INITIAL_PAGE: SchedulePage = { items: [], totalCount: 0, totalPages: 0 };
37
+
38
+ /**
39
+ * Data hook that fetches a paginated list of an organization's schedules.
40
+ *
41
+ * Backed by the direct `listSchedules` query — not the search service —
42
+ * so each entry is a full `Schedule` proto with the operational status
43
+ * fields a schedule list exists to show (`next_fire_at`, enabled/paused
44
+ * state, `last_fire_at`). There is no text query or visibility scope:
45
+ * schedules are org-only and have no server-side search.
46
+ *
47
+ * Pass `null` as `org` to skip fetching (stable no-op).
48
+ *
49
+ * @example
50
+ * ```tsx
51
+ * const { schedules, totalCount, isLoading } = useScheduleList("isc", {
52
+ * page: 1,
53
+ * pageSize: 20,
54
+ * });
55
+ * ```
56
+ */
57
+ export function useScheduleList(
58
+ org: string | null,
59
+ options?: UseScheduleListOptions,
60
+ ): UseScheduleListReturn {
61
+ const stigmer = useStigmer();
62
+ const pageSize = options?.pageSize;
63
+ const page = options?.page ?? 1;
64
+
65
+ const { data, isLoading, isRefetching, error, refetch } = useFetch<SchedulePage>(
66
+ org
67
+ ? () => listSchedulesPage(stigmer, org, { num: page, size: pageSize })
68
+ : null,
69
+ [stigmer, org, page, pageSize],
70
+ INITIAL_PAGE,
71
+ );
72
+
73
+ return {
74
+ schedules: data.items,
75
+ totalCount: data.totalCount,
76
+ totalPages: data.totalPages,
77
+ currentPage: page,
78
+ isLoading,
79
+ isRefetching,
80
+ error,
81
+ refetch,
82
+ };
83
+ }
@@ -0,0 +1,93 @@
1
+ "use client";
2
+
3
+ import { create } from "@bufbuild/protobuf";
4
+ import {
5
+ ListScheduleRunsRequestSchema,
6
+ type ScheduleRun,
7
+ } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/io_pb";
8
+ import { useStigmer } from "../hooks.js";
9
+ import { useFetch } from "../internal/useFetch.js";
10
+
11
+ /** Options for {@link useScheduleRuns}. */
12
+ export interface UseScheduleRunsOptions {
13
+ /** Maximum runs per page. @default 25 */
14
+ readonly pageSize?: number;
15
+ /** Page number (1-indexed). @default 1 */
16
+ readonly page?: number;
17
+ }
18
+
19
+ /** Return value of {@link useScheduleRuns}. */
20
+ export interface UseScheduleRunsReturn {
21
+ /** Recorded fires for the current page, newest first. */
22
+ readonly runs: readonly ScheduleRun[];
23
+ /** Total number of recorded runs for the schedule. */
24
+ readonly totalCount: number;
25
+ /** `true` while the initial fetch is in flight. */
26
+ readonly isLoading: boolean;
27
+ /** `true` while a background refetch is in flight. */
28
+ readonly isRefetching: boolean;
29
+ /** Error from the last failed request, or `null` when healthy. */
30
+ readonly error: Error | null;
31
+ /** Discard cached data and re-fetch the current page from the server. */
32
+ readonly refetch: () => void;
33
+ }
34
+
35
+ interface RunsPage {
36
+ readonly runs: readonly ScheduleRun[];
37
+ readonly totalCount: number;
38
+ }
39
+
40
+ const INITIAL_PAGE: RunsPage = { runs: [], totalCount: 0 };
41
+
42
+ /**
43
+ * Data hook that fetches a schedule's run history, newest first — the
44
+ * fire ledger (project DD-017 D-7).
45
+ *
46
+ * Every fire leaves a row, INCLUDING the fires that created no execution
47
+ * (a refused launch gate, a missing target agent), carrying the refusing
48
+ * gate's copy verbatim. This is the surface that finally explains
49
+ * `status.consecutive_failures`: the reason is one row away instead of
50
+ * buried in server logs. Rows for in-flight runs are enriched server-side
51
+ * with the execution's live phase, so outcomes never lie.
52
+ *
53
+ * Pass `null` as `scheduleId` to skip fetching (stable no-op) — the
54
+ * detail view does this while the schedule itself is still loading.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * const { runs, totalCount, isLoading } = useScheduleRuns(schedule?.metadata?.id ?? null);
59
+ * ```
60
+ */
61
+ export function useScheduleRuns(
62
+ scheduleId: string | null,
63
+ options?: UseScheduleRunsOptions,
64
+ ): UseScheduleRunsReturn {
65
+ const stigmer = useStigmer();
66
+ const pageSize = options?.pageSize ?? 25;
67
+ const page = options?.page ?? 1;
68
+
69
+ const { data, isLoading, isRefetching, error, refetch } = useFetch<RunsPage>(
70
+ scheduleId
71
+ ? async () => {
72
+ const result = await stigmer.schedule.listRuns(
73
+ create(ListScheduleRunsRequestSchema, {
74
+ scheduleId,
75
+ pageInfo: { num: page, size: pageSize },
76
+ }),
77
+ );
78
+ return { runs: result.items, totalCount: result.totalCount };
79
+ }
80
+ : null,
81
+ [stigmer, scheduleId, page, pageSize],
82
+ INITIAL_PAGE,
83
+ );
84
+
85
+ return {
86
+ runs: data.runs,
87
+ totalCount: data.totalCount,
88
+ isLoading,
89
+ isRefetching,
90
+ error,
91
+ refetch,
92
+ };
93
+ }
@@ -0,0 +1,84 @@
1
+ "use client";
2
+
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import { clone } from "@bufbuild/protobuf";
5
+ import {
6
+ ScheduleSchema,
7
+ type Schedule,
8
+ } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/api_pb";
9
+ import { getUserMessage, manifestDocumentForResource } from "@stigmer/sdk";
10
+ import { useStigmer } from "../hooks.js";
11
+ import { toast } from "../feedback/toast.js";
12
+ import { toError } from "../internal/toError.js";
13
+
14
+ /** Return value of {@link useSetScheduleEnabled}. */
15
+ export interface UseSetScheduleEnabledReturn {
16
+ /**
17
+ * Flip the owner's `spec.enabled` switch. Takes the full fetched
18
+ * schedule (not just an id) because the write re-applies the whole
19
+ * resource. Resolves with the post-apply schedule; the caller
20
+ * refetches or replaces its local copy from it.
21
+ */
22
+ readonly setEnabled: (schedule: Schedule, enabled: boolean) => Promise<Schedule>;
23
+ /** `true` while the apply is in flight. */
24
+ readonly isPending: boolean;
25
+ /** Error from the last failed apply, or `null` when healthy. */
26
+ readonly error: Error | null;
27
+ }
28
+
29
+ /**
30
+ * Behavior hook that flips a schedule's owner-controlled `enabled` flag.
31
+ *
32
+ * The write path is deliberate: clone the fetched proto, flip one
33
+ * field, and re-apply the WHOLE resource through the manifest engine
34
+ * (`stigmer.manifest.apply`) — never down-convert to the curated
35
+ * `ScheduleInput` shape. The server replaces spec and mutable metadata
36
+ * wholesale on update, and `ScheduleInput` cannot express every
37
+ * metadata field (tags, description), so the input route would silently
38
+ * wipe them. The full-proto route is lossless by construction; the
39
+ * server ignores client-provided status, and re-applying never clears a
40
+ * platform pause (Resume is the one clearing path — see
41
+ * {@link useResumeSchedule}).
42
+ */
43
+ export function useSetScheduleEnabled(): UseSetScheduleEnabledReturn {
44
+ const stigmer = useStigmer();
45
+ const [isPending, setIsPending] = useState(false);
46
+ const [error, setError] = useState<Error | null>(null);
47
+
48
+ const setEnabled = useCallback(
49
+ async (schedule: Schedule, enabled: boolean): Promise<Schedule> => {
50
+ if (!schedule.spec) {
51
+ throw new Error(
52
+ "Cannot toggle this schedule: it has no spec. Pass a schedule " +
53
+ "as returned by the server (get/getByReference).",
54
+ );
55
+ }
56
+
57
+ setIsPending(true);
58
+ setError(null);
59
+ try {
60
+ const updated = clone(ScheduleSchema, schedule);
61
+ updated.spec!.enabled = enabled;
62
+
63
+ const applied = await stigmer.manifest.apply(
64
+ manifestDocumentForResource(updated),
65
+ );
66
+ toast.success(enabled ? "Schedule enabled" : "Schedule disabled");
67
+ return applied.message as Schedule;
68
+ } catch (err) {
69
+ const wrapped = toError(err);
70
+ setError(wrapped);
71
+ toast.error(getUserMessage(err));
72
+ throw wrapped;
73
+ } finally {
74
+ setIsPending(false);
75
+ }
76
+ },
77
+ [stigmer],
78
+ );
79
+
80
+ return useMemo(
81
+ () => ({ setEnabled, isPending, error }),
82
+ [setEnabled, isPending, error],
83
+ );
84
+ }
@@ -0,0 +1,90 @@
1
+ "use client";
2
+
3
+ import { useCallback, useMemo, useState } from "react";
4
+ import {
5
+ ScheduleRunOutcome,
6
+ type ScheduleTriggerResult,
7
+ } from "@stigmer/protos/ai/stigmer/agentic/schedule/v1/io_pb";
8
+ import { getUserMessage } from "@stigmer/sdk";
9
+ import { useStigmer } from "../hooks.js";
10
+ import { toast } from "../feedback/toast.js";
11
+ import { toError } from "../internal/toError.js";
12
+
13
+ /** Return value of {@link useTriggerSchedule}. */
14
+ export interface UseTriggerScheduleReturn {
15
+ /**
16
+ * Fire the schedule once, now — a real agent execution, outside the
17
+ * cron cadence. Resolves with the {@link ScheduleTriggerResult}: the
18
+ * run's REAL outcome (started with an execution id, or refused with the
19
+ * gate's copy), so a caller can navigate to the execution or surface
20
+ * the refusal. Refetch the schedule afterwards to pick up the freshly
21
+ * stamped `status.last_fire_at` / `status.last_execution_id`.
22
+ */
23
+ readonly triggerSchedule: (scheduleId: string) => Promise<ScheduleTriggerResult>;
24
+ /** `true` while the trigger request is in flight. */
25
+ readonly isTriggering: boolean;
26
+ /** Error from the last failed or refused trigger, or `null` when healthy. */
27
+ readonly error: Error | null;
28
+ }
29
+
30
+ /**
31
+ * Behavior hook that fires a schedule once, immediately, and reports the
32
+ * run's real outcome (project DD-017 D-5/D-6).
33
+ *
34
+ * The trigger is a two-level contract, and this hook honors both levels:
35
+ *
36
+ * - A **gRPC error** means the trigger itself was refused — a disabled
37
+ * schedule answers `FAILED_PRECONDITION` with copy that names the
38
+ * remedy ("enable it before triggering"). The error toast relays that
39
+ * copy verbatim (byte-identical across editions) and the promise
40
+ * rejects.
41
+ * - A **success** means the fire happened. The result's `outcome` then
42
+ * says what the RUN did: `STARTED` (an execution was created — a
43
+ * success toast), or `REFUSED` / `TARGET_MISSING` (a launch gate said
44
+ * no — an error toast carrying the gate's `refusalReason` verbatim).
45
+ * The promise RESOLVES in every one of these cases: a refused run is a
46
+ * successful trigger honestly reported, and the caller decides what to
47
+ * do with it (navigate to the execution, show the reason).
48
+ *
49
+ * Triggering starts a real, billable execution — gate the call behind a
50
+ * confirmation (the detail view uses `ConfirmDialog`).
51
+ */
52
+ export function useTriggerSchedule(): UseTriggerScheduleReturn {
53
+ const stigmer = useStigmer();
54
+ const [isTriggering, setIsTriggering] = useState(false);
55
+ const [error, setError] = useState<Error | null>(null);
56
+
57
+ const triggerSchedule = useCallback(
58
+ async (scheduleId: string): Promise<ScheduleTriggerResult> => {
59
+ setIsTriggering(true);
60
+ setError(null);
61
+ try {
62
+ const result = await stigmer.schedule.trigger(scheduleId);
63
+ if (result.outcome === ScheduleRunOutcome.STARTED) {
64
+ toast.success("Run started");
65
+ } else {
66
+ // The fire happened but the run was refused — surface the
67
+ // gate's own copy, never a generic message. The promise still
68
+ // resolves; the caller renders the reason inline too.
69
+ toast.error(
70
+ result.refusalReason || "The run was refused by a launch gate",
71
+ );
72
+ }
73
+ return result;
74
+ } catch (err) {
75
+ const wrapped = toError(err);
76
+ setError(wrapped);
77
+ toast.error(getUserMessage(err));
78
+ throw wrapped;
79
+ } finally {
80
+ setIsTriggering(false);
81
+ }
82
+ },
83
+ [stigmer],
84
+ );
85
+
86
+ return useMemo(
87
+ () => ({ triggerSchedule, isTriggering, error }),
88
+ [triggerSchedule, isTriggering, error],
89
+ );
90
+ }