@namzu/sdk 45.0.0 → 46.0.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 (281) hide show
  1. package/CHANGELOG.md +166 -0
  2. package/dist/authorization/gate.d.ts +5 -2
  3. package/dist/authorization/gate.d.ts.map +1 -1
  4. package/dist/authorization/gate.js +35 -4
  5. package/dist/authorization/gate.js.map +1 -1
  6. package/dist/authorization/rules.d.ts.map +1 -1
  7. package/dist/authorization/rules.js +56 -6
  8. package/dist/authorization/rules.js.map +1 -1
  9. package/dist/authorization/shell-lexer.d.ts +38 -0
  10. package/dist/authorization/shell-lexer.d.ts.map +1 -1
  11. package/dist/authorization/shell-lexer.js +88 -57
  12. package/dist/authorization/shell-lexer.js.map +1 -1
  13. package/dist/bridge/a2a/mapper.d.ts.map +1 -1
  14. package/dist/bridge/a2a/mapper.js +2 -0
  15. package/dist/bridge/a2a/mapper.js.map +1 -1
  16. package/dist/bridge/sse/mapper.d.ts.map +1 -1
  17. package/dist/bridge/sse/mapper.js +1 -0
  18. package/dist/bridge/sse/mapper.js.map +1 -1
  19. package/dist/directory/types.d.ts +2 -0
  20. package/dist/directory/types.d.ts.map +1 -1
  21. package/dist/directory/types.js.map +1 -1
  22. package/dist/manager/resident/outbox.d.ts +4 -4
  23. package/dist/pricing/catalogue.generated.d.ts.map +1 -1
  24. package/dist/pricing/catalogue.generated.js +28 -4
  25. package/dist/pricing/catalogue.generated.js.map +1 -1
  26. package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
  27. package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
  28. package/dist/prompt/coding-agent-doctrine.js +1 -0
  29. package/dist/prompt/coding-agent-doctrine.js.map +1 -1
  30. package/dist/public-runtime.d.ts +6 -3
  31. package/dist/public-runtime.d.ts.map +1 -1
  32. package/dist/public-runtime.js +14 -2
  33. package/dist/public-runtime.js.map +1 -1
  34. package/dist/public-tools.d.ts +7 -2
  35. package/dist/public-tools.d.ts.map +1 -1
  36. package/dist/public-tools.js +15 -2
  37. package/dist/public-tools.js.map +1 -1
  38. package/dist/public-types.d.ts +8 -2
  39. package/dist/public-types.d.ts.map +1 -1
  40. package/dist/registry/tool/callable.d.ts +22 -0
  41. package/dist/registry/tool/callable.d.ts.map +1 -0
  42. package/dist/registry/tool/callable.js +29 -0
  43. package/dist/registry/tool/callable.js.map +1 -0
  44. package/dist/registry/tool/execute.d.ts.map +1 -1
  45. package/dist/registry/tool/execute.js +8 -1
  46. package/dist/registry/tool/execute.js.map +1 -1
  47. package/dist/runtime/query/declined.d.ts +12 -0
  48. package/dist/runtime/query/declined.d.ts.map +1 -0
  49. package/dist/runtime/query/declined.js +12 -0
  50. package/dist/runtime/query/declined.js.map +1 -0
  51. package/dist/runtime/query/executor/tool-call-admission.d.ts +37 -11
  52. package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
  53. package/dist/runtime/query/executor/tool-call-admission.js +38 -12
  54. package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
  55. package/dist/runtime/query/executor.d.ts +7 -3
  56. package/dist/runtime/query/executor.d.ts.map +1 -1
  57. package/dist/runtime/query/executor.js +32 -7
  58. package/dist/runtime/query/executor.js.map +1 -1
  59. package/dist/runtime/query/index.d.ts.map +1 -1
  60. package/dist/runtime/query/index.js +1 -0
  61. package/dist/runtime/query/index.js.map +1 -1
  62. package/dist/runtime/query/iteration/index.d.ts.map +1 -1
  63. package/dist/runtime/query/iteration/index.js +7 -0
  64. package/dist/runtime/query/iteration/index.js.map +1 -1
  65. package/dist/runtime/query/iteration/phases/context.d.ts +6 -0
  66. package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
  67. package/dist/runtime/query/iteration/phases/context.js.map +1 -1
  68. package/dist/runtime/query/iteration/phases/handoff.d.ts +22 -0
  69. package/dist/runtime/query/iteration/phases/handoff.d.ts.map +1 -0
  70. package/dist/runtime/query/iteration/phases/handoff.js +65 -0
  71. package/dist/runtime/query/iteration/phases/handoff.js.map +1 -0
  72. package/dist/runtime/query/iteration/phases/index.d.ts +1 -0
  73. package/dist/runtime/query/iteration/phases/index.d.ts.map +1 -1
  74. package/dist/runtime/query/iteration/phases/index.js +1 -0
  75. package/dist/runtime/query/iteration/phases/index.js.map +1 -1
  76. package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
  77. package/dist/runtime/query/iteration/phases/tool-review.js +8 -3
  78. package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
  79. package/dist/runtime/query/resume-pending.d.ts.map +1 -1
  80. package/dist/runtime/query/resume-pending.js +3 -2
  81. package/dist/runtime/query/resume-pending.js.map +1 -1
  82. package/dist/runtime/query/review-policy.d.ts +43 -0
  83. package/dist/runtime/query/review-policy.d.ts.map +1 -1
  84. package/dist/runtime/query/review-policy.js +63 -19
  85. package/dist/runtime/query/review-policy.js.map +1 -1
  86. package/dist/schedules/cron.d.ts +21 -0
  87. package/dist/schedules/cron.d.ts.map +1 -0
  88. package/dist/schedules/cron.js +167 -0
  89. package/dist/schedules/cron.js.map +1 -0
  90. package/dist/schedules/describe.d.ts +14 -0
  91. package/dist/schedules/describe.d.ts.map +1 -0
  92. package/dist/schedules/describe.js +133 -0
  93. package/dist/schedules/describe.js.map +1 -0
  94. package/dist/schedules/errors.d.ts +11 -0
  95. package/dist/schedules/errors.d.ts.map +1 -0
  96. package/dist/schedules/errors.js +15 -0
  97. package/dist/schedules/errors.js.map +1 -0
  98. package/dist/schedules/evaluate.d.ts +35 -0
  99. package/dist/schedules/evaluate.d.ts.map +1 -0
  100. package/dist/schedules/evaluate.js +158 -0
  101. package/dist/schedules/evaluate.js.map +1 -0
  102. package/dist/schedules/index.d.ts +11 -0
  103. package/dist/schedules/index.d.ts.map +1 -0
  104. package/dist/schedules/index.js +8 -0
  105. package/dist/schedules/index.js.map +1 -0
  106. package/dist/schedules/next-fire.d.ts +50 -0
  107. package/dist/schedules/next-fire.d.ts.map +1 -0
  108. package/dist/schedules/next-fire.js +250 -0
  109. package/dist/schedules/next-fire.js.map +1 -0
  110. package/dist/schedules/spec.d.ts +30 -0
  111. package/dist/schedules/spec.d.ts.map +1 -0
  112. package/dist/schedules/spec.js +169 -0
  113. package/dist/schedules/spec.js.map +1 -0
  114. package/dist/schedules/types.d.ts +144 -0
  115. package/dist/schedules/types.d.ts.map +1 -0
  116. package/dist/schedules/types.js +11 -0
  117. package/dist/schedules/types.js.map +1 -0
  118. package/dist/schedules/tz.d.ts +44 -0
  119. package/dist/schedules/tz.d.ts.map +1 -0
  120. package/dist/schedules/tz.js +141 -0
  121. package/dist/schedules/tz.js.map +1 -0
  122. package/dist/skills/index.d.ts +1 -1
  123. package/dist/skills/index.d.ts.map +1 -1
  124. package/dist/skills/index.js +1 -1
  125. package/dist/skills/index.js.map +1 -1
  126. package/dist/skills/loader.d.ts +16 -3
  127. package/dist/skills/loader.d.ts.map +1 -1
  128. package/dist/skills/loader.js +48 -4
  129. package/dist/skills/loader.js.map +1 -1
  130. package/dist/skills/registry.d.ts +6 -0
  131. package/dist/skills/registry.d.ts.map +1 -1
  132. package/dist/skills/registry.js +1 -0
  133. package/dist/skills/registry.js.map +1 -1
  134. package/dist/tools/builtins/browser-url.d.ts +83 -0
  135. package/dist/tools/builtins/browser-url.d.ts.map +1 -0
  136. package/dist/tools/builtins/browser-url.js +240 -0
  137. package/dist/tools/builtins/browser-url.js.map +1 -0
  138. package/dist/tools/builtins/browser.d.ts +367 -0
  139. package/dist/tools/builtins/browser.d.ts.map +1 -0
  140. package/dist/tools/builtins/browser.js +704 -0
  141. package/dist/tools/builtins/browser.js.map +1 -0
  142. package/dist/tools/builtins/computer-use-coordinates.d.ts +65 -0
  143. package/dist/tools/builtins/computer-use-coordinates.d.ts.map +1 -0
  144. package/dist/tools/builtins/computer-use-coordinates.js +123 -0
  145. package/dist/tools/builtins/computer-use-coordinates.js.map +1 -0
  146. package/dist/tools/builtins/computer-use-image.d.ts +77 -0
  147. package/dist/tools/builtins/computer-use-image.d.ts.map +1 -0
  148. package/dist/tools/builtins/computer-use-image.js +223 -0
  149. package/dist/tools/builtins/computer-use-image.js.map +1 -0
  150. package/dist/tools/builtins/computer-use.d.ts +519 -14
  151. package/dist/tools/builtins/computer-use.d.ts.map +1 -1
  152. package/dist/tools/builtins/computer-use.js +1188 -183
  153. package/dist/tools/builtins/computer-use.js.map +1 -1
  154. package/dist/tools/builtins/index.d.ts +2 -1
  155. package/dist/tools/builtins/index.d.ts.map +1 -1
  156. package/dist/tools/builtins/index.js +1 -1
  157. package/dist/tools/builtins/index.js.map +1 -1
  158. package/dist/tools/builtins/skill.d.ts +74 -0
  159. package/dist/tools/builtins/skill.d.ts.map +1 -1
  160. package/dist/tools/builtins/skill.js +214 -159
  161. package/dist/tools/builtins/skill.js.map +1 -1
  162. package/dist/tools/defineTool.d.ts +4 -0
  163. package/dist/tools/defineTool.d.ts.map +1 -1
  164. package/dist/tools/defineTool.js +8 -0
  165. package/dist/tools/defineTool.js.map +1 -1
  166. package/dist/tools/schedules/index.d.ts +5 -0
  167. package/dist/tools/schedules/index.d.ts.map +1 -0
  168. package/dist/tools/schedules/index.js +4 -0
  169. package/dist/tools/schedules/index.js.map +1 -0
  170. package/dist/tools/schedules/loop-tool.d.ts +14 -0
  171. package/dist/tools/schedules/loop-tool.d.ts.map +1 -0
  172. package/dist/tools/schedules/loop-tool.js +81 -0
  173. package/dist/tools/schedules/loop-tool.js.map +1 -0
  174. package/dist/tools/schedules/present.d.ts +16 -0
  175. package/dist/tools/schedules/present.d.ts.map +1 -0
  176. package/dist/tools/schedules/present.js +71 -0
  177. package/dist/tools/schedules/present.js.map +1 -0
  178. package/dist/tools/schedules/prompt-scan.d.ts +17 -0
  179. package/dist/tools/schedules/prompt-scan.d.ts.map +1 -0
  180. package/dist/tools/schedules/prompt-scan.js +92 -0
  181. package/dist/tools/schedules/prompt-scan.js.map +1 -0
  182. package/dist/tools/schedules/schedule-tool.d.ts +17 -0
  183. package/dist/tools/schedules/schedule-tool.d.ts.map +1 -0
  184. package/dist/tools/schedules/schedule-tool.js +418 -0
  185. package/dist/tools/schedules/schedule-tool.js.map +1 -0
  186. package/dist/tools/schedules/types.d.ts +252 -0
  187. package/dist/tools/schedules/types.d.ts.map +1 -0
  188. package/dist/tools/schedules/types.js +11 -0
  189. package/dist/tools/schedules/types.js.map +1 -0
  190. package/dist/types/authorization/index.d.ts +107 -9
  191. package/dist/types/authorization/index.d.ts.map +1 -1
  192. package/dist/types/authorization/index.js +16 -1
  193. package/dist/types/authorization/index.js.map +1 -1
  194. package/dist/types/browser/index.d.ts +280 -0
  195. package/dist/types/browser/index.d.ts.map +1 -0
  196. package/dist/types/browser/index.js +12 -0
  197. package/dist/types/browser/index.js.map +1 -0
  198. package/dist/types/computer-use/index.d.ts +176 -0
  199. package/dist/types/computer-use/index.d.ts.map +1 -1
  200. package/dist/types/computer-use/index.js.map +1 -1
  201. package/dist/types/session/events.d.ts +6 -0
  202. package/dist/types/session/events.d.ts.map +1 -1
  203. package/dist/types/session/events.js.map +1 -1
  204. package/dist/types/session/records.d.ts +23 -0
  205. package/dist/types/session/records.d.ts.map +1 -1
  206. package/dist/types/session/records.js +9 -0
  207. package/dist/types/session/records.js.map +1 -1
  208. package/dist/types/tool/index.d.ts +60 -0
  209. package/dist/types/tool/index.d.ts.map +1 -1
  210. package/dist/types/tool/index.js.map +1 -1
  211. package/dist/types/tool/presentation.d.ts +7 -0
  212. package/dist/types/tool/presentation.d.ts.map +1 -1
  213. package/dist/utils/frontmatter.d.ts +18 -2
  214. package/dist/utils/frontmatter.d.ts.map +1 -1
  215. package/dist/utils/frontmatter.js +13 -3
  216. package/dist/utils/frontmatter.js.map +1 -1
  217. package/dist/utils/id.d.ts +8 -0
  218. package/dist/utils/id.d.ts.map +1 -1
  219. package/dist/utils/id.js +12 -0
  220. package/dist/utils/id.js.map +1 -1
  221. package/package.json +3 -1
  222. package/src/authorization/gate.ts +37 -4
  223. package/src/authorization/rules.ts +55 -7
  224. package/src/authorization/shell-lexer.ts +109 -51
  225. package/src/bridge/a2a/mapper.ts +2 -0
  226. package/src/bridge/sse/mapper.ts +1 -0
  227. package/src/directory/types.ts +2 -0
  228. package/src/pricing/catalogue.generated.ts +28 -4
  229. package/src/pricing/rates.source.json +27 -6
  230. package/src/prompt/coding-agent-doctrine.ts +1 -0
  231. package/src/public-runtime.ts +43 -1
  232. package/src/public-tools.ts +54 -1
  233. package/src/public-types.ts +55 -0
  234. package/src/registry/tool/callable.ts +37 -0
  235. package/src/registry/tool/execute.ts +8 -1
  236. package/src/runtime/query/declined.ts +12 -0
  237. package/src/runtime/query/executor/tool-call-admission.ts +60 -16
  238. package/src/runtime/query/executor.ts +36 -5
  239. package/src/runtime/query/index.ts +1 -0
  240. package/src/runtime/query/iteration/index.ts +8 -0
  241. package/src/runtime/query/iteration/phases/context.ts +6 -0
  242. package/src/runtime/query/iteration/phases/handoff.ts +74 -0
  243. package/src/runtime/query/iteration/phases/index.ts +1 -0
  244. package/src/runtime/query/iteration/phases/tool-review.ts +11 -4
  245. package/src/runtime/query/resume-pending.ts +3 -2
  246. package/src/runtime/query/review-policy.ts +107 -18
  247. package/src/schedules/cron.ts +202 -0
  248. package/src/schedules/describe.ts +138 -0
  249. package/src/schedules/errors.ts +15 -0
  250. package/src/schedules/evaluate.ts +178 -0
  251. package/src/schedules/index.ts +18 -0
  252. package/src/schedules/next-fire.ts +257 -0
  253. package/src/schedules/spec.ts +210 -0
  254. package/src/schedules/types.ts +163 -0
  255. package/src/schedules/tz.ts +155 -0
  256. package/src/skills/index.ts +1 -1
  257. package/src/skills/loader.ts +55 -4
  258. package/src/skills/registry.ts +8 -0
  259. package/src/tools/builtins/browser-url.ts +251 -0
  260. package/src/tools/builtins/browser.ts +817 -0
  261. package/src/tools/builtins/computer-use-coordinates.ts +144 -0
  262. package/src/tools/builtins/computer-use-image.ts +278 -0
  263. package/src/tools/builtins/computer-use.ts +1485 -191
  264. package/src/tools/builtins/index.ts +7 -1
  265. package/src/tools/builtins/skill.ts +304 -156
  266. package/src/tools/defineTool.ts +13 -0
  267. package/src/tools/schedules/index.ts +4 -0
  268. package/src/tools/schedules/loop-tool.ts +85 -0
  269. package/src/tools/schedules/present.ts +88 -0
  270. package/src/tools/schedules/prompt-scan.ts +96 -0
  271. package/src/tools/schedules/schedule-tool.ts +482 -0
  272. package/src/tools/schedules/types.ts +265 -0
  273. package/src/types/authorization/index.ts +81 -2
  274. package/src/types/browser/index.ts +341 -0
  275. package/src/types/computer-use/index.ts +202 -0
  276. package/src/types/session/events.ts +6 -0
  277. package/src/types/session/records.ts +10 -0
  278. package/src/types/tool/index.ts +61 -0
  279. package/src/types/tool/presentation.ts +7 -0
  280. package/src/utils/frontmatter.ts +29 -3
  281. package/src/utils/id.ts +14 -0
@@ -0,0 +1,265 @@
1
+ /**
2
+ * The host side of the `schedule` and `session_loop` tools.
3
+ *
4
+ * The SDK holds the tool's contract with the model — its schema, its refusals
5
+ * and its confirmation rule — and nothing about where jobs are stored or how
6
+ * a confirmation is drawn. The host supplies both, and it computes every
7
+ * field a person is asked to confirm: the model's own words are never what
8
+ * the confirmation shows as fact.
9
+ */
10
+
11
+ /** A rule effect, in the vocabulary of the CLI's `[permissions]` table. */
12
+ export type ScheduleRuleEffect = 'allow' | 'ask' | 'deny'
13
+
14
+ /** What the model proposes. Validated by the tool's schema, then by the host. */
15
+ export interface ScheduleJobDraft {
16
+ readonly name: string
17
+ readonly prompt: string
18
+ /** Schedule words: `every 30m`, `0 9 * * 1-5`, `at 09:00`, `in 2h`. */
19
+ readonly when: string
20
+ /** Folder the job runs in. Absent: the session's working directory. */
21
+ readonly folder?: string
22
+ /** IANA zone for a cron expression or a local time. Absent: the host's. */
23
+ readonly tz?: string
24
+ readonly permissions: {
25
+ readonly preset?: 'read-only' | 'edit-in-folder'
26
+ /**
27
+ * What happens to a call no rule covers. The model may choose `park`
28
+ * (wait for the operator) or `deny`; running uncovered calls without
29
+ * asking is an operator decision the tool cannot propose.
30
+ */
31
+ readonly unmatched: 'park' | 'deny'
32
+ readonly execution?: 'host' | 'sandbox'
33
+ readonly rules?: Readonly<
34
+ Record<string, ScheduleRuleEffect | Readonly<Record<string, ScheduleRuleEffect>>>
35
+ >
36
+ /**
37
+ * Browser access for the run. Absent: the `browser` and `browser_act`
38
+ * tools are denied. Present: only the listed sites are reachable, at
39
+ * the listed level, and every other site is denied — there is no
40
+ * catch-all key. The tool refuses this block unless the host sets
41
+ * {@link ScheduleToolHost.browserGrants}.
42
+ */
43
+ readonly browser?: ScheduleBrowserGrant
44
+ }
45
+ readonly budget?: {
46
+ readonly maxIterations?: number
47
+ readonly tokenBudget?: number
48
+ readonly timeoutMs?: number
49
+ }
50
+ }
51
+
52
+ /**
53
+ * How far a scheduled run may go on one site. `read`: open and read pages,
54
+ * never change them. `ask`: open and change pages, each change parked for the
55
+ * operator. `act`: open and change pages without asking.
56
+ */
57
+ export type ScheduleBrowserSiteLevel = 'read' | 'ask' | 'act'
58
+
59
+ /** A scheduled job's browser grant. */
60
+ export interface ScheduleBrowserGrant {
61
+ /** The browser profile the run uses; the operator's, signed in beforehand. */
62
+ readonly profile: string
63
+ /**
64
+ * Canonical site key (`https://github.com`, `https://*.example.com`,
65
+ * `http://localhost:*`) to level. The tool canonicalises the keys the
66
+ * model wrote (see `canonicalizeBrowserSitePattern`) before the host sees
67
+ * them. Unlisted sites are denied.
68
+ */
69
+ readonly sites: Readonly<Record<string, ScheduleBrowserSiteLevel>>
70
+ /** Show the browser window during the run. Default: no window. */
71
+ readonly headed?: boolean
72
+ }
73
+
74
+ /** What the person confirming is shown. Every field is the host's own computation. */
75
+ export interface ScheduleJobPreview {
76
+ readonly name: string
77
+ /** The canonical folder the job would run in. */
78
+ readonly folder: string
79
+ /** True when `folder` is outside the session's working directory and added directories. */
80
+ readonly outsideSessionRoots: boolean
81
+ readonly prompt: string
82
+ /** The schedule in words, with its zone. */
83
+ readonly schedule: string
84
+ /** The next fire times, ISO-8601 UTC. */
85
+ readonly nextFireTimes: readonly string[]
86
+ /** The permission set expanded to one line per rule, config denies included. */
87
+ readonly rules: readonly string[]
88
+ readonly unmatched: 'park' | 'deny' | 'allow'
89
+ readonly execution: 'host' | 'sandbox'
90
+ /** A rule lets the run reach the network. */
91
+ readonly networkAccess: boolean
92
+ readonly budget: {
93
+ readonly maxIterations: number
94
+ readonly tokenBudget: number
95
+ readonly timeoutMs: number
96
+ }
97
+ /** Runs per day at most, times the token budget. Absent for a one-shot. */
98
+ readonly dailyTokenCeiling?: number
99
+ /** Provider and model the job is pinned to. */
100
+ readonly model: string
101
+ /** Where the run's credential comes from, in words. */
102
+ readonly credentialSource?: string
103
+ /** Anything the host wants said in the warning colour. */
104
+ readonly warnings: readonly string[]
105
+ }
106
+
107
+ /** A job as the `list` action reports it. */
108
+ export interface ScheduleJobSummary {
109
+ readonly name: string
110
+ readonly folder: string
111
+ readonly state: string
112
+ readonly schedule: string
113
+ readonly nextFireAt?: string
114
+ readonly lastStatus?: string
115
+ /** Present only for jobs in the session's own folder. */
116
+ readonly prompt?: string
117
+ /**
118
+ * True for a job whose folder is the session's own. A host that lists
119
+ * other folders' jobs sets it so the model can tell them apart; the tool
120
+ * marks such a job `(this folder)`.
121
+ */
122
+ readonly inSessionFolder?: boolean
123
+ }
124
+
125
+ /**
126
+ * What the model proposes to change in an existing job. Every field left
127
+ * out keeps the job's current value. `permissions`, when given, is the whole
128
+ * new set, with the same limits as a new job's; the host keeps the job's
129
+ * `execution` when it is not given, and its additional directories.
130
+ */
131
+ export interface ScheduleJobChanges {
132
+ readonly prompt?: string
133
+ readonly when?: string
134
+ readonly folder?: string
135
+ readonly tz?: string
136
+ readonly permissions?: ScheduleJobDraft['permissions']
137
+ readonly budget?: ScheduleJobDraft['budget']
138
+ }
139
+
140
+ /** A proposed change to a job, as the host computed it. */
141
+ export interface ScheduleJobUpdateProposal {
142
+ /** The job as it would be once changed. Every field is the host's own computation. */
143
+ readonly preview: ScheduleJobPreview
144
+ /**
145
+ * What differs from the job as it stands (and from edits saved since it
146
+ * was last confirmed), one line each: `- ` what goes, `+ ` what comes.
147
+ */
148
+ readonly changes: readonly string[]
149
+ /** The change touches what a run may do: its rules, `unmatched`, where it runs, its browser grant. */
150
+ readonly permissionsChange: boolean
151
+ }
152
+
153
+ /** What the person confirming a change is shown. */
154
+ export interface ScheduleUpdateRequest extends ScheduleJobUpdateProposal {
155
+ /** The prompt tripwire's findings over `preview.prompt`. */
156
+ readonly promptFindings: readonly string[]
157
+ /** Always `model` from this tool. */
158
+ readonly proposedBy: 'model'
159
+ }
160
+
161
+ /** What the person answered to a proposed job. */
162
+ export type ScheduleConfirmAnswer = 'create' | 'create-paused' | 'cancel'
163
+
164
+ export interface ScheduleConfirmRequest {
165
+ readonly preview: ScheduleJobPreview
166
+ /** The prompt tripwire's findings over `preview.prompt`. */
167
+ readonly promptFindings: readonly string[]
168
+ /** Always `model` from this tool: the banner says it was not the operator. */
169
+ readonly proposedBy: 'model'
170
+ }
171
+
172
+ export interface ScheduleToolHost {
173
+ /**
174
+ * The host can store and enforce {@link ScheduleJobDraft.permissions}
175
+ * `.browser`. Absent or false: the tool refuses a draft carrying one,
176
+ * rather than let the host drop it and confirm a job the model believes
177
+ * can use the browser.
178
+ */
179
+ readonly browserGrants?: boolean
180
+ /** Validate the draft and compute what the person will be shown. Throws with a message on a refusal. */
181
+ preview(draft: ScheduleJobDraft): Promise<ScheduleJobPreview>
182
+ /**
183
+ * Ask the person. Anything but `create` or `create-paused` — `cancel`, a
184
+ * thrown error, a closed screen — means no job.
185
+ *
186
+ * `signal` fires when the tool's own confirmation deadline elapses or the
187
+ * turn is aborted; a host that draws a screen closes it then rather than
188
+ * leaving it live after the tool has given up on the answer.
189
+ */
190
+ confirm(request: ScheduleConfirmRequest, signal?: AbortSignal): Promise<ScheduleConfirmAnswer>
191
+ /**
192
+ * Create the job the person confirmed. `note`, when given, is appended to
193
+ * what the model is told, for what the person must still do before the
194
+ * job runs (install a scheduler, say): the model reports the job as set
195
+ * up otherwise.
196
+ */
197
+ create(
198
+ draft: ScheduleJobDraft,
199
+ preview: ScheduleJobPreview,
200
+ options: { readonly paused: boolean },
201
+ ): Promise<{ readonly name: string; readonly note?: string }>
202
+ /**
203
+ * Jobs, the session folder's in full, other folders' without their
204
+ * prompts. `allFolders: false` lets a host list only the session
205
+ * folder's; a host may list every job regardless, marking the session
206
+ * folder's with {@link ScheduleJobSummary.inSessionFolder}. The tool says
207
+ * "No scheduled jobs." when this returns none, so a host that filters
208
+ * says so only for its folder.
209
+ */
210
+ list(options: { readonly allFolders: boolean }): Promise<readonly ScheduleJobSummary[]>
211
+ /** A job by name or id prefix, or undefined. */
212
+ find(job: string): Promise<ScheduleJobSummary | undefined>
213
+ /** Ask the person to confirm resuming or deleting a job. See `confirm` on `signal`. */
214
+ confirmAction(
215
+ job: ScheduleJobSummary,
216
+ action: 'resume' | 'delete',
217
+ signal?: AbortSignal,
218
+ ): Promise<boolean>
219
+ pause(job: string): Promise<void>
220
+ resume(job: string): Promise<void>
221
+ delete(job: string): Promise<void>
222
+ /**
223
+ * Validate a change to `job` (a name or id prefix) and compute what the
224
+ * person will be shown. Throws with a message on a refusal. The tool
225
+ * offers `update` only when a host has all three of `previewUpdate`,
226
+ * `confirmUpdate` and `update`.
227
+ */
228
+ previewUpdate?(job: string, changes: ScheduleJobChanges): Promise<ScheduleJobUpdateProposal>
229
+ /**
230
+ * Ask the person whether to save the change. Anything but `true` — a
231
+ * thrown error, a closed screen — changes nothing. See `confirm` on
232
+ * `signal`.
233
+ */
234
+ confirmUpdate?(request: ScheduleUpdateRequest, signal?: AbortSignal): Promise<boolean>
235
+ /**
236
+ * Save the change the person confirmed, to the same job: its id and its
237
+ * history are kept, and the confirmation is the person's. `note` as for
238
+ * `create`.
239
+ */
240
+ update?(preview: ScheduleJobPreview): Promise<{ readonly name: string; readonly note?: string }>
241
+ }
242
+
243
+ /** A prompt the session re-sends to itself on an interval. */
244
+ export interface SessionLoop {
245
+ readonly id: string
246
+ /** The interval in words. */
247
+ readonly schedule: string
248
+ readonly prompt: string
249
+ readonly createdAt: string
250
+ readonly expiresAt?: string
251
+ readonly lastFiredAt?: string
252
+ readonly createdBy: 'operator' | 'model'
253
+ }
254
+
255
+ export interface SessionLoopHost {
256
+ /** Throws with a message when the interval is not usable or the loop limit is reached. */
257
+ create(request: {
258
+ readonly interval: string
259
+ readonly prompt: string
260
+ readonly createdBy: 'model'
261
+ }): Promise<SessionLoop>
262
+ list(): readonly SessionLoop[]
263
+ /** Stop one loop by id, or every loop with `all`. Returns how many stopped. */
264
+ delete(id: string): Promise<number>
265
+ }
@@ -1,5 +1,6 @@
1
1
  import { z } from 'zod'
2
2
  import { MAX_CUSTOM_PATTERN_LENGTH } from '../../constants/authorization/index.js'
3
+ import type { ShellDialect, ToolDefinition } from '../tool/index.js'
3
4
 
4
5
  export type GateDecision = 'allow' | 'deny' | 'review'
5
6
 
@@ -81,9 +82,69 @@ export type AuthorizationRule =
81
82
  /** The argument key, at the top level of the tool's input. */
82
83
  argument: string
83
84
  pattern: string
84
- decision: 'allow' | 'deny'
85
+ /**
86
+ * `review` sends a matching call to the review policy — a person,
87
+ * or the turn's mode — instead of deciding it here. It matches as
88
+ * `deny` does (any segment of a command line), because it is a
89
+ * restriction: a rule that asks before `git push` must also ask
90
+ * before `true; git push`.
91
+ */
92
+ decision: 'allow' | 'deny' | 'review'
85
93
  }
86
94
  | { type: 'allow_by_tier'; tiers: string[] }
95
+ | {
96
+ /**
97
+ * A decision the host computes in code, in its place in the list.
98
+ *
99
+ * A pattern is the wrong tool for a rule about what a command line
100
+ * DOES: a regular expression over its text has to re-implement the
101
+ * shell's quoting, and every form it misses (`$'…'`, a line
102
+ * continuation, a quoted separator) is a way past the rule. A host
103
+ * that needs such a rule reads the line with `lexShellCommandLine`
104
+ * and decides on the words bash will pass, here.
105
+ *
106
+ * `decide` returns a decision, or `null` to let the next rule
107
+ * decide. A `decide` that throws is read as `deny`: a rule that
108
+ * could not reach a verdict must not let the call through.
109
+ */
110
+ type: 'predicate'
111
+ /**
112
+ * What the rule refuses or allows, in words. It is the reason the
113
+ * gate reports when this rule decides, so it should tell a model
114
+ * whether a different input could fare better.
115
+ */
116
+ description: string
117
+ decide: AuthorizationPredicate
118
+ /**
119
+ * The reason for THIS call, when `decide` returned a decision: what
120
+ * in the input matched, and where. The gate reports it instead of
121
+ * {@link description}. Absent, returning `null` or throwing, the
122
+ * gate reports `description`.
123
+ *
124
+ * A rule that refuses on several grounds and reports one fixed
125
+ * sentence leaves the model, and the person reading the refusal,
126
+ * to guess which ground it was. A scheduled run's refusal listed
127
+ * everything the rule protects when one word of the command had
128
+ * matched.
129
+ */
130
+ describe?: (call: AuthorizationPredicateCall) => string | null
131
+ }
132
+
133
+ /** The call an `AuthorizationRule` of type `predicate` is asked about. */
134
+ export interface AuthorizationPredicateCall {
135
+ readonly toolName: string
136
+ readonly toolInput: unknown
137
+ readonly toolDef: ToolDefinition | undefined
138
+ /**
139
+ * The shell a command line in this call runs in: the caller's
140
+ * (`ToolCallContext.commandDialect`), or `sh` when it did not say, which
141
+ * is the reading that holds whichever shell runs it.
142
+ */
143
+ readonly commandDialect: ShellDialect
144
+ }
145
+
146
+ /** The code behind an `AuthorizationRule` of type `predicate`. */
147
+ export type AuthorizationPredicate = (call: AuthorizationPredicateCall) => GateDecision | null
87
148
 
88
149
  const AllowReadOnlySchema = z.object({
89
150
  type: z.literal('allow_read_only'),
@@ -121,12 +182,29 @@ const ArgumentPatternSchema = z.object({
121
182
  // fail-open shape this rule type exists to remove.
122
183
  argument: z.string().min(1),
123
184
  pattern: z.string().max(MAX_CUSTOM_PATTERN_LENGTH),
124
- decision: z.enum(['allow', 'deny']),
185
+ decision: z.enum(['allow', 'deny', 'review']),
125
186
  })
126
187
  const AllowByTierSchema = z.object({
127
188
  type: z.literal('allow_by_tier'),
128
189
  tiers: z.array(z.string()),
129
190
  })
191
+ const PredicateSchema = z.object({
192
+ type: z.literal('predicate'),
193
+ // A rule that says nothing about itself produces a refusal nobody can
194
+ // reason about.
195
+ description: z.string().min(1),
196
+ decide: z.custom<AuthorizationPredicate>((value) => typeof value === 'function', {
197
+ message: 'decide must be a function',
198
+ }),
199
+ // Named here so the gate's own parse keeps it: zod strips what a schema
200
+ // does not name.
201
+ describe: z
202
+ .custom<(call: AuthorizationPredicateCall) => string | null>(
203
+ (value) => typeof value === 'function',
204
+ { message: 'describe must be a function' },
205
+ )
206
+ .optional(),
207
+ })
130
208
 
131
209
  export const AuthorizationRuleSchema = z.discriminatedUnion('type', [
132
210
  AllowReadOnlySchema,
@@ -137,6 +215,7 @@ export const AuthorizationRuleSchema = z.discriminatedUnion('type', [
137
215
  CustomPatternSchema,
138
216
  ArgumentPatternSchema,
139
217
  AllowByTierSchema,
218
+ PredicateSchema,
140
219
  ])
141
220
 
142
221
  export const AuthorizationGateConfigSchema = z.object({