@namzu/sdk 44.3.0 → 45.1.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 (271) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/dist/authorization/command-line.d.ts +66 -19
  3. package/dist/authorization/command-line.d.ts.map +1 -1
  4. package/dist/authorization/command-line.js +130 -270
  5. package/dist/authorization/command-line.js.map +1 -1
  6. package/dist/authorization/gate.d.ts +7 -0
  7. package/dist/authorization/gate.d.ts.map +1 -1
  8. package/dist/authorization/gate.js +13 -3
  9. package/dist/authorization/gate.js.map +1 -1
  10. package/dist/authorization/rules.d.ts +10 -1
  11. package/dist/authorization/rules.d.ts.map +1 -1
  12. package/dist/authorization/rules.js +55 -8
  13. package/dist/authorization/rules.js.map +1 -1
  14. package/dist/authorization/shell-lexer.d.ts +152 -0
  15. package/dist/authorization/shell-lexer.d.ts.map +1 -0
  16. package/dist/authorization/shell-lexer.js +2156 -0
  17. package/dist/authorization/shell-lexer.js.map +1 -0
  18. package/dist/authorization/skill-grant.d.ts +182 -0
  19. package/dist/authorization/skill-grant.d.ts.map +1 -0
  20. package/dist/authorization/skill-grant.js +314 -0
  21. package/dist/authorization/skill-grant.js.map +1 -0
  22. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  23. package/dist/bridge/a2a/mapper.js +2 -0
  24. package/dist/bridge/a2a/mapper.js.map +1 -1
  25. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  26. package/dist/bridge/sse/mapper.js +1 -0
  27. package/dist/bridge/sse/mapper.js.map +1 -1
  28. package/dist/directory/types.d.ts +2 -0
  29. package/dist/directory/types.d.ts.map +1 -1
  30. package/dist/directory/types.js.map +1 -1
  31. package/dist/manager/resident/outbox.d.ts +4 -4
  32. package/dist/persona/assembler.d.ts.map +1 -1
  33. package/dist/persona/assembler.js +5 -2
  34. package/dist/persona/assembler.js.map +1 -1
  35. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  36. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  37. package/dist/prompt/coding-agent-doctrine.js +1 -0
  38. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  39. package/dist/public-runtime.d.ts +5 -1
  40. package/dist/public-runtime.d.ts.map +1 -1
  41. package/dist/public-runtime.js +15 -1
  42. package/dist/public-runtime.js.map +1 -1
  43. package/dist/public-tools.d.ts +4 -0
  44. package/dist/public-tools.d.ts.map +1 -1
  45. package/dist/public-tools.js +12 -1
  46. package/dist/public-tools.js.map +1 -1
  47. package/dist/public-types.d.ts +9 -1
  48. package/dist/public-types.d.ts.map +1 -1
  49. package/dist/runtime/jobs/registry.d.ts +2 -2
  50. package/dist/runtime/jobs/registry.d.ts.map +1 -1
  51. package/dist/runtime/jobs/registry.js +6 -2
  52. package/dist/runtime/jobs/registry.js.map +1 -1
  53. package/dist/runtime/query/declined.d.ts +12 -0
  54. package/dist/runtime/query/declined.d.ts.map +1 -0
  55. package/dist/runtime/query/declined.js +12 -0
  56. package/dist/runtime/query/declined.js.map +1 -0
  57. package/dist/runtime/query/executor.d.ts +36 -40
  58. package/dist/runtime/query/executor.d.ts.map +1 -1
  59. package/dist/runtime/query/executor.js +95 -53
  60. package/dist/runtime/query/executor.js.map +1 -1
  61. package/dist/runtime/query/index.d.ts.map +1 -1
  62. package/dist/runtime/query/index.js +8 -0
  63. package/dist/runtime/query/index.js.map +1 -1
  64. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  65. package/dist/runtime/query/iteration/index.js +13 -0
  66. package/dist/runtime/query/iteration/index.js.map +1 -1
  67. package/dist/runtime/query/iteration/phases/context.d.ts +13 -0
  68. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  69. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  70. package/dist/runtime/query/iteration/phases/handoff.d.ts +22 -0
  71. package/dist/runtime/query/iteration/phases/handoff.d.ts.map +1 -0
  72. package/dist/runtime/query/iteration/phases/handoff.js +65 -0
  73. package/dist/runtime/query/iteration/phases/handoff.js.map +1 -0
  74. package/dist/runtime/query/iteration/phases/index.d.ts +1 -0
  75. package/dist/runtime/query/iteration/phases/index.d.ts.map +1 -1
  76. package/dist/runtime/query/iteration/phases/index.js +1 -0
  77. package/dist/runtime/query/iteration/phases/index.js.map +1 -1
  78. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  79. package/dist/runtime/query/iteration/phases/tool-review.js +56 -3
  80. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  81. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  82. package/dist/runtime/query/resume-pending.js +3 -2
  83. package/dist/runtime/query/resume-pending.js.map +1 -1
  84. package/dist/runtime/query/review-policy.d.ts +11 -0
  85. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  86. package/dist/runtime/query/review-policy.js +36 -3
  87. package/dist/runtime/query/review-policy.js.map +1 -1
  88. package/dist/runtime/query/tooling.d.ts +3 -0
  89. package/dist/runtime/query/tooling.d.ts.map +1 -1
  90. package/dist/runtime/query/tooling.js +1 -0
  91. package/dist/runtime/query/tooling.js.map +1 -1
  92. package/dist/schedules/cron.d.ts +21 -0
  93. package/dist/schedules/cron.d.ts.map +1 -0
  94. package/dist/schedules/cron.js +167 -0
  95. package/dist/schedules/cron.js.map +1 -0
  96. package/dist/schedules/describe.d.ts +14 -0
  97. package/dist/schedules/describe.d.ts.map +1 -0
  98. package/dist/schedules/describe.js +133 -0
  99. package/dist/schedules/describe.js.map +1 -0
  100. package/dist/schedules/errors.d.ts +11 -0
  101. package/dist/schedules/errors.d.ts.map +1 -0
  102. package/dist/schedules/errors.js +15 -0
  103. package/dist/schedules/errors.js.map +1 -0
  104. package/dist/schedules/evaluate.d.ts +35 -0
  105. package/dist/schedules/evaluate.d.ts.map +1 -0
  106. package/dist/schedules/evaluate.js +158 -0
  107. package/dist/schedules/evaluate.js.map +1 -0
  108. package/dist/schedules/index.d.ts +11 -0
  109. package/dist/schedules/index.d.ts.map +1 -0
  110. package/dist/schedules/index.js +8 -0
  111. package/dist/schedules/index.js.map +1 -0
  112. package/dist/schedules/next-fire.d.ts +50 -0
  113. package/dist/schedules/next-fire.d.ts.map +1 -0
  114. package/dist/schedules/next-fire.js +250 -0
  115. package/dist/schedules/next-fire.js.map +1 -0
  116. package/dist/schedules/spec.d.ts +30 -0
  117. package/dist/schedules/spec.d.ts.map +1 -0
  118. package/dist/schedules/spec.js +169 -0
  119. package/dist/schedules/spec.js.map +1 -0
  120. package/dist/schedules/types.d.ts +144 -0
  121. package/dist/schedules/types.d.ts.map +1 -0
  122. package/dist/schedules/types.js +11 -0
  123. package/dist/schedules/types.js.map +1 -0
  124. package/dist/schedules/tz.d.ts +44 -0
  125. package/dist/schedules/tz.d.ts.map +1 -0
  126. package/dist/schedules/tz.js +141 -0
  127. package/dist/schedules/tz.js.map +1 -0
  128. package/dist/skills/index.d.ts +1 -1
  129. package/dist/skills/index.d.ts.map +1 -1
  130. package/dist/skills/index.js +1 -1
  131. package/dist/skills/index.js.map +1 -1
  132. package/dist/skills/loader.d.ts +21 -0
  133. package/dist/skills/loader.d.ts.map +1 -1
  134. package/dist/skills/loader.js +51 -1
  135. package/dist/skills/loader.js.map +1 -1
  136. package/dist/tools/builtins/bash.d.ts.map +1 -1
  137. package/dist/tools/builtins/bash.js +18 -6
  138. package/dist/tools/builtins/bash.js.map +1 -1
  139. package/dist/tools/builtins/browser-url.d.ts +83 -0
  140. package/dist/tools/builtins/browser-url.d.ts.map +1 -0
  141. package/dist/tools/builtins/browser-url.js +240 -0
  142. package/dist/tools/builtins/browser-url.js.map +1 -0
  143. package/dist/tools/builtins/browser.d.ts +367 -0
  144. package/dist/tools/builtins/browser.d.ts.map +1 -0
  145. package/dist/tools/builtins/browser.js +704 -0
  146. package/dist/tools/builtins/browser.js.map +1 -0
  147. package/dist/tools/builtins/skill.d.ts +2 -9
  148. package/dist/tools/builtins/skill.d.ts.map +1 -1
  149. package/dist/tools/builtins/skill.js +74 -51
  150. package/dist/tools/builtins/skill.js.map +1 -1
  151. package/dist/tools/command-shell.d.ts +90 -0
  152. package/dist/tools/command-shell.d.ts.map +1 -0
  153. package/dist/tools/command-shell.js +129 -0
  154. package/dist/tools/command-shell.js.map +1 -0
  155. package/dist/tools/defineTool.d.ts +13 -0
  156. package/dist/tools/defineTool.d.ts.map +1 -1
  157. package/dist/tools/defineTool.js +30 -1
  158. package/dist/tools/defineTool.js.map +1 -1
  159. package/dist/tools/schedules/index.d.ts +5 -0
  160. package/dist/tools/schedules/index.d.ts.map +1 -0
  161. package/dist/tools/schedules/index.js +4 -0
  162. package/dist/tools/schedules/index.js.map +1 -0
  163. package/dist/tools/schedules/loop-tool.d.ts +14 -0
  164. package/dist/tools/schedules/loop-tool.d.ts.map +1 -0
  165. package/dist/tools/schedules/loop-tool.js +81 -0
  166. package/dist/tools/schedules/loop-tool.js.map +1 -0
  167. package/dist/tools/schedules/present.d.ts +16 -0
  168. package/dist/tools/schedules/present.d.ts.map +1 -0
  169. package/dist/tools/schedules/present.js +69 -0
  170. package/dist/tools/schedules/present.js.map +1 -0
  171. package/dist/tools/schedules/prompt-scan.d.ts +17 -0
  172. package/dist/tools/schedules/prompt-scan.d.ts.map +1 -0
  173. package/dist/tools/schedules/prompt-scan.js +92 -0
  174. package/dist/tools/schedules/prompt-scan.js.map +1 -0
  175. package/dist/tools/schedules/schedule-tool.d.ts +16 -0
  176. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -0
  177. package/dist/tools/schedules/schedule-tool.js +327 -0
  178. package/dist/tools/schedules/schedule-tool.js.map +1 -0
  179. package/dist/tools/schedules/types.d.ts +184 -0
  180. package/dist/tools/schedules/types.d.ts.map +1 -0
  181. package/dist/tools/schedules/types.js +11 -0
  182. package/dist/tools/schedules/types.js.map +1 -0
  183. package/dist/types/authorization/index.d.ts +86 -9
  184. package/dist/types/authorization/index.d.ts.map +1 -1
  185. package/dist/types/authorization/index.js +11 -1
  186. package/dist/types/authorization/index.js.map +1 -1
  187. package/dist/types/browser/index.d.ts +280 -0
  188. package/dist/types/browser/index.d.ts.map +1 -0
  189. package/dist/types/browser/index.js +12 -0
  190. package/dist/types/browser/index.js.map +1 -0
  191. package/dist/types/hitl/index.d.ts +23 -0
  192. package/dist/types/hitl/index.d.ts.map +1 -1
  193. package/dist/types/hitl/index.js.map +1 -1
  194. package/dist/types/session/events.d.ts +6 -0
  195. package/dist/types/session/events.d.ts.map +1 -1
  196. package/dist/types/session/events.js.map +1 -1
  197. package/dist/types/session/records.d.ts +23 -0
  198. package/dist/types/session/records.d.ts.map +1 -1
  199. package/dist/types/session/records.js +9 -0
  200. package/dist/types/session/records.js.map +1 -1
  201. package/dist/types/tool/index.d.ts +108 -5
  202. package/dist/types/tool/index.d.ts.map +1 -1
  203. package/dist/types/tool/index.js.map +1 -1
  204. package/dist/types/tool/presentation.d.ts +7 -0
  205. package/dist/types/tool/presentation.d.ts.map +1 -1
  206. package/dist/utils/frontmatter.d.ts +35 -3
  207. package/dist/utils/frontmatter.d.ts.map +1 -1
  208. package/dist/utils/frontmatter.js +45 -5
  209. package/dist/utils/frontmatter.js.map +1 -1
  210. package/dist/utils/id.d.ts +8 -0
  211. package/dist/utils/id.d.ts.map +1 -1
  212. package/dist/utils/id.js +12 -0
  213. package/dist/utils/id.js.map +1 -1
  214. package/package.json +1 -1
  215. package/src/authorization/command-line.ts +148 -293
  216. package/src/authorization/gate.ts +22 -2
  217. package/src/authorization/rules.ts +67 -8
  218. package/src/authorization/shell-lexer.ts +2349 -0
  219. package/src/authorization/skill-grant.ts +400 -0
  220. package/src/bridge/a2a/mapper.ts +2 -0
  221. package/src/bridge/sse/mapper.ts +1 -0
  222. package/src/directory/types.ts +2 -0
  223. package/src/persona/assembler.ts +5 -2
  224. package/src/prompt/coding-agent-doctrine.ts +1 -0
  225. package/src/public-runtime.ts +37 -0
  226. package/src/public-tools.ts +37 -1
  227. package/src/public-types.ts +57 -0
  228. package/src/runtime/jobs/registry.ts +19 -11
  229. package/src/runtime/query/declined.ts +12 -0
  230. package/src/runtime/query/executor.ts +116 -56
  231. package/src/runtime/query/index.ts +8 -0
  232. package/src/runtime/query/iteration/index.ts +13 -0
  233. package/src/runtime/query/iteration/phases/context.ts +13 -0
  234. package/src/runtime/query/iteration/phases/handoff.ts +74 -0
  235. package/src/runtime/query/iteration/phases/index.ts +1 -0
  236. package/src/runtime/query/iteration/phases/tool-review.ts +55 -3
  237. package/src/runtime/query/resume-pending.ts +3 -2
  238. package/src/runtime/query/review-policy.ts +57 -3
  239. package/src/runtime/query/tooling.ts +4 -0
  240. package/src/schedules/cron.ts +202 -0
  241. package/src/schedules/describe.ts +138 -0
  242. package/src/schedules/errors.ts +15 -0
  243. package/src/schedules/evaluate.ts +178 -0
  244. package/src/schedules/index.ts +18 -0
  245. package/src/schedules/next-fire.ts +257 -0
  246. package/src/schedules/spec.ts +210 -0
  247. package/src/schedules/types.ts +163 -0
  248. package/src/schedules/tz.ts +155 -0
  249. package/src/skills/index.ts +1 -1
  250. package/src/skills/loader.ts +59 -1
  251. package/src/tools/builtins/bash.ts +24 -6
  252. package/src/tools/builtins/browser-url.ts +251 -0
  253. package/src/tools/builtins/browser.ts +817 -0
  254. package/src/tools/builtins/skill.ts +92 -53
  255. package/src/tools/command-shell.ts +166 -0
  256. package/src/tools/defineTool.ts +36 -1
  257. package/src/tools/schedules/index.ts +4 -0
  258. package/src/tools/schedules/loop-tool.ts +85 -0
  259. package/src/tools/schedules/present.ts +86 -0
  260. package/src/tools/schedules/prompt-scan.ts +96 -0
  261. package/src/tools/schedules/schedule-tool.ts +376 -0
  262. package/src/tools/schedules/types.ts +197 -0
  263. package/src/types/authorization/index.ts +60 -2
  264. package/src/types/browser/index.ts +341 -0
  265. package/src/types/hitl/index.ts +21 -0
  266. package/src/types/session/events.ts +6 -0
  267. package/src/types/session/records.ts +10 -0
  268. package/src/types/tool/index.ts +109 -5
  269. package/src/types/tool/presentation.ts +7 -0
  270. package/src/utils/frontmatter.ts +81 -5
  271. package/src/utils/id.ts +14 -0
@@ -0,0 +1,400 @@
1
+ /**
2
+ * A skill's `allowed-tools`, as what it is everywhere else: a pre-approval.
3
+ *
4
+ * The field comes from the Agent Skills format, and the runtime that made it
5
+ * popular documents it plainly: the listed tools may be used without asking
6
+ * for the rest of the turn that loaded the skill, and "it does not restrict
7
+ * which tools are available: every tool remains callable, and your permission
8
+ * settings still govern tools that are not listed."
9
+ *
10
+ * This kernel read it the other way round, as a RESTRICTION. A skill written
11
+ * for that ecosystem says `allowed-tools: Read Grep` to mean "these two are
12
+ * fine without a prompt", and a turn that loaded it here lost `bash` on its
13
+ * next batch and was told to "restrict yourself to" two tools — so the model
14
+ * stopped doing the work and tried to do everything through whatever the
15
+ * skill described. The field was never meant to take anything away.
16
+ *
17
+ * What it grants, and what it does not:
18
+ *
19
+ * - **Grants**: a call that matches an entry skips the approval PROMPT for the
20
+ * rest of the turn, on the same footing as a person answering "allow" for
21
+ * the turn. The turn ends, the grant ends; loading the skill again in a
22
+ * later turn grants again.
23
+ * - **Never overrides**: an operator `deny` rule, an operator `ask` rule, plan
24
+ * mode, `strict` mode, an escalation (a path argument outside the working
25
+ * directory, a sandbox escape), or a call the tool itself declares
26
+ * destructive. Those are all statements by the operator or the tool; a
27
+ * skill is repository content and cannot outrank either. `bash` has no path
28
+ * argument, so a pattern entry refuses output redirection itself (see
29
+ * `coveringSkill`); a whole-tool `Bash` entry grants what any line does.
30
+ * - **Ends early**: when the operator sends another message into the running
31
+ * turn, the iteration clears the set.
32
+ * - **Never adds a tool**: an entry names a tool this turn already has, or it
33
+ * is ignored and the model is told so. An unknown name widens nothing.
34
+ *
35
+ * Granting is equivalent to the operator trusting that skill's commands,
36
+ * which is why only a skill the host chose to load can grant anything; see
37
+ * `docs/` for the CLI's folder-trust story.
38
+ */
39
+
40
+ import { MAX_CUSTOM_PATTERN_LENGTH } from '../constants/authorization/index.js'
41
+ import type { ToolDefinition } from '../types/tool/index.js'
42
+ import { writesThroughRedirection } from './command-line.js'
43
+ import { evaluateRule } from './rules.js'
44
+ import type { ShellDialect } from './shell-lexer.js'
45
+
46
+ /**
47
+ * Split an `allowed-tools` value into entries.
48
+ *
49
+ * Accepts every spelling the format uses: space-separated (`Read Grep Bash`),
50
+ * comma-separated (`Read, Grep`), and — once the frontmatter reader has turned
51
+ * a YAML list into one line — the items of a list. Separators inside
52
+ * parentheses belong to the entry, so `Bash(git add *)` stays one entry.
53
+ *
54
+ * `undefined` means the skill declared nothing. An empty array means it
55
+ * declared the field empty. Neither grants anything, and neither restricts
56
+ * anything, so the distinction survives only for a host that wants to show
57
+ * what the author wrote.
58
+ */
59
+ export function parseAllowedTools(declared: string | undefined): readonly string[] | undefined {
60
+ if (declared === undefined) return undefined
61
+ const entries: string[] = []
62
+ let current = ''
63
+ let depth = 0
64
+ const flush = () => {
65
+ const entry = current.trim()
66
+ if (entry.length > 0) entries.push(entry)
67
+ current = ''
68
+ }
69
+ for (const char of declared) {
70
+ if (char === '(') depth += 1
71
+ if (char === ')' && depth > 0) depth -= 1
72
+ if (depth === 0 && (char === ',' || /\s/.test(char))) {
73
+ flush()
74
+ continue
75
+ }
76
+ current += char
77
+ }
78
+ flush()
79
+ return entries
80
+ }
81
+
82
+ /**
83
+ * The tool names the Agent Skills ecosystem writes, and what they are here.
84
+ *
85
+ * Keyed lower-case: names are matched without regard to case, because a skill
86
+ * author writes `Read` and this kernel's tool is `read`, and a grant lost to
87
+ * capitalisation is a prompt nobody can explain.
88
+ */
89
+ export const SKILL_TOOL_NAME_ALIASES: Readonly<Record<string, string>> = Object.freeze({
90
+ read: 'read',
91
+ write: 'write',
92
+ edit: 'edit',
93
+ multiedit: 'edit',
94
+ bash: 'bash',
95
+ grep: 'grep',
96
+ glob: 'glob',
97
+ ls: 'ls',
98
+ webfetch: 'web_fetch',
99
+ websearch: 'web_search',
100
+ skill: 'skill',
101
+ askuserquestion: 'ask_user_question',
102
+ task: 'create_task',
103
+ agent: 'create_task',
104
+ lsp: 'lsp',
105
+ toolsearch: 'search_tools',
106
+ // A background shell's output and its termination are one tool here,
107
+ // `job`, whatever the ecosystem's release called them. Granting `job`
108
+ // for `BashOutput` does not grant a kill without review: `job` declares
109
+ // `kill` destructive, and a destructive call is never skill-approved.
110
+ bashoutput: 'job',
111
+ taskoutput: 'job',
112
+ killshell: 'job',
113
+ killbash: 'job',
114
+ taskstop: 'job',
115
+ taskcreate: 'task_create',
116
+ taskupdate: 'task_update',
117
+ tasklist: 'task_list',
118
+ })
119
+
120
+ /**
121
+ * How a grant compiler learns what a name means in this turn: the registered
122
+ * tool a name refers to, or `undefined` for one this turn does not have.
123
+ * `commandArgument` is what lets a `Bash(<pattern>)` entry be matched against
124
+ * the command line rather than the serialised input.
125
+ */
126
+ export type SkillGrantToolResolver = (name: string) =>
127
+ | {
128
+ readonly name: string
129
+ readonly commandArgument?: string
130
+ /**
131
+ * Every call of this tool is destructive, whatever its input (the
132
+ * shipped `write` and `run_code`). A destructive call is always
133
+ * reviewed, so an entry naming such a tool can grant nothing and is
134
+ * reported as ignored rather than listed as pre-approved.
135
+ */
136
+ readonly alwaysDestructive?: boolean
137
+ /**
138
+ * The tool is registered but withheld from this turn or step by
139
+ * `allowedTools`. The model cannot call it, so an entry naming it is
140
+ * reported as ignored rather than listed as pre-approved.
141
+ */
142
+ readonly unavailable?: boolean
143
+ }
144
+ | undefined
145
+
146
+ /** One compiled entry: a whole tool, or one tool's command line matching a pattern. */
147
+ export interface SkillGrantEntry {
148
+ /** The registered tool name. */
149
+ readonly tool: string
150
+ /** Present for a pattern entry: the argument holding the command line. */
151
+ readonly argument?: string
152
+ /** Present for a pattern entry: an anchored regular-expression source. */
153
+ readonly pattern?: string
154
+ /** The entry as the author wrote it, for messages. */
155
+ readonly declared: string
156
+ }
157
+
158
+ export interface CompiledSkillGrant {
159
+ readonly entries: readonly SkillGrantEntry[]
160
+ /** Entries that granted nothing, with the reason, for the model and the log. */
161
+ readonly ignored: readonly {
162
+ readonly entry: string
163
+ readonly reason: string
164
+ }[]
165
+ }
166
+
167
+ /** The two placeholders a pattern may use for the skill's own directory. */
168
+ const SKILL_DIR_PLACEHOLDERS = ['${CLAUDE_SKILL_DIR}', '${NAMZU_SKILL_DIR}'] as const
169
+
170
+ const ENTRY_SHAPE = /^([A-Za-z0-9_.\-]+)(?:\(([\s\S]*)\))?$/
171
+
172
+ /**
173
+ * Turn a permission glob into an anchored regular-expression source.
174
+ *
175
+ * The one glob dialect for command permissions, shared with the CLI's
176
+ * `[permissions]` table so that `Bash(git status *)` in a skill and
177
+ * `bash = { "git status *" = "allow" }` in config mean the same commands:
178
+ *
179
+ * - `*` matches any run of characters, `?` exactly one, everything else is
180
+ * literal;
181
+ * - backslashes become forward slashes, so one pattern works on every platform;
182
+ * - a pattern ending in `<space>*` also matches the bare command, so
183
+ * `git status *` covers `git status` as well as `git status -s`, and does
184
+ * not cover `git statusx`.
185
+ */
186
+ export function permissionPatternToRegExpSource(pattern: string): string {
187
+ const normalized = pattern.replaceAll('\\', '/')
188
+ const escaped = normalized
189
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
190
+ .replace(/\*/g, '.*')
191
+ .replace(/\?/g, '.')
192
+ const trailingSpaceStar = escaped.endsWith(' .*') ? `${escaped.slice(0, -3)}( .*)?` : escaped
193
+ return `^${trailingSpaceStar}$`
194
+ }
195
+
196
+ /**
197
+ * Compile a skill's parsed `allowed-tools` into grant entries.
198
+ *
199
+ * Pure: the resolver supplies everything the turn knows. An entry that cannot
200
+ * be honoured exactly is ignored and reported, never approximated — the only
201
+ * safe approximation of a permission is a narrower one, and "ignored" is the
202
+ * narrowest.
203
+ */
204
+ export function compileSkillGrant(
205
+ declared: readonly string[],
206
+ options: {
207
+ readonly resolveTool: SkillGrantToolResolver
208
+ /** The skill's directory, for `${CLAUDE_SKILL_DIR}` / `${NAMZU_SKILL_DIR}`. */
209
+ readonly skillDirectory?: string
210
+ },
211
+ ): CompiledSkillGrant {
212
+ const entries: SkillGrantEntry[] = []
213
+ const ignored: { entry: string; reason: string }[] = []
214
+
215
+ for (const entry of declared) {
216
+ const shape = ENTRY_SHAPE.exec(entry)
217
+ if (!shape) {
218
+ ignored.push({ entry, reason: 'not a tool name or `Tool(pattern)`' })
219
+ continue
220
+ }
221
+ const written = shape[1] ?? ''
222
+ const specifier = shape[2]?.trim()
223
+ const alias = SKILL_TOOL_NAME_ALIASES[written.toLowerCase()]
224
+ const tool = options.resolveTool(alias ?? written)
225
+ if (!tool) {
226
+ ignored.push({ entry, reason: 'this turn has no tool by that name' })
227
+ continue
228
+ }
229
+ if (tool.unavailable) {
230
+ ignored.push({
231
+ entry,
232
+ reason: `\`${tool.name}\` is not available in this turn, so nothing was granted for it`,
233
+ })
234
+ continue
235
+ }
236
+ if (tool.alwaysDestructive) {
237
+ ignored.push({
238
+ entry,
239
+ reason: `every \`${tool.name}\` call is destructive and is always reviewed, so nothing was granted for it`,
240
+ })
241
+ continue
242
+ }
243
+
244
+ if (specifier === undefined || specifier === '' || specifier.replaceAll('*', '') === '') {
245
+ entries.push({ tool: tool.name, declared: entry })
246
+ continue
247
+ }
248
+
249
+ if (tool.commandArgument === undefined) {
250
+ ignored.push({
251
+ entry,
252
+ reason: `a pattern is honoured only for a tool that takes a command line, and \`${tool.name}\` does not; nothing was granted for it`,
253
+ })
254
+ continue
255
+ }
256
+
257
+ let pattern = specifier
258
+ // The legacy prefix spelling `npm run test:*` means `npm run test *`.
259
+ if (pattern.endsWith(':*')) pattern = `${pattern.slice(0, -2)} *`
260
+ if (SKILL_DIR_PLACEHOLDERS.some((placeholder) => pattern.includes(placeholder))) {
261
+ if (!options.skillDirectory) {
262
+ ignored.push({
263
+ entry,
264
+ reason: "the skill's directory is not known in this turn",
265
+ })
266
+ continue
267
+ }
268
+ for (const placeholder of SKILL_DIR_PLACEHOLDERS) {
269
+ pattern = pattern.replaceAll(placeholder, options.skillDirectory)
270
+ }
271
+ }
272
+ const source = permissionPatternToRegExpSource(pattern)
273
+ if (source.length > MAX_CUSTOM_PATTERN_LENGTH) {
274
+ ignored.push({ entry, reason: 'the pattern is too long to evaluate' })
275
+ continue
276
+ }
277
+ entries.push({
278
+ tool: tool.name,
279
+ argument: tool.commandArgument,
280
+ pattern: source,
281
+ declared: entry,
282
+ })
283
+ }
284
+
285
+ return { entries, ignored }
286
+ }
287
+
288
+ interface HeldGrant {
289
+ readonly skill: string
290
+ readonly entry: SkillGrantEntry
291
+ readonly compiled?: RegExp
292
+ readonly names: Set<string>
293
+ }
294
+
295
+ /**
296
+ * The skill grants in force for one turn.
297
+ *
298
+ * Turn-scoped for the reason `ToolGrantSet` is: a grant is a statement about
299
+ * this turn's work. It is created with the turn and dropped with it, so it
300
+ * never reaches the next message, and a delegated child — which runs its own
301
+ * turn — starts with an empty one of its own rather than its parent's.
302
+ */
303
+ export class SkillGrantSet {
304
+ private readonly held: HeldGrant[] = []
305
+
306
+ /** Record a skill's compiled entries. Loading the same skill twice is harmless. */
307
+ grant(skill: string, compiled: CompiledSkillGrant): void {
308
+ for (const entry of compiled.entries) {
309
+ const duplicate = this.held.some(
310
+ (held) =>
311
+ held.skill === skill &&
312
+ held.entry.tool === entry.tool &&
313
+ held.entry.argument === entry.argument &&
314
+ held.entry.pattern === entry.pattern,
315
+ )
316
+ if (duplicate) continue
317
+ this.held.push({
318
+ skill,
319
+ entry,
320
+ ...(entry.pattern !== undefined ? { compiled: new RegExp(entry.pattern) } : {}),
321
+ names: new Set([entry.tool]),
322
+ })
323
+ }
324
+ }
325
+
326
+ /**
327
+ * The skill whose grant covers this call, or `undefined`.
328
+ *
329
+ * A pattern entry is matched the way an operator's `allow` pattern is: per
330
+ * command, every command in the line must match, and a line the reader
331
+ * cannot see through (a substitution, `eval`, a line that does not parse)
332
+ * matches nothing. So
333
+ * `Bash(git status *)` covers `git status -s` and not
334
+ * `git status && git push`.
335
+ *
336
+ * A pattern entry also never covers a line that redirects output into a
337
+ * file (`git status > ~/.bashrc`). The pattern names a command; where its
338
+ * output lands is not part of that command, and the shell's redirection
339
+ * writes wherever the line says without the tool reporting a path.
340
+ * `/dev/null` and descriptor duplication (`2>&1`) are not writes and stay
341
+ * covered. A whole-tool entry (`Bash`) grants the tool as it is, which
342
+ * includes redirection.
343
+ */
344
+ coveringSkill(
345
+ call: { readonly name: string; readonly input: unknown },
346
+ toolDef?: ToolDefinition,
347
+ options: { readonly commandDialect?: ShellDialect } = {},
348
+ ): string | undefined {
349
+ // Read the line for the shell that will run it; unknown is `sh`, the
350
+ // reading that holds for any POSIX shell.
351
+ const dialect = options.commandDialect ?? 'sh'
352
+ for (const held of this.held) {
353
+ if (held.entry.tool !== call.name) continue
354
+ if (held.entry.pattern === undefined || held.entry.argument === undefined) return held.skill
355
+ const line =
356
+ call.input !== null && typeof call.input === 'object'
357
+ ? (call.input as Record<string, unknown>)[held.entry.argument]
358
+ : undefined
359
+ if (typeof line !== 'string' || writesThroughRedirection(line, dialect)) continue
360
+ const decision = evaluateRule(
361
+ {
362
+ type: 'argument_pattern',
363
+ toolNames: [held.entry.tool],
364
+ argument: held.entry.argument,
365
+ pattern: held.entry.pattern,
366
+ decision: 'allow',
367
+ },
368
+ call.name,
369
+ call.input,
370
+ toolDef,
371
+ held.compiled,
372
+ held.names,
373
+ { commandDialect: dialect },
374
+ )
375
+ if (decision === 'allow') return held.skill
376
+ }
377
+ return undefined
378
+ }
379
+
380
+ /**
381
+ * Drop every grant. Called when the operator speaks again inside a running
382
+ * turn: the grant belonged to the request that loaded the skill, and a new
383
+ * message is a new request, even when it reaches the same `query()`.
384
+ */
385
+ clear(): void {
386
+ this.held.length = 0
387
+ }
388
+
389
+ get size(): number {
390
+ return this.held.length
391
+ }
392
+
393
+ /** What is granted, by skill, as the authors wrote it. */
394
+ list(): { readonly skill: string; readonly entry: string }[] {
395
+ return this.held.map((held) => ({
396
+ skill: held.skill,
397
+ entry: held.entry.declared,
398
+ }))
399
+ }
400
+ }
@@ -227,6 +227,8 @@ const MAPPING: {
227
227
  // it whether and when a retry is justified.
228
228
  {
229
229
  checkpointId: e.checkpointId,
230
+ // A person, not a retry, is what this pause waits for.
231
+ ...(e.handoff ? { handoff: e.handoff } : {}),
230
232
  ...(e.failure
231
233
  ? {
232
234
  code: e.failure.code,
@@ -297,6 +297,7 @@ const MAPPING: {
297
297
  ...(e.failure ? { failure: e.failure } : {}),
298
298
  ...(e.providerError ? { provider_error: e.providerError } : {}),
299
299
  ...(e.explanation ? { explanation: e.explanation } : {}),
300
+ ...(e.handoff ? { handoff: e.handoff } : {}),
300
301
  }),
301
302
  },
302
303
 
@@ -16,6 +16,8 @@ import type { ToolDefinition } from '../types/tool/index.js'
16
16
  * those is a `major` waiting to happen on a published type. The layering
17
17
  * question — does a convention belong outside the kernel — was answered yes
18
18
  * and stands; the shape question had simply never been asked.
19
+ * Schedules were later answered outside this loader, with a zone per spec and
20
+ * a claimed occurrence key: see `docs/sdk/schedules.md` (`../schedules/`).
19
21
  */
20
22
  export type DirectorySlot = 'agent' | 'instructions' | 'tools' | 'skills' | 'agents'
21
23
 
@@ -67,8 +67,11 @@ export function renderSkillsSection(skills?: Skill[]): string | null {
67
67
  if (s.metadata.license) {
68
68
  lines.push(`<license>${s.metadata.license}</license>`)
69
69
  }
70
+ // Named for what it does. Rendered as `<allowed_tools>` it read as a
71
+ // whitelist, and a model that took it that way stopped reaching for
72
+ // tools the skill did not list — the reverse of the field's meaning.
70
73
  if (s.metadata.allowedTools) {
71
- lines.push(`<allowed_tools>${s.metadata.allowedTools}</allowed_tools>`)
74
+ lines.push(`<pre_approved_tools>${s.metadata.allowedTools}</pre_approved_tools>`)
72
75
  }
73
76
  lines.push('</skill>')
74
77
  return lines.join('\n')
@@ -81,7 +84,7 @@ export function renderSkillsSection(skills?: Skill[]): string | null {
81
84
  // instructions and no listing that would let it reason about them.
82
85
  const loadedSkills = forModel.filter((s) => s.body)
83
86
  const sections = [
84
- `## Available Skills\nThe following block is a manifest, not the full skill content. Skill metadata is always visible; SKILL.md bodies are loaded only when the user's task matches the skill description.\n\n<available_skills>\n${available}\n</available_skills>\n\nSkill usage protocol:\n- Plain questions do not require a skill.\n- When a matching skill is already listed under Loaded Skills, apply its loaded instructions.\n- When a matching skill is not loaded and the runtime exposes filesystem or skill-loading tools, read the SKILL.md at its <location> before writing code, creating files, running shell commands for that workflow, or calling mutation tools guided by the skill.\n- Do not claim to have read a SKILL.md until its content is actually present in the prompt or returned by a tool.\n- Tool schemas and runtime permissions remain authoritative; skills provide guidance, not hidden tools.`,
87
+ `## Available Skills\nThe following block is a manifest, not the full skill content. Skill metadata is always visible; SKILL.md bodies are loaded only when the user's task matches the skill description.\n\n<available_skills>\n${available}\n</available_skills>\n\nSkill usage protocol:\n- Plain questions do not require a skill.\n- When a matching skill is already listed under Loaded Skills, apply its loaded instructions.\n- When a matching skill is not loaded and the runtime exposes filesystem or skill-loading tools, read the SKILL.md at its <location> before writing code, creating files, running shell commands for that workflow, or calling mutation tools guided by the skill.\n- Do not claim to have read a SKILL.md until its content is actually present in the prompt or returned by a tool.\n- Tool schemas and runtime permissions remain authoritative; skills provide guidance, not hidden tools.\n- <pre_approved_tools> lists tools a skill lets run without an approval prompt once it is loaded. It never limits which tools you may use: every tool stays available.`,
85
88
  ]
86
89
 
87
90
  if (loadedSkills.length > 0) {
@@ -69,6 +69,7 @@ export const CODING_AGENT_WORKING_DOCTRINE = `## How you work
69
69
  - Before any command that could discard uncommitted work, run \`git status\`. If there are changes there that you did not make, stop and ask rather than stashing, committing or discarding somebody else's work.
70
70
  - Commit only when the user asks, on the branch that is checked out. Do not create or switch branches unless the user asks or the project's instructions require it.
71
71
  - After a broad \`git add\`, review what was staged before committing; a file whose name looks harmless can still carry a secret.
72
+ - Never change git configuration or other persistent settings without asking: not \`user.name\` or \`user.email\`, hooks, remotes, credential helpers, or any \`git config\` (local or global), nor a shell profile or a tool's own config file. If a commit fails because no identity is set, stop and tell the user the command to set one; do not invent one.
72
73
 
73
74
  ### Keeping the user informed
74
75
  - Before a batch of tool calls, say in one short line what you are about to do and why. When you have been working for a while without saying anything, say in a few words where you are, then continue. One line, not a paragraph; the tool rows on screen already show the details.
@@ -318,6 +318,15 @@ export { deriveTurnStatus } from './types/session/derive-status.js'
318
318
  // wide their yes is, instead of choosing between 'this one call' and
319
319
  // 'everything for the session'.
320
320
  export { ToolGrantSet, toolGrantKeys } from './runtime/query/tool-grants.js'
321
+ // A skill's `allowed-tools` as a turn-scoped pre-approval: the parser, the
322
+ // compiler a host can run against its own registry, the per-turn set, and
323
+ // the one permission-glob dialect the CLI's `[permissions]` table shares.
324
+ export {
325
+ SKILL_TOOL_NAME_ALIASES,
326
+ SkillGrantSet,
327
+ compileSkillGrant,
328
+ permissionPatternToRegExpSource,
329
+ } from './authorization/skill-grant.js'
321
330
  export type { ToolGrantKeys } from './runtime/query/tool-grants.js'
322
331
  // `toWireTurnStatus` comes through `./contracts/session/index.js`.
323
332
  // Durable turn state: the snapshot a different process picks a turn up from.
@@ -414,6 +423,7 @@ export {
414
423
  discoverSkills,
415
424
  loadSkill,
416
425
  resolveSkillChain,
426
+ SKILL_FRONTMATTER_KEYS,
417
427
  SkillRegistry,
418
428
  } from './skills/index.js'
419
429
  // The one frontmatter reader. `loadSkill` is built on it, and a host reading
@@ -622,6 +632,26 @@ export {
622
632
  formatCompletionNotification,
623
633
  } from './scheduler/completion-inbox.js'
624
634
 
635
+ // Scheduled jobs: WHEN something is due, and nothing about how a host stores
636
+ // or runs a job. The time engine and the evaluator are pure (`Intl` for time
637
+ // zones, no clock, no I/O); the CLI keeps its job files and history to itself.
638
+ export {
639
+ countOccurrences,
640
+ describeSchedule,
641
+ evaluateJob,
642
+ hostTimeZone,
643
+ nextFireTime,
644
+ parseCronExpression,
645
+ parseDuration,
646
+ parseScheduleSpec,
647
+ previousFireTime,
648
+ SCHEDULE_CATCH_UP_WINDOW_MS,
649
+ SCHEDULE_LATE_GRACE_MS,
650
+ ScheduleValidationError,
651
+ upcomingFireTimes,
652
+ validateTimeZone,
653
+ } from './schedules/index.js'
654
+
625
655
  // ─── providers, sandbox, vault ───────────────────────────────────────────
626
656
 
627
657
  export {
@@ -890,6 +920,11 @@ export {
890
920
  AuthorizationGate,
891
921
  } from './authorization/index.js'
892
922
 
923
+ // The one reader of a bash command line the gate itself uses. A host that
924
+ // writes a `predicate` rule about what a line runs decides on this reading,
925
+ // so its rule and the SDK's own never disagree about where a quote ends.
926
+ export { lexShellCommandLine } from './authorization/shell-lexer.js'
927
+
893
928
  // NZ-BOOT-03: the module-attributed invariant registry. `compaction.ts` and
894
929
  // `claim-disk.ts` register themselves against the shared `invariants`
895
930
  // instance at import time (see each file); `namzu doctor` and any host can
@@ -1274,6 +1309,8 @@ export {
1274
1309
  isReviewExempt,
1275
1310
  isReviewMode,
1276
1311
  } from './runtime/query/review-policy.js'
1312
+ // What the model is told when a person declines a call without words of their own.
1313
+ export { DECLINED_TOOL_CALL_FEEDBACK } from './runtime/query/declined.js'
1277
1314
 
1278
1315
  // The system prompt is open: a contribution registry the assembler
1279
1316
  // consumes, with skills as its first contributor. See `prompt/contributions.ts`.
@@ -61,7 +61,8 @@ export { JobTool } from './tools/builtins/job.js'
61
61
  // the same reason `job` does: a job with nothing that can block on it is
62
62
  // the same unbacked suggestion `job` itself exists to fix.
63
63
  export { WaitForJobTool } from './tools/builtins/wait-for-job.js'
64
- // Loads a skill's instructions, and adopts the tool scope it declares.
64
+ // Loads a skill's instructions, and pre-approves what its `allowed-tools`
65
+ // names for the rest of the turn (never narrowing the tool set).
65
66
  // NOT in the default builtin set: a turn with no skills has nothing for it
66
67
  // to do, and offering a tool that can only refuse is worse than not
67
68
  // offering it. Hosts register it alongside a skills registry.
@@ -106,6 +107,29 @@ export {
106
107
  COMPUTER_USE_TOOL_NAME,
107
108
  createComputerUseTool,
108
109
  } from './tools/builtins/computer-use.js'
110
+ // The browser contract: the two tools over a host a separate package
111
+ // provides, and the canonicalisers a host and a site-rule compiler must share
112
+ // with the tools so every party reads one spelling of an address.
113
+ export {
114
+ BROWSER_ACT_TOOL_NAME,
115
+ BROWSER_TOOL_NAME,
116
+ browserHostErrorOf,
117
+ createBrowserTools,
118
+ formatBrowserPageHeader,
119
+ isBrowserCallReadOnly,
120
+ } from './tools/builtins/browser.js'
121
+ export {
122
+ BROWSER_URL_MAX_LENGTH,
123
+ canonicalizeBrowserOrigin,
124
+ canonicalizeBrowserSitePattern,
125
+ canonicalizeBrowserUrl,
126
+ isCloudMetadataHost,
127
+ } from './tools/builtins/browser-url.js'
128
+ export {
129
+ BROWSER_FILL_FORM_MAX_FIELDS,
130
+ BROWSER_SNAPSHOT_MAX_CHARS,
131
+ BROWSER_WAIT_MAX_MS,
132
+ } from './types/browser/index.js'
109
133
 
110
134
  // ─── Domain tool builders ────────────────────────────────────────────────
111
135
 
@@ -128,6 +152,18 @@ export {
128
152
  } from './tools/coordinator/ask-user-question.js'
129
153
  export { buildAgentTool, type AgentToolOptions } from './tools/coordinator/agent.js'
130
154
 
155
+ // Scheduled jobs and in-session loops, over host callbacks: the host stores
156
+ // jobs, draws the confirmation and computes every field it shows. Register
157
+ // only where a person can confirm (never headless, scheduled or delegated).
158
+ export {
159
+ buildScheduleTools,
160
+ buildSessionLoopTools,
161
+ revealHiddenCharacters,
162
+ scanSchedulePrompt,
163
+ SCHEDULE_TOOL_NAME,
164
+ SESSION_LOOP_TOOL_NAME,
165
+ } from './tools/schedules/index.js'
166
+
131
167
  // ─── RAG tool builder ────────────────────────────────────────────────────
132
168
 
133
169
  export { createRAGTool } from './rag/index.js'
@@ -62,6 +62,13 @@ export type * from './types/sandbox/index.js'
62
62
  export type * from './types/structured-output/index.js'
63
63
  export type * from './types/invocation/index.js'
64
64
  export type * from './types/computer-use/index.js'
65
+ export type * from './types/browser/index.js'
66
+ export type { BrowserActToolInput, BrowserToolInput } from './tools/builtins/browser.js'
67
+ export type {
68
+ BrowserOriginVerdict,
69
+ BrowserSitePatternVerdict,
70
+ BrowserUrlVerdict,
71
+ } from './tools/builtins/browser-url.js'
65
72
  export type * from './types/authorization/index.js'
66
73
  export type * from './types/bus/index.js'
67
74
  export type * from './types/probe/index.js'
@@ -113,9 +120,16 @@ export type { CacheRates, ModelPricing } from './utils/cost.js'
113
120
  export type { VendorRates } from './pricing/index.js'
114
121
  export type { PricingSubject } from './manager/session/turn-recorder.js'
115
122
  export type {
123
+ FrontmatterOptions,
116
124
  FrontmatterValue,
125
+ ParseFrontmatterOptions,
117
126
  ParsedFrontmatter,
118
127
  } from './utils/frontmatter.js'
128
+ export type {
129
+ CompiledSkillGrant,
130
+ SkillGrantEntry,
131
+ SkillGrantToolResolver,
132
+ } from './authorization/skill-grant.js'
119
133
  export type { Logger } from './utils/logger.js'
120
134
  export type {
121
135
  LevelFilter,
@@ -255,6 +269,14 @@ export type { AgentBusConfig } from './bus/index.js'
255
269
 
256
270
  export type { ToolCallContext } from './authorization/index.js'
257
271
  export type { PermissionPreset } from './authorization/index.js'
272
+ export type { EvaluateRuleOptions } from './authorization/rules.js'
273
+ export type {
274
+ ShellCommand,
275
+ ShellLexOptions,
276
+ ShellLexResult,
277
+ ShellRedirection,
278
+ ShellWord,
279
+ } from './authorization/shell-lexer.js'
258
280
 
259
281
  export type {
260
282
  DiskSessionStoreConfig,
@@ -622,3 +644,38 @@ export type {
622
644
  ParsedSessionLogLine,
623
645
  SessionLogLineFault,
624
646
  } from './session/log-hash.js'
647
+
648
+ // Scheduled jobs: the time engine's and evaluator's types. The unions here
649
+ // may grow in a minor release; switch over them with a `default:` branch.
650
+ export type {
651
+ CronExpression,
652
+ DescribeScheduleOptions,
653
+ OccurrenceCount,
654
+ ParseScheduleOptions,
655
+ ScheduleAtSpec,
656
+ ScheduleCronSpec,
657
+ ScheduleDecision,
658
+ ScheduleEvaluationInput,
659
+ ScheduleEvaluationJob,
660
+ ScheduleEvaluationState,
661
+ ScheduleEverySpec,
662
+ ScheduleFireTrigger,
663
+ ScheduleJobLifecycle,
664
+ ScheduleMissedReason,
665
+ ScheduleObservedGap,
666
+ ScheduleSkipReason,
667
+ ScheduleSpec,
668
+ } from './schedules/index.js'
669
+ export type {
670
+ ScheduleBrowserGrant,
671
+ ScheduleBrowserSiteLevel,
672
+ ScheduleConfirmAnswer,
673
+ ScheduleConfirmRequest,
674
+ ScheduleJobDraft,
675
+ ScheduleJobPreview,
676
+ ScheduleJobSummary,
677
+ ScheduleRuleEffect,
678
+ ScheduleToolHost,
679
+ SessionLoop,
680
+ SessionLoopHost,
681
+ } from './tools/schedules/index.js'