@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
|
@@ -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,56 @@ 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
|
-
|
|
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
|
+
|
|
120
|
+
/** The call an `AuthorizationRule` of type `predicate` is asked about. */
|
|
121
|
+
export interface AuthorizationPredicateCall {
|
|
122
|
+
readonly toolName: string
|
|
123
|
+
readonly toolInput: unknown
|
|
124
|
+
readonly toolDef: ToolDefinition | undefined
|
|
125
|
+
/**
|
|
126
|
+
* The shell a command line in this call runs in: the caller's
|
|
127
|
+
* (`ToolCallContext.commandDialect`), or `sh` when it did not say, which
|
|
128
|
+
* is the reading that holds whichever shell runs it.
|
|
129
|
+
*/
|
|
130
|
+
readonly commandDialect: ShellDialect
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** The code behind an `AuthorizationRule` of type `predicate`. */
|
|
134
|
+
export type AuthorizationPredicate = (call: AuthorizationPredicateCall) => GateDecision | null
|
|
87
135
|
|
|
88
136
|
const AllowReadOnlySchema = z.object({
|
|
89
137
|
type: z.literal('allow_read_only'),
|
|
@@ -121,12 +169,21 @@ const ArgumentPatternSchema = z.object({
|
|
|
121
169
|
// fail-open shape this rule type exists to remove.
|
|
122
170
|
argument: z.string().min(1),
|
|
123
171
|
pattern: z.string().max(MAX_CUSTOM_PATTERN_LENGTH),
|
|
124
|
-
decision: z.enum(['allow', 'deny']),
|
|
172
|
+
decision: z.enum(['allow', 'deny', 'review']),
|
|
125
173
|
})
|
|
126
174
|
const AllowByTierSchema = z.object({
|
|
127
175
|
type: z.literal('allow_by_tier'),
|
|
128
176
|
tiers: z.array(z.string()),
|
|
129
177
|
})
|
|
178
|
+
const PredicateSchema = z.object({
|
|
179
|
+
type: z.literal('predicate'),
|
|
180
|
+
// A rule that says nothing about itself produces a refusal nobody can
|
|
181
|
+
// reason about.
|
|
182
|
+
description: z.string().min(1),
|
|
183
|
+
decide: z.custom<AuthorizationPredicate>((value) => typeof value === 'function', {
|
|
184
|
+
message: 'decide must be a function',
|
|
185
|
+
}),
|
|
186
|
+
})
|
|
130
187
|
|
|
131
188
|
export const AuthorizationRuleSchema = z.discriminatedUnion('type', [
|
|
132
189
|
AllowReadOnlySchema,
|
|
@@ -137,6 +194,7 @@ export const AuthorizationRuleSchema = z.discriminatedUnion('type', [
|
|
|
137
194
|
CustomPatternSchema,
|
|
138
195
|
ArgumentPatternSchema,
|
|
139
196
|
AllowByTierSchema,
|
|
197
|
+
PredicateSchema,
|
|
140
198
|
])
|
|
141
199
|
|
|
142
200
|
export const AuthorizationGateConfigSchema = z.object({
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// The browser contract: what a browser host does for the `browser` and
|
|
3
|
+
// `browser_act` tools. The SDK owns the model-facing tools and this
|
|
4
|
+
// interface; a host package (for example `@namzu/browser`) owns the engine.
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
/** Every action the `browser` tool (observe and navigate) can ask for. */
|
|
8
|
+
export type BrowserObserveActionName =
|
|
9
|
+
| 'navigate'
|
|
10
|
+
| 'back'
|
|
11
|
+
| 'forward'
|
|
12
|
+
| 'reload'
|
|
13
|
+
| 'snapshot'
|
|
14
|
+
| 'screenshot'
|
|
15
|
+
| 'scroll'
|
|
16
|
+
| 'wait_for'
|
|
17
|
+
| 'tabs'
|
|
18
|
+
|
|
19
|
+
/** Every action the `browser_act` tool (change the page) can ask for. */
|
|
20
|
+
export type BrowserActActionName =
|
|
21
|
+
| 'click'
|
|
22
|
+
| 'type'
|
|
23
|
+
| 'fill_form'
|
|
24
|
+
| 'select'
|
|
25
|
+
| 'press'
|
|
26
|
+
| 'hover'
|
|
27
|
+
| 'upload'
|
|
28
|
+
| 'dialog'
|
|
29
|
+
|
|
30
|
+
export type BrowserActionName = BrowserObserveActionName | BrowserActActionName
|
|
31
|
+
|
|
32
|
+
export type BrowserScrollDirection = 'up' | 'down' | 'left' | 'right'
|
|
33
|
+
|
|
34
|
+
export type BrowserTabsOp = 'list' | 'select' | 'close' | 'new'
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Capabilities — frozen at host construction; the model reads them through
|
|
38
|
+
// the tools' descriptions and schemas.
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
export interface BrowserCapabilities {
|
|
42
|
+
/** Which engine drives the browser, in words: `local-chromium`, `windows-cdp`. */
|
|
43
|
+
readonly engine: string
|
|
44
|
+
/** The browser window is not shown. */
|
|
45
|
+
readonly headless: boolean
|
|
46
|
+
/** `screenshot` can return an image. */
|
|
47
|
+
readonly screenshot: boolean
|
|
48
|
+
/** `upload` can attach a local file to a file input. */
|
|
49
|
+
readonly upload: boolean
|
|
50
|
+
/**
|
|
51
|
+
* Exact action subset when known. Absent: every action whose broad flag
|
|
52
|
+
* above allows it. Actions outside the subset are removed from the model
|
|
53
|
+
* schema and refused before the host is called.
|
|
54
|
+
*/
|
|
55
|
+
readonly supportedActions?: readonly BrowserActionName[]
|
|
56
|
+
/**
|
|
57
|
+
* The most snapshot text one call returns. The tool cuts anything longer.
|
|
58
|
+
* Absent: {@link BROWSER_SNAPSHOT_MAX_CHARS}.
|
|
59
|
+
*/
|
|
60
|
+
readonly snapshotMaxChars?: number
|
|
61
|
+
/**
|
|
62
|
+
* Why the browser cannot be used at all — the engine is not installed,
|
|
63
|
+
* the profile is missing. Present, both tools stay mounted, say this in
|
|
64
|
+
* their descriptions and refuse every call with it, so the model reads
|
|
65
|
+
* the reason once and tells the user instead of retrying.
|
|
66
|
+
*/
|
|
67
|
+
readonly unavailableReason?: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Default and ceiling of snapshot text per call, in characters. */
|
|
71
|
+
export const BROWSER_SNAPSHOT_MAX_CHARS = 20_000
|
|
72
|
+
|
|
73
|
+
/** Longest `wait_for` the tool accepts, in milliseconds. */
|
|
74
|
+
export const BROWSER_WAIT_MAX_MS = 30_000
|
|
75
|
+
|
|
76
|
+
/** Most fields one `fill_form` call may set. */
|
|
77
|
+
export const BROWSER_FILL_FORM_MAX_FIELDS = 20
|
|
78
|
+
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
// Actions
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* What the `browser` tool asks of the host. Every URL here has already been
|
|
85
|
+
* canonicalised by the tool (see `canonicalizeBrowserUrl`): only http, https
|
|
86
|
+
* or `about:blank`, no credentials, never a cloud metadata address.
|
|
87
|
+
*/
|
|
88
|
+
export type BrowserObserveAction =
|
|
89
|
+
| { readonly action: 'navigate'; readonly url: string }
|
|
90
|
+
| { readonly action: 'back' }
|
|
91
|
+
| { readonly action: 'forward' }
|
|
92
|
+
| { readonly action: 'reload' }
|
|
93
|
+
| { readonly action: 'snapshot'; readonly ref?: string; readonly cursor?: string }
|
|
94
|
+
| { readonly action: 'screenshot'; readonly ref?: string; readonly fullPage?: boolean }
|
|
95
|
+
| {
|
|
96
|
+
readonly action: 'scroll'
|
|
97
|
+
readonly direction: BrowserScrollDirection
|
|
98
|
+
readonly ref?: string
|
|
99
|
+
/** Screens to scroll; the host's default when absent. */
|
|
100
|
+
readonly amount?: number
|
|
101
|
+
}
|
|
102
|
+
| {
|
|
103
|
+
readonly action: 'wait_for'
|
|
104
|
+
readonly text?: string
|
|
105
|
+
readonly textGone?: string
|
|
106
|
+
readonly timeMs?: number
|
|
107
|
+
}
|
|
108
|
+
| {
|
|
109
|
+
readonly action: 'tabs'
|
|
110
|
+
readonly op: BrowserTabsOp
|
|
111
|
+
/** `select` and `close`: the tab id from `list` or a page header. */
|
|
112
|
+
readonly tab?: string
|
|
113
|
+
/** `new`: the address to open; `about:blank` when absent. */
|
|
114
|
+
readonly url?: string
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface BrowserFormField {
|
|
118
|
+
readonly ref: string
|
|
119
|
+
/** Text for a text box; `true`/`false` for a checkbox; the option's label for a select. */
|
|
120
|
+
readonly value: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The change a `browser_act` call makes. */
|
|
124
|
+
export type BrowserActOperation =
|
|
125
|
+
| { readonly action: 'click'; readonly ref: string; readonly doubleClick?: boolean }
|
|
126
|
+
| {
|
|
127
|
+
readonly action: 'type'
|
|
128
|
+
readonly ref: string
|
|
129
|
+
readonly text: string
|
|
130
|
+
/** Press Enter after typing. */
|
|
131
|
+
readonly submit?: boolean
|
|
132
|
+
}
|
|
133
|
+
| { readonly action: 'fill_form'; readonly fields: readonly BrowserFormField[] }
|
|
134
|
+
| { readonly action: 'select'; readonly ref: string; readonly values: readonly string[] }
|
|
135
|
+
| { readonly action: 'press'; readonly key: string; readonly ref?: string }
|
|
136
|
+
| { readonly action: 'hover'; readonly ref: string }
|
|
137
|
+
| { readonly action: 'upload'; readonly ref: string; readonly path: string }
|
|
138
|
+
| { readonly action: 'dialog'; readonly accept: boolean; readonly promptText?: string }
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* What the `browser_act` tool asks of the host.
|
|
142
|
+
*
|
|
143
|
+
* `origin` is the page origin the model read from the snapshot header
|
|
144
|
+
* (`Page: <origin> — …`), canonicalised by the tool. **The host MUST compare
|
|
145
|
+
* it with the live origin of the page it is about to act on, immediately
|
|
146
|
+
* before acting, and throw a {@link BrowserOriginMismatch} without acting
|
|
147
|
+
* when they differ.** That comparison is what binds an approval of "click
|
|
148
|
+
* Place order on shop.example.com" to shop.example.com: a redirect between
|
|
149
|
+
* the snapshot and the click must not carry the click to another site.
|
|
150
|
+
*/
|
|
151
|
+
export type BrowserActAction = BrowserActOperation & {
|
|
152
|
+
readonly origin: string
|
|
153
|
+
/** Return a snapshot of the page after the action. */
|
|
154
|
+
readonly snapshot?: boolean
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
// Results
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
|
|
161
|
+
/** The page an action left the browser on, as the host observed it. */
|
|
162
|
+
export interface BrowserPageInfo {
|
|
163
|
+
/** Canonical origin (`https://github.com`), or `null` for `about:blank`. */
|
|
164
|
+
readonly origin: string
|
|
165
|
+
readonly url: string
|
|
166
|
+
/** The document title. Page-controlled: the tool quotes and cuts it. */
|
|
167
|
+
readonly title: string
|
|
168
|
+
/** The tab's id, e.g. `t1`. */
|
|
169
|
+
readonly tab: string
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface BrowserTabInfo extends BrowserPageInfo {
|
|
173
|
+
readonly active: boolean
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export interface BrowserSnapshot {
|
|
177
|
+
readonly page: BrowserPageInfo
|
|
178
|
+
/**
|
|
179
|
+
* The accessibility tree as text, one element per line, each actionable
|
|
180
|
+
* element carrying `[ref=eN]`. Page-controlled: the tool wraps it as
|
|
181
|
+
* untrusted content.
|
|
182
|
+
*/
|
|
183
|
+
readonly text: string
|
|
184
|
+
/** Present when more text follows; pass it back as `cursor`. */
|
|
185
|
+
readonly nextCursor?: string
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface BrowserScreenshot {
|
|
189
|
+
readonly page: BrowserPageInfo
|
|
190
|
+
readonly data: Uint8Array
|
|
191
|
+
readonly mimeType: 'image/png' | 'image/jpeg'
|
|
192
|
+
readonly width: number
|
|
193
|
+
readonly height: number
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* What an action produced. Every field is optional because actions differ;
|
|
198
|
+
* the tool renders whichever are present.
|
|
199
|
+
*/
|
|
200
|
+
export interface BrowserResult {
|
|
201
|
+
/** The page after the action. */
|
|
202
|
+
readonly page?: BrowserPageInfo
|
|
203
|
+
/**
|
|
204
|
+
* The host's own note, in the host's words — "download of report.pdf
|
|
205
|
+
* cancelled", "dialog accepted". Never page text: the tool shows it
|
|
206
|
+
* outside the untrusted envelope.
|
|
207
|
+
*/
|
|
208
|
+
readonly message?: string
|
|
209
|
+
readonly snapshot?: BrowserSnapshot
|
|
210
|
+
readonly screenshot?: BrowserScreenshot
|
|
211
|
+
readonly tabs?: readonly BrowserTabInfo[]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/** What a snapshot said about one ref, for labelling a call before it runs. */
|
|
215
|
+
export interface BrowserRefDescription {
|
|
216
|
+
/** ARIA role: `button`, `link`, `textbox`. */
|
|
217
|
+
readonly role: string
|
|
218
|
+
/** Accessible name. Page-controlled. */
|
|
219
|
+
readonly name?: string
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** Who and where, for labels and reviews. May change between calls. */
|
|
223
|
+
export interface BrowserSessionInfo {
|
|
224
|
+
/** The profile the browser runs under. */
|
|
225
|
+
readonly profile?: string
|
|
226
|
+
/** Canonical origin of the active tab, when the host knows it. */
|
|
227
|
+
readonly origin?: string
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// Structural errors. Hosts throw values carrying these shapes; the tools
|
|
232
|
+
// recognise them by shape, so a separately installed host and SDK need not
|
|
233
|
+
// share an error class.
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
|
|
236
|
+
/** The live page is not on the origin a `browser_act` call named. Nothing was done. */
|
|
237
|
+
export interface BrowserOriginMismatch {
|
|
238
|
+
readonly code: 'browser_origin_mismatch'
|
|
239
|
+
readonly expected: string
|
|
240
|
+
readonly actual: string
|
|
241
|
+
readonly message: string
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/** The ref is not on the current page: it came from an older snapshot. Nothing was done. */
|
|
245
|
+
export interface BrowserStaleRef {
|
|
246
|
+
readonly code: 'browser_stale_ref'
|
|
247
|
+
readonly ref: string
|
|
248
|
+
readonly message: string
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Why the page needs a person. */
|
|
252
|
+
export type BrowserHumanRequiredReason =
|
|
253
|
+
| 'sign-in'
|
|
254
|
+
| 'two-factor'
|
|
255
|
+
| 'captcha'
|
|
256
|
+
| 'bot-block'
|
|
257
|
+
| 'http-auth'
|
|
258
|
+
| 'credential-field'
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* The page needs a person: a sign-in, a second factor, a CAPTCHA, a bot
|
|
262
|
+
* wall, or a field that takes a password or one-time code. The agent must
|
|
263
|
+
* stop and hand over; it never signs in, solves or types a credential.
|
|
264
|
+
*/
|
|
265
|
+
export interface BrowserHumanRequired {
|
|
266
|
+
readonly code: 'browser_human_required'
|
|
267
|
+
readonly reason: BrowserHumanRequiredReason
|
|
268
|
+
readonly origin: string
|
|
269
|
+
readonly message: string
|
|
270
|
+
readonly profile?: string
|
|
271
|
+
/** The command that opens a visible window on this profile, e.g. `namzu browser login work https://…`. */
|
|
272
|
+
readonly loginCommand?: string
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* A page-changing action started and did not report a clean completion. The
|
|
277
|
+
* page may already have changed, so replaying it is unsafe.
|
|
278
|
+
*/
|
|
279
|
+
export interface BrowserOutcomeUnknown {
|
|
280
|
+
readonly code: 'browser_outcome_unknown'
|
|
281
|
+
readonly action: BrowserActionName
|
|
282
|
+
readonly outcome: 'unknown'
|
|
283
|
+
readonly retrySafety: 'unsafe'
|
|
284
|
+
readonly message: string
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** The site policy does not allow this origin at the level the call needs. */
|
|
288
|
+
export interface BrowserSiteDenied {
|
|
289
|
+
readonly code: 'browser_site_denied'
|
|
290
|
+
readonly origin: string
|
|
291
|
+
readonly message: string
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export type BrowserHostError =
|
|
295
|
+
| BrowserOriginMismatch
|
|
296
|
+
| BrowserStaleRef
|
|
297
|
+
| BrowserHumanRequired
|
|
298
|
+
| BrowserOutcomeUnknown
|
|
299
|
+
| BrowserSiteDenied
|
|
300
|
+
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
// Host
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
|
|
305
|
+
export interface BrowserCallOptions {
|
|
306
|
+
/** Fires when the call is cancelled or times out. */
|
|
307
|
+
readonly signal?: AbortSignal
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* A browser the tools drive. Implementations live outside `@namzu/sdk`.
|
|
312
|
+
*
|
|
313
|
+
* The host is where the site policy is enforced after the fact: whatever the
|
|
314
|
+
* gate approved, the host re-checks the page a navigation, redirect or popup
|
|
315
|
+
* actually landed on, and the live origin before every `act`.
|
|
316
|
+
*/
|
|
317
|
+
export interface BrowserHost {
|
|
318
|
+
readonly id: string
|
|
319
|
+
readonly capabilities: BrowserCapabilities
|
|
320
|
+
|
|
321
|
+
/** Observe or navigate. Throws a {@link BrowserHostError} shape to refuse. */
|
|
322
|
+
observe(action: BrowserObserveAction, options?: BrowserCallOptions): Promise<BrowserResult>
|
|
323
|
+
/**
|
|
324
|
+
* Change the page. MUST check `action.origin` against the live page first
|
|
325
|
+
* (see {@link BrowserActAction}). Throws a {@link BrowserHostError} shape
|
|
326
|
+
* to refuse.
|
|
327
|
+
*/
|
|
328
|
+
act(action: BrowserActAction, options?: BrowserCallOptions): Promise<BrowserResult>
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* What the most recent snapshot said about `ref`, synchronously and
|
|
332
|
+
* without touching the page, for the label a person approves. Undefined
|
|
333
|
+
* when the ref is unknown.
|
|
334
|
+
*/
|
|
335
|
+
describeRef?(ref: string): BrowserRefDescription | undefined
|
|
336
|
+
/** The current profile and page, synchronously, for labels. */
|
|
337
|
+
session?(): BrowserSessionInfo
|
|
338
|
+
|
|
339
|
+
initialize?(): Promise<void>
|
|
340
|
+
dispose?(): Promise<void>
|
|
341
|
+
}
|
package/src/types/hitl/index.ts
CHANGED
|
@@ -40,6 +40,15 @@ export type HITLResumeDecision =
|
|
|
40
40
|
* person said yes to a batch that showed the escape.
|
|
41
41
|
*/
|
|
42
42
|
confirmedEscalations?: readonly string[]
|
|
43
|
+
/**
|
|
44
|
+
* Ids of calls approved on the strength of a skill's `allowed-tools`
|
|
45
|
+
* grant ({@link ToolCallSummary.skillGrant}), with nobody asked.
|
|
46
|
+
*
|
|
47
|
+
* The kernel writes each one to the session's audit trail naming the
|
|
48
|
+
* skill, and only for a call that actually carried the grant — an id
|
|
49
|
+
* listed here for an unmarked call is ignored rather than trusted.
|
|
50
|
+
*/
|
|
51
|
+
skillGranted?: readonly string[]
|
|
43
52
|
}
|
|
44
53
|
| {
|
|
45
54
|
action: 'modify_tools'
|
|
@@ -126,6 +135,18 @@ export interface ToolCallSummary {
|
|
|
126
135
|
* approve it on their own. A `deny` rule still refuses it outright.
|
|
127
136
|
*/
|
|
128
137
|
escalation?: ToolCallEscalation
|
|
138
|
+
/**
|
|
139
|
+
* Present when a skill loaded earlier in this turn pre-approved this call
|
|
140
|
+
* through its `allowed-tools`, and nothing stronger stands in the way.
|
|
141
|
+
*
|
|
142
|
+
* Marked only on a call the operator's policy left to review (no `deny`,
|
|
143
|
+
* no explicit `ask` rule), that is not destructive and that carries no
|
|
144
|
+
* {@link escalation}. The review policy decides what the mark is worth:
|
|
145
|
+
* `createReviewHandler` approves a batch without asking when every call
|
|
146
|
+
* it would have asked about carries one, and still refuses under `plan`
|
|
147
|
+
* and `strict`. A host's own handler may ignore it.
|
|
148
|
+
*/
|
|
149
|
+
skillGrant?: { readonly skill: string }
|
|
129
150
|
}
|
|
130
151
|
|
|
131
152
|
/** See {@link ToolCallSummary.escalation}. */
|
|
@@ -534,6 +534,12 @@ type CoreSessionEvent =
|
|
|
534
534
|
providerError?: import('../provider/error.js').ProviderErrorInfo
|
|
535
535
|
/** Curated operator copy, absent when no catalog rule matched. */
|
|
536
536
|
explanation?: { id: string; message: string; hint: string }
|
|
537
|
+
/**
|
|
538
|
+
* Present when a tool asked for a person: its `ToolResult.handoff`.
|
|
539
|
+
* The results of the batch are already committed; resuming the turn
|
|
540
|
+
* calls the model with them.
|
|
541
|
+
*/
|
|
542
|
+
handoff?: import('../tool/index.js').ToolHandoff
|
|
537
543
|
}
|
|
538
544
|
/** A paused turn continues from its checkpoint, under the same `turnId`. */
|
|
539
545
|
| {
|
|
@@ -201,6 +201,15 @@ const providerError = z
|
|
|
201
201
|
|
|
202
202
|
const explanation = z.object({ id: text, message: text, hint: text }).strict()
|
|
203
203
|
|
|
204
|
+
/** A tool's request for a person, as `turn_paused` carries it. */
|
|
205
|
+
const toolHandoff = z
|
|
206
|
+
.object({
|
|
207
|
+
kind: z.literal('human-required'),
|
|
208
|
+
reason: text,
|
|
209
|
+
detail: z.record(text).optional(),
|
|
210
|
+
})
|
|
211
|
+
.strict()
|
|
212
|
+
|
|
204
213
|
const stopReason = z.enum([
|
|
205
214
|
'end_turn',
|
|
206
215
|
'token_budget',
|
|
@@ -361,6 +370,7 @@ export const TurnPausedRecordSchema = inTurn('turn_paused', {
|
|
|
361
370
|
providerError: providerError.optional(),
|
|
362
371
|
explanation: explanation.optional(),
|
|
363
372
|
budget: tokenBudgetSummary.optional(),
|
|
373
|
+
handoff: toolHandoff.optional(),
|
|
364
374
|
})
|
|
365
375
|
|
|
366
376
|
export const TurnResumingRecordSchema = inTurn('turn_resuming', {
|
package/src/types/tool/index.ts
CHANGED
|
@@ -77,6 +77,8 @@ export interface SkillRegistryRef {
|
|
|
77
77
|
invocation?: 'model' | 'operator' | 'both'
|
|
78
78
|
}
|
|
79
79
|
body?: string
|
|
80
|
+
/** The skill's directory, which `${CLAUDE_SKILL_DIR}` in `allowed-tools` names. */
|
|
81
|
+
dirPath?: string
|
|
80
82
|
}
|
|
81
83
|
}
|
|
82
84
|
| undefined
|
|
@@ -473,18 +475,56 @@ export interface ToolContext {
|
|
|
473
475
|
}
|
|
474
476
|
|
|
475
477
|
/**
|
|
476
|
-
*
|
|
478
|
+
* Formerly: narrow the turn's tools to what a skill's `allowed-tools`
|
|
479
|
+
* named. That reading was backwards — the field pre-approves, it never
|
|
480
|
+
* restricts — and the kernel no longer supplies this member, so a tool
|
|
481
|
+
* that calls it through `?.` does nothing.
|
|
477
482
|
*
|
|
478
|
-
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
* retroactively refuse them.
|
|
483
|
+
* @deprecated Never supplied by the kernel since `allowed-tools` became a
|
|
484
|
+
* pre-approval. Use {@link ToolContext.grantSkillTools}. Removed in the
|
|
485
|
+
* next major.
|
|
482
486
|
*/
|
|
483
487
|
adoptSkillScope?: (scope: {
|
|
484
488
|
skill: string
|
|
485
489
|
allowedTools: readonly string[]
|
|
486
490
|
}) => void
|
|
487
491
|
|
|
492
|
+
/**
|
|
493
|
+
* Pre-approve what a loaded skill's `allowed-tools` names, for the rest of
|
|
494
|
+
* this turn.
|
|
495
|
+
*
|
|
496
|
+
* Called by the `skill` tool. It never narrows anything: every tool the
|
|
497
|
+
* turn had stays callable, and a call the grant does not cover is reviewed
|
|
498
|
+
* exactly as before. A covered call skips the approval prompt, but not an
|
|
499
|
+
* operator `deny` or `ask` rule, plan mode, `strict` mode, a destructive
|
|
500
|
+
* call or one that reaches outside the turn's roots or sandbox. Each call
|
|
501
|
+
* approved this way is written to the session's audit trail naming the
|
|
502
|
+
* skill.
|
|
503
|
+
*
|
|
504
|
+
* Returns what would be granted and what was ignored (an unknown tool
|
|
505
|
+
* name, a pattern on a tool without a command line, a tool every call of
|
|
506
|
+
* which is destructive), so the tool can tell the model. Nothing is
|
|
507
|
+
* recorded until `commit()` is called: the caller commits only once the
|
|
508
|
+
* skill's instructions have actually been delivered, so a load that fails
|
|
509
|
+
* afterwards leaves no approval behind. Absent outside a turn, where
|
|
510
|
+
* there is nothing to grant into.
|
|
511
|
+
*/
|
|
512
|
+
grantSkillTools?: (grant: {
|
|
513
|
+
readonly skill: string
|
|
514
|
+
/** The parsed entries, as `parseAllowedTools` returns them. */
|
|
515
|
+
readonly allowedTools: readonly string[]
|
|
516
|
+
/** The skill's directory, for `${CLAUDE_SKILL_DIR}` / `${NAMZU_SKILL_DIR}`. */
|
|
517
|
+
readonly skillDirectory?: string
|
|
518
|
+
}) => {
|
|
519
|
+
readonly granted: readonly string[]
|
|
520
|
+
readonly ignored: readonly {
|
|
521
|
+
readonly entry: string
|
|
522
|
+
readonly reason: string
|
|
523
|
+
}[]
|
|
524
|
+
/** Record the grant in the turn. Idempotent. */
|
|
525
|
+
readonly commit: () => void
|
|
526
|
+
}
|
|
527
|
+
|
|
488
528
|
/**
|
|
489
529
|
* Effective model-visible character cap for this tool result.
|
|
490
530
|
*
|
|
@@ -675,8 +715,41 @@ export interface ToolResult {
|
|
|
675
715
|
* must not lose: what its controls do, where things are, what failed.
|
|
676
716
|
*/
|
|
677
717
|
workingState?: readonly import('../../compaction/types.js').WorkingStatePin[]
|
|
718
|
+
/**
|
|
719
|
+
* This result needs a person before the turn can go on — a sign-in page,
|
|
720
|
+
* a CAPTCHA, a second factor, anything the model must not try to answer
|
|
721
|
+
* itself.
|
|
722
|
+
*
|
|
723
|
+
* The result is committed like any other: it reaches the transcript and
|
|
724
|
+
* the session log with the rest of its batch. Then, instead of calling
|
|
725
|
+
* the model again, the kernel writes a checkpoint and ends the segment
|
|
726
|
+
* with `turn_paused` carrying this value. Resuming the turn continues
|
|
727
|
+
* from that checkpoint, and the next step is a model call that sees the
|
|
728
|
+
* results. Inside a delegated child there is no person to hand to, so
|
|
729
|
+
* the child's turn fails with {@link ToolHandoff.reason} instead.
|
|
730
|
+
*/
|
|
731
|
+
handoff?: ToolHandoff
|
|
678
732
|
}
|
|
679
733
|
|
|
734
|
+
/**
|
|
735
|
+
* A tool's request to stop the turn for a person. See {@link ToolResult.handoff}.
|
|
736
|
+
*/
|
|
737
|
+
export interface ToolHandoff {
|
|
738
|
+
readonly kind: 'human-required'
|
|
739
|
+
/** Operator-facing text: what the person has to do before the turn resumes. */
|
|
740
|
+
readonly reason: string
|
|
741
|
+
/** Structured facts a host can render or act on, such as an origin or a command. */
|
|
742
|
+
readonly detail?: Readonly<Record<string, string>>
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
/**
|
|
746
|
+
* The shell a command line will run in, as the permission rules read it.
|
|
747
|
+
* `bash` reads it as bash does. `sh` reads it for a shell that may be bash or
|
|
748
|
+
* a POSIX shell such as `dash`: every construct the two read differently
|
|
749
|
+
* makes the line opaque, so a line that is not opaque means the same in both.
|
|
750
|
+
*/
|
|
751
|
+
export type ShellDialect = 'bash' | 'sh'
|
|
752
|
+
|
|
680
753
|
export interface ToolDefinition<TInput = unknown> extends ToolPresentation<TInput> {
|
|
681
754
|
name: string
|
|
682
755
|
description: string
|
|
@@ -737,6 +810,20 @@ export interface ToolDefinition<TInput = unknown> extends ToolPresentation<TInpu
|
|
|
737
810
|
* chaining — has nothing to decompose and must not claim otherwise.
|
|
738
811
|
*/
|
|
739
812
|
commandArgument?: string
|
|
813
|
+
/**
|
|
814
|
+
* The shell {@link commandArgument} runs in, as the dialect the permission
|
|
815
|
+
* rules must read it in.
|
|
816
|
+
*
|
|
817
|
+
* A rule reads a command line before it runs, and the reading is only
|
|
818
|
+
* right for the shell that runs it: `$'\x3b'`, `|&` and `&>` mean one
|
|
819
|
+
* thing to bash and another to `dash`. `bash` reads the line as bash
|
|
820
|
+
* does. `sh`, the default when this is absent, reads it for a shell that
|
|
821
|
+
* may be bash or a POSIX shell, and every construct the two read
|
|
822
|
+
* differently makes the line opaque, so no allow rule approves it. The
|
|
823
|
+
* shipped `bash` tool answers `bash` when it will spawn bash on the host
|
|
824
|
+
* and `sh` inside a sandbox, whose guest may not have bash.
|
|
825
|
+
*/
|
|
826
|
+
commandDialect?: (context: { readonly sandboxed: boolean }) => ShellDialect
|
|
740
827
|
/**
|
|
741
828
|
* The argument that holds a filesystem path the tool resolves against the
|
|
742
829
|
* turn's roots (the working directory and the added directories).
|
|
@@ -748,6 +835,23 @@ export interface ToolDefinition<TInput = unknown> extends ToolPresentation<TInpu
|
|
|
748
835
|
* the safe direction to be wrong in.
|
|
749
836
|
*/
|
|
750
837
|
pathArgument?: string
|
|
838
|
+
/**
|
|
839
|
+
* The argument that holds an absolute URL the tool has already
|
|
840
|
+
* canonicalised in its input schema — one spelling, no whitespace.
|
|
841
|
+
*
|
|
842
|
+
* Declared so an `argument_pattern` rule tests the URL whole. Without it
|
|
843
|
+
* the rule reads every argument as a possible command line, and a URL's
|
|
844
|
+
* query separators (`&`, `;`, `|`) cut it into "segments": an `allow` for
|
|
845
|
+
* `^https://github\.com(?:[/?#]|$)` then declined
|
|
846
|
+
* `https://github.com/search?q=a&type=code`, because `type=code` is not
|
|
847
|
+
* GitHub. A `deny` or `review` is unaffected either way; only an `allow`
|
|
848
|
+
* needed every segment to match.
|
|
849
|
+
*
|
|
850
|
+
* Declare it only for an argument the input schema itself canonicalises
|
|
851
|
+
* to a URL. A free-text argument that happens to hold one keeps the
|
|
852
|
+
* command-line reading, which is the safe direction to be wrong in.
|
|
853
|
+
*/
|
|
854
|
+
urlArgument?: string
|
|
751
855
|
/**
|
|
752
856
|
* The boolean argument by which a call asks to run outside the turn's
|
|
753
857
|
* sandbox, when the tool offers that at all (the shipped `bash` does).
|
|
@@ -26,6 +26,13 @@ export type ToolCallView =
|
|
|
26
26
|
readonly activity?: 'exploration'
|
|
27
27
|
/** A successful result may add no information beyond the completed call row. */
|
|
28
28
|
readonly visibility?: 'hidden'
|
|
29
|
+
/**
|
|
30
|
+
* For a result: the person declined on the tool's own screen (a
|
|
31
|
+
* confirmation they cancelled). The call did not succeed, but
|
|
32
|
+
* nothing failed either, so a host draws it as neither: `label` says
|
|
33
|
+
* what did not happen ("Cancelled — nothing was saved").
|
|
34
|
+
*/
|
|
35
|
+
readonly outcome?: 'cancelled'
|
|
29
36
|
}
|
|
30
37
|
/**
|
|
31
38
|
* A change to a document. `path` is optional because not every diff is
|