@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
@@ -423,6 +423,7 @@ export {
423
423
  discoverSkills,
424
424
  loadSkill,
425
425
  resolveSkillChain,
426
+ SKILL_FRONTMATTER_KEYS,
426
427
  SkillRegistry,
427
428
  } from './skills/index.js'
428
429
  // The one frontmatter reader. `loadSkill` is built on it, and a host reading
@@ -631,6 +632,26 @@ export {
631
632
  formatCompletionNotification,
632
633
  } from './scheduler/completion-inbox.js'
633
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
+
634
655
  // ─── providers, sandbox, vault ───────────────────────────────────────────
635
656
 
636
657
  export {
@@ -899,6 +920,17 @@ export {
899
920
  AuthorizationGate,
900
921
  } from './authorization/index.js'
901
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
+ // `nestedShellCommand` says which `-c` payloads that reading already
927
+ // includes, so a host treats every other text a program runs as unread.
928
+ export {
929
+ NESTED_SHELLS,
930
+ lexShellCommandLine,
931
+ nestedShellCommand,
932
+ } from './authorization/shell-lexer.js'
933
+
902
934
  // NZ-BOOT-03: the module-attributed invariant registry. `compaction.ts` and
903
935
  // `claim-disk.ts` register themselves against the shared `invariants`
904
936
  // instance at import time (see each file); `namzu doctor` and any host can
@@ -1276,6 +1308,8 @@ export {
1276
1308
  REVIEW_EXEMPT_WRITES,
1277
1309
  REVIEW_MODES,
1278
1310
  SANDBOX_ESCAPE_UNATTENDED_REFUSAL,
1311
+ SCREEN_CONSENT_DECLINED_FEEDBACK,
1312
+ SCREEN_CONSENT_UNATTENDED_REFUSAL,
1279
1313
  STRICT_MODE_REFUSAL,
1280
1314
  batchNeedsReview,
1281
1315
  createReviewHandler,
@@ -1283,6 +1317,8 @@ export {
1283
1317
  isReviewExempt,
1284
1318
  isReviewMode,
1285
1319
  } from './runtime/query/review-policy.js'
1320
+ // What the model is told when a person declines a call without words of their own.
1321
+ export { DECLINED_TOOL_CALL_FEEDBACK } from './runtime/query/declined.js'
1286
1322
 
1287
1323
  // The system prompt is open: a contribution registry the assembler
1288
1324
  // consumes, with skills as its first contributor. See `prompt/contributions.ts`.
@@ -1405,7 +1441,13 @@ export type {
1405
1441
  export type { BroadcastHandoffDeps } from './session/handoff/broadcast.js'
1406
1442
  export type { SingleHandoffDeps } from './session/handoff/single.js'
1407
1443
  export type { InterventionChainLoader } from './session/intervention/prev-artifact.js'
1408
- export type { ActionInput } from './tools/builtins/computer-use.js'
1444
+ export type {
1445
+ ActionInput,
1446
+ ComputerUseTool,
1447
+ ComputerUseToolOptions,
1448
+ ImageSize,
1449
+ ScreenshotLimits,
1450
+ } from './tools/builtins/computer-use.js'
1409
1451
  export type { Project } from './types/project/entity.js'
1410
1452
  export type { CreatedLogger } from './utils/log/create-logger.js'
1411
1453
  export type {
@@ -66,7 +66,21 @@ export { WaitForJobTool } from './tools/builtins/wait-for-job.js'
66
66
  // NOT in the default builtin set: a turn with no skills has nothing for it
67
67
  // to do, and offering a tool that can only refuse is worse than not
68
68
  // offering it. Hosts register it alongside a skills registry.
69
- export { SKILL_TOOL_NAME, SkillTool, parseAllowedTools } from './tools/builtins/skill.js'
69
+ // `createSkillTool` takes what the host knows about where its model's tools
70
+ // run: `resolveModelDirectory` names the directory the model can open for
71
+ // each skill, which a sandboxed host's own path is not.
72
+ export {
73
+ SKILL_TOOL_NAME,
74
+ SkillTool,
75
+ createSkillTool,
76
+ parseAllowedTools,
77
+ } from './tools/builtins/skill.js'
78
+ export type {
79
+ SkillDirectoryContext,
80
+ SkillDirectoryRequest,
81
+ SkillDirectoryResolver,
82
+ SkillToolOptions,
83
+ } from './tools/builtins/skill.js'
70
84
  // Both declare `category: 'network'`, which is what the authorization
71
85
  // presets branch on. NOT in the default builtin set: a turn with no web
72
86
  // provider has nothing for them to do, and only the `unattended` preset --
@@ -105,8 +119,35 @@ export {
105
119
  } from './tools/builtins/structuredOutput.js'
106
120
  export {
107
121
  COMPUTER_USE_TOOL_NAME,
122
+ HIGH_RES_SCREENSHOT_LIMITS,
123
+ STANDARD_SCREENSHOT_LIMITS,
124
+ computerUseUnavailableReason,
108
125
  createComputerUseTool,
126
+ screenshotTargetSize,
109
127
  } from './tools/builtins/computer-use.js'
128
+ // The browser contract: the two tools over a host a separate package
129
+ // provides, and the canonicalisers a host and a site-rule compiler must share
130
+ // with the tools so every party reads one spelling of an address.
131
+ export {
132
+ BROWSER_ACT_TOOL_NAME,
133
+ BROWSER_TOOL_NAME,
134
+ browserHostErrorOf,
135
+ createBrowserTools,
136
+ formatBrowserPageHeader,
137
+ isBrowserCallReadOnly,
138
+ } from './tools/builtins/browser.js'
139
+ export {
140
+ BROWSER_URL_MAX_LENGTH,
141
+ canonicalizeBrowserOrigin,
142
+ canonicalizeBrowserSitePattern,
143
+ canonicalizeBrowserUrl,
144
+ isCloudMetadataHost,
145
+ } from './tools/builtins/browser-url.js'
146
+ export {
147
+ BROWSER_FILL_FORM_MAX_FIELDS,
148
+ BROWSER_SNAPSHOT_MAX_CHARS,
149
+ BROWSER_WAIT_MAX_MS,
150
+ } from './types/browser/index.js'
110
151
 
111
152
  // ─── Domain tool builders ────────────────────────────────────────────────
112
153
 
@@ -129,6 +170,18 @@ export {
129
170
  } from './tools/coordinator/ask-user-question.js'
130
171
  export { buildAgentTool, type AgentToolOptions } from './tools/coordinator/agent.js'
131
172
 
173
+ // Scheduled jobs and in-session loops, over host callbacks: the host stores
174
+ // jobs, draws the confirmation and computes every field it shows. Register
175
+ // only where a person can confirm (never headless, scheduled or delegated).
176
+ export {
177
+ buildScheduleTools,
178
+ buildSessionLoopTools,
179
+ revealHiddenCharacters,
180
+ scanSchedulePrompt,
181
+ SCHEDULE_TOOL_NAME,
182
+ SESSION_LOOP_TOOL_NAME,
183
+ } from './tools/schedules/index.js'
184
+
132
185
  // ─── RAG tool builder ────────────────────────────────────────────────────
133
186
 
134
187
  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'
@@ -115,6 +122,7 @@ export type { PricingSubject } from './manager/session/turn-recorder.js'
115
122
  export type {
116
123
  FrontmatterOptions,
117
124
  FrontmatterValue,
125
+ ParseFrontmatterOptions,
118
126
  ParsedFrontmatter,
119
127
  } from './utils/frontmatter.js'
120
128
  export type {
@@ -262,6 +270,14 @@ export type { AgentBusConfig } from './bus/index.js'
262
270
  export type { ToolCallContext } from './authorization/index.js'
263
271
  export type { PermissionPreset } from './authorization/index.js'
264
272
  export type { EvaluateRuleOptions } from './authorization/rules.js'
273
+ export type {
274
+ ShellCommand,
275
+ NestedShellCommand,
276
+ ShellLexOptions,
277
+ ShellLexResult,
278
+ ShellRedirection,
279
+ ShellWord,
280
+ } from './authorization/shell-lexer.js'
265
281
 
266
282
  export type {
267
283
  DiskSessionStoreConfig,
@@ -388,6 +404,7 @@ export type {
388
404
  ReviewExemption,
389
405
  ReviewMode,
390
406
  ReviewPolicyOptions,
407
+ ScreenConsentRecord,
391
408
  ToolReviewAnswer,
392
409
  ToolReviewPrompt,
393
410
  ToolReviewRequest,
@@ -629,3 +646,41 @@ export type {
629
646
  ParsedSessionLogLine,
630
647
  SessionLogLineFault,
631
648
  } from './session/log-hash.js'
649
+
650
+ // Scheduled jobs: the time engine's and evaluator's types. The unions here
651
+ // may grow in a minor release; switch over them with a `default:` branch.
652
+ export type {
653
+ CronExpression,
654
+ DescribeScheduleOptions,
655
+ OccurrenceCount,
656
+ ParseScheduleOptions,
657
+ ScheduleAtSpec,
658
+ ScheduleCronSpec,
659
+ ScheduleDecision,
660
+ ScheduleEvaluationInput,
661
+ ScheduleEvaluationJob,
662
+ ScheduleEvaluationState,
663
+ ScheduleEverySpec,
664
+ ScheduleFireTrigger,
665
+ ScheduleJobLifecycle,
666
+ ScheduleMissedReason,
667
+ ScheduleObservedGap,
668
+ ScheduleSkipReason,
669
+ ScheduleSpec,
670
+ } from './schedules/index.js'
671
+ export type {
672
+ ScheduleBrowserGrant,
673
+ ScheduleBrowserSiteLevel,
674
+ ScheduleConfirmAnswer,
675
+ ScheduleConfirmRequest,
676
+ ScheduleJobChanges,
677
+ ScheduleJobDraft,
678
+ ScheduleJobPreview,
679
+ ScheduleJobSummary,
680
+ ScheduleJobUpdateProposal,
681
+ ScheduleRuleEffect,
682
+ ScheduleToolHost,
683
+ ScheduleUpdateRequest,
684
+ SessionLoop,
685
+ SessionLoopHost,
686
+ } from './tools/schedules/index.js'
@@ -0,0 +1,37 @@
1
+ import type { ToolRegistryContract } from '../../types/tool/index.js'
2
+
3
+ /**
4
+ * The tools a call on this step can reach: registered now, active, and on
5
+ * the step's allow-list when it has one. In registry order.
6
+ *
7
+ * This is what every "Available: …" a model is shown must say, because a
8
+ * model takes it literally and calls the next name on it. Two answers used
9
+ * to build that list separately and disagreed. A refusal echoed the step's
10
+ * allow-list, which is a snapshot taken when the request was built and so
11
+ * can name a tool unregistered since — a connector that disconnected — or
12
+ * one that is deferred or suspended, which the executor refuses. An
13
+ * unknown-tool error listed the whole registry, which on a narrowed step is
14
+ * mostly tools the step refuses. Each sent the model to a name the other
15
+ * one answered, and a run went round between them until it was stopped.
16
+ *
17
+ * `allowed` absent means the step is not narrowed. An EMPTY list is a step
18
+ * that may call nothing, and the answer is then empty too.
19
+ */
20
+ export function callableToolNames(
21
+ tools: Pick<ToolRegistryContract, 'listNames' | 'getAvailability'>,
22
+ allowed: readonly string[] | undefined,
23
+ ): string[] {
24
+ const permitted = allowed === undefined ? undefined : new Set(allowed)
25
+ return tools
26
+ .listNames()
27
+ .filter(
28
+ (name) =>
29
+ (permitted === undefined || permitted.has(name)) &&
30
+ tools.getAvailability(name) === 'active',
31
+ )
32
+ }
33
+
34
+ /** The list as a model reads it: comma-separated, or `(none)`. */
35
+ export function formatToolNames(names: readonly string[]): string {
36
+ return names.length > 0 ? names.join(', ') : '(none)'
37
+ }
@@ -20,6 +20,7 @@ import type {
20
20
  import { toErrorMessage } from '../../utils/error.js'
21
21
  import { cloneJsonValue as clonePreparedInput } from '../../utils/json-snapshot.js'
22
22
  import { ManagedRegistry } from '../ManagedRegistry.js'
23
+ import { callableToolNames, formatToolNames } from './callable.js'
23
24
  import { renderToolSchema, toolWireSchema } from './schema.js'
24
25
  import { ToolResultHalted, screenToolResult } from './screen.js'
25
26
 
@@ -636,9 +637,15 @@ Executable tool names, descriptions, and JSON input schemas are attached through
636
637
  // that may call nothing, and treating it as "no restriction" is
637
638
  // the fail-open reading this codebase has already been bitten by
638
639
  // once, in the delegate roster.
640
+ //
641
+ // What it says is available is what would run, not the list
642
+ // itself: the list was taken when the request was built, and a
643
+ // name on it may since have been unregistered, or be deferred or
644
+ // suspended. Echoing it sent a model to a name that was then
645
+ // answered "unknown tool". See `callableToolNames`.
639
646
  const allowed = context.allowedTools
640
647
  if (allowed !== undefined && !allowed.includes(toolName)) {
641
- const msg = `Tool "${toolName}" is not available on this step. Available: ${allowed.length > 0 ? allowed.join(', ') : '(none)'}`
648
+ const msg = `Tool "${toolName}" is not available on this step. Available: ${formatToolNames(callableToolNames(this, allowed))}`
642
649
  this.log.warn('Blocked a tool outside the step allow-list', {
643
650
  [GENAI.TOOL_NAME]: toolName,
644
651
  'namzu.registry.allowed': allowed.length,
@@ -0,0 +1,12 @@
1
+ /**
2
+ * What the model is told when a person declines its tool calls and gave no
3
+ * words of their own.
4
+ *
5
+ * "Declined" alone reads to a model as an obstacle to route around: in a live
6
+ * session an operator refused a browser navigation and the model fetched the
7
+ * same page through web search instead. The refusal is about the outcome, not
8
+ * the tool, so the text says so — for every tool, since any of them can be
9
+ * swapped for another that reaches the same place.
10
+ */
11
+ export const DECLINED_TOOL_CALL_FEEDBACK =
12
+ 'The user declined this. Do not get the same content or result another way (another tool, another site or address, or a web search) unless you ask the user first and they agree. Say what you wanted to do, or carry on without it.'
@@ -1,4 +1,5 @@
1
1
  import { GENAI, NAMZU } from '../../../constants/telemetry/index.js'
2
+ import { callableToolNames, formatToolNames } from '../../../registry/tool/callable.js'
2
3
  import { renderToolSchema } from '../../../registry/tool/schema.js'
3
4
  import type { ToolCall } from '../../../types/message/index.js'
4
5
  import type { PluginHookResult } from '../../../types/plugin/index.js'
@@ -24,16 +25,43 @@ import { skippedToolResultText } from '../plugin-hooks.js'
24
25
  * here dispatches a tool, and nothing here writes a result: that is the
25
26
  * executor's half.
26
27
  *
27
- * The family reads exactly three things off the executor it serves, and they
28
+ * The family reads exactly four things off the executor it serves, and they
28
29
  * arrive as one value rather than as a captured reference: the tool registry
29
- * config, the event sink and the logger. `config` in particular is read
30
- * per call and never held — `ToolExecutor.setSandbox` REPLACES it, so a host
31
- * captured once would hand the next admission a stale sandbox.
30
+ * config, the event sink, the logger and the current step's allow-list.
31
+ * `config` in particular is read per call and never held —
32
+ * `ToolExecutor.setSandbox` REPLACES it, so a host captured once would hand
33
+ * the next admission a stale sandbox.
32
34
  */
33
35
  export interface ToolAdmissionHost {
34
36
  readonly config: ToolExecutorConfig
35
37
  readonly emitEvent: EmitEvent
36
38
  readonly log: Logger
39
+ /**
40
+ * What the current step may call: the step's own list where
41
+ * `prepareStep` gave one, the turn's `allowedTools` otherwise, absent
42
+ * when nothing narrowed the turn. NOT `config.allowedTools`, which is
43
+ * only the turn's; the step's list lives on the executor.
44
+ *
45
+ * Required, with `undefined` as a value, so that a host has to say.
46
+ * Leaving it out would list the whole registry to a model on a narrowed
47
+ * step, which is the answer that sent a model round in a circle.
48
+ */
49
+ readonly allowedTools: readonly string[] | undefined
50
+ }
51
+
52
+ /**
53
+ * The answer to a call naming a tool the registry does not hold, without
54
+ * the `Error: ` a direct call's result carries.
55
+ *
56
+ * It lists what the current step can call — the same list a step refusal
57
+ * gives — rather than what the registry holds. The registry's own
58
+ * "Not found" lists every tool it has, and on a narrowed step that is
59
+ * mostly tools the next call would be refused.
60
+ */
61
+ export function unknownToolMessage(host: ToolAdmissionHost, toolName: string): string {
62
+ return `Unknown tool "${toolName}". Available: ${formatToolNames(
63
+ callableToolNames(host.config.tools, host.allowedTools),
64
+ )}`
37
65
  }
38
66
 
39
67
  export async function runPreToolHook(
@@ -163,7 +191,11 @@ export async function prepareDirectCall(
163
191
  try {
164
192
  preparation = prepare.call(host.config.tools, toolName, parsed)
165
193
  } catch (err) {
166
- const message = `Error: Unknown or unavailable tool "${toolName}": ${toErrorMessage(err)}`
194
+ // A name the registry does not hold gets the step's list, not the
195
+ // registry's "Not found", which lists everything it holds.
196
+ const message = isUnregistered(host, toolName)
197
+ ? `Error: ${unknownToolMessage(host, toolName)}`
198
+ : `Error: Unknown or unavailable tool "${toolName}": ${toErrorMessage(err)}`
167
199
  const repair =
168
200
  !repairUsed && host.config.repairToolCall
169
201
  ? await requestRepair(host, toolCall, toolName, {
@@ -295,13 +327,15 @@ function interpretPreToolResults(
295
327
  * broken will not do better on a second look, and an unbounded loop
296
328
  * here is a hang rather than a degradation.
297
329
  *
298
- * `invalid_json` is the ONLY failure that stops the call here, and it
299
- * stopped it before this function existed too. `unknown_tool` and
300
- * `schema_validation` merely OFFER the repair and otherwise fall
301
- * through to the registry, which reports both with better messages —
302
- * its schema error already ships a "Required: <field>: <type>" hint the
303
- * model can self-correct from. So with no repairer configured this is
304
- * behaviorally identical to the bare `JSON.parse` it replaced.
330
+ * `invalid_json` stops the call here, and it stopped it before this
331
+ * function existed too. So does an `unknown_tool` the registry confirms
332
+ * it does not hold: the registry's own answer to that is "Not found",
333
+ * listing every tool it has, where the model needs the ones this step can
334
+ * call — see `unknownToolMessage`. `schema_validation`, and an unknown
335
+ * tool on a registry that cannot say, merely OFFER the repair and
336
+ * otherwise fall through to the registry, whose schema error already
337
+ * ships a "Required: <field>: <type>" hint the model can self-correct
338
+ * from.
305
339
  */
306
340
  export async function resolveCall(
307
341
  host: ToolAdmissionHost,
@@ -322,7 +356,10 @@ export async function resolveCall(
322
356
  : null
323
357
 
324
358
  if (!repair) {
325
- if (failure.reason === 'invalid_json') {
359
+ if (
360
+ failure.reason === 'invalid_json' ||
361
+ (failure.reason === 'unknown_tool' && isUnregistered(host, toolName))
362
+ ) {
326
363
  return { ok: false, toolName, message: failure.message }
327
364
  }
328
365
  return { ok: true, toolName, input: parseArguments(raw) }
@@ -392,11 +429,13 @@ function inspectCall(
392
429
  const tool = host.config.tools.get?.(toolName)
393
430
  if (!tool) {
394
431
  // Either the model named a tool that does not exist, or this
395
- // registry does not implement `get`. Both are the registry's to
396
- // answer; a repairer still gets offered the `unknown_tool` case.
432
+ // registry does not implement `get`. A repairer gets offered both;
433
+ // only the first is answered here, and with the step's list.
397
434
  return {
398
435
  reason: 'unknown_tool',
399
- message: `Error: Unknown tool "${toolName}"`,
436
+ message: isUnregistered(host, toolName)
437
+ ? `Error: ${unknownToolMessage(host, toolName)}`
438
+ : `Error: Unknown tool "${toolName}"`,
400
439
  }
401
440
  }
402
441
 
@@ -416,6 +455,11 @@ function inspectCall(
416
455
  return null
417
456
  }
418
457
 
458
+ /** The registry says it does not hold this name — not merely that it cannot look it up. */
459
+ export function isUnregistered(host: ToolAdmissionHost, toolName: string): boolean {
460
+ return typeof host.config.tools.has === 'function' && !host.config.tools.has(toolName)
461
+ }
462
+
419
463
  async function requestRepair(
420
464
  host: ToolAdmissionHost,
421
465
  toolCall: ToolCall,
@@ -39,6 +39,7 @@ import type {
39
39
  SkillRegistryRef,
40
40
  ToolContext,
41
41
  ToolDispatchOptions,
42
+ ToolHandoff,
42
43
  ToolRegistryContract,
43
44
  ToolResult,
44
45
  } from '../../types/tool/index.js'
@@ -54,11 +55,13 @@ import { type BackgroundJobRegistry, type JobProcess, bindOwner } from '../jobs/
54
55
  import {
55
56
  type ToolAdmissionHost,
56
57
  formatFailedToolOutput,
58
+ isUnregistered,
57
59
  prepareDirectCall,
58
60
  repairTruncatedCall,
59
61
  resolveCall,
60
62
  runPreToolHook,
61
63
  truncatedToolInputMessage,
64
+ unknownToolMessage,
62
65
  } from './executor/tool-call-admission.js'
63
66
  import { describeVisibleFileEvidence } from './file-evidence-context.js'
64
67
  import { seedObservationLedger } from './file-evidence-seed.js'
@@ -489,6 +492,8 @@ export interface ToolCallOutcome {
489
492
  /** Rich form for the model, when the tool supplied one. */
490
493
  content?: ToolResultContent
491
494
  isError?: boolean
495
+ /** The tool asked for a person; see `ToolResult.handoff`. */
496
+ handoff?: ToolHandoff
492
497
  }
493
498
 
494
499
  export interface ToolExecutionBatch {
@@ -1446,9 +1451,16 @@ export class ToolExecutor {
1446
1451
  }
1447
1452
 
1448
1453
  private resultPresentation(name: string, input: unknown, result: ToolResult) {
1449
- if (!result.success) return {}
1450
1454
  try {
1451
1455
  const view = this.config.tools.get(name)?.presentResult?.(input, result)
1456
+ // A failed call carries one view only: the person's No on the tool's
1457
+ // own screen, which a host draws as cancelled rather than failed and
1458
+ // cannot tell apart from the result text alone.
1459
+ if (!result.success) {
1460
+ return view?.kind === 'generic' && view.outcome === 'cancelled'
1461
+ ? { presentation: { kind: 'generic', label: view.label, outcome: 'cancelled' } as const }
1462
+ : {}
1463
+ }
1452
1464
  if (view?.kind !== 'diff') return {}
1453
1465
  const serialized = JSON.stringify(view)
1454
1466
  if (serialized.length > (this.config.maxToolOutputChars ?? DEFAULT_MAX_TOOL_OUTPUT_CHARS))
@@ -2004,6 +2016,12 @@ export class ToolExecutor {
2004
2016
  // a result whose image is unaffected — and a hook that needs it gone
2005
2017
  // says so with `content`, which wins over both.
2006
2018
  ...(modelContent !== undefined ? { content: modelContent } : {}),
2019
+ // Carried whatever a post-tool hook did to the text: the request is
2020
+ // the tool's statement about the world, not about its output, and a
2021
+ // hook that redacts a sign-in page has not signed anyone in.
2022
+ ...(result.handoff !== undefined && !this.config.abortSignal.aborted
2023
+ ? { handoff: result.handoff }
2024
+ : {}),
2007
2025
  }
2008
2026
  }
2009
2027
 
@@ -2186,10 +2204,12 @@ export class ToolExecutor {
2186
2204
  }
2187
2205
 
2188
2206
  /**
2189
- * The three things the admission family reads off this executor.
2207
+ * The four things the admission family reads off this executor.
2190
2208
  *
2191
2209
  * Built per call rather than held: `setSandbox` REPLACES `config`, so a
2192
- * host captured once would hand the next admission a stale sandbox.
2210
+ * host captured once would hand the next admission a stale sandbox. The
2211
+ * allow-list is the step's, taken the same way and for a like reason:
2212
+ * `setStepAllowedTools` replaces it every step.
2193
2213
  *
2194
2214
  * The one way this differs from the inline code it replaced, which
2195
2215
  * re-read `this.config` at every use: an admission that spans a
@@ -2200,7 +2220,12 @@ export class ToolExecutor {
2200
2220
  * before the loop, so nothing in this tree can tell them apart.
2201
2221
  */
2202
2222
  private admissionHost(): ToolAdmissionHost {
2203
- return { config: this.config, emitEvent: this.emitEvent, log: this.log }
2223
+ return {
2224
+ config: this.config,
2225
+ emitEvent: this.emitEvent,
2226
+ log: this.log,
2227
+ allowedTools: this.effectiveAllowedTools(),
2228
+ }
2204
2229
  }
2205
2230
 
2206
2231
  private async prepareNestedCall(
@@ -2235,10 +2260,16 @@ export class ToolExecutor {
2235
2260
  try {
2236
2261
  preparation = prepare.call(this.config.tools, toolName, input)
2237
2262
  } catch (err) {
2263
+ // A name the registry does not hold is answered with what this step
2264
+ // can call, as a model's own call is; the registry's "Not found"
2265
+ // lists everything it holds.
2266
+ const host = this.admissionHost()
2238
2267
  return {
2239
2268
  kind: 'synthetic',
2240
2269
  input,
2241
- message: `Tool "${toolName}" could not be prepared: ${toErrorMessage(err)}`,
2270
+ message: isUnregistered(host, toolName)
2271
+ ? unknownToolMessage(host, toolName)
2272
+ : `Tool "${toolName}" could not be prepared: ${toErrorMessage(err)}`,
2242
2273
  isError: true,
2243
2274
  }
2244
2275
  }
@@ -1462,6 +1462,7 @@ export async function* query(params: QueryParams): AsyncGenerator<SessionEvent,
1462
1462
  provider: resilientProvider,
1463
1463
  providerCapabilities: capabilities,
1464
1464
  strictCapabilities: params.strictCapabilities === true,
1465
+ ...(params.parentSessionId !== undefined ? { delegated: true } : {}),
1465
1466
  servingMember: () => serving.current,
1466
1467
  turnConfig,
1467
1468
  ...(params.stopWhen ? { stopWhen: params.stopWhen } : {}),
@@ -71,6 +71,7 @@ import {
71
71
  relieveOverflow,
72
72
  runCompactionCheck,
73
73
  } from './phases/compaction.js'
74
+ import { runHandoffPause } from './phases/handoff.js'
74
75
  import type { IterationContext } from './phases/index.js'
75
76
  import { runPlanGate } from './phases/plan.js'
76
77
  import { runToolReview } from './phases/tool-review.js'
@@ -1421,6 +1422,13 @@ export class IterationOrchestrator {
1421
1422
  return
1422
1423
  }
1423
1424
 
1425
+ // A tool asked for a person. The whole batch is committed; the
1426
+ // turn parks here rather than asking the model what to do about
1427
+ // something only the operator can do.
1428
+ if ((yield* runHandoffPause(this.ctx, iterationNum, reviewOutcome.results)) === 'stop') {
1429
+ return
1430
+ }
1431
+
1424
1432
  if (reviewOutcome.decision === 'rejected') {
1425
1433
  continue
1426
1434
  }
@@ -44,6 +44,12 @@ import type { ToolGrantSet } from '../../tool-grants.js'
44
44
 
45
45
  export interface IterationContext {
46
46
  readonly provider: LLMProvider
47
+ /**
48
+ * The turn runs in a delegated child session. A tool's request for a
49
+ * person then fails the turn instead of pausing it: nobody is watching
50
+ * a child to resume it, and its parent is waiting on a result.
51
+ */
52
+ readonly delegated?: boolean
47
53
  /** Driver-level request shapes negotiated for this turn. */
48
54
  readonly providerCapabilities?: ResolvedProviderCapabilities
49
55
  /** Refuse a capability mismatch instead of emitting a warning and degrading. */