@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.
- package/CHANGELOG.md +94 -0
- package/dist/authorization/command-line.d.ts +66 -19
- package/dist/authorization/command-line.d.ts.map +1 -1
- package/dist/authorization/command-line.js +130 -270
- package/dist/authorization/command-line.js.map +1 -1
- package/dist/authorization/gate.d.ts +7 -0
- package/dist/authorization/gate.d.ts.map +1 -1
- package/dist/authorization/gate.js +13 -3
- package/dist/authorization/gate.js.map +1 -1
- package/dist/authorization/rules.d.ts +10 -1
- package/dist/authorization/rules.d.ts.map +1 -1
- package/dist/authorization/rules.js +55 -8
- package/dist/authorization/rules.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts +152 -0
- package/dist/authorization/shell-lexer.d.ts.map +1 -0
- package/dist/authorization/shell-lexer.js +2156 -0
- package/dist/authorization/shell-lexer.js.map +1 -0
- package/dist/authorization/skill-grant.d.ts +182 -0
- package/dist/authorization/skill-grant.d.ts.map +1 -0
- package/dist/authorization/skill-grant.js +314 -0
- package/dist/authorization/skill-grant.js.map +1 -0
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +2 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +1 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/directory/types.d.ts +2 -0
- package/dist/directory/types.d.ts.map +1 -1
- package/dist/directory/types.js.map +1 -1
- package/dist/manager/resident/outbox.d.ts +4 -4
- package/dist/persona/assembler.d.ts.map +1 -1
- package/dist/persona/assembler.js +5 -2
- package/dist/persona/assembler.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +1 -0
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/public-runtime.d.ts +5 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +15 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +4 -0
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +12 -1
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +9 -1
- package/dist/public-types.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.d.ts +2 -2
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +6 -2
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/declined.d.ts +12 -0
- package/dist/runtime/query/declined.d.ts.map +1 -0
- package/dist/runtime/query/declined.js +12 -0
- package/dist/runtime/query/declined.js.map +1 -0
- package/dist/runtime/query/executor.d.ts +36 -40
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +95 -53
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +8 -0
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +13 -0
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +13 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/handoff.d.ts +22 -0
- package/dist/runtime/query/iteration/phases/handoff.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/handoff.js +65 -0
- package/dist/runtime/query/iteration/phases/handoff.js.map +1 -0
- package/dist/runtime/query/iteration/phases/index.d.ts +1 -0
- package/dist/runtime/query/iteration/phases/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/index.js +1 -0
- package/dist/runtime/query/iteration/phases/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +56 -3
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/resume-pending.d.ts.map +1 -1
- package/dist/runtime/query/resume-pending.js +3 -2
- package/dist/runtime/query/resume-pending.js.map +1 -1
- package/dist/runtime/query/review-policy.d.ts +11 -0
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +36 -3
- package/dist/runtime/query/review-policy.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +3 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +1 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/schedules/cron.d.ts +21 -0
- package/dist/schedules/cron.d.ts.map +1 -0
- package/dist/schedules/cron.js +167 -0
- package/dist/schedules/cron.js.map +1 -0
- package/dist/schedules/describe.d.ts +14 -0
- package/dist/schedules/describe.d.ts.map +1 -0
- package/dist/schedules/describe.js +133 -0
- package/dist/schedules/describe.js.map +1 -0
- package/dist/schedules/errors.d.ts +11 -0
- package/dist/schedules/errors.d.ts.map +1 -0
- package/dist/schedules/errors.js +15 -0
- package/dist/schedules/errors.js.map +1 -0
- package/dist/schedules/evaluate.d.ts +35 -0
- package/dist/schedules/evaluate.d.ts.map +1 -0
- package/dist/schedules/evaluate.js +158 -0
- package/dist/schedules/evaluate.js.map +1 -0
- package/dist/schedules/index.d.ts +11 -0
- package/dist/schedules/index.d.ts.map +1 -0
- package/dist/schedules/index.js +8 -0
- package/dist/schedules/index.js.map +1 -0
- package/dist/schedules/next-fire.d.ts +50 -0
- package/dist/schedules/next-fire.d.ts.map +1 -0
- package/dist/schedules/next-fire.js +250 -0
- package/dist/schedules/next-fire.js.map +1 -0
- package/dist/schedules/spec.d.ts +30 -0
- package/dist/schedules/spec.d.ts.map +1 -0
- package/dist/schedules/spec.js +169 -0
- package/dist/schedules/spec.js.map +1 -0
- package/dist/schedules/types.d.ts +144 -0
- package/dist/schedules/types.d.ts.map +1 -0
- package/dist/schedules/types.js +11 -0
- package/dist/schedules/types.js.map +1 -0
- package/dist/schedules/tz.d.ts +44 -0
- package/dist/schedules/tz.d.ts.map +1 -0
- package/dist/schedules/tz.js +141 -0
- package/dist/schedules/tz.js.map +1 -0
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -1
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/loader.d.ts +21 -0
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +51 -1
- package/dist/skills/loader.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +18 -6
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/browser-url.d.ts +83 -0
- package/dist/tools/builtins/browser-url.d.ts.map +1 -0
- package/dist/tools/builtins/browser-url.js +240 -0
- package/dist/tools/builtins/browser-url.js.map +1 -0
- package/dist/tools/builtins/browser.d.ts +367 -0
- package/dist/tools/builtins/browser.d.ts.map +1 -0
- package/dist/tools/builtins/browser.js +704 -0
- package/dist/tools/builtins/browser.js.map +1 -0
- package/dist/tools/builtins/skill.d.ts +2 -9
- package/dist/tools/builtins/skill.d.ts.map +1 -1
- package/dist/tools/builtins/skill.js +74 -51
- package/dist/tools/builtins/skill.js.map +1 -1
- package/dist/tools/command-shell.d.ts +90 -0
- package/dist/tools/command-shell.d.ts.map +1 -0
- package/dist/tools/command-shell.js +129 -0
- package/dist/tools/command-shell.js.map +1 -0
- package/dist/tools/defineTool.d.ts +13 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +30 -1
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/tools/schedules/index.d.ts +5 -0
- package/dist/tools/schedules/index.d.ts.map +1 -0
- package/dist/tools/schedules/index.js +4 -0
- package/dist/tools/schedules/index.js.map +1 -0
- package/dist/tools/schedules/loop-tool.d.ts +14 -0
- package/dist/tools/schedules/loop-tool.d.ts.map +1 -0
- package/dist/tools/schedules/loop-tool.js +81 -0
- package/dist/tools/schedules/loop-tool.js.map +1 -0
- package/dist/tools/schedules/present.d.ts +16 -0
- package/dist/tools/schedules/present.d.ts.map +1 -0
- package/dist/tools/schedules/present.js +69 -0
- package/dist/tools/schedules/present.js.map +1 -0
- package/dist/tools/schedules/prompt-scan.d.ts +17 -0
- package/dist/tools/schedules/prompt-scan.d.ts.map +1 -0
- package/dist/tools/schedules/prompt-scan.js +92 -0
- package/dist/tools/schedules/prompt-scan.js.map +1 -0
- package/dist/tools/schedules/schedule-tool.d.ts +16 -0
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -0
- package/dist/tools/schedules/schedule-tool.js +327 -0
- package/dist/tools/schedules/schedule-tool.js.map +1 -0
- package/dist/tools/schedules/types.d.ts +184 -0
- package/dist/tools/schedules/types.d.ts.map +1 -0
- package/dist/tools/schedules/types.js +11 -0
- package/dist/tools/schedules/types.js.map +1 -0
- package/dist/types/authorization/index.d.ts +86 -9
- package/dist/types/authorization/index.d.ts.map +1 -1
- package/dist/types/authorization/index.js +11 -1
- package/dist/types/authorization/index.js.map +1 -1
- package/dist/types/browser/index.d.ts +280 -0
- package/dist/types/browser/index.d.ts.map +1 -0
- package/dist/types/browser/index.js +12 -0
- package/dist/types/browser/index.js.map +1 -0
- package/dist/types/hitl/index.d.ts +23 -0
- package/dist/types/hitl/index.d.ts.map +1 -1
- package/dist/types/hitl/index.js.map +1 -1
- package/dist/types/session/events.d.ts +6 -0
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +23 -0
- package/dist/types/session/records.d.ts.map +1 -1
- package/dist/types/session/records.js +9 -0
- package/dist/types/session/records.js.map +1 -1
- package/dist/types/tool/index.d.ts +108 -5
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/types/tool/presentation.d.ts +7 -0
- package/dist/types/tool/presentation.d.ts.map +1 -1
- package/dist/utils/frontmatter.d.ts +35 -3
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +45 -5
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/id.d.ts +8 -0
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +12 -0
- package/dist/utils/id.js.map +1 -1
- package/package.json +1 -1
- package/src/authorization/command-line.ts +148 -293
- package/src/authorization/gate.ts +22 -2
- package/src/authorization/rules.ts +67 -8
- package/src/authorization/shell-lexer.ts +2349 -0
- package/src/authorization/skill-grant.ts +400 -0
- package/src/bridge/a2a/mapper.ts +2 -0
- package/src/bridge/sse/mapper.ts +1 -0
- package/src/directory/types.ts +2 -0
- package/src/persona/assembler.ts +5 -2
- package/src/prompt/coding-agent-doctrine.ts +1 -0
- package/src/public-runtime.ts +37 -0
- package/src/public-tools.ts +37 -1
- package/src/public-types.ts +57 -0
- package/src/runtime/jobs/registry.ts +19 -11
- package/src/runtime/query/declined.ts +12 -0
- package/src/runtime/query/executor.ts +116 -56
- package/src/runtime/query/index.ts +8 -0
- package/src/runtime/query/iteration/index.ts +13 -0
- package/src/runtime/query/iteration/phases/context.ts +13 -0
- package/src/runtime/query/iteration/phases/handoff.ts +74 -0
- package/src/runtime/query/iteration/phases/index.ts +1 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +55 -3
- package/src/runtime/query/resume-pending.ts +3 -2
- package/src/runtime/query/review-policy.ts +57 -3
- package/src/runtime/query/tooling.ts +4 -0
- package/src/schedules/cron.ts +202 -0
- package/src/schedules/describe.ts +138 -0
- package/src/schedules/errors.ts +15 -0
- package/src/schedules/evaluate.ts +178 -0
- package/src/schedules/index.ts +18 -0
- package/src/schedules/next-fire.ts +257 -0
- package/src/schedules/spec.ts +210 -0
- package/src/schedules/types.ts +163 -0
- package/src/schedules/tz.ts +155 -0
- package/src/skills/index.ts +1 -1
- package/src/skills/loader.ts +59 -1
- package/src/tools/builtins/bash.ts +24 -6
- package/src/tools/builtins/browser-url.ts +251 -0
- package/src/tools/builtins/browser.ts +817 -0
- package/src/tools/builtins/skill.ts +92 -53
- package/src/tools/command-shell.ts +166 -0
- package/src/tools/defineTool.ts +36 -1
- package/src/tools/schedules/index.ts +4 -0
- package/src/tools/schedules/loop-tool.ts +85 -0
- package/src/tools/schedules/present.ts +86 -0
- package/src/tools/schedules/prompt-scan.ts +96 -0
- package/src/tools/schedules/schedule-tool.ts +376 -0
- package/src/tools/schedules/types.ts +197 -0
- package/src/types/authorization/index.ts +60 -2
- package/src/types/browser/index.ts +341 -0
- package/src/types/hitl/index.ts +21 -0
- package/src/types/session/events.ts +6 -0
- package/src/types/session/records.ts +10 -0
- package/src/types/tool/index.ts +109 -5
- package/src/types/tool/presentation.ts +7 -0
- package/src/utils/frontmatter.ts +81 -5
- package/src/utils/id.ts +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,99 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 45.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2b96136: Add the browser tool contract, let `argument_pattern` rules ask for review, and let a scheduled-job proposal carry a browser grant.
|
|
8
|
+
|
|
9
|
+
**Browser tools (new).** `createBrowserTools(host)` returns two tools over a `BrowserHost` you supply: `browser` (navigate, back, forward, reload, snapshot, screenshot, scroll, wait_for, tabs) and `browser_act` (click, type, fill_form, select, press, hover, upload, dialog). The SDK ships no browser engine. Every `browser_act` call carries a required `origin`, and the host contract says the host compares it with the live page before acting. `url` and `origin` are canonicalised by the input schema (WHATWG form, punycode, no default port, no trailing dot on the host). Other schemes, credentials in the URL and cloud metadata addresses in any spelling are refused. Because the gate sees the canonical value, a site rule matches the address the browser loads. Page text is returned inside `wrapUntrusted`, under a `Page: <origin> — "<title>" (tab tN)` header. Hosts refuse by throwing structural shapes (`browser_origin_mismatch`, `browser_stale_ref`, `browser_human_required`, `browser_outcome_unknown`, `browser_site_denied`). New exports: `createBrowserTools`, `BROWSER_TOOL_NAME`, `BROWSER_ACT_TOOL_NAME`, `isBrowserCallReadOnly`, `browserHostErrorOf`, `formatBrowserPageHeader`, `canonicalizeBrowserUrl`, `canonicalizeBrowserOrigin`, `canonicalizeBrowserSitePattern`, `isCloudMetadataHost`, `BROWSER_URL_MAX_LENGTH`, `BROWSER_SNAPSHOT_MAX_CHARS`, `BROWSER_WAIT_MAX_MS`, `BROWSER_FILL_FORM_MAX_FIELDS`, and the types in their signatures (`BrowserHost`, `BrowserCapabilities`, the action, result and error types). Both tools are `category: 'network'`. Do not pair them with a preset that allows network tools by category because a sandbox confines egress: the browser runs outside the sandbox.
|
|
10
|
+
|
|
11
|
+
**`argument_pattern` with `decision: 'review'` (widened union).** `AuthorizationRule`'s `argument_pattern` variant now accepts `'review'`. It matches as `deny` does: the whole value, then every segment of a command line. Code that switches exhaustively over that variant's `decision`, or narrows it to `'allow' | 'deny'`, needs a `review` branch. Existing rules behave as before.
|
|
12
|
+
|
|
13
|
+
**`ToolDefinition.urlArgument` (new, optional).** A tool whose input schema canonicalises an argument to a URL can declare it. An `argument_pattern` rule on that argument then tests the value whole, instead of cutting it at `&`, `;` or `|` as a command line, which made an `allow` for a site decline every address with a query string. Tools that do not declare it are unchanged. `defineTool` accepts it too.
|
|
14
|
+
|
|
15
|
+
**Reason text.** A `custom_pattern` rule with `decision: 'review'` is now described as `sent for review by a pattern rule …`; it used to say `allowed by …`. If you match on the old text, update the match.
|
|
16
|
+
|
|
17
|
+
**Scheduled jobs.** `ScheduleJobDraft.permissions.browser?: ScheduleBrowserGrant` (`profile`, `sites` mapping each site to `read`, `ask` or `act`, `headed?`) and `ScheduleToolHost.browserGrants?: boolean` are new. The `schedule` tool refuses a proposed browser grant unless your host sets `browserGrants: true`, so a host that does not know the field keeps working unchanged and never silently drops a grant. It canonicalises site keys and refuses `*`. It also treats the grant as network access, so the grant is refused beside a shell on the host. The refusal for web access beside a host shell now says "web or browser access".
|
|
18
|
+
|
|
19
|
+
See `docs/sdk/browser-tools.md` and `docs/sdk/review-policy.md#rules-that-ask`.
|
|
20
|
+
|
|
21
|
+
- 2b96136: A generic tool result view may now set `outcome: 'cancelled'` for a call the person declined on the tool's own screen. `save_skill` and the `schedule` tool's `create`, `resume` and `delete` use it (the `schedule` tool also sets `data.cancelled` on those results), and the TUI shows the row as `○ … Cancelled — nothing was saved` instead of `✗ … failed: Error: The operator cancelled`. The model still receives the same refusal text.
|
|
22
|
+
- 2b96136: A tool call a person declines without giving a reason now tells the model not to get the same content or result another way — another tool, another site or address, or a web search — unless it asks first and the person agrees. The text was "User declined to run the proposed tool(s)." (and "The user rejected this tool call." on a resumed decision); in a live session a model whose browser navigation was declined fetched the same page through web search instead.
|
|
23
|
+
|
|
24
|
+
New export: `DECLINED_TOOL_CALL_FEEDBACK`, the text. A host that passes its own `feedback` with a refusal is unchanged. A test or host that matched the old default text must match the new one.
|
|
25
|
+
|
|
26
|
+
- d233f26: Add a `predicate` authorization rule, and export the command-line lexer the gate uses.
|
|
27
|
+
|
|
28
|
+
- `AuthorizationRule` gains `{ type: 'predicate', description, decide }`. `decide(call)` receives the tool name, input, definition and the `commandDialect` the line runs in (`sh` when the caller did not say) and returns `allow`, `deny`, `review` or `null`; it sits in its place in the rule list, after the dangerous-command floor. A `decide` that throws is read as `deny`. New types `AuthorizationPredicate` and `AuthorizationPredicateCall`.
|
|
29
|
+
- `lexShellCommandLine` is exported, with `ShellLexResult`, `ShellCommand`, `ShellWord`, `ShellRedirection` and `ShellLexOptions`, so a predicate reads a command line exactly as the gate does.
|
|
30
|
+
- A lexer result also reports `compoundWords` (a `for` or `select` loop's variable and list, a `case` statement's subject and patterns) and, on a here-document redirection, its `body`.
|
|
31
|
+
|
|
32
|
+
Nothing existing changes behaviour. `AuthorizationRule` is also the type of `GateEvaluationResult.matchedRule`: code that switches over `rule.type` with an exhaustive check (`const x: never = rule`) needs a `predicate` case or a `default:` branch to compile.
|
|
33
|
+
|
|
34
|
+
- 2b96136: `ScheduleToolHost.create()` may return an optional `note`, which the `schedule` tool appends to what the model is told about the new job. Existing hosts that return only `{ name }` are unaffected. The CLI uses it to tell the model that no scheduler is installed, so its reply no longer promises a run that cannot happen until you run `namzu schedule install`.
|
|
35
|
+
- d233f26: Add a schedule time engine and evaluator, and the `schedule` and `session_loop` tools.
|
|
36
|
+
|
|
37
|
+
New exports, all additive: `parseScheduleSpec`, `parseCronExpression`, `nextFireTime`, `previousFireTime`, `upcomingFireTimes`, `countOccurrences`, `describeSchedule`, `validateTimeZone`, `hostTimeZone`, `parseDuration`, `evaluateJob`, `ScheduleValidationError`, `SCHEDULE_CATCH_UP_WINDOW_MS`, `SCHEDULE_LATE_GRACE_MS`, `buildScheduleTools`, `buildSessionLoopTools`, `scanSchedulePrompt`, `revealHiddenCharacters`, `SCHEDULE_TOOL_NAME`, `SESSION_LOOP_TOOL_NAME`, `generateScheduleJobId`, `generateScheduleRunId`, and the types in their signatures (`ScheduleSpec` and its three variants, `CronExpression`, `ScheduleEvaluationInput`, `ScheduleDecision`, `ScheduleSkipReason`, `ScheduleMissedReason`, `ScheduleToolHost`, `ScheduleJobDraft`, `ScheduleJobPreview`, `SessionLoopHost`, `SessionLoop` and their neighbours).
|
|
38
|
+
|
|
39
|
+
Everything here is pure: `Intl` for time zones, no clock, no I/O, no new dependency. Cron follows cronie's DST rule (a fixed-time job fires once across a change; a wildcard job fires at every matching instant). Nothing existing changes. `ScheduleDecision`, `ScheduleSkipReason` and `ScheduleMissedReason` may gain members in a later minor release, so switch over them with a `default:` branch. See `docs/sdk/schedules.md`.
|
|
40
|
+
|
|
41
|
+
- 2b96136: `loadSkill` (and so `SkillRegistry`) skips frontmatter keys it does not read, whatever YAML they are written in, instead of refusing the whole file: a `SKILL.md` carrying `argument-hint: [file]` or a `hooks:` block with a list now loads with those fields ignored. The keys it does read are still parsed strictly; they are exported as `SKILL_FRONTMATTER_KEYS`. `disable-model-invocation: true` now reads as `invocation: operator`; a value other than `true` or `false`, or one that contradicts an explicit `invocation`, refuses the file. `parseFrontmatter` takes an optional third argument, `{ readsKey }`, to get the same leniency for a caller's own vocabulary; without it every key is parsed and refused as before. A skill file that used to be refused over an unread key now loads, and one with `disable-model-invocation: true` is no longer offered to the model — nothing else changes.
|
|
42
|
+
- 2b96136: A tool can now stop the turn for a person: return `handoff: { kind: 'human-required', reason, detail? }` on its `ToolResult` (new type `ToolHandoff`). The kernel commits the batch's results, writes a checkpoint and ends the segment with `turn_paused` instead of calling the model again. The event and its session-log record carry the new optional `handoff` field, and the SSE (`turn.paused`) and A2A bridges forward it. `resumeSession` continues the turn from that checkpoint as it does after a provider pause, with a model call that sees the results. In a delegated child (a turn with `parentSessionId`) the handoff fails the child's turn with a non-retryable `tool_error` naming the reason, so the parent receives a failed child result.
|
|
43
|
+
|
|
44
|
+
Nothing changes for tools that do not set the field. A consumer that switches exhaustively on `turn_paused` fields, or validates session-log records with its own strict schema, should accept `handoff`.
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- 2b96136: The `browser` tool's `cursor` field tells the model it is only the `nextCursor` a previous snapshot returned, to be left out for the top of the page, and never a URL. A model passed the page's address as the cursor and got a refusal before it could read the page.
|
|
49
|
+
- 2b96136: A `browser_human_required` refusal from a browser host now pauses the turn. The browser tools set `ToolResult.handoff` (`reason` in words such as `https://github.com is showing a sign-in page`; `detail` carries `tool: 'browser'`, `cause`, `origin`, `profile` and `loginCommand`) as well as `data.handoff`, so the kernel stops before the next model call and waits for the person, as it does for any tool handoff. Before this, the model read the refusal and carried on. Nothing changes for other refusals.
|
|
50
|
+
- 2b96136: The coding-agent working doctrine now tells the model never to change git configuration (`user.name`/`user.email`, hooks, remotes, credential helpers) or other persistent settings without asking. When a commit fails because no identity is set, it tells you the command instead of inventing an identity.
|
|
51
|
+
- 2b96136: The `schedule` tool's input schema now says that `budget` limits one run and that `maxIterations` counts model steps, not repetitions of the job. A model proposed `maxIterations: 1` for a job meant to post once per run, and every run stopped after its first model call. The CLI's confirmation of a job, on a terminal or in the TUI, warns when it allows fewer than 10 iterations.
|
|
52
|
+
- 2b96136: The `schedule` tool asks the model to leave optional fields (folder, time zone, execution, budget, a visible browser window) unset unless the user asked for them, and the TUI's confirmation of a proposed job marks every such value the model set that differs from what you would get by default, e.g. `Chosen by the model, not the default: time zone America/New_York, not this machine's Europe/Istanbul`.
|
|
53
|
+
- 2b96136: A job the model proposes, resumes or deletes in the TUI is confirmed once, on the job's own screen. The permission review no longer asks "Do you want to run schedule?" first in `prompt`, `accept-edits` or `auto`. `plan` and `strict` still refuse the call, a `schedule` rule of `ask` or `deny` still applies, and `pause` is still reviewed. The SDK's `schedule` tool no longer declares `delete` destructive, since the host confirms it before anything is removed; a host that relied on that flag to review deletes should add an `ask` rule for `schedule`.
|
|
54
|
+
- 2b96136: The `schedule` tool no longer refuses a proposal that uses the `read-only` preset with web or browser access as "a shell on the host". The preset denies `bash`, but the check looked only at explicit rules and `unmatched`, so `{ preset: 'read-only', unmatched: 'park', browser: … }` was refused. A proposal with `edit-in-folder`, or with a `bash` rule that is not `deny`, is still refused.
|
|
55
|
+
- 2b96136: The `schedule` tool's input schema describes `budget.tokenBudget` as what the whole run may spend, with every model call resending the prompt, and the CLI's confirmation of a job warns when it allows fewer than 50 000 tokens. A model proposed 4 000 tokens for a browser job whose runs each took about 110 000.
|
|
56
|
+
- 2b96136: The `skill` tool now presents its calls as `Read skill <name>` (or `List skills`) and hides a successful result, so a host shows one row instead of the raw input and the skill's body. In the TUI, the Working row says `Waiting for you` while the screen that saves a skill is open, instead of counting on as if the turn were working.
|
|
57
|
+
|
|
58
|
+
## 45.0.0
|
|
59
|
+
|
|
60
|
+
### Major Changes
|
|
61
|
+
|
|
62
|
+
- 2e2ea14: A skill's `allowed-tools` now pre-approves its tools. It no longer restricts the tool set.
|
|
63
|
+
|
|
64
|
+
The field comes from the Agent Skills format, and that format defines it this way: the listed tools skip the approval prompt for the rest of the turn that loaded the skill, and every other tool stays callable. Namzu read it the other way. After the `skill` tool loaded a skill, the next batch was narrowed to the listed tools and the model was told to "restrict yourself to" them. A skill with `allowed-tools: Read Grep` therefore took `bash` away, and the model stopped doing the work.
|
|
65
|
+
|
|
66
|
+
**What breaks in `@namzu/sdk`**
|
|
67
|
+
|
|
68
|
+
- A loaded skill no longer narrows `ToolContext.allowedTools`. If a host relied on `allowed-tools` to confine the model, it should narrow the turn itself with `QueryParams.allowedTools`, a step's `allowedTools`, or `deny` rules.
|
|
69
|
+
- `ToolContext.adoptSkillScope` is deprecated. The kernel never supplies it, so a tool that calls it through `?.` now does nothing. It will be removed in the next major. Use `ToolContext.grantSkillTools`.
|
|
70
|
+
- `createReviewHandler` / `createReviewPolicy` in `prompt` and `accept-edits` modes now approve a batch without asking when every call it would ask about is covered by a skill loaded earlier in the turn. To keep asking about every call, pass `skillGrants: 'ignore'`. `plan` and `strict` still refuse such calls, and an operator `deny` or `ask` rule, a destructive call, or a path outside the roots or the sandbox is never covered. Each approval made this way is written to the audit trail under the skill's name.
|
|
71
|
+
- The `bash` tool runs `bash -c` instead of `/bin/sh -c` wherever bash exists (the first `bash` on `PATH`, then `/bin/bash`, then `/usr/bin/bash`), including for background jobs. On a host whose `/bin/sh` is `dash` or `busybox sh` (Debian, Ubuntu, Alpine), commands now run in bash; a command that relied on `dash` behaviour, such as `echo` expanding `\n`, behaves as bash does. `BASH_ENV`, `ENV`, `SHELLOPTS`, `BASHOPTS` and `BASH_FUNC_*` are removed from its environment. To keep `/bin/sh`, set `NAMZU_BASH_SHELL=/bin/sh` in the environment of the process that runs the SDK. In a sandbox the tool now passes the guest `/bin/sh -c '<launcher>' sh '<command>'`, which runs bash when the guest has it; a custom `Sandbox.exec` or `spawnDetached` that inspected its arguments for `['-c', command]` sees the launcher instead. With no bash, the host still runs `/bin/sh -c`.
|
|
72
|
+
- A command line is read for the shell that runs it. `AuthorizationGate.evaluate`, `evaluateRule` and `SkillGrantSet.coveringSkill` called without a dialect read it for any POSIX shell (`sh`), so an allow rule or `Bash(<pattern>)` entry no longer approves a line using a bash-only construct (`$'…'`, `&>`, `|&`, `<<<`, `[[`, arrays, brace expansion, `time` and others) unless the caller says the shell is bash. The kernel says so for the `bash` tool on a host that has bash; inside a sandbox it reads in `sh`, because the guest may not have bash. A host calling the gate itself passes `commandDialect: 'bash'` in the `ToolCallContext` (or `{ commandDialect: 'bash' }` as the last argument of `evaluateRule` and `coveringSkill`) when the command will run in bash. Deny rules are unaffected: they still see every command.
|
|
73
|
+
- `parseAllowedTools` splits on whitespace as well as commas, and keeps `Tool(pattern)` entries whole. `"read write edit"` used to be one name and is now three.
|
|
74
|
+
- The skill manifest in the system prompt renders the field as `<pre_approved_tools>` instead of `<allowed_tools>`. The `skill` tool's notice lists what was pre-approved and what was ignored, and says every other tool remains available.
|
|
75
|
+
|
|
76
|
+
**Added:** `ToolDefinition.commandDialect` (and the `defineTool` option), `ToolCallContext.commandDialect`, `EvaluateRuleOptions`, the `ShellDialect` type, and `NAMZU_BASH_SHELL`; `ToolContext.grantSkillTools`, `ToolCallSummary.skillGrant`, `approve_tools.skillGranted`, `ReviewPolicyOptions.skillGrants`, `SkillGrantSet`, `compileSkillGrant`, `SKILL_TOOL_NAME_ALIASES`, `permissionPatternToRegExpSource`, and a `FrontmatterOptions` third argument to `parseFrontmatter` (`lists`), which the skill loader uses so that `allowed-tools` can be a YAML list. Names are matched case-insensitively and through the format's aliases (`Read` → `read`, `WebFetch` → `web_fetch`). `Bash(git status *)` uses the CLI permission-table glob, applied to each command in the line. `${CLAUDE_SKILL_DIR}` and `${NAMZU_SKILL_DIR}` expand to the skill's directory. An unknown name is ignored and reported, and never widens the grant. A tool that is destructive for every input (the shipped `write` and `run_code`) is ignored and reported too, because each of its calls is reviewed anyway. `BashOutput`, `KillShell`, `TaskOutput` and `TaskStop` map to `job`, and `TaskCreate`, `TaskUpdate` and `TaskList` to `task_*`. `ToolContext.grantSkillTools` returns a `commit()`, and the `skill` tool records the grant only once it has delivered the skill's instructions. The grant also ends when the operator sends a message while the turn is still running (`inboundMessages` or steering), through the new `SkillGrantSet.clear()`. A `Bash(<pattern>)` entry never covers a line that redirects output into a file (`git status > ~/.bashrc`); `/dev/null` and `2>&1` stay covered. A whole-tool `Bash` entry grants the tool as it is, writes outside the working directory included, because bash has no path argument for the escalation check. An entry naming a tool that `allowedTools` withholds from the turn or step is ignored as not available, and `SkillGrantToolResolver` gains an optional `unavailable` field for that.
|
|
77
|
+
|
|
78
|
+
**`@namzu/cli`:** a plugin skill's `allowed-tools` pre-approves for the turn and no longer takes tools away. `SKILL.md` files whose `allowed-tools` is a YAML list are now listed instead of refused. The `[permissions]` glob now comes from the SDK, and it matches the same commands as before. `permissionChecks` read a builtin tool's command line in the dialect that tool reports, as the runtime does.
|
|
79
|
+
|
|
80
|
+
### Patch Changes
|
|
81
|
+
|
|
82
|
+
- 2e2ea14: Permission rules on a command line now read it the way bash does. A `deny` rule catches commands it used to miss, and a few lines that used to be approved or refused by accident are now decided on what they run.
|
|
83
|
+
|
|
84
|
+
An `argument_pattern` rule on a command argument, a skill's `Bash(<pattern>)` entry and the check that such an entry never covers a write through redirection used to rely on three separate readers of bash quoting, which disagreed in places. With `Bash(git status *)` granted, `git status $'\'' ; touch pwned #'` and `git status $'\'' > ~/.bashrc #'` were pre-approved, because `$'\''` was read as a closed quote and an open one. One lexer now serves all three (see `docs/sdk/command-lines.md`). It was checked against bash 5.2 and 5.3 on 2.9 million generated lines with no disagreement.
|
|
85
|
+
|
|
86
|
+
What changes for a host:
|
|
87
|
+
|
|
88
|
+
- A `deny` rule also matches each command's words after quote removal. `^git push` now denies `'git' push`, `g\it push`, `$'\x67it' push`, `GIT_DIR=. git push`, `bash "-c" "git push"` (the quoted `-c` is still the flag) and `bash -lc 'git push'`. None of these were denied before.
|
|
89
|
+
- A line whose only quoting is an ANSI-C quote is decoded rather than refused: an `allow` rule or a `Bash(<pattern>)` entry that matches `git status $'-s'` now approves it, since it runs `git status -s`. `> $'/dev/nul\x6c'` is `/dev/null` and is not a write.
|
|
90
|
+
- A here-document body is data, not commands, so `cat <<EOF … EOF` is matched as `cat <<EOF`.
|
|
91
|
+
- A line is refused by `allow` (opaque) in some cases it used to approve: a syntax error, `[[ … ]]`, arithmetic on a variable (`$((x))`), `${!x}`, a function definition, `shopt`/`set -o posix`, `time` followed by an option (bash as `/bin/sh` runs the command `time` there), and two forms bash itself reads two ways (`"$${…"` in double quotes, and a quoted or expanding `>&` target, whose substitution bash 5.2 runs). They now go to review.
|
|
92
|
+
- A segment no longer carries a trailing comment: `git push #'` is `git push`.
|
|
93
|
+
- An `argument_pattern` rule on an argument the tool declares as its `pathArgument` tests the whole value and does not read it as shell, so `src/app/(auth)/page.tsx` is not refused as a syntax error.
|
|
94
|
+
|
|
95
|
+
No configuration change is needed.
|
|
96
|
+
|
|
3
97
|
## 44.3.0
|
|
4
98
|
|
|
5
99
|
### Minor Changes
|
|
@@ -32,8 +32,9 @@
|
|
|
32
32
|
* caller must read the two decisions differently, and {@link evaluateRule}
|
|
33
33
|
* does:
|
|
34
34
|
*
|
|
35
|
-
* - **deny** matches when ANY segment matches
|
|
36
|
-
*
|
|
35
|
+
* - **deny** matches when ANY segment matches, or when any command's decoded
|
|
36
|
+
* words ({@link decodedCommands}) do. One prohibited command poisons the
|
|
37
|
+
* line it rides on, however it is quoted.
|
|
37
38
|
* - **allow** matches only when EVERY segment matches, and never when the line
|
|
38
39
|
* is {@link CommandLineDecomposition.opaque}. Permission is a claim about the
|
|
39
40
|
* whole line, and a claim that cannot be checked is not granted.
|
|
@@ -41,34 +42,45 @@
|
|
|
41
42
|
* That asymmetry is the same one `refuse-do-not-degrade` describes: when the
|
|
42
43
|
* analysis is uncertain, the uncertainty spends against the permissive answer.
|
|
43
44
|
*
|
|
45
|
+
* ## Where the commands come from
|
|
46
|
+
*
|
|
47
|
+
* One lexer, {@link lexShellCommandLine}, reads the line the way bash does and
|
|
48
|
+
* is the only thing in the SDK that knows bash's quoting. This module and
|
|
49
|
+
* {@link writesThroughRedirection} are views of its result. There used to be
|
|
50
|
+
* three hand-written walkers here, each with its own idea of where a quote
|
|
51
|
+
* ends, and every disagreement between them was a way to run a command the
|
|
52
|
+
* rules never saw.
|
|
53
|
+
*
|
|
44
54
|
* ## What `opaque` means
|
|
45
55
|
*
|
|
46
56
|
* Some lines contain text that is not the command that runs. Command
|
|
47
57
|
* substitution (`$(…)`, backticks, `<(…)`) executes something whose text is
|
|
48
|
-
* not in the line at all, and `eval` runs a string assembled at
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
58
|
+
* not in the line at all, and `eval` or `source` runs a string assembled at
|
|
59
|
+
* runtime. The lexer also reports a line opaque when it does not parse, or
|
|
60
|
+
* contains a construct it does not model. No decomposition of the source can
|
|
61
|
+
* be a decomposition of what ran, so `allow` declines it. `deny` still tests
|
|
62
|
+
* what is visible, because a deny that matches too much costs a prompt and a
|
|
63
|
+
* deny that matches too little costs the thing it was written to prevent.
|
|
53
64
|
*
|
|
54
65
|
* ## What it deliberately does not do
|
|
55
66
|
*
|
|
56
|
-
* A value
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
67
|
+
* A value that is one plain command comes back as itself, byte for byte. That
|
|
68
|
+
* keeps every rule about a non-command argument — a path, a number, a URL —
|
|
69
|
+
* behaving exactly as it did, and confines this machinery to the case that
|
|
70
|
+
* motivated it.
|
|
60
71
|
*
|
|
61
|
-
* It is a decomposition, not a shell. `xargs sh -c`,
|
|
62
|
-
* file, and a shell invoked through an interpreter it does not
|
|
63
|
-
* pass through as ordinary text. Each of those either denies as
|
|
64
|
-
* an allow rule, fails to match every segment and so declines.
|
|
65
|
-
* is a prompt, never a silent grant.
|
|
72
|
+
* It is a decomposition, not a shell. `xargs sh -c`, `env git push`, a command
|
|
73
|
+
* read from a file, and a shell invoked through an interpreter it does not
|
|
74
|
+
* recognise all pass through as ordinary text. Each of those either denies as
|
|
75
|
+
* before or, for an allow rule, fails to match every segment and so declines.
|
|
76
|
+
* The failure mode is a prompt, never a silent grant.
|
|
66
77
|
*/
|
|
78
|
+
import { type ShellDialect } from './shell-lexer.js';
|
|
67
79
|
/** The commands a line runs, and whether that list can be trusted as complete. */
|
|
68
80
|
export interface CommandLineDecomposition {
|
|
69
81
|
/**
|
|
70
|
-
* The individual commands, in
|
|
71
|
-
* decomposes to nothing yields the original.
|
|
82
|
+
* The individual commands' source text, in the order they were read. Never
|
|
83
|
+
* empty: a line that decomposes to nothing yields the original.
|
|
72
84
|
*/
|
|
73
85
|
readonly segments: readonly string[];
|
|
74
86
|
/**
|
|
@@ -77,5 +89,40 @@ export interface CommandLineDecomposition {
|
|
|
77
89
|
*/
|
|
78
90
|
readonly opaque: boolean;
|
|
79
91
|
}
|
|
80
|
-
|
|
92
|
+
/**
|
|
93
|
+
* `dialect` is the shell that will run the line (see `ShellDialect`); a
|
|
94
|
+
* caller that does not know passes `sh`, whose reading holds for any POSIX
|
|
95
|
+
* shell.
|
|
96
|
+
*/
|
|
97
|
+
export declare function decomposeCommandLine(command: string, dialect?: ShellDialect): CommandLineDecomposition;
|
|
98
|
+
/**
|
|
99
|
+
* Each command's words as bash passes them (quotes removed, `$'…'` decoded),
|
|
100
|
+
* joined by single spaces — and, for a command led by assignments, the same
|
|
101
|
+
* without them. For `deny` only.
|
|
102
|
+
*
|
|
103
|
+
* A deny rule written as `^git push` must not be evaded by `'git' push`,
|
|
104
|
+
* `g\it push`, `$'git' push` or `GIT_DIR=x git push`: the source text of each
|
|
105
|
+
* differs from the pattern and the command that runs does not. `allow` does
|
|
106
|
+
* not use these. Its subject stays the source text, so a pattern that names
|
|
107
|
+
* quotes keeps meaning what its author wrote, and a decoded form can only ever
|
|
108
|
+
* add a match — which for `deny` is the safe direction and for `allow` is not.
|
|
109
|
+
*/
|
|
110
|
+
export declare function decodedCommands(command: string, dialect?: ShellDialect): readonly string[];
|
|
111
|
+
/**
|
|
112
|
+
* Whether a command line sends output into a file through a shell redirection.
|
|
113
|
+
*
|
|
114
|
+
* A permission pattern names commands. `>`, `>>`, `>|`, `&>`, `&>>`, `<>` and
|
|
115
|
+
* `>&word` open a file for writing whose path is not the command's argument,
|
|
116
|
+
* so a pattern that covers `git status *` would otherwise also cover
|
|
117
|
+
* `git status > ~/.bashrc`. Callers that grant on a pattern's say-so decline
|
|
118
|
+
* such a line.
|
|
119
|
+
*
|
|
120
|
+
* Not writes: a target of `/dev/null`, descriptor duplication and closing
|
|
121
|
+
* (`2>&1`, `>&2`, `>&-`), and anything quoted or escaped so that it is not an
|
|
122
|
+
* operator. Anything whose target is not known before the line runs — a
|
|
123
|
+
* target built from a variable, a glob or a tilde — counts as a write, and so
|
|
124
|
+
* does a line that does not parse or holds a process substitution: the
|
|
125
|
+
* uncertainty spends against the grant.
|
|
126
|
+
*/
|
|
127
|
+
export declare function writesThroughRedirection(command: string, dialect?: ShellDialect): boolean;
|
|
81
128
|
//# sourceMappingURL=command-line.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-line.d.ts","sourceRoot":"","sources":["../../src/authorization/command-line.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"command-line.d.ts","sourceRoot":"","sources":["../../src/authorization/command-line.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4EG;AAEH,OAAO,EACN,KAAK,YAAY,EAKjB,MAAM,kBAAkB,CAAA;AAEzB,kFAAkF;AAClF,MAAM,WAAW,wBAAwB;IACxC;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IACpC;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACxB;AAYD;;;;GAIG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAqB,GAC5B,wBAAwB,CAmC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,YAAqB,GAC5B,SAAS,MAAM,EAAE,CAenB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,YAAqB,GAAG,OAAO,CAKjG"}
|