experimental-ash 0.4.0-alpha.3 → 0.4.0-alpha.4

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 (104) hide show
  1. package/README.md +3 -1
  2. package/dist/docs/internals/discovery.md +28 -13
  3. package/dist/docs/internals/schedule.md +95 -0
  4. package/dist/docs/public/project-layout.md +4 -4
  5. package/dist/docs/public/runs-and-streaming.md +1 -1
  6. package/dist/docs/public/schedules.md +94 -81
  7. package/dist/docs/public/session-context.md +1 -1
  8. package/dist/docs/public/typescript-api.md +2 -2
  9. package/dist/src/channel/schedule.d.ts +14 -5
  10. package/dist/src/channel/schedule.d.ts.map +1 -1
  11. package/dist/src/channel/schedule.js +14 -4
  12. package/dist/src/channel/schedule.js.map +1 -1
  13. package/dist/src/channel/slack-render.d.ts.map +1 -1
  14. package/dist/src/channel/slack-render.js +9 -2
  15. package/dist/src/channel/slack-render.js.map +1 -1
  16. package/dist/src/chunks/{chunk-WKCLLJVA.js → chunk-26J42T7K.js} +422 -441
  17. package/dist/src/chunks/chunk-26J42T7K.js.map +7 -0
  18. package/dist/src/chunks/{chunk-JYG2I2QJ.js → chunk-RFVUX6HI.js} +16 -11
  19. package/dist/src/chunks/{chunk-JYG2I2QJ.js.map → chunk-RFVUX6HI.js.map} +2 -2
  20. package/dist/src/chunks/{chunk-LOV2DSY3.js → chunk-VUESBSNV.js} +4 -4
  21. package/dist/src/chunks/{dev-authored-source-watcher-W2JT7UYC.js → dev-authored-source-watcher-6TM2MLOF.js} +3 -3
  22. package/dist/src/chunks/{host-BU6WPO36.js → host-DABU6JKC.js} +4 -4
  23. package/dist/src/chunks/{just-bash-GRSOFQHN.js → just-bash-SZDIBLW5.js} +6862 -6026
  24. package/dist/src/chunks/just-bash-SZDIBLW5.js.map +7 -0
  25. package/dist/src/cli/commands/info.js +1 -1
  26. package/dist/src/cli/run.js +2 -2
  27. package/dist/src/compiled/.vendor-stamp.json +1 -1
  28. package/dist/src/compiled/just-bash/index.js +6868 -6063
  29. package/dist/src/compiled/just-bash/index.js.map +4 -4
  30. package/dist/src/compiled/just-bash/package.json +1 -1
  31. package/dist/src/compiler/manifest.d.ts +18 -9
  32. package/dist/src/compiler/manifest.d.ts.map +1 -1
  33. package/dist/src/compiler/manifest.js +2 -2
  34. package/dist/src/compiler/manifest.js.map +1 -1
  35. package/dist/src/compiler/normalize-schedule.d.ts +8 -5
  36. package/dist/src/compiler/normalize-schedule.d.ts.map +1 -1
  37. package/dist/src/compiler/normalize-schedule.js +41 -36
  38. package/dist/src/compiler/normalize-schedule.js.map +1 -1
  39. package/dist/src/compiler/normalize-tool.d.ts +8 -0
  40. package/dist/src/compiler/normalize-tool.d.ts.map +1 -1
  41. package/dist/src/compiler/normalize-tool.js +13 -5
  42. package/dist/src/compiler/normalize-tool.js.map +1 -1
  43. package/dist/src/discover/discover-agent.d.ts +2 -2
  44. package/dist/src/discover/discover-agent.d.ts.map +1 -1
  45. package/dist/src/discover/discover-agent.js +15 -104
  46. package/dist/src/discover/discover-agent.js.map +1 -1
  47. package/dist/src/discover/discover-subagent.js +4 -4
  48. package/dist/src/discover/discover-subagent.js.map +1 -1
  49. package/dist/src/discover/grammar.d.ts +2 -53
  50. package/dist/src/discover/grammar.d.ts.map +1 -1
  51. package/dist/src/discover/grammar.js +4 -116
  52. package/dist/src/discover/grammar.js.map +1 -1
  53. package/dist/src/discover/lib.d.ts +3 -3
  54. package/dist/src/discover/lib.d.ts.map +1 -1
  55. package/dist/src/discover/lib.js +16 -64
  56. package/dist/src/discover/lib.js.map +1 -1
  57. package/dist/src/discover/manifest.d.ts +6 -2
  58. package/dist/src/discover/manifest.d.ts.map +1 -1
  59. package/dist/src/discover/manifest.js.map +1 -1
  60. package/dist/src/discover/named-source-directory.d.ts +99 -0
  61. package/dist/src/discover/named-source-directory.d.ts.map +1 -0
  62. package/dist/src/discover/named-source-directory.js +189 -0
  63. package/dist/src/discover/named-source-directory.js.map +1 -0
  64. package/dist/src/discover/schedules.d.ts +50 -0
  65. package/dist/src/discover/schedules.d.ts.map +1 -0
  66. package/dist/src/discover/schedules.js +119 -0
  67. package/dist/src/discover/schedules.js.map +1 -0
  68. package/dist/src/discover/system.d.ts +2 -2
  69. package/dist/src/discover/system.d.ts.map +1 -1
  70. package/dist/src/discover/system.js +16 -54
  71. package/dist/src/discover/system.js.map +1 -1
  72. package/dist/src/evals/cli/eval.js +3 -3
  73. package/dist/src/internal/application/package.js +1 -1
  74. package/dist/src/internal/authored-definition/core.d.ts +2 -1
  75. package/dist/src/internal/authored-definition/core.d.ts.map +1 -1
  76. package/dist/src/internal/authored-definition/core.js +9 -7
  77. package/dist/src/internal/authored-definition/core.js.map +1 -1
  78. package/dist/src/internal/nitro/routes/schedule-task.d.ts.map +1 -1
  79. package/dist/src/internal/nitro/routes/schedule-task.js +3 -2
  80. package/dist/src/internal/nitro/routes/schedule-task.js.map +1 -1
  81. package/dist/src/public/definitions/schedule.d.ts +18 -5
  82. package/dist/src/public/definitions/schedule.d.ts.map +1 -1
  83. package/dist/src/public/definitions/schedule.js +11 -2
  84. package/dist/src/public/definitions/schedule.js.map +1 -1
  85. package/dist/src/public/helpers/markdown.d.ts +11 -0
  86. package/dist/src/public/helpers/markdown.d.ts.map +1 -1
  87. package/dist/src/public/helpers/markdown.js +25 -1
  88. package/dist/src/public/helpers/markdown.js.map +1 -1
  89. package/dist/src/runtime/schedules/resolve-schedule.d.ts.map +1 -1
  90. package/dist/src/runtime/schedules/resolve-schedule.js +14 -9
  91. package/dist/src/runtime/schedules/resolve-schedule.js.map +1 -1
  92. package/dist/src/runtime/types.d.ts +8 -2
  93. package/dist/src/runtime/types.d.ts.map +1 -1
  94. package/package.json +2 -2
  95. package/dist/src/chunks/chunk-WKCLLJVA.js.map +0 -7
  96. package/dist/src/chunks/just-bash-GRSOFQHN.js.map +0 -7
  97. package/dist/src/compiled/.vendor-lock/owner.json +0 -1
  98. package/dist/src/discover/resource-tree.d.ts +0 -20
  99. package/dist/src/discover/resource-tree.d.ts.map +0 -1
  100. package/dist/src/discover/resource-tree.js +0 -44
  101. package/dist/src/discover/resource-tree.js.map +0 -1
  102. /package/dist/src/chunks/{chunk-LOV2DSY3.js.map → chunk-VUESBSNV.js.map} +0 -0
  103. /package/dist/src/chunks/{dev-authored-source-watcher-W2JT7UYC.js.map → dev-authored-source-watcher-6TM2MLOF.js.map} +0 -0
  104. /package/dist/src/chunks/{host-BU6WPO36.js.map → host-DABU6JKC.js.map} +0 -0
package/README.md CHANGED
@@ -103,12 +103,14 @@ export default defineAgent({
103
103
  ## Quick Start
104
104
 
105
105
  ```bash
106
- pnpm dlx experimental-ash@latest init my-agent
106
+ pnpm create experimental-ash-agent
107
107
  cd my-agent
108
108
  pnpm install
109
109
  pnpm dev
110
110
  ```
111
111
 
112
+ To create an agent in the current empty directory, run `pnpm create experimental-ash-agent .`.
113
+
112
114
  Useful commands:
113
115
 
114
116
  - `ash info` shows discovery results and compiled artifacts
@@ -20,7 +20,7 @@ Discovery answers: given an app root and agent root, what authored sources exist
20
20
  - `skills/` — flat markdown/module files, or packaged `skills/<name>/SKILL.md`
21
21
  - `sandbox/` — single folder. Optional `sandbox.<ext>` lifecycle module + `workspace/**` seed files.
22
22
  - `subagents/` — local subagent packages, recursively discovered
23
- - `schedules/` — each schedule is a directory containing `schedule.ts` (module definition with `cron` and `channel`) and `prompt.md` (prompt text)
23
+ - `schedules/` — single-file schedules (`<name>.ts` or `<name>.md`), recursively nested. Markdown form has frontmatter `cron:` plus the body as the prompt.
24
24
  - `lib/` — package-local helpers, not a runtime surface
25
25
 
26
26
  **Markdown sources** are read and lowered into definition objects during discovery. **Module sources** are preserved as `ModuleSourceRef` (`logicalPath`, `sourceId`, optional `exportName`) — never imported.
@@ -37,18 +37,33 @@ Discovery accumulates diagnostics instead of failing early. Partial results are
37
37
 
38
38
  ## Unified Slot Walker
39
39
 
40
- `channels/`, `hooks/`, and `tools/` all ride the unified
41
- `discoverNamedModuleDirectory` helper in `discover/grammar.ts`. It supports both
42
- flat (`tools/`) and recursive (`channels/`, `hooks/`) walks, plus per-segment
43
- validation (used by `channels/`, `hooks/`, `tools/`). Adding a new authored
44
- module slot typically means: register a directory name in `filesystem.ts`, add
45
- a slug validator in `grammar.ts`, call `discoverNamedModuleDirectory` from the
46
- parent discoverer.
47
-
48
- `schedules/` retains a bespoke `discoverScheduleSources` walker because each
49
- schedule is a directory containing `schedule.ts` plus `prompt.md`, which does
50
- not fit the flat-or-recursive "module-only" shape the unified helper expects.
51
- When the helper grows a markdown extension, `schedules/` collapses into it.
40
+ `channels/`, `hooks/`, `tools/`, `lib/`, `system/` (prompt layers), and
41
+ `schedules/` all ride the unified `discoverNamedSourceDirectory` helper in
42
+ `discover/named-source-directory.ts`. The helper supports:
43
+
44
+ - flat (`tools/`) or recursive (`channels/`, `hooks/`, `lib/`, `system/`,
45
+ `schedules/`) walks
46
+ - module-only or module-or-markdown leaves (with a `markdownLowerer` callback
47
+ that converts raw markdown into a typed definition)
48
+ - per-segment slug validation (`channels/`, `hooks/`, `tools/`)
49
+ - optional unsupported-leaf diagnostics for callers (`lib/`, `system/`,
50
+ `schedules/`) that want strict file-type checking; tools/channels/hooks
51
+ silently ignore stray non-module files
52
+
53
+ Adding a new authored slot typically means: register a directory name in
54
+ `filesystem.ts`, add a slug validator in `grammar.ts` (if needed), and call
55
+ `discoverNamedSourceDirectory` from the parent discoverer.
56
+
57
+ The remaining bespoke discoverers all have grammars that don't fit the unified
58
+ shape:
59
+
60
+ - `skills/` — triple form: `<name>.md`, `<name>.{ts,...}`, or
61
+ `<name>/SKILL.md` (packaged), with collision-by-`skillId`
62
+ - `connections/` — file-form vs folder-form duality with cross-form
63
+ collision detection
64
+ - `sandbox/` — singleton with workspace mount semantics
65
+ - `subagents/` — recursively builds whole sub-manifests, not leaves
66
+ - `evals/` — separate package, doesn't go through `ProjectSource`
52
67
 
53
68
  ## Extension Pattern
54
69
 
@@ -0,0 +1,95 @@
1
+ # Schedules
2
+
3
+ Schedules let an authored agent run on a cron cadence. The runtime owns the
4
+ dispatch contract; the channel layer (when present) owns delivery.
5
+
6
+ ## Authoring shape
7
+
8
+ Each schedule is a single file under `schedules/`:
9
+
10
+ - `schedules/<name>.{ts,cts,mts,js,cjs,mjs}` — TypeScript module with a default
11
+ export of `defineSchedule({ cron, markdown, channel? })`.
12
+ - `schedules/<name>.md` — markdown with frontmatter (`cron:`) and the body as
13
+ the prompt. The markdown form does not support a channel.
14
+
15
+ Recursive nesting is supported. The schedule name is derived from the relative
16
+ path under `schedules/` minus the file extension
17
+ (`schedules/billing/invoice-sweep.ts` → `"billing/invoice-sweep"`).
18
+
19
+ The legacy directory form (`<name>/schedule.ts` + `<name>/prompt.md`) is no
20
+ longer supported; discovery emits a clear migration diagnostic.
21
+
22
+ ## Discovery
23
+
24
+ `discoverScheduleSources` (`packages/ash/src/discover/schedules.ts`) delegates
25
+ to the unified `discoverNamedSourceDirectory` walker with
26
+ `allowMarkdown: true` and `markdownLowerer: lowerScheduleMarkdown`. Before the
27
+ walker runs, the schedule discoverer scans for legacy directory layouts and
28
+ emits a migration diagnostic for each one found, then directs the walker to
29
+ skip those subdirectories so the stale `prompt.md` never reaches the markdown
30
+ lowerer.
31
+
32
+ ## Compile
33
+
34
+ `compileScheduleDefinition` (`packages/ash/src/compiler/normalize-schedule.ts`)
35
+ hydrates each `ScheduleSourceRef` into a `CompiledScheduleDefinition`:
36
+
37
+ - TypeScript modules go through `loadModuleBackedDefinition` and
38
+ `normalizeScheduleDefinition` (rejects unknown keys).
39
+ - Markdown sources have already been lowered at discovery time; the compiler
40
+ re-runs `normalizeScheduleDefinition` for type safety.
41
+ - When `channel` is present, the compiler resolves the imported route to a
42
+ channel name through the `channelIdentityMap` built when channels were
43
+ loaded. Plain `{ name, args }` literals are accepted as a test-fixture
44
+ fallback.
45
+ - The compiled `markdown` field is `definition.markdown.trim()`.
46
+ - The schedule name is derived from the logical path
47
+ (`stripLogicalPathExtension(...).replace(/^schedules\//, "")`).
48
+
49
+ ## Runtime
50
+
51
+ `ScheduleDispatcher.trigger` (`packages/ash/src/channel/schedule.ts`) takes
52
+ two paths:
53
+
54
+ - **With a channel:** resolve the channel by name, call its `receive()` with
55
+ `{ message: markdown, args, auth: APP_AUTH }`. The channel handles delivery
56
+ through its normal code path.
57
+ - **Without a channel:** start a session via `runtime.run({...})` directly with
58
+ a minimal `{ kind: "schedule" }` adapter, `auth: APP_AUTH`, `mode: "task"`,
59
+ and the schedule's `markdown` as the seed message. Output is discarded; the
60
+ agent can still call tools, log, or hit backends.
61
+
62
+ Both branches use the framework app principal: `principalId: "ash:app"`,
63
+ `principalType: "runtime"`.
64
+
65
+ ## Why markdown form omits channel
66
+
67
+ A typed `receive(channel, args)` reference depends on importing the channel
68
+ module so the route's args type is in scope. Markdown frontmatter has no such
69
+ import boundary — args would have to be opaque `Record<string, unknown>`,
70
+ losing the type safety that makes `receive()` worth using. The simple,
71
+ type-safe answer is: if you need a channel, write a `.ts` schedule.
72
+
73
+ ## Nitro task wiring
74
+
75
+ Each compiled schedule produces a `ScheduleRegistration` whose `taskName` is
76
+ the base64url of its `sourceId`. `registerScheduleTaskHandlers` wires those
77
+ tasks into Nitro's `tasks` and `scheduledTasks` options via a synthetic
78
+ virtual handler module that imports `dispatchScheduleTask` and forwards the
79
+ event name plus a baked-in artifacts config.
80
+
81
+ ## Tests
82
+
83
+ - `src/channel/schedule.test.ts` — dispatcher behavior in both branches.
84
+ - `src/discover/agent.integration.test.ts` — discovery shapes including
85
+ recursive nesting, markdown form, .md/.ts collision, legacy migration
86
+ diagnostic, and unsupported leaves.
87
+ - `src/internal/nitro/host/schedule-task-routes.test.ts` — Nitro task
88
+ registration round-trip.
89
+ - `test/runtime-schedule-resolution.test.ts`, `test/runtime-schedule-registration.test.ts`
90
+ — runtime resolution and Nitro task registration with mixed module/markdown
91
+ schedules.
92
+ - `test/scenarios/compile-agent.scenario.test.ts` — end-to-end compile with
93
+ module + markdown schedules including the no-channel form.
94
+ - `test/scenarios/runtime-loaders.scenario.test.ts` — runtime artifact
95
+ loaders round-trip.
@@ -45,7 +45,7 @@ my-agent/
45
45
  | `lib/` | Shared authored helper code | Import-only source, not mounted into the workspace |
46
46
  | `sandbox/` or `sandbox.ts` | The agent's single sandbox. Use top-level `sandbox.ts` for a definition-only override; use `sandbox/sandbox.ts` + optional `sandbox/workspace/**` when you also want seeded files. Framework default applies when neither is authored. | Supported on the root agent and local subagents |
47
47
  | `tools/` | Typed executable integrations | Module-backed only |
48
- | `schedules/` | Recurring jobs; each schedule is a directory with `schedule.ts` + `prompt.md` | Root-only today |
48
+ | `schedules/` | Recurring jobs; each schedule is a single `<name>.ts` (with `defineSchedule({...})` as the default export) or `<name>.md` (frontmatter `cron:` plus the prompt as the body). Recursive nesting supported. | Root-only today |
49
49
  | `subagents/` | Specialist child agents | Each child is its own local package |
50
50
 
51
51
  ## Root Agent Example
@@ -78,9 +78,9 @@ agent/
78
78
  ├── tools/
79
79
  │ └── lookup-customer.ts
80
80
  ├── schedules/
81
- └── daily-digest/
82
- ├── schedule.ts
83
- │ └── prompt.md
81
+ ├── daily-digest.ts
82
+ └── billing/
83
+ │ └── invoice-sweep.md
84
84
  └── subagents/
85
85
  └── researcher/
86
86
  ├── agent.ts
@@ -101,7 +101,7 @@ overall session remains durable.
101
101
  Important behavior:
102
102
 
103
103
  - follow-up messages reuse the same session through the continuation token
104
- - schedules do not wait for follow-up HTTP messages
104
+ - schedules without a channel run in task mode and do not wait for follow-up messages; channel-targeted schedules inherit the channel's mode
105
105
  - delegated subagents publish progress on their own child-session stream
106
106
  - the parent session emits `subagent.called` with `childSessionId` so clients can attach to that
107
107
  child stream
@@ -1,135 +1,148 @@
1
1
  ---
2
2
  title: "Schedules"
3
- description: "Define recurring cron jobs that deliver messages through channels."
3
+ description: "Define recurring cron jobs that run an agent and optionally deliver the result through a channel."
4
4
  ---
5
5
 
6
- Schedules let an agent initiate recurring work -- digests, syncs, maintenance -- and deliver the results through a channel such as Slack.
6
+ Schedules let an agent initiate recurring work digests, syncs, maintenance, heartbeat checks — on a cron cadence. The agent can either deliver its output through a channel (e.g. Slack) or run fire-and-forget while calling tools, hitting backends, or writing logs.
7
7
 
8
8
  Schedules live under `schedules/` at the root agent package.
9
9
 
10
- ## Current Boundaries
10
+ ## Boundaries
11
11
 
12
- - schedules are root-only today
13
- - local subagents cannot declare `schedules/`
14
- - every schedule targets a channel
12
+ - schedules are root-only — local subagents cannot declare `schedules/`
13
+ - a schedule is a single file: `<name>.ts` or `<name>.md`
14
+ - the markdown form does not support targeting a channel — use the `.ts` form for that
15
+ - the channel argument is **optional**
15
16
 
16
- ## Directory Structure
17
+ ## Authoring shapes
17
18
 
18
- Each schedule is a directory containing `schedule.ts` and `prompt.md`:
19
+ ### TypeScript
19
20
 
20
- ```text
21
- agent/schedules/
22
- └── daily-digest/
23
- ├── schedule.ts
24
- └── prompt.md
25
- ```
26
-
27
- The schedule name is derived from the directory name (e.g. `schedules/daily-digest`).
21
+ ```ts
22
+ // agent/schedules/daily-digest.ts
23
+ import { defineSchedule, receive } from "experimental-ash/schedules";
28
24
 
29
- `prompt.md` contains the prompt text for the scheduled run:
25
+ import slack from "../channels/slack.js";
30
26
 
31
- ```md
32
- Summarize yesterday's activity and post the digest.
27
+ export default defineSchedule({
28
+ cron: "0 9 * * 1-5",
29
+ markdown: "Summarize yesterday's activity and post the digest.",
30
+ channel: receive(slack, { channelId: "C0123ABC" }),
31
+ });
33
32
  ```
34
33
 
35
- `schedule.ts` contains the schedule definition:
34
+ Without a channel — the agent runs and the output is discarded:
36
35
 
37
36
  ```ts
38
- import { defineSchedule } from "experimental-ash";
39
- import { slackReceive } from "experimental-ash/channels/slack";
37
+ // agent/schedules/heartbeat.ts
38
+ import { defineSchedule } from "experimental-ash/schedules";
40
39
 
41
40
  export default defineSchedule({
42
- cron: "0 9 * * 1-5",
43
- channel: slackReceive("slack", { channelId: "C0123ABC" }),
41
+ cron: "*/5 * * * *",
42
+ markdown: "Pull open Linear issues and POST a summary to the metrics endpoint.",
44
43
  });
45
44
  ```
46
45
 
47
- ## The `defineSchedule` API
46
+ ### Markdown
48
47
 
49
- `defineSchedule` accepts:
48
+ ```md
49
+ ## <!-- agent/schedules/cleanup.md -->
50
50
 
51
- - `cron` (required) -- a cron expression for when the schedule fires
52
- - `channel` (required) -- a channel reference that tells Ash where to deliver the message
51
+ ## cron: "0 0 \* \* 0"
53
52
 
54
- There is no `markdown` field. The prompt lives in the sibling `prompt.md` file.
53
+ Sweep stale workflow state.
54
+ ```
55
55
 
56
- ## Channel Targeting
56
+ The body is the prompt. The frontmatter accepts `cron` only — markdown-form schedules cannot reference a channel.
57
57
 
58
- Every schedule targets a channel. The channel reference is created using a typed receive helper exported from the channel's subpath:
58
+ ## Recursive nesting
59
59
 
60
- ```ts
61
- import { slackReceive } from "experimental-ash/channels/slack";
60
+ Schedules support nested directories. The schedule name is derived from the relative path under `schedules/` minus the file extension:
62
61
 
63
- slackReceive("slack", { channelId: "C0123ABC" });
62
+ ```text
63
+ agent/schedules/
64
+ ├── billing/
65
+ │ ├── invoice-sweep.ts → name "billing/invoice-sweep"
66
+ │ └── dunning/
67
+ │ └── retry.md → name "billing/dunning/retry"
68
+ └── daily-digest.ts → name "daily-digest"
64
69
  ```
65
70
 
66
- Each channel defines its own args shape. `slackReceive` takes a channel name and requires a `channelId`. Other channels define their own helpers (e.g. a hypothetical `emailReceive({ to })` or `discordReceive({ guildId, channelId })`).
71
+ ## `defineSchedule` API
67
72
 
68
- At compile time, Ash validates that the channel referenced by the schedule exists in `agent/channels/` and that the channel's route implements a `receive` method.
73
+ ```ts
74
+ interface ScheduleDefinition {
75
+ cron: string;
76
+ markdown: string;
77
+ channel?: ChannelReceiveRef<unknown>;
78
+ }
79
+ ```
69
80
 
70
- ## Runtime Behavior
81
+ - `cron` (required) — a cron expression for when the schedule fires
82
+ - `markdown` (required) — the prompt the agent receives when the schedule runs
83
+ - `channel` (optional) — a typed channel reference produced by `receive(channel, args)`
71
84
 
72
- When a schedule fires:
85
+ The `markdown` field is the prompt body — the same convention used by `defineSystem({ markdown })` and `defineSkill({ markdown })`.
73
86
 
74
- 1. The dispatcher loads the resolved schedule and finds the channel reference.
75
- 2. The dispatcher calls `route.receive()` on the targeted channel, passing the prompt from `prompt.md` and the channel-specific args.
76
- 3. The channel builds an adapter and starts a session, the same way it handles a webhook-initiated message.
77
- 4. The agent runs and delivers output through the channel.
87
+ ## Channel targeting
78
88
 
79
- Important behavior:
89
+ When a schedule should deliver its output through a channel, use the `receive(channel, args)` helper from `experimental-ash/schedules`:
80
90
 
81
- - the schedule id is derived from its directory path, for example `schedules/daily-digest`
82
- - the schedule session goes through the same durable runtime engine as other sessions
83
- - the channel determines the session mode: if the channel supports replies (e.g. Slack), the session runs in **conversation mode** and can receive follow-up messages; if the channel does not support replies, the session runs in task mode
84
- - when a Slack-targeted schedule runs, the agent's output is posted as a top-level message in the Slack channel; if someone replies in the thread, the conversation continues identically to a webhook-initiated session
91
+ ```ts
92
+ import { receive } from "experimental-ash/schedules";
93
+ import slack from "../channels/slack.js";
85
94
 
86
- ## Auth
95
+ receive(slack, { channelId: "C0123ABC" });
96
+ ```
87
97
 
88
- Schedule sessions use the app principal. `getSession().auth.current` and `getSession().auth.initiator` are both set to `"ash:app"` with `principalType: "service"`.
98
+ The `args` object's shape is inferred from the channel's typed receive route — Slack requires `channelId`; other channels define their own args shape. At compile time, Ash validates that the channel reference resolves to an authored channel under `agent/channels/` whose route implements a `receive()` method.
89
99
 
90
- ## Complete Example
100
+ ## Runtime behavior
91
101
 
92
- ```text
93
- agent/
94
- ├── channels/
95
- │ └── slack.ts
96
- └── schedules/
97
- └── daily-digest/
98
- ├── schedule.ts
99
- └── prompt.md
100
- ```
102
+ When a schedule fires, the dispatcher takes one of two paths:
101
103
 
102
- `agent/schedules/daily-digest/prompt.md`:
104
+ ### With a channel
103
105
 
104
- ```md
105
- Summarize yesterday's activity and post the digest.
106
- ```
106
+ 1. The dispatcher resolves the channel route by name.
107
+ 2. It calls `route.receive()` with the schedule's `markdown` and the channel-specific `args`.
108
+ 3. The channel builds its adapter, starts a session, and handles output delivery the same way it handles webhook-initiated messages.
107
109
 
108
- `agent/schedules/daily-digest/schedule.ts`:
110
+ ### Without a channel
109
111
 
110
- ```ts
111
- import { defineSchedule } from "experimental-ash";
112
- import { slackReceive } from "experimental-ash/channels/slack";
112
+ 1. The dispatcher starts a session through the runtime directly with a minimal scheduled-task adapter.
113
+ 2. The agent runs in **task mode** with the app principal.
114
+ 3. Output is discarded but the agent is still free to call tools, write to backends, log, etc.
113
115
 
114
- export default defineSchedule({
115
- cron: "0 9 * * 1-5",
116
- channel: slackReceive("slack", { channelId: "C0123ABC" }),
117
- });
116
+ In both cases, the schedule session uses the **app principal**: `getSession().auth.current` and `getSession().auth.initiator` are set to `"ash:app"` with `principalType: "runtime"`.
117
+
118
+ The session goes through the same durable runtime engine as any other Ash session.
119
+
120
+ ## Migrating from the legacy directory form
121
+
122
+ The directory form (`schedules/<name>/schedule.ts` + `schedules/<name>/prompt.md`) is no longer supported. To migrate, collapse each directory into a single file:
123
+
124
+ ```text
125
+ agent/schedules/daily-digest/schedule.ts → agent/schedules/daily-digest.ts
126
+ agent/schedules/daily-digest/prompt.md → inlined as `markdown:` on
127
+ the `defineSchedule({...})` call
118
128
  ```
119
129
 
120
- ## When To Use A Schedule
130
+ Discovery emits a clear migration diagnostic when it sees a legacy directory layout.
131
+
132
+ ## When to use a schedule
121
133
 
122
- Use a schedule when the agent should initiate work on its own cadence, such as:
134
+ Use a schedule when the agent should initiate work on its own cadence:
123
135
 
124
- - daily digests
125
- - data syncs
136
+ - daily digests delivered to Slack
137
+ - data syncs that hit a backend with no user-visible output
126
138
  - cleanup or maintenance tasks
127
- - automated checks or reports
139
+ - heartbeat checks
140
+ - automated reports
128
141
 
129
- If the workflow starts from an inbound user message, use the normal channel route instead.
142
+ If the workflow starts from an inbound user message, use a [channel](./channels/README.md) instead.
130
143
 
131
- ## What To Read Next
144
+ ## What to read next
132
145
 
133
- - [`channels/README.md`](./channels/README.md)
134
- - [`runs-and-streaming.md`](./runs-and-streaming.md)
135
- - [`session-context.md`](./session-context.md)
146
+ - [Channels](./channels/README.md)
147
+ - [Runs and streaming](./runs-and-streaming.md)
148
+ - [Session context](./session-context.md)
@@ -60,7 +60,7 @@ Important behavior:
60
60
  - `auth.current` is the caller for the active inbound turn
61
61
  - `auth.initiator` is the caller that started the durable session
62
62
  - unprotected agents expose both as `null`
63
- - top-level schedule sessions expose a framework-owned `schedule` principal
63
+ - top-level schedule sessions expose the framework app principal (`principalId: "ash:app"`, `principalType: "runtime"`)
64
64
  - `parent` is present for child subagent sessions
65
65
 
66
66
  ## `getSandbox()`
@@ -29,7 +29,7 @@ barrel for agent config, routes, schedules, and systems.
29
29
  - `defineHook(...)` - lifecycle and stream-event subscriber in `hooks/<slug>.ts` (`experimental-ash/hooks`)
30
30
  - `defineRoute(...)` - messaging-platform or HTTP route entrypoints in `channels/`
31
31
  - `defineSandbox(...)` - override the agent's single sandbox in `sandbox.ts` (or `sandbox/sandbox.ts` when paired with a `workspace/` folder) (`experimental-ash/sandbox`)
32
- - `defineSchedule(...)` - recurring jobs in `schedules/<name>/schedule.ts`; requires `cron` and `channel`
32
+ - `defineSchedule(...)` - recurring jobs in `schedules/<name>.ts` or `schedules/<name>.md`; requires `cron` and `markdown`, `channel` is optional (`experimental-ash/schedules`)
33
33
  - `defineSkill(...)` - module-authored skills (`experimental-ash/skills`)
34
34
  - `defineSystem(...)` - module-authored system prompt (`experimental-ash/system`)
35
35
  - `defineTool(...)` - typed executable integration in `tools/<name>.ts` (`experimental-ash/tools`)
@@ -89,7 +89,7 @@ Ash also exports helpers for turning markdown into the same shapes as module-aut
89
89
  - `parseMarkdownDocument(markdown)`
90
90
  - `lowerSystemMarkdown(markdown, options?)`
91
91
  - `lowerSkillMarkdown(markdown, options?)` — supports both packaged (`SKILL.md` with frontmatter) and flat (`<name>.md`) skill files; pass `options.name` for flat mode
92
- - `lowerScheduleMarkdown(markdown, options?)` — parses a schedule's `prompt.md` content
92
+ - `lowerScheduleMarkdown(markdown)` — parses a `schedules/<name>.md` file (frontmatter `cron:` plus the body as the prompt) into a `ScheduleDefinition`
93
93
 
94
94
  These are most useful if you are building higher-level authoring tools or tests around Ash's public
95
95
  shapes.
@@ -4,7 +4,14 @@ import type { RunHandle, Runtime } from "#channel/types.js";
4
4
  * Input for triggering a schedule run.
5
5
  */
6
6
  export interface ScheduleTriggerInput {
7
- readonly channel: {
7
+ /**
8
+ * Optional channel target. When present, the dispatcher resolves the
9
+ * channel route by name and calls its `receive()` method so the channel
10
+ * can deliver the agent's output. When absent, the agent runs with a
11
+ * minimal scheduled-task adapter and the output is discarded — the
12
+ * agent is still free to call tools, log, or hit backends.
13
+ */
14
+ readonly channel?: {
8
15
  readonly name: string;
9
16
  readonly args: Readonly<Record<string, unknown>>;
10
17
  };
@@ -14,10 +21,12 @@ export interface ScheduleTriggerInput {
14
21
  /**
15
22
  * Dispatcher for scheduled task execution.
16
23
  *
17
- * The dispatcher calls `route.receive()` on the target channel the
18
- * channel builds the adapter, starts the session, and handles output
19
- * delivery through its normal code path. The schedule is just another
20
- * message source.
24
+ * When the schedule targets a channel, the dispatcher hands the message
25
+ * off to `route.receive()` — the channel builds the adapter, starts the
26
+ * session, and handles output delivery through its normal code path. When
27
+ * the schedule has no channel, the dispatcher starts the session through
28
+ * the runtime directly with a minimal schedule adapter and discards the
29
+ * output.
21
30
  */
22
31
  export declare class ScheduleDispatcher {
23
32
  private readonly runtime;
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../src/channel/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAsB,MAAM,mBAAmB,CAAC;AAShF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KAClD,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IAEzE,YAAY,MAAM,EAAE;QAClB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;KAClE,EAGA;IAEK,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC,CAyB7D;CACF"}
1
+ {"version":3,"file":"schedule.d.ts","sourceRoot":"","sources":["../../../src/channel/schedule.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAsB,MAAM,mBAAmB,CAAC;AAShF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;KAClD,CAAC;IACF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0C;IAEzE,YAAY,MAAM,EAAE;QAClB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;KAClE,EAGA;IAEK,OAAO,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC,CAkC7D;CACF"}
@@ -7,10 +7,12 @@ const APP_AUTH = {
7
7
  /**
8
8
  * Dispatcher for scheduled task execution.
9
9
  *
10
- * The dispatcher calls `route.receive()` on the target channel the
11
- * channel builds the adapter, starts the session, and handles output
12
- * delivery through its normal code path. The schedule is just another
13
- * message source.
10
+ * When the schedule targets a channel, the dispatcher hands the message
11
+ * off to `route.receive()` — the channel builds the adapter, starts the
12
+ * session, and handles output delivery through its normal code path. When
13
+ * the schedule has no channel, the dispatcher starts the session through
14
+ * the runtime directly with a minimal schedule adapter and discards the
15
+ * output.
14
16
  */
15
17
  export class ScheduleDispatcher {
16
18
  runtime;
@@ -20,6 +22,14 @@ export class ScheduleDispatcher {
20
22
  this.resolveChannel = config.resolveChannel;
21
23
  }
22
24
  async trigger(input) {
25
+ if (input.channel === undefined) {
26
+ return await this.runtime.run({
27
+ adapter: { kind: "schedule" },
28
+ auth: APP_AUTH,
29
+ input: { message: input.markdown },
30
+ mode: "task",
31
+ });
32
+ }
23
33
  const { channel } = input;
24
34
  const route = await this.resolveChannel(channel.name);
25
35
  if (!route.receive) {
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../../src/channel/schedule.ts"],"names":[],"mappings":"AAGA,MAAM,QAAQ,GAAuB;IACnC,UAAU,EAAE,EAAE;IACd,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;CACzB,CAAC;AAcF;;;;;;;GAOG;AACH,MAAM,OAAO,kBAAkB;IACZ,OAAO,CAAU;IACjB,cAAc,CAA0C;IAEzE,YAAY,MAGX;QACC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA2B;QACvC,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAC1B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,UAAU,sBAAsB,OAAO,CAAC,IAAI,IAAI;gBACjE,gDAAgD,CACnD,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,GAAiB;YACjC,OAAO,EAAE,KAAK,CAAC,QAAQ;YACvB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,QAAQ;SACf,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE;YAC/C,KAAK,EAAE,IAAI,CAAC,OAAO;YACnB,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,UAAU,cAAc,OAAO,CAAC,IAAI,IAAI;gBACzD,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
1
+ {"version":3,"file":"schedule.js","sourceRoot":"","sources":["../../../src/channel/schedule.ts"],"names":[],"mappings":"AAGA,MAAM,QAAQ,GAAuB;IACnC,UAAU,EAAE,EAAE;IACd,aAAa,EAAE,KAAK;IACpB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;CACzB,CAAC;AAqBF;;;;;;;;;GASG;AACH,MAAM,OAAO,kBAAkB;IACZ,OAAO,CAAU;IACjB,cAAc,CAA0C;IAEzE,YAAY,MAGX;QACC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IAC9C,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAA2B;QACvC,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;gBAC5B,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE;gBAC7B,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE;gBAClC,IAAI,EAAE,MAAM;aACb,CAAC,CAAC;QACL,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAC1B,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,UAAU,sBAAsB,OAAO,CAAC,IAAI,IAAI;gBACjE,gDAAgD,CACnD,CAAC;QACJ,CAAC;QACD,MAAM,YAAY,GAAiB;YACjC,OAAO,EAAE,KAAK,CAAC,QAAQ;YACvB,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,IAAI,EAAE,QAAQ;SACf,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE;YAC/C,KAAK,EAAE,IAAI,CAAC,OAAO;YACnB,SAAS,EAAE,GAAG,EAAE,GAAE,CAAC;SACpB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CACb,aAAa,KAAK,CAAC,UAAU,cAAc,OAAO,CAAC,IAAI,IAAI;gBACzD,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"slack-render.d.ts","sourceRoot":"","sources":["../../../src/channel/slack-render.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAe,MAAM,MAAM,CAAC;AAYhE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAKpE,eAAO,MAAM,4BAA4B,kBAAkB,CAAC;AAC5D,eAAO,MAAM,0BAA0B,wBAAwB,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,sBAAsB,CAuFnF;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC;CACtC,GAAG,sBAAsB,CAczB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,GAAG,sBAAsB,CAazB"}
1
+ {"version":3,"file":"slack-render.d.ts","sourceRoot":"","sources":["../../../src/channel/slack-render.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAe,MAAM,MAAM,CAAC;AAYhE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAMpE,eAAO,MAAM,4BAA4B,kBAAkB,CAAC;AAC5D,eAAO,MAAM,0BAA0B,wBAAwB,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,sBAAsB,CAuFnF;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC;IACjC,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC;CACtC,GAAG,sBAAsB,CAczB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE;IAC5C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,GAAG,sBAAsB,CAazB"}
@@ -4,6 +4,7 @@
4
4
  import { Actions, Button, Card, CardText, LinkButton, RadioSelect, Select, SelectOption, } from "chat";
5
5
  const RADIO_SELECT_OPTION_LIMIT = 6;
6
6
  const SLACK_OPTION_DESCRIPTION_MAX_LENGTH = 150;
7
+ const SLACK_OPTION_LABEL_MAX_LENGTH = 150;
7
8
  export const FREEFORM_MODAL_ACTION_PREFIX = "ash_freeform_";
8
9
  export const FREEFORM_MODAL_CALLBACK_ID = "ash_freeform_submit";
9
10
  /**
@@ -38,7 +39,7 @@ export function buildInputRequestCard(request) {
38
39
  label: "Choose an option",
39
40
  options: request.options.map((opt) => SelectOption({
40
41
  description: truncateOptionDescription(opt.description),
41
- label: opt.label,
42
+ label: truncateOptionLabel(opt.label),
42
43
  value: opt.id,
43
44
  })),
44
45
  }),
@@ -57,7 +58,7 @@ export function buildInputRequestCard(request) {
57
58
  placeholder: "Choose an option",
58
59
  options: request.options.map((opt) => SelectOption({
59
60
  description: truncateOptionDescription(opt.description),
60
- label: opt.label,
61
+ label: truncateOptionLabel(opt.label),
61
62
  value: opt.id,
62
63
  })),
63
64
  }),
@@ -138,4 +139,10 @@ function truncateOptionDescription(description) {
138
139
  }
139
140
  return `${description.slice(0, SLACK_OPTION_DESCRIPTION_MAX_LENGTH - 3)}...`;
140
141
  }
142
+ function truncateOptionLabel(label) {
143
+ if (label.length <= SLACK_OPTION_LABEL_MAX_LENGTH) {
144
+ return label;
145
+ }
146
+ return `${label.slice(0, SLACK_OPTION_LABEL_MAX_LENGTH - 3)}...`;
147
+ }
141
148
  //# sourceMappingURL=slack-render.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slack-render.js","sourceRoot":"","sources":["../../../src/channel/slack-render.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-render.js","sourceRoot":"","sources":["../../../src/channel/slack-render.ts"],"names":[],"mappings":"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"}