@truefoundry/trueforge-ui 0.3.0-rc.2 → 0.3.0-rc.3

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 (107) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +17 -9
  3. package/dist/{AgentCodeSnippets-637HQUXD.js → AgentCodeSnippets-N546FNNS.js} +38 -23
  4. package/dist/AgentCodeSnippets-N546FNNS.js.map +1 -0
  5. package/dist/AgentMetricChart-YWJYVYYA.js +15 -0
  6. package/dist/{AgentOverview-3FJ5EE6N.js → AgentOverview-VF74XC7I.js} +7 -7
  7. package/dist/{AgentSessionEventTimeline-VELWUYPR.js → AgentSessionEventTimeline-RFR6LQMY.js} +8 -8
  8. package/dist/{AgentSessionEventTimeline-VELWUYPR.js.map → AgentSessionEventTimeline-RFR6LQMY.js.map} +1 -1
  9. package/dist/{AgentSessionEventTimelineChart-CUKETHWM.js → AgentSessionEventTimelineChart-27CQF6FX.js} +12 -12
  10. package/dist/AgentSessionEventTimelineChart-27CQF6FX.js.map +1 -0
  11. package/dist/{AgentSessions-T7MOGOTZ.js → AgentSessions-4IVX2SGD.js} +36 -12
  12. package/dist/AgentSessions-4IVX2SGD.js.map +1 -0
  13. package/dist/{ConnectorSettings-ESZ2RSRG.js → ConnectorSettings-R5VEP7BO.js} +156 -116
  14. package/dist/ConnectorSettings-R5VEP7BO.js.map +1 -0
  15. package/dist/{DockLayout-NLFNU6F2.js → DockLayout-F44RWGEY.js} +10 -10
  16. package/dist/{DrawerLayout-PR3SMKA6.js → DrawerLayout-SQ323AVM.js} +13 -11
  17. package/dist/DrawerLayout-SQ323AVM.js.map +1 -0
  18. package/dist/{ModelSettings-LYW64IRR.js → ModelSettings-6QLS63HM.js} +10 -10
  19. package/dist/{ModelSettings-LYW64IRR.js.map → ModelSettings-6QLS63HM.js.map} +1 -1
  20. package/dist/OpenUiFenceBlock-4ROX3G4X.js +9 -0
  21. package/dist/{SandboxSettings-DF64LHYI.js → SandboxSettings-OLKDXIQS.js} +9 -9
  22. package/dist/SchedulesPage-TMOTK6DR.js +15 -0
  23. package/dist/{SettingsBuilder-LSXK2VN4.js → SettingsBuilder-GISAH2WU.js} +8 -8
  24. package/dist/{ShellRouteSync-B22IAV2W.js → ShellRouteSync-EN33DUQ7.js} +157 -22
  25. package/dist/ShellRouteSync-EN33DUQ7.js.map +1 -0
  26. package/dist/{SidebarLayout-XW6LXB7R.js → SidebarLayout-35K4AKTC.js} +74 -53
  27. package/dist/SidebarLayout-35K4AKTC.js.map +1 -0
  28. package/dist/{SkillSettings-64VXUO6J.js → SkillSettings-JSX2BTII.js} +18 -13
  29. package/dist/SkillSettings-JSX2BTII.js.map +1 -0
  30. package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js → TrueForgeUIWithRouter-6VCR7ES3.js} +9 -9
  31. package/dist/{WidgetLayout-Q5P7PYSJ.js → WidgetLayout-RKBSN2FZ.js} +10 -10
  32. package/dist/{chunk-YQO2NMJ3.js → chunk-2O5EJ6QS.js} +4096 -2825
  33. package/dist/chunk-2O5EJ6QS.js.map +1 -0
  34. package/dist/chunk-6WCIL3H2.js +517 -0
  35. package/dist/chunk-6WCIL3H2.js.map +1 -0
  36. package/dist/{chunk-SQGT43Z3.js → chunk-73FQVITT.js} +21 -4
  37. package/dist/chunk-73FQVITT.js.map +1 -0
  38. package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
  39. package/dist/chunk-7AAO4UDQ.js.map +1 -0
  40. package/dist/{chunk-LGRHHFHN.js → chunk-F5QVQIBH.js} +166 -45
  41. package/dist/chunk-F5QVQIBH.js.map +1 -0
  42. package/dist/{chunk-I3AL54MA.js → chunk-GIPFF6FZ.js} +28 -24
  43. package/dist/chunk-GIPFF6FZ.js.map +1 -0
  44. package/dist/{chunk-GXYAOAK5.js → chunk-GSJAYYLR.js} +219 -162
  45. package/dist/chunk-GSJAYYLR.js.map +1 -0
  46. package/dist/{chunk-VJ7BZGAF.js → chunk-J5BPHEDT.js} +2 -2
  47. package/dist/chunk-KR7WYHVF.js +195 -0
  48. package/dist/chunk-KR7WYHVF.js.map +1 -0
  49. package/dist/{chunk-VUMGMGKZ.js → chunk-LUG7E6BL.js} +52 -8
  50. package/dist/chunk-LUG7E6BL.js.map +1 -0
  51. package/dist/chunk-LXJMINS6.js +587 -0
  52. package/dist/chunk-LXJMINS6.js.map +1 -0
  53. package/dist/{chunk-FQK2XVVE.js → chunk-PT4EENB3.js} +224 -72
  54. package/dist/chunk-PT4EENB3.js.map +1 -0
  55. package/dist/{chunk-H6WTY5PM.js → chunk-Q6TCT7ZJ.js} +17 -227
  56. package/dist/chunk-Q6TCT7ZJ.js.map +1 -0
  57. package/dist/{chunk-5I2COQNL.js → chunk-XLFOXQKZ.js} +13 -11
  58. package/dist/chunk-XLFOXQKZ.js.map +1 -0
  59. package/dist/{chunk-G2TUAD65.js → chunk-XY6LZQES.js} +235 -108
  60. package/dist/chunk-XY6LZQES.js.map +1 -0
  61. package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
  62. package/dist/index.d.ts +291 -89
  63. package/dist/index.js +63 -488
  64. package/dist/index.js.map +1 -1
  65. package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +36 -13
  66. package/dist/plugins/trueforge-agent-server-adapter/index.js +69 -35
  67. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  68. package/dist/styles.css +1 -1
  69. package/package.json +3 -3
  70. package/dist/AgentCodeSnippets-637HQUXD.js.map +0 -1
  71. package/dist/AgentMetricChart-4FYECRIN.js +0 -15
  72. package/dist/AgentSessionEventTimelineChart-CUKETHWM.js.map +0 -1
  73. package/dist/AgentSessions-T7MOGOTZ.js.map +0 -1
  74. package/dist/ConnectorSettings-ESZ2RSRG.js.map +0 -1
  75. package/dist/DrawerLayout-PR3SMKA6.js.map +0 -1
  76. package/dist/OpenUiFenceBlock-JEPNPJ7U.js +0 -9
  77. package/dist/SchedulesPage-WQU4H25F.js +0 -15
  78. package/dist/ShellRouteSync-B22IAV2W.js.map +0 -1
  79. package/dist/SidebarLayout-XW6LXB7R.js.map +0 -1
  80. package/dist/SkillSettings-64VXUO6J.js.map +0 -1
  81. package/dist/chunk-5I2COQNL.js.map +0 -1
  82. package/dist/chunk-BWHOZFIV.js +0 -587
  83. package/dist/chunk-BWHOZFIV.js.map +0 -1
  84. package/dist/chunk-FQK2XVVE.js.map +0 -1
  85. package/dist/chunk-G2TUAD65.js.map +0 -1
  86. package/dist/chunk-GXYAOAK5.js.map +0 -1
  87. package/dist/chunk-H6WTY5PM.js.map +0 -1
  88. package/dist/chunk-I3AL54MA.js.map +0 -1
  89. package/dist/chunk-LGRHHFHN.js.map +0 -1
  90. package/dist/chunk-NHHSZB5N.js +0 -74
  91. package/dist/chunk-NHHSZB5N.js.map +0 -1
  92. package/dist/chunk-QC42MLAK.js.map +0 -1
  93. package/dist/chunk-SFZNIO6U.js +0 -18
  94. package/dist/chunk-SFZNIO6U.js.map +0 -1
  95. package/dist/chunk-SQGT43Z3.js.map +0 -1
  96. package/dist/chunk-VUMGMGKZ.js.map +0 -1
  97. package/dist/chunk-YQO2NMJ3.js.map +0 -1
  98. /package/dist/{AgentMetricChart-4FYECRIN.js.map → AgentMetricChart-YWJYVYYA.js.map} +0 -0
  99. /package/dist/{AgentOverview-3FJ5EE6N.js.map → AgentOverview-VF74XC7I.js.map} +0 -0
  100. /package/dist/{DockLayout-NLFNU6F2.js.map → DockLayout-F44RWGEY.js.map} +0 -0
  101. /package/dist/{OpenUiFenceBlock-JEPNPJ7U.js.map → OpenUiFenceBlock-4ROX3G4X.js.map} +0 -0
  102. /package/dist/{SandboxSettings-DF64LHYI.js.map → SandboxSettings-OLKDXIQS.js.map} +0 -0
  103. /package/dist/{SchedulesPage-WQU4H25F.js.map → SchedulesPage-TMOTK6DR.js.map} +0 -0
  104. /package/dist/{SettingsBuilder-LSXK2VN4.js.map → SettingsBuilder-GISAH2WU.js.map} +0 -0
  105. /package/dist/{TrueForgeUIWithRouter-3TSLV22Q.js.map → TrueForgeUIWithRouter-6VCR7ES3.js.map} +0 -0
  106. /package/dist/{WidgetLayout-Q5P7PYSJ.js.map → WidgetLayout-RKBSN2FZ.js.map} +0 -0
  107. /package/dist/{chunk-VJ7BZGAF.js.map → chunk-J5BPHEDT.js.map} +0 -0
@@ -24,29 +24,32 @@ import {
24
24
  Tooltip,
25
25
  auiInputClass,
26
26
  mountName,
27
- searchAllAgents,
27
+ useResourcePermissions,
28
+ useSlot,
28
29
  useToasterOptional
29
- } from "./chunk-YQO2NMJ3.js";
30
+ } from "./chunk-2O5EJ6QS.js";
30
31
  import {
31
32
  readScheduleShareSearch,
32
- replaceScheduleShareSearch
33
- } from "./chunk-NHHSZB5N.js";
33
+ replaceScheduleShareSearch,
34
+ searchAllAgents
35
+ } from "./chunk-KR7WYHVF.js";
34
36
  import {
35
37
  DraftCatalogProvider,
36
38
  Icon,
37
39
  PageHeader,
38
40
  auiButtonClass,
39
41
  useDraftCatalog
40
- } from "./chunk-H6WTY5PM.js";
42
+ } from "./chunk-Q6TCT7ZJ.js";
41
43
  import {
42
44
  libraryAgentId,
43
45
  useOptionalCatalogServer,
46
+ useOptionalShellMode,
44
47
  useScheduleServer,
45
48
  useServer
46
- } from "./chunk-FQK2XVVE.js";
49
+ } from "./chunk-PT4EENB3.js";
47
50
  import {
48
51
  cn
49
- } from "./chunk-BWHOZFIV.js";
52
+ } from "./chunk-LXJMINS6.js";
50
53
 
51
54
  // src/atoms/schedules/SchedulesPage.tsx
52
55
  import { useCallback, useEffect as useEffect3, useMemo as useMemo2, useRef, useState as useState3 } from "react";
@@ -278,7 +281,9 @@ function ScheduleFormFields({
278
281
  agentId,
279
282
  onAgentIdChange,
280
283
  agentOptions,
281
- agentPickerDisabled = false
284
+ agentOptionsLoaded = true,
285
+ agentPickerDisabled = false,
286
+ onBuildAgent
282
287
  }) {
283
288
  const cron = valuesToCron(values);
284
289
  const cadence = formatCadenceSummary({ cron, timezone: values.timezone });
@@ -302,7 +307,12 @@ function ScheduleFormFields({
302
307
  value: agentId,
303
308
  options: agentOptions.map((agent) => ({ value: agent.agentId, label: agent.name })),
304
309
  onValueChange: (value) => onAgentIdChange?.(value),
305
- disabled: agentPickerDisabled || onAgentIdChange == null
310
+ disabled: agentPickerDisabled || onAgentIdChange == null,
311
+ emptyContent: agentOptionsLoaded ? /* @__PURE__ */ jsx("p", { className: "text-text-secondary px-3 py-5 text-center text-sm", children: "No Agents created yet" }) : null,
312
+ footer: agentOptionsLoaded && agentOptions.length === 0 && onBuildAgent != null ? /* @__PURE__ */ jsx("div", { className: "flex justify-end border-t border-border px-2 pt-2", children: /* @__PURE__ */ jsxs(Button.Ghost, { type: "button", onClick: onBuildAgent, children: [
313
+ /* @__PURE__ */ jsx(Icon, { name: "plus", className: "size-3.5" }),
314
+ "Build Agent"
315
+ ] }) }) : null
306
316
  }
307
317
  )
308
318
  ] }),
@@ -334,107 +344,96 @@ function ScheduleFormFields({
334
344
  )
335
345
  ] }),
336
346
  /* @__PURE__ */ jsxs("fieldset", { children: [
337
- /* @__PURE__ */ jsx("legend", { className: "mb-1.5 text-sm font-medium", children: "Recurrence" }),
338
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 rounded-lg border border-border p-1", children: RECURRENCE_OPTIONS.map((opt) => {
339
- const selected = values.recurrence === opt.value;
340
- return /* @__PURE__ */ jsx(
341
- "button",
342
- {
343
- type: "button",
344
- className: cn(
345
- "rounded-md px-2 py-1.5 text-xs font-medium transition-colors",
346
- selected ? "border border-primary-button-bg/40 bg-primary-button-bg/10 text-primary-button-bg" : "text-text-secondary hover:bg-ghost-button-hover border border-transparent"
347
- ),
348
- "aria-pressed": selected,
349
- onClick: () => set("recurrence", opt.value),
350
- children: opt.label
351
- },
352
- opt.value
353
- );
354
- }) })
355
- ] }),
356
- values.recurrence === "hourly" ? /* @__PURE__ */ jsxs("div", { className: "block max-w-[8rem]", children: [
357
- /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Minute" }),
358
- /* @__PURE__ */ jsx(
359
- PopoverSelect,
360
- {
361
- "aria-label": "Minute",
362
- value: String(values.minute),
363
- options: MINUTE_OPTIONS,
364
- onValueChange: (value) => set("minute", Number(value))
365
- }
366
- )
367
- ] }) : null,
368
- values.recurrence === "daily" || values.recurrence === "weekly" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3", children: [
369
- /* @__PURE__ */ jsxs("div", { className: "block min-w-[7rem] flex-1", children: [
370
- /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Hour" }),
371
- /* @__PURE__ */ jsx(
372
- PopoverSelect,
373
- {
374
- "aria-label": "Hour",
375
- value: String(values.hour),
376
- options: HOUR_OPTIONS,
377
- onValueChange: (value) => set("hour", Number(value))
378
- }
379
- )
380
- ] }),
381
- /* @__PURE__ */ jsxs("div", { className: "block min-w-[7rem] flex-1", children: [
382
- /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Minute" }),
383
- /* @__PURE__ */ jsx(
384
- PopoverSelect,
385
- {
386
- "aria-label": "Minute",
387
- value: String(values.minute),
388
- options: MINUTE_OPTIONS,
389
- onValueChange: (value) => set("minute", Number(value))
390
- }
391
- )
392
- ] })
393
- ] }) : null,
394
- values.recurrence === "weekly" ? /* @__PURE__ */ jsxs("fieldset", { children: [
395
- /* @__PURE__ */ jsx("legend", { className: "mb-1.5 text-sm font-medium", children: "Days" }),
396
- /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1.5", children: WEEKDAY_OPTIONS.map((day) => {
397
- const selected = values.weekdays.includes(day.value);
398
- return /* @__PURE__ */ jsx(
399
- "button",
400
- {
401
- type: "button",
402
- className: cn(
403
- "rounded-md border px-2.5 py-1 text-xs font-medium",
404
- selected ? "border-primary-button-bg/40 bg-primary-button-bg/10 text-primary-button-bg" : "border-border text-text-secondary hover:bg-ghost-button-hover"
405
- ),
406
- "aria-pressed": selected,
407
- onClick: () => toggleWeekday(day.value),
408
- children: day.label
409
- },
410
- day.value
411
- );
412
- }) })
413
- ] }) : null,
414
- values.recurrence === "custom" ? /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-secondary-bg/40 px-3 py-2", children: [
415
- /* @__PURE__ */ jsx("span", { className: "text-text-secondary block text-xs", children: "Existing custom schedule" }),
416
- /* @__PURE__ */ jsx("code", { className: "text-text-primary mt-1 block font-mono text-sm", children: values.customCron }),
417
- /* @__PURE__ */ jsx("span", { className: "text-text-secondary mt-1 block text-xs", children: "Select Hourly, Daily, or Weekly to replace this schedule." })
418
- ] }) : null,
419
- /* @__PURE__ */ jsxs("div", { className: "block", children: [
420
- /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Timezone" }),
421
- /* @__PURE__ */ jsx(
422
- PopoverSelect,
423
- {
424
- "aria-label": "Timezone",
425
- value: values.timezone,
426
- options: timezoneOptions,
427
- onValueChange: (value) => set("timezone", value),
428
- menuPlacement: "top"
429
- }
430
- )
431
- ] }),
432
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-border bg-secondary-bg/40 px-3 py-3", children: [
433
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
434
- /* @__PURE__ */ jsx("span", { className: "text-text-secondary text-[10px] font-semibold tracking-wide uppercase", children: "Frequency" }),
435
- /* @__PURE__ */ jsx("code", { className: "text-text-secondary font-mono text-xs", children: cron || "\u2014" })
436
- ] }),
437
- /* @__PURE__ */ jsx("p", { className: "text-text-primary mt-1 text-sm font-semibold", children: cadence || "\u2014" })
347
+ /* @__PURE__ */ jsx("legend", { className: "mb-1.5 text-sm font-medium", children: "Frequency" }),
348
+ /* @__PURE__ */ jsx("div", { className: "rounded-t-lg border border-border p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
349
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-1 rounded-lg border border-border bg-primary-bg p-1", children: RECURRENCE_OPTIONS.map((opt) => {
350
+ const selected = values.recurrence === opt.value;
351
+ return /* @__PURE__ */ jsx(
352
+ "button",
353
+ {
354
+ type: "button",
355
+ className: cn(
356
+ "rounded-md border px-2 py-2 text-sm font-medium transition-colors",
357
+ selected ? "border-primary-button-bg/40 bg-primary-button-bg/10 font-semibold text-primary-button-bg" : "border-transparent text-text-secondary hover:bg-ghost-button-hover"
358
+ ),
359
+ "aria-pressed": selected,
360
+ onClick: () => set("recurrence", opt.value),
361
+ children: opt.label
362
+ },
363
+ opt.value
364
+ );
365
+ }) }),
366
+ values.recurrence === "custom" ? /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-border bg-secondary-bg/40 px-3 py-2", children: [
367
+ /* @__PURE__ */ jsx("span", { className: "block text-xs text-text-secondary", children: "Existing custom schedule" }),
368
+ /* @__PURE__ */ jsx("code", { className: "mt-1 block font-mono text-sm text-text-primary", children: values.customCron }),
369
+ /* @__PURE__ */ jsx("span", { className: "mt-1 block text-xs text-text-secondary", children: "Select Hourly, Daily, or Weekly to replace this schedule." })
370
+ ] }) : null,
371
+ values.recurrence === "weekly" ? /* @__PURE__ */ jsxs("fieldset", { children: [
372
+ /* @__PURE__ */ jsx("legend", { className: "mb-2 text-sm font-medium", children: "Days" }),
373
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: WEEKDAY_OPTIONS.map((day) => {
374
+ const selected = values.weekdays.includes(day.value);
375
+ return /* @__PURE__ */ jsx(
376
+ "button",
377
+ {
378
+ type: "button",
379
+ className: cn(
380
+ "min-w-0 flex-1 rounded-md border px-3 py-2 text-[0.8125rem] font-medium",
381
+ selected ? "border-primary-button-bg/40 bg-primary-button-bg/10 font-semibold text-primary-button-bg" : "border-border text-text-secondary hover:bg-ghost-button-hover"
382
+ ),
383
+ "aria-pressed": selected,
384
+ onClick: () => toggleWeekday(day.value),
385
+ children: day.label
386
+ },
387
+ day.value
388
+ );
389
+ }) })
390
+ ] }) : null,
391
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4", children: [
392
+ values.recurrence === "daily" || values.recurrence === "weekly" ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
393
+ /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Hour" }),
394
+ /* @__PURE__ */ jsx(
395
+ PopoverSelect,
396
+ {
397
+ "aria-label": "Hour",
398
+ value: String(values.hour),
399
+ options: HOUR_OPTIONS,
400
+ onValueChange: (value) => set("hour", Number(value))
401
+ }
402
+ )
403
+ ] }) : null,
404
+ values.recurrence !== "custom" ? /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
405
+ /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Minute" }),
406
+ /* @__PURE__ */ jsx(
407
+ PopoverSelect,
408
+ {
409
+ "aria-label": "Minute",
410
+ value: String(values.minute),
411
+ options: MINUTE_OPTIONS,
412
+ onValueChange: (value) => set("minute", Number(value))
413
+ }
414
+ )
415
+ ] }) : null,
416
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
417
+ /* @__PURE__ */ jsx("span", { className: "mb-1.5 block text-sm font-medium", children: "Timezone" }),
418
+ /* @__PURE__ */ jsx(
419
+ PopoverSelect,
420
+ {
421
+ "aria-label": "Timezone",
422
+ value: values.timezone,
423
+ options: timezoneOptions,
424
+ onValueChange: (value) => set("timezone", value),
425
+ menuClassName: "w-full min-w-0"
426
+ }
427
+ )
428
+ ] })
429
+ ] })
430
+ ] }) }),
431
+ /* @__PURE__ */ jsx("div", { className: "rounded-b-lg border border-t-0 border-border bg-primary-button-bg/10 px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
432
+ /* @__PURE__ */ jsx(Icon, { name: "clock", className: "size-4 shrink-0 text-primary-button-bg" }),
433
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs font-medium text-text-secondary", children: "Schedule" }),
434
+ /* @__PURE__ */ jsx("p", { className: "min-w-0 flex-1 truncate text-sm text-text-primary", children: cadence || "\u2014" }),
435
+ /* @__PURE__ */ jsx("code", { className: "shrink-0 whitespace-nowrap font-mono text-[0.8125rem] font-bold text-text-secondary", children: cron || "\u2014" })
436
+ ] }) })
438
437
  ] })
439
438
  ] });
440
439
  }
@@ -525,7 +524,7 @@ function ScheduleStatusBadge({ status }) {
525
524
  {
526
525
  className: cn(
527
526
  "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-0.5 text-xs font-medium",
528
- active ? "border-emerald-600/30 bg-emerald-500/10 text-emerald-700 dark:border-emerald-400/35 dark:bg-emerald-500/15 dark:text-emerald-300" : "border-border bg-secondary-bg text-text-secondary"
527
+ active ? "border-emerald-600/30 bg-emerald-500/10 text-emerald-700 dark:border-emerald-400/35 dark:bg-emerald-500/15 dark:text-emerald-300" : "border-amber-600/30 bg-amber-500/10 text-amber-800 dark:border-amber-400/35 dark:bg-amber-500/15 dark:text-amber-300"
529
528
  ),
530
529
  children: [
531
530
  /* @__PURE__ */ jsx4(
@@ -533,7 +532,7 @@ function ScheduleStatusBadge({ status }) {
533
532
  {
534
533
  className: cn(
535
534
  "size-1.5 shrink-0 rounded-full",
536
- active ? "bg-emerald-600 dark:bg-emerald-400" : "bg-text-secondary"
535
+ active ? "bg-emerald-600 dark:bg-emerald-400" : "bg-amber-600 dark:bg-amber-400"
537
536
  ),
538
537
  "aria-hidden": true
539
538
  }
@@ -592,12 +591,12 @@ function TestScheduleScreen({ schedule, agentName, mcpMounts, onEditConfiguratio
592
591
  /* @__PURE__ */ jsxs4("section", { className: "overflow-hidden rounded-lg border border-border bg-card-bg", children: [
593
592
  /* @__PURE__ */ jsx5(DetailRow, { label: "Agent", children: agentName }),
594
593
  /* @__PURE__ */ jsx5(DetailRow, { label: "Name", children: schedule.name }),
594
+ /* @__PURE__ */ jsx5(DetailRow, { label: "Status", children: /* @__PURE__ */ jsx5(ScheduleStatusBadge, { status: schedule.status }) }),
595
595
  /* @__PURE__ */ jsx5(DetailRow, { label: "Task", children: /* @__PURE__ */ jsx5("span", { className: "whitespace-pre-wrap break-words", children: schedule.task }) }),
596
- /* @__PURE__ */ jsx5(DetailRow, { label: "Cadence", children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
596
+ /* @__PURE__ */ jsx5(DetailRow, { label: "Frequency", children: /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center justify-end gap-1.5", children: [
597
597
  /* @__PURE__ */ jsx5("span", { children: cadence }),
598
598
  /* @__PURE__ */ jsx5("code", { className: "text-text-secondary font-mono text-xs", children: schedule.cron })
599
599
  ] }) }),
600
- /* @__PURE__ */ jsx5(DetailRow, { label: "Status", children: /* @__PURE__ */ jsx5(ScheduleStatusBadge, { status: schedule.status }) }),
601
600
  /* @__PURE__ */ jsx5("div", { className: "flex justify-end px-3 py-2.5", children: /* @__PURE__ */ jsxs4(Button.Secondary, { type: "button", size: "small", onClick: onEditConfiguration, children: [
602
601
  /* @__PURE__ */ jsx5(Icon, { name: "pencil", className: "size-3.5" }),
603
602
  "Edit Configuration"
@@ -657,10 +656,12 @@ function ScheduleFormDrawerBody({
657
656
  }) {
658
657
  const scheduleServer = useScheduleServer();
659
658
  const server = useServer();
659
+ const shell = useOptionalShellMode();
660
660
  const toaster = useToasterOptional();
661
661
  const [form, setForm] = useState2(defaultScheduleFormValues);
662
662
  const [agentId, setAgentId] = useState2(initialAgentId);
663
663
  const [agents, setAgents] = useState2([]);
664
+ const [agentsLoaded, setAgentsLoaded] = useState2(false);
664
665
  const [view, setView] = useState2({ kind: "form" });
665
666
  const [saving, setSaving] = useState2(false);
666
667
  const [activating, setActivating] = useState2(false);
@@ -668,12 +669,19 @@ function ScheduleFormDrawerBody({
668
669
  const savedFromCreate = view.kind === "form" ? view.saved : view.schedule;
669
670
  const isExternalEdit = mode === "edit" && view.kind === "form" && view.saved == null && schedule != null;
670
671
  const isCreatedEdit = view.kind === "form" && view.saved != null;
672
+ const isInitialCreate = mode === "create" && view.kind === "form" && view.saved == null;
673
+ const { allows: allowsAgent } = useResourcePermissions({
674
+ resourceType: "agent",
675
+ resourceIds: agentId.length === 0 ? [] : [agentId]
676
+ });
671
677
  useEffect2(() => {
672
678
  if (!open) return;
673
679
  let cancelled = false;
680
+ setAgentsLoaded(false);
674
681
  void searchAllAgents(server).then((rows) => {
675
682
  if (cancelled) return;
676
683
  setAgents(rows);
684
+ setAgentsLoaded(true);
677
685
  }).catch(() => void 0);
678
686
  return () => {
679
687
  cancelled = true;
@@ -720,8 +728,8 @@ function ScheduleFormDrawerBody({
720
728
  }, [selectedAgent]);
721
729
  const canSubmit = useMemo(() => {
722
730
  const cron = valuesToCron(form);
723
- return form.name.trim().length > 0 && form.task.trim().length > 0 && cron.length > 0 && agentId.length > 0;
724
- }, [form, agentId]);
731
+ return form.name.trim().length > 0 && form.task.trim().length > 0 && cron.length > 0 && agentId.length > 0 && (!isInitialCreate || allowsAgent(agentId, "USE"));
732
+ }, [agentId, allowsAgent, form, isInitialCreate]);
725
733
  const enterTestView = (saved) => {
726
734
  setView({ kind: "test", schedule: saved });
727
735
  setForm(
@@ -822,7 +830,7 @@ function ScheduleFormDrawerBody({
822
830
  if (view.kind === "test") {
823
831
  footer = /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
824
832
  error != null ? /* @__PURE__ */ jsx6("p", { className: "text-failure-bg text-sm", children: error }) : null,
825
- /* @__PURE__ */ jsx6(Button.Secondary, { type: "button", className: "w-full", disabled: activating, onClick: () => void handleActivate(), children: "Activate Anyway" })
833
+ /* @__PURE__ */ jsx6(Button.Secondary, { type: "button", className: "w-full", disabled: activating, onClick: () => void handleActivate(), children: "Activate Schedule" })
826
834
  ] });
827
835
  } else {
828
836
  footer = /* @__PURE__ */ jsxs5("div", { className: "flex flex-col gap-2", children: [
@@ -841,7 +849,7 @@ function ScheduleFormDrawerBody({
841
849
  title,
842
850
  description,
843
851
  anchor: "right",
844
- size: "lg",
852
+ size: "xl",
845
853
  headerIcon: /* @__PURE__ */ jsx6("span", { className: "text-primary-button-bg inline-flex size-8 items-center justify-center", children: /* @__PURE__ */ jsx6(
846
854
  Icon,
847
855
  {
@@ -869,7 +877,12 @@ function ScheduleFormDrawerBody({
869
877
  agentId,
870
878
  onAgentIdChange: isExternalEdit || isCreatedEdit ? void 0 : setAgentId,
871
879
  agentOptions,
872
- agentPickerDisabled: isExternalEdit || isCreatedEdit
880
+ agentOptionsLoaded: agentsLoaded,
881
+ agentPickerDisabled: isExternalEdit || isCreatedEdit,
882
+ onBuildAgent: mode === "create" && shell?.isComposerEnabled === true ? () => {
883
+ onOpenChange(false);
884
+ shell.openAgentBuilder();
885
+ } : void 0
873
886
  }
874
887
  ) })
875
888
  }
@@ -908,16 +921,28 @@ function filtersFromSearch(search) {
908
921
  agentFilter: share.agent ?? "all"
909
922
  };
910
923
  }
924
+ function initialDrawerState(agentId) {
925
+ const share = readScheduleShareSearch(window.location.search);
926
+ if (!share.isNew) return { kind: "closed" };
927
+ const initialAgentId = agentId ?? share.agent;
928
+ return {
929
+ kind: "create",
930
+ ...initialAgentId == null ? {} : { agentId: initialAgentId }
931
+ };
932
+ }
911
933
  function ScheduleRowActions({
912
934
  schedule,
913
935
  running,
936
+ canManage,
937
+ canDelete,
914
938
  onRunNow,
915
939
  onEdit,
916
940
  onTogglePause,
917
941
  onDelete
918
942
  }) {
943
+ const PermissionGuard = useSlot("PermissionGuard");
919
944
  return /* @__PURE__ */ jsxs6("div", { className: "inline-flex items-center justify-end gap-1.5", children: [
920
- /* @__PURE__ */ jsxs6(
945
+ /* @__PURE__ */ jsx8(PermissionGuard, { allowed: canManage, children: /* @__PURE__ */ jsxs6(
921
946
  Button.Secondary,
922
947
  {
923
948
  type: "button",
@@ -930,7 +955,7 @@ function ScheduleRowActions({
930
955
  "Run now"
931
956
  ]
932
957
  }
933
- ),
958
+ ) }),
934
959
  /* @__PURE__ */ jsxs6(
935
960
  DropdownMenu,
936
961
  {
@@ -945,28 +970,32 @@ function ScheduleRowActions({
945
970
  }
946
971
  ),
947
972
  children: [
948
- /* @__PURE__ */ jsxs6(DropdownMenuItem, { onClick: onEdit, children: [
973
+ /* @__PURE__ */ jsx8(PermissionGuard, { allowed: canManage, children: /* @__PURE__ */ jsxs6(DropdownMenuItem, { onClick: onEdit, children: [
949
974
  /* @__PURE__ */ jsx8(Icon, { name: "pencil", className: "size-3.5" }),
950
975
  "Edit"
951
- ] }),
952
- /* @__PURE__ */ jsxs6(DropdownMenuItem, { onClick: onTogglePause, children: [
976
+ ] }) }),
977
+ /* @__PURE__ */ jsx8(PermissionGuard, { allowed: canManage, children: /* @__PURE__ */ jsxs6(DropdownMenuItem, { onClick: onTogglePause, children: [
953
978
  /* @__PURE__ */ jsx8(Icon, { name: schedule.status === "active" ? "pause" : "play", className: "size-3.5" }),
954
979
  schedule.status === "active" ? "Pause" : "Resume"
955
- ] }),
956
- /* @__PURE__ */ jsxs6(DropdownMenuItem, { className: "text-failure-bg focus:text-failure-bg", onClick: onDelete, children: [
980
+ ] }) }),
981
+ /* @__PURE__ */ jsx8(PermissionGuard, { allowed: canDelete, children: /* @__PURE__ */ jsxs6(DropdownMenuItem, { className: "text-failure-bg focus:text-failure-bg", onClick: onDelete, children: [
957
982
  /* @__PURE__ */ jsx8(Icon, { name: "trash", className: "size-3.5" }),
958
983
  "Delete"
959
- ] })
984
+ ] }) })
960
985
  ]
961
986
  }
962
987
  )
963
988
  ] });
964
989
  }
965
- function SchedulesPage() {
990
+ function SchedulesPage({ agentId }) {
966
991
  const scheduleServer = useScheduleServer();
967
992
  const server = useServer();
968
993
  const toaster = useToasterOptional();
969
994
  const [schedules, setSchedules] = useState3([]);
995
+ const { allows } = useResourcePermissions({
996
+ resourceType: "schedule",
997
+ resourceIds: schedules.map((schedule) => schedule.id)
998
+ });
970
999
  const [runsByScheduleId, setRunsByScheduleId] = useState3({});
971
1000
  const [runsLoading, setRunsLoading] = useState3(false);
972
1001
  const [runningScheduleIds, setRunningScheduleIds] = useState3(() => /* @__PURE__ */ new Set());
@@ -977,8 +1006,20 @@ function SchedulesPage() {
977
1006
  const [statusFilter, setStatusFilter] = useState3(
978
1007
  () => filtersFromSearch(window.location.search).statusFilter
979
1008
  );
980
- const [agentFilter, setAgentFilter] = useState3(() => filtersFromSearch(window.location.search).agentFilter);
981
- const [drawer, setDrawer] = useState3({ kind: "closed" });
1009
+ const [agentFilter, setAgentFilter] = useState3(
1010
+ () => agentId ?? filtersFromSearch(window.location.search).agentFilter
1011
+ );
1012
+ const permissionAgentId = agentId ?? (agentFilter === "all" ? null : agentFilter);
1013
+ const permissionAgentIds = useMemo2(
1014
+ () => permissionAgentId == null ? agentOptions.map((option) => option.agentId) : [permissionAgentId],
1015
+ [agentOptions, permissionAgentId]
1016
+ );
1017
+ const { allows: allowsAgent } = useResourcePermissions({
1018
+ resourceType: "agent",
1019
+ resourceIds: permissionAgentIds
1020
+ });
1021
+ const canCreateSchedule = server.permissions == null || (permissionAgentId == null ? agentOptions.some((option) => allowsAgent(option.agentId, "USE")) : allowsAgent(permissionAgentId, "USE"));
1022
+ const [drawer, setDrawer] = useState3(() => initialDrawerState(agentId));
982
1023
  const [pendingDelete, setPendingDelete] = useState3(null);
983
1024
  const [pageSize, setPageSize] = useState3(() => clampPageSize(DEFAULT_TABLE_PAGE_SIZE));
984
1025
  const [pageToken, setPageToken] = useState3(void 0);
@@ -1014,7 +1055,7 @@ function SchedulesPage() {
1014
1055
  [scheduleServer]
1015
1056
  );
1016
1057
  const loadSchedules = useCallback(
1017
- async ({ token, size, agentId }) => {
1058
+ async ({ token, size, agentId: agentId2 }) => {
1018
1059
  const gen = ++loadGenRef.current;
1019
1060
  setLoading(true);
1020
1061
  setError(null);
@@ -1022,7 +1063,7 @@ function SchedulesPage() {
1022
1063
  const page = await scheduleServer.listSchedules({
1023
1064
  limit: clampPageSize(size),
1024
1065
  ...token === void 0 || token === "" ? {} : { pageToken: token },
1025
- ...agentId === "all" ? {} : { agentIds: [agentId] }
1066
+ ...agentId2 === "all" ? {} : { agentIds: [agentId2] }
1026
1067
  });
1027
1068
  if (gen !== loadGenRef.current) return;
1028
1069
  setSchedules(page.data);
@@ -1044,29 +1085,34 @@ function SchedulesPage() {
1044
1085
  const resetToFirstPage = useCallback(
1045
1086
  (next) => {
1046
1087
  const size = next?.size ?? pageSize;
1047
- const agentId = next?.agentId ?? agentFilter;
1088
+ const agentId2 = next?.agentId ?? agentFilter;
1048
1089
  setPageToken(void 0);
1049
1090
  setPrevTokenStack([]);
1050
- void loadSchedules({ token: void 0, size, agentId });
1091
+ void loadSchedules({ token: void 0, size, agentId: agentId2 });
1051
1092
  },
1052
1093
  [agentFilter, loadSchedules, pageSize]
1053
1094
  );
1054
1095
  useEffect3(() => {
1055
1096
  replaceScheduleShareSearch({
1056
- agent: agentFilter === "all" ? null : agentFilter,
1097
+ agent: agentId === void 0 && agentFilter !== "all" ? agentFilter : null,
1057
1098
  status: statusFilter === "all" ? null : statusFilter,
1058
1099
  q: nameQuery.trim().length === 0 ? null : nameQuery
1059
1100
  });
1060
- }, [agentFilter, statusFilter, nameQuery]);
1101
+ }, [agentFilter, agentId, statusFilter, nameQuery]);
1102
+ useEffect3(() => {
1103
+ if (agentId === void 0) return;
1104
+ setAgentFilter((current) => {
1105
+ if (current === agentId) return current;
1106
+ setPageToken(void 0);
1107
+ setPrevTokenStack([]);
1108
+ return agentId;
1109
+ });
1110
+ }, [agentId]);
1061
1111
  useEffect3(() => {
1062
1112
  if (didConsumeIsNewRef.current) return;
1063
1113
  const share = readScheduleShareSearch(window.location.search);
1064
1114
  if (!share.isNew) return;
1065
1115
  didConsumeIsNewRef.current = true;
1066
- setDrawer({
1067
- kind: "create",
1068
- ...share.agent != null ? { agentId: share.agent } : {}
1069
- });
1070
1116
  replaceScheduleShareSearch({ isNew: null });
1071
1117
  }, []);
1072
1118
  useEffect3(() => {
@@ -1075,17 +1121,18 @@ function SchedulesPage() {
1075
1121
  setNameQuery(next.nameQuery);
1076
1122
  setStatusFilter(next.statusFilter);
1077
1123
  setAgentFilter((current) => {
1078
- if (current === next.agentFilter) return current;
1124
+ const nextAgentFilter = agentId ?? next.agentFilter;
1125
+ if (current === nextAgentFilter) return current;
1079
1126
  setPageToken(void 0);
1080
1127
  setPrevTokenStack([]);
1081
- return next.agentFilter;
1128
+ return nextAgentFilter;
1082
1129
  });
1083
1130
  };
1084
1131
  window.addEventListener("popstate", syncFromUrl);
1085
1132
  return () => {
1086
1133
  window.removeEventListener("popstate", syncFromUrl);
1087
1134
  };
1088
- }, []);
1135
+ }, [agentId]);
1089
1136
  useEffect3(() => {
1090
1137
  void loadSchedules({ token: pageToken, size: pageSize, agentId: agentFilter });
1091
1138
  }, [agentFilter, pageSize, pageToken, loadSchedules]);
@@ -1116,6 +1163,7 @@ function SchedulesPage() {
1116
1163
  }, [schedules, nameQuery, statusFilter]);
1117
1164
  const hasPageNav = prevTokenStack.length > 0 || nextPageToken != null;
1118
1165
  const handleTogglePause = async (schedule) => {
1166
+ if (!allows(schedule.id, "MANAGE")) return;
1119
1167
  const nextStatus = schedule.status === "active" ? "paused" : "active";
1120
1168
  try {
1121
1169
  await scheduleServer.updateSchedule({ ...schedule, status: nextStatus });
@@ -1125,6 +1173,7 @@ function SchedulesPage() {
1125
1173
  }
1126
1174
  };
1127
1175
  const handleRunNow = async (schedule) => {
1176
+ if (!allows(schedule.id, "MANAGE")) return;
1128
1177
  setRunningScheduleIds((prev) => new Set(prev).add(schedule.id));
1129
1178
  try {
1130
1179
  await scheduleServer.createScheduleRun({ scheduleId: schedule.id });
@@ -1142,6 +1191,7 @@ function SchedulesPage() {
1142
1191
  }
1143
1192
  };
1144
1193
  const handleDelete = async (schedule) => {
1194
+ if (!allows(schedule.id, "DELETE")) return;
1145
1195
  setPendingDelete(null);
1146
1196
  try {
1147
1197
  await scheduleServer.deleteSchedule({ id: schedule.id });
@@ -1166,7 +1216,7 @@ function SchedulesPage() {
1166
1216
  /* @__PURE__ */ jsx8(
1167
1217
  PageHeader,
1168
1218
  {
1169
- title: "Scheduled Agents",
1219
+ title: agentId === void 0 ? "Scheduled Agents" : void 0,
1170
1220
  end: /* @__PURE__ */ jsxs6(Fragment, { children: [
1171
1221
  /* @__PURE__ */ jsx8("div", { className: "w-full sm:w-56", children: /* @__PURE__ */ jsx8(SearchInput_default, { query: nameQuery, setQuery: setNameQuery, placeholder: "Search schedules by name" }) }),
1172
1222
  /* @__PURE__ */ jsx8(
@@ -1179,7 +1229,7 @@ function SchedulesPage() {
1179
1229
  "aria-label": "Filter by status"
1180
1230
  }
1181
1231
  ),
1182
- /* @__PURE__ */ jsx8(
1232
+ agentId === void 0 ? /* @__PURE__ */ jsx8(
1183
1233
  PopoverSelect,
1184
1234
  {
1185
1235
  value: agentFilter,
@@ -1195,12 +1245,13 @@ function SchedulesPage() {
1195
1245
  className: "sm:w-40",
1196
1246
  "aria-label": "Filter by agent"
1197
1247
  }
1198
- ),
1248
+ ) : null,
1199
1249
  /* @__PURE__ */ jsxs6(
1200
1250
  Button.Primary,
1201
1251
  {
1202
1252
  type: "button",
1203
- onClick: () => setDrawer({
1253
+ disabled: !canCreateSchedule,
1254
+ onClick: () => canCreateSchedule && setDrawer({
1204
1255
  kind: "create",
1205
1256
  agentId: agentFilter !== "all" ? agentFilter : void 0
1206
1257
  }),
@@ -1213,7 +1264,7 @@ function SchedulesPage() {
1213
1264
  ] })
1214
1265
  }
1215
1266
  ),
1216
- /* @__PURE__ */ jsx8("div", { className: "min-h-0 flex-1 overflow-auto px-4 py-4 md:px-6", children: loading ? /* @__PURE__ */ jsx8("div", { className: "flex flex-col gap-2", role: "status", "aria-label": "Loading schedules", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx8(Skeleton, { className: "h-12 w-full rounded-md" }, i)) }) : error != null ? /* @__PURE__ */ jsx8("p", { className: "text-failure-bg px-3 py-8 text-center text-sm", children: error }) : schedules.length === 0 ? /* @__PURE__ */ jsx8(EmptyScreen, { title: "No Schedules Found", description: "Create one to get started.", className: "min-h-full" }) : filtered.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex min-h-full flex-col", children: [
1267
+ /* @__PURE__ */ jsx8("div", { className: "min-h-0 flex-1 overflow-auto px-4 py-4", children: loading ? /* @__PURE__ */ jsx8("div", { className: "flex flex-col gap-2", role: "status", "aria-label": "Loading schedules", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx8(Skeleton, { className: "h-12 w-full rounded-md" }, i)) }) : error != null ? /* @__PURE__ */ jsx8("p", { className: "text-failure-bg px-3 py-8 text-center text-sm", children: error }) : schedules.length === 0 ? /* @__PURE__ */ jsx8(EmptyScreen, { title: "No Schedules Found", description: "Create one to get started.", className: "min-h-full" }) : filtered.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex min-h-full flex-col", children: [
1217
1268
  /* @__PURE__ */ jsx8(EmptyScreen, { title: "No Schedules Found", description: "No schedules match your filters.", className: "flex-1" }),
1218
1269
  hasPageNav ? /* @__PURE__ */ jsx8(
1219
1270
  TableTokenPagination,
@@ -1238,7 +1289,7 @@ function SchedulesPage() {
1238
1289
  /* @__PURE__ */ jsx8(TableHeader, { children: /* @__PURE__ */ jsxs6(TableRow, { className: "hover:bg-transparent", children: [
1239
1290
  /* @__PURE__ */ jsx8(TableHead, { children: "Name" }),
1240
1291
  /* @__PURE__ */ jsx8(TableHead, { children: "Agent" }),
1241
- /* @__PURE__ */ jsx8(TableHead, { children: "Cadence" }),
1292
+ /* @__PURE__ */ jsx8(TableHead, { children: "Frequency" }),
1242
1293
  /* @__PURE__ */ jsx8(TableHead, { children: "Status" }),
1243
1294
  /* @__PURE__ */ jsx8(TableHead, { children: "Last 5 runs" }),
1244
1295
  /* @__PURE__ */ jsx8(TableHead, { children: /* @__PURE__ */ jsx8("span", { className: "sr-only", children: "Actions" }) })
@@ -1247,15 +1298,7 @@ function SchedulesPage() {
1247
1298
  const cadence = formatCadenceSummary({ cron: schedule.cron, timezone: schedule.timezone });
1248
1299
  const agentLabel = schedule.agentName ?? agentNameById.get(schedule.agentId) ?? schedule.agentId;
1249
1300
  return /* @__PURE__ */ jsxs6(TableRow, { children: [
1250
- /* @__PURE__ */ jsx8(TableCell, { className: "text-text-primary font-medium", children: /* @__PURE__ */ jsx8(
1251
- "button",
1252
- {
1253
- type: "button",
1254
- className: "cursor-pointer text-left",
1255
- onClick: () => setDrawer({ kind: "edit", schedule }),
1256
- children: schedule.name
1257
- }
1258
- ) }),
1301
+ /* @__PURE__ */ jsx8(TableCell, { className: "text-text-primary font-medium", children: /* @__PURE__ */ jsx8("span", { className: "text-left !no-underline", children: schedule.name }) }),
1259
1302
  /* @__PURE__ */ jsx8(TableCell, { children: agentLabel }),
1260
1303
  /* @__PURE__ */ jsx8(TableCell, { children: cadence }),
1261
1304
  /* @__PURE__ */ jsx8(TableCell, { children: /* @__PURE__ */ jsx8(ScheduleStatusBadge, { status: schedule.status }) }),
@@ -1265,10 +1308,16 @@ function SchedulesPage() {
1265
1308
  {
1266
1309
  schedule,
1267
1310
  running: runningScheduleIds.has(schedule.id),
1311
+ canManage: allows(schedule.id, "MANAGE"),
1312
+ canDelete: allows(schedule.id, "DELETE"),
1268
1313
  onRunNow: () => void handleRunNow(schedule),
1269
- onEdit: () => setDrawer({ kind: "edit", schedule }),
1314
+ onEdit: () => {
1315
+ if (allows(schedule.id, "MANAGE")) setDrawer({ kind: "edit", schedule });
1316
+ },
1270
1317
  onTogglePause: () => void handleTogglePause(schedule),
1271
- onDelete: () => setPendingDelete(schedule)
1318
+ onDelete: () => {
1319
+ if (allows(schedule.id, "DELETE")) setPendingDelete(schedule);
1320
+ }
1272
1321
  }
1273
1322
  ) })
1274
1323
  ] }, schedule.id);
@@ -1337,7 +1386,15 @@ function SchedulesPage() {
1337
1386
  ] }) }),
1338
1387
  /* @__PURE__ */ jsxs6(DialogFooter, { children: [
1339
1388
  /* @__PURE__ */ jsx8(Button.Secondary, { type: "button", onClick: () => setPendingDelete(null), children: "Cancel" }),
1340
- /* @__PURE__ */ jsx8(Button.Destructive, { type: "button", onClick: () => void handleDelete(pendingDelete), children: "Delete" })
1389
+ /* @__PURE__ */ jsx8(
1390
+ Button.Destructive,
1391
+ {
1392
+ type: "button",
1393
+ disabled: !allows(pendingDelete.id, "DELETE"),
1394
+ onClick: () => void handleDelete(pendingDelete),
1395
+ children: "Delete"
1396
+ }
1397
+ )
1341
1398
  ] })
1342
1399
  ]
1343
1400
  }
@@ -1354,4 +1411,4 @@ export {
1354
1411
  ScheduleLastRunsCell,
1355
1412
  SchedulesPage
1356
1413
  };
1357
- //# sourceMappingURL=chunk-GXYAOAK5.js.map
1414
+ //# sourceMappingURL=chunk-GSJAYYLR.js.map