@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.
- package/CHANGELOG.md +166 -0
- package/dist/authorization/gate.d.ts +5 -2
- package/dist/authorization/gate.d.ts.map +1 -1
- package/dist/authorization/gate.js +35 -4
- package/dist/authorization/gate.js.map +1 -1
- package/dist/authorization/rules.d.ts.map +1 -1
- package/dist/authorization/rules.js +56 -6
- package/dist/authorization/rules.js.map +1 -1
- package/dist/authorization/shell-lexer.d.ts +38 -0
- package/dist/authorization/shell-lexer.d.ts.map +1 -1
- package/dist/authorization/shell-lexer.js +88 -57
- package/dist/authorization/shell-lexer.js.map +1 -1
- 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/pricing/catalogue.generated.d.ts.map +1 -1
- package/dist/pricing/catalogue.generated.js +28 -4
- package/dist/pricing/catalogue.generated.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 +6 -3
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +14 -2
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +7 -2
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +15 -2
- package/dist/public-tools.js.map +1 -1
- package/dist/public-types.d.ts +8 -2
- package/dist/public-types.d.ts.map +1 -1
- package/dist/registry/tool/callable.d.ts +22 -0
- package/dist/registry/tool/callable.d.ts.map +1 -0
- package/dist/registry/tool/callable.js +29 -0
- package/dist/registry/tool/callable.js.map +1 -0
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +8 -1
- package/dist/registry/tool/execute.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/tool-call-admission.d.ts +37 -11
- package/dist/runtime/query/executor/tool-call-admission.d.ts.map +1 -1
- package/dist/runtime/query/executor/tool-call-admission.js +38 -12
- package/dist/runtime/query/executor/tool-call-admission.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +7 -3
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +32 -7
- 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 +1 -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 +7 -0
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +6 -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 +8 -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 +43 -0
- package/dist/runtime/query/review-policy.d.ts.map +1 -1
- package/dist/runtime/query/review-policy.js +63 -19
- package/dist/runtime/query/review-policy.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 +16 -3
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +48 -4
- package/dist/skills/loader.js.map +1 -1
- package/dist/skills/registry.d.ts +6 -0
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +1 -0
- package/dist/skills/registry.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/computer-use-coordinates.d.ts +65 -0
- package/dist/tools/builtins/computer-use-coordinates.d.ts.map +1 -0
- package/dist/tools/builtins/computer-use-coordinates.js +123 -0
- package/dist/tools/builtins/computer-use-coordinates.js.map +1 -0
- package/dist/tools/builtins/computer-use-image.d.ts +77 -0
- package/dist/tools/builtins/computer-use-image.d.ts.map +1 -0
- package/dist/tools/builtins/computer-use-image.js +223 -0
- package/dist/tools/builtins/computer-use-image.js.map +1 -0
- package/dist/tools/builtins/computer-use.d.ts +519 -14
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +1188 -183
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +2 -1
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +1 -1
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/skill.d.ts +74 -0
- package/dist/tools/builtins/skill.d.ts.map +1 -1
- package/dist/tools/builtins/skill.js +214 -159
- package/dist/tools/builtins/skill.js.map +1 -1
- package/dist/tools/defineTool.d.ts +4 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +8 -0
- 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 +71 -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 +17 -0
- package/dist/tools/schedules/schedule-tool.d.ts.map +1 -0
- package/dist/tools/schedules/schedule-tool.js +418 -0
- package/dist/tools/schedules/schedule-tool.js.map +1 -0
- package/dist/tools/schedules/types.d.ts +252 -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 +107 -9
- package/dist/types/authorization/index.d.ts.map +1 -1
- package/dist/types/authorization/index.js +16 -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/computer-use/index.d.ts +176 -0
- package/dist/types/computer-use/index.d.ts.map +1 -1
- package/dist/types/computer-use/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 +60 -0
- 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 +18 -2
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +13 -3
- 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 +3 -1
- package/src/authorization/gate.ts +37 -4
- package/src/authorization/rules.ts +55 -7
- package/src/authorization/shell-lexer.ts +109 -51
- 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/pricing/catalogue.generated.ts +28 -4
- package/src/pricing/rates.source.json +27 -6
- package/src/prompt/coding-agent-doctrine.ts +1 -0
- package/src/public-runtime.ts +43 -1
- package/src/public-tools.ts +54 -1
- package/src/public-types.ts +55 -0
- package/src/registry/tool/callable.ts +37 -0
- package/src/registry/tool/execute.ts +8 -1
- package/src/runtime/query/declined.ts +12 -0
- package/src/runtime/query/executor/tool-call-admission.ts +60 -16
- package/src/runtime/query/executor.ts +36 -5
- package/src/runtime/query/index.ts +1 -0
- package/src/runtime/query/iteration/index.ts +8 -0
- package/src/runtime/query/iteration/phases/context.ts +6 -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 +11 -4
- package/src/runtime/query/resume-pending.ts +3 -2
- package/src/runtime/query/review-policy.ts +107 -18
- 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 +55 -4
- package/src/skills/registry.ts +8 -0
- package/src/tools/builtins/browser-url.ts +251 -0
- package/src/tools/builtins/browser.ts +817 -0
- package/src/tools/builtins/computer-use-coordinates.ts +144 -0
- package/src/tools/builtins/computer-use-image.ts +278 -0
- package/src/tools/builtins/computer-use.ts +1485 -191
- package/src/tools/builtins/index.ts +7 -1
- package/src/tools/builtins/skill.ts +304 -156
- package/src/tools/defineTool.ts +13 -0
- package/src/tools/schedules/index.ts +4 -0
- package/src/tools/schedules/loop-tool.ts +85 -0
- package/src/tools/schedules/present.ts +88 -0
- package/src/tools/schedules/prompt-scan.ts +96 -0
- package/src/tools/schedules/schedule-tool.ts +482 -0
- package/src/tools/schedules/types.ts +265 -0
- package/src/types/authorization/index.ts +81 -2
- package/src/types/browser/index.ts +341 -0
- package/src/types/computer-use/index.ts +202 -0
- package/src/types/session/events.ts +6 -0
- package/src/types/session/records.ts +10 -0
- package/src/types/tool/index.ts +61 -0
- package/src/types/tool/presentation.ts +7 -0
- package/src/utils/frontmatter.ts +29 -3
- package/src/utils/id.ts +14 -0
|
@@ -7,7 +7,13 @@ export { LSP_TOOL_NAME, LspTool, getCodeNavigationTools } from './lsp.js'
|
|
|
7
7
|
export { GrepTool } from './grep.js'
|
|
8
8
|
export { JobTool } from './job.js'
|
|
9
9
|
export { WaitForJobTool } from './wait-for-job.js'
|
|
10
|
-
export { SKILL_TOOL_NAME, SkillTool, parseAllowedTools } from './skill.js'
|
|
10
|
+
export { SKILL_TOOL_NAME, SkillTool, createSkillTool, parseAllowedTools } from './skill.js'
|
|
11
|
+
export type {
|
|
12
|
+
SkillDirectoryContext,
|
|
13
|
+
SkillDirectoryRequest,
|
|
14
|
+
SkillDirectoryResolver,
|
|
15
|
+
SkillToolOptions,
|
|
16
|
+
} from './skill.js'
|
|
11
17
|
export {
|
|
12
18
|
WEB_FETCH_TOOL_NAME,
|
|
13
19
|
WEB_SEARCH_TOOL_NAME,
|
|
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto'
|
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
|
|
4
4
|
import { parseAllowedTools } from '../../authorization/skill-grant.js'
|
|
5
|
+
import type { Sandbox } from '../../types/sandbox/index.js'
|
|
5
6
|
import { isInvocableBy, skillInvocation } from '../../types/skills/index.js'
|
|
6
7
|
import { defineTool } from '../defineTool.js'
|
|
7
8
|
|
|
@@ -22,8 +23,63 @@ export { parseAllowedTools }
|
|
|
22
23
|
* else, from the next batch — which inverted what skill authors mean by it
|
|
23
24
|
* and left a model that loaded `allowed-tools: Read Grep` without `bash`.
|
|
24
25
|
* See `authorization/skill-grant.ts` for what a grant can and cannot do.
|
|
26
|
+
*
|
|
27
|
+
* A skill's body often names files beside it (`scripts/`, `references/`,
|
|
28
|
+
* `assets/`), and the load result carried no directory to open them from. The
|
|
29
|
+
* listing reported the registry's `location`, which is where the HOST reads
|
|
30
|
+
* the skill — a path the model cannot open once its tools run in a sandbox or
|
|
31
|
+
* a remote workspace, so it hard-coded what the skill said to read, or went
|
|
32
|
+
* searching the filesystem. Only the host knows what its tools can reach, so
|
|
33
|
+
* the host says it: {@link SkillToolOptions.resolveModelDirectory}.
|
|
25
34
|
*/
|
|
26
35
|
|
|
36
|
+
/** One skill, as the `skill` tool asks a host about it. */
|
|
37
|
+
export interface SkillDirectoryRequest {
|
|
38
|
+
/** The name the registry accepts, namespaced for a plugin skill (`plugin__skill`). */
|
|
39
|
+
readonly name: string
|
|
40
|
+
/**
|
|
41
|
+
* Where the host loads the skill from (`Skill.dirPath`, or the catalog
|
|
42
|
+
* entry's `directory`); undefined when the registry does not say.
|
|
43
|
+
*/
|
|
44
|
+
readonly directory: string | undefined
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** What the call knows about where the model's tools run. */
|
|
48
|
+
export interface SkillDirectoryContext {
|
|
49
|
+
/** The turn's sandbox, when its tools run in one. Absent on the host. */
|
|
50
|
+
readonly sandbox?: Sandbox
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The directory the model's tools can open for a skill, or undefined when
|
|
55
|
+
* they cannot reach it.
|
|
56
|
+
*
|
|
57
|
+
* Asked per call, with the turn's sandbox, because the answer is a property
|
|
58
|
+
* of where the tools run and not of the skill: the same skill is at its own
|
|
59
|
+
* path on the host, somewhere else inside a container, and absent from a
|
|
60
|
+
* sandbox that does not mount it.
|
|
61
|
+
*/
|
|
62
|
+
export type SkillDirectoryResolver = (
|
|
63
|
+
skill: SkillDirectoryRequest,
|
|
64
|
+
context: SkillDirectoryContext,
|
|
65
|
+
) => string | undefined | Promise<string | undefined>
|
|
66
|
+
|
|
67
|
+
export interface SkillToolOptions {
|
|
68
|
+
/**
|
|
69
|
+
* Say which directory the model can open for each skill.
|
|
70
|
+
*
|
|
71
|
+
* Absent, the tool behaves as it always has: the listing carries the
|
|
72
|
+
* registry's `location` and a load names no directory. Present, a load
|
|
73
|
+
* opens with the directory it returns, or with a line saying the skill's
|
|
74
|
+
* files are not reachable when it returns undefined; the listing carries
|
|
75
|
+
* that `directory` and never the registry's `location`, which is the
|
|
76
|
+
* host's path; and `${CLAUDE_SKILL_DIR}` in `allowed-tools` expands to it,
|
|
77
|
+
* since a command line the model writes names the path the model was
|
|
78
|
+
* given. The skill is still LOADED from the registry's own path.
|
|
79
|
+
*/
|
|
80
|
+
readonly resolveModelDirectory?: SkillDirectoryResolver
|
|
81
|
+
}
|
|
82
|
+
|
|
27
83
|
const inputSchema = z.object({
|
|
28
84
|
name: z
|
|
29
85
|
.string()
|
|
@@ -53,6 +109,8 @@ interface SkillSnapshot {
|
|
|
53
109
|
readonly allowedTools: readonly string[] | undefined
|
|
54
110
|
/** Bound into the cursor because `${CLAUDE_SKILL_DIR}` in a grant expands to it. */
|
|
55
111
|
readonly skillDirectory: string | undefined
|
|
112
|
+
/** What the first page opens with: where the skill's files are, or that they are out of reach. */
|
|
113
|
+
readonly header: string
|
|
56
114
|
readonly invocation: ReturnType<typeof skillInvocation>
|
|
57
115
|
}
|
|
58
116
|
|
|
@@ -64,7 +122,10 @@ interface SkillPage {
|
|
|
64
122
|
interface ListedSkill {
|
|
65
123
|
readonly name: string
|
|
66
124
|
readonly description: string
|
|
67
|
-
|
|
125
|
+
/** The registry's path to the SKILL.md; only when no host resolver is configured. */
|
|
126
|
+
readonly location?: string
|
|
127
|
+
/** The directory the model can open, from the host's resolver. */
|
|
128
|
+
readonly directory?: string
|
|
68
129
|
readonly allowedTools?: string
|
|
69
130
|
}
|
|
70
131
|
|
|
@@ -85,6 +146,7 @@ function snapshotDigest(snapshot: SkillSnapshot): string {
|
|
|
85
146
|
...(snapshot.skillDirectory === undefined
|
|
86
147
|
? {}
|
|
87
148
|
: { skillDirectory: snapshot.skillDirectory }),
|
|
149
|
+
...(snapshot.header === '' ? {} : { header: snapshot.header }),
|
|
88
150
|
invocation: snapshot.invocation,
|
|
89
151
|
}),
|
|
90
152
|
)
|
|
@@ -218,7 +280,9 @@ function pageSkillBody(input: {
|
|
|
218
280
|
readonly maxChars: number | undefined
|
|
219
281
|
}): SkillPage | undefined {
|
|
220
282
|
const { snapshot, digest, start, notice, maxChars } = input
|
|
221
|
-
|
|
283
|
+
// The first page only: a continuation is read after it, in the same history.
|
|
284
|
+
const header = start === 0 ? snapshot.header : ''
|
|
285
|
+
const remaining = `${header}${snapshot.body.slice(start)}${notice}`
|
|
222
286
|
if (maxChars === undefined || maxChars <= 0 || remaining.length <= maxChars) {
|
|
223
287
|
return { output: remaining }
|
|
224
288
|
}
|
|
@@ -229,7 +293,7 @@ function pageSkillBody(input: {
|
|
|
229
293
|
let end = boundaryAtOrBefore(snapshot.body, Math.min(snapshot.body.length - 1, start + maxChars))
|
|
230
294
|
while (end > start) {
|
|
231
295
|
const nextCursor = cursorFor(end, digest)
|
|
232
|
-
const output = `${snapshot.body.slice(start, end)}${continuationNotice(
|
|
296
|
+
const output = `${header}${snapshot.body.slice(start, end)}${continuationNotice(
|
|
233
297
|
snapshot.name,
|
|
234
298
|
nextCursor,
|
|
235
299
|
)}${notice}`
|
|
@@ -242,198 +306,282 @@ function pageSkillBody(input: {
|
|
|
242
306
|
|
|
243
307
|
export const SKILL_TOOL_NAME = 'skill'
|
|
244
308
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
309
|
+
/**
|
|
310
|
+
* Build the `skill` tool, with what the host knows about where its model's
|
|
311
|
+
* tools run. {@link SkillTool} is this with no options.
|
|
312
|
+
*/
|
|
313
|
+
export function createSkillTool(options: SkillToolOptions = {}) {
|
|
314
|
+
const resolveModelDirectory = options.resolveModelDirectory
|
|
315
|
+
return defineTool({
|
|
316
|
+
name: SKILL_TOOL_NAME,
|
|
317
|
+
description:
|
|
318
|
+
'Lists model-invocable skills when called without a name, or loads one skill by its exact listed name. Long lists and bodies return an opaque continuation cursor; keep calling in the same mode with that cursor until no continuation remains. The manifest carries only names and descriptions.',
|
|
319
|
+
inputSchema,
|
|
320
|
+
category: 'analysis',
|
|
321
|
+
permissions: [],
|
|
322
|
+
// Reads instructions and changes nothing on disk. What it does change is
|
|
323
|
+
// the turn's approvals, through `grantSkillTools`, and only ever towards
|
|
324
|
+
// fewer prompts for calls the operator's policy already leaves to review.
|
|
325
|
+
readOnly: true,
|
|
326
|
+
destructive: false,
|
|
327
|
+
concurrencySafe: true,
|
|
328
|
+
|
|
329
|
+
// The body is instructions for the model, often a hundred lines; the
|
|
330
|
+
// person needs the row that says which skill was read, not the text.
|
|
331
|
+
presentCall(input: SkillInput) {
|
|
332
|
+
const name = typeof input?.name === 'string' ? input.name : undefined
|
|
261
333
|
return {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
334
|
+
kind: 'generic',
|
|
335
|
+
presentation: 'activity',
|
|
336
|
+
label:
|
|
337
|
+
name === undefined
|
|
338
|
+
? input?.cursor === undefined
|
|
339
|
+
? 'List skills'
|
|
340
|
+
: 'List more skills'
|
|
341
|
+
: `Read skill ${name}${input.cursor === undefined ? '' : ' (continued)'}`,
|
|
266
342
|
}
|
|
267
|
-
}
|
|
343
|
+
},
|
|
344
|
+
presentResult: (_input: SkillInput, result) =>
|
|
345
|
+
result.success ? { kind: 'generic', label: 'read', visibility: 'hidden' } : undefined,
|
|
268
346
|
|
|
269
|
-
|
|
270
|
-
if (!context.skills
|
|
347
|
+
async execute(input: SkillInput, context) {
|
|
348
|
+
if (!context.skills) {
|
|
271
349
|
return {
|
|
272
350
|
success: false,
|
|
273
351
|
output: '',
|
|
274
352
|
error:
|
|
275
|
-
'This skills registry
|
|
353
|
+
'This turn has no skills registry, so there is nothing to load. Proceed without the skill.',
|
|
276
354
|
}
|
|
277
355
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
356
|
+
|
|
357
|
+
if (input.name === undefined) {
|
|
358
|
+
if (!context.skills.catalog) {
|
|
359
|
+
return {
|
|
360
|
+
success: false,
|
|
361
|
+
output: '',
|
|
362
|
+
error:
|
|
363
|
+
'This skills registry cannot enumerate model-safe metadata. Use a skill name from the available-skills manifest.',
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const directoryContext = directoryContextOf(context.sandbox)
|
|
367
|
+
const skills = await Promise.all(
|
|
368
|
+
(await context.skills.catalog())
|
|
369
|
+
.filter(
|
|
370
|
+
(entry) =>
|
|
371
|
+
entry.invocation === undefined ||
|
|
372
|
+
entry.invocation === 'model' ||
|
|
373
|
+
entry.invocation === 'both',
|
|
374
|
+
)
|
|
375
|
+
.map(async (entry): Promise<ListedSkill> => {
|
|
376
|
+
// With a resolver the registry's `location` is left out, not
|
|
377
|
+
// shown beside the directory: it is the host's path, the one
|
|
378
|
+
// a sandboxed model cannot open.
|
|
379
|
+
let where: Pick<ListedSkill, 'location' | 'directory'>
|
|
380
|
+
if (resolveModelDirectory) {
|
|
381
|
+
const directory = nonEmpty(
|
|
382
|
+
await resolveModelDirectory(
|
|
383
|
+
{ name: entry.registeredName, directory: entry.directory },
|
|
384
|
+
directoryContext,
|
|
385
|
+
),
|
|
386
|
+
)
|
|
387
|
+
where = directory === undefined ? {} : { directory }
|
|
388
|
+
} else {
|
|
389
|
+
where = { location: entry.location }
|
|
390
|
+
}
|
|
391
|
+
return {
|
|
392
|
+
name: entry.registeredName,
|
|
393
|
+
description: entry.description,
|
|
394
|
+
...where,
|
|
395
|
+
...(entry.allowedTools === undefined ? {} : { allowedTools: entry.allowedTools }),
|
|
396
|
+
}
|
|
397
|
+
}),
|
|
292
398
|
)
|
|
293
|
-
|
|
294
|
-
|
|
399
|
+
const maxChars = activeOutputCap(context.maxToolOutputChars)
|
|
400
|
+
const digest = listDigest(skills, maxChars)
|
|
401
|
+
let start = 0
|
|
402
|
+
let warningAlreadyShown = false
|
|
403
|
+
if (input.cursor !== undefined) {
|
|
404
|
+
const parsed = parseListCursor(input.cursor)
|
|
405
|
+
if (!parsed || parsed.digest !== digest || parsed.offset >= skills.length) {
|
|
406
|
+
return {
|
|
407
|
+
success: false,
|
|
408
|
+
output: '',
|
|
409
|
+
error:
|
|
410
|
+
'The skill-list continuation cursor is stale or invalid. Call skill again without a cursor to read the current catalog.',
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
start = parsed.offset
|
|
414
|
+
warningAlreadyShown = parsed.warned
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const page = pageSkillCatalog({
|
|
418
|
+
skills,
|
|
419
|
+
digest,
|
|
420
|
+
start,
|
|
421
|
+
warningAlreadyShown,
|
|
422
|
+
maxChars,
|
|
423
|
+
})
|
|
424
|
+
if (!page) {
|
|
425
|
+
return {
|
|
426
|
+
success: false,
|
|
427
|
+
output: '',
|
|
428
|
+
error:
|
|
429
|
+
'The model-visible tool-output budget is too small to list skill metadata safely. Increase maxToolOutputChars and retry.',
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
success: true,
|
|
435
|
+
output: serializeListPage(page),
|
|
436
|
+
data: {
|
|
437
|
+
kind: 'list',
|
|
438
|
+
count: page.skills.length,
|
|
439
|
+
...(page.nextCursor === null ? {} : { nextCursor: page.nextCursor }),
|
|
440
|
+
},
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// The registry answers with a load RESULT, not a skill — the shape
|
|
445
|
+
// mirrors the implementation rather than an adapter, so there is
|
|
446
|
+
// nothing between them to drift.
|
|
447
|
+
const loaded = await context.skills.load(input.name)
|
|
448
|
+
if (!loaded) {
|
|
449
|
+
// Named, with what IS available. A bare "not found" sends the model
|
|
450
|
+
// guessing at spellings, and the manifest it is guessing from is
|
|
451
|
+
// right there in its own prompt.
|
|
452
|
+
const available = context.skills.names()
|
|
453
|
+
return {
|
|
454
|
+
success: false,
|
|
455
|
+
output: '',
|
|
456
|
+
error: `No skill named "${input.name}". Available: ${available.length > 0 ? available.join(', ') : '(none)'}`,
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const skill = loaded.skill
|
|
461
|
+
const invocation = skillInvocation(skill)
|
|
462
|
+
if (!isInvocableBy(skill, 'model')) {
|
|
463
|
+
// Reachable even though the manifest omits it: the model can name
|
|
464
|
+
// anything, and a check that only filtered the listing would be a
|
|
465
|
+
// menu restriction rather than a kitchen one — the exact defect
|
|
466
|
+
// `allowedTools` had before it was enforced at dispatch.
|
|
467
|
+
return {
|
|
468
|
+
success: false,
|
|
469
|
+
output: '',
|
|
470
|
+
error: `The skill "${input.name}" is ${skillInvocation(skill)}-invocable; it is not for you to run.`,
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
const allowed = parseAllowedTools(skill.metadata.allowedTools)
|
|
475
|
+
// Asked on every call, first page or continuation: the digest binds
|
|
476
|
+
// the answer, so a mount that changed between pages is a stale cursor
|
|
477
|
+
// rather than a second half written for a different directory.
|
|
478
|
+
const modelDirectory = resolveModelDirectory
|
|
479
|
+
? nonEmpty(
|
|
480
|
+
await resolveModelDirectory(
|
|
481
|
+
{ name: input.name, directory: skill.dirPath },
|
|
482
|
+
directoryContextOf(context.sandbox),
|
|
483
|
+
),
|
|
484
|
+
)
|
|
485
|
+
: undefined
|
|
486
|
+
const snapshot: SkillSnapshot = {
|
|
487
|
+
name: input.name,
|
|
488
|
+
body: skill.body ?? '(this skill has no body)',
|
|
489
|
+
allowedTools: allowed,
|
|
490
|
+
// The model's path when the host gave one: `${CLAUDE_SKILL_DIR}` in a
|
|
491
|
+
// pattern is matched against a command line the model writes, and it
|
|
492
|
+
// writes the path it was told.
|
|
493
|
+
skillDirectory: resolveModelDirectory ? modelDirectory : skill.dirPath,
|
|
494
|
+
header: resolveModelDirectory ? directoryHeader(modelDirectory) : '',
|
|
495
|
+
invocation,
|
|
496
|
+
}
|
|
497
|
+
const digest = snapshotDigest(snapshot)
|
|
295
498
|
let start = 0
|
|
296
|
-
let warningAlreadyShown = false
|
|
297
499
|
if (input.cursor !== undefined) {
|
|
298
|
-
const parsed =
|
|
299
|
-
if (
|
|
500
|
+
const parsed = parseCursor(input.cursor)
|
|
501
|
+
if (
|
|
502
|
+
!parsed ||
|
|
503
|
+
parsed.digest !== digest ||
|
|
504
|
+
parsed.offset >= snapshot.body.length ||
|
|
505
|
+
!isCodePointBoundary(snapshot.body, parsed.offset)
|
|
506
|
+
) {
|
|
300
507
|
return {
|
|
301
508
|
success: false,
|
|
302
509
|
output: '',
|
|
303
|
-
error:
|
|
304
|
-
'The skill-list continuation cursor is stale or invalid. Call skill again without a cursor to read the current catalog.',
|
|
510
|
+
error: `The continuation cursor for "${input.name}" is stale or invalid. Call skill again without a cursor to read the current instructions.`,
|
|
305
511
|
}
|
|
306
512
|
}
|
|
307
513
|
start = parsed.offset
|
|
308
|
-
warningAlreadyShown = parsed.warned
|
|
309
514
|
}
|
|
310
515
|
|
|
311
|
-
|
|
312
|
-
|
|
516
|
+
// Compiled before paging so the notice can say what the grant is, and
|
|
517
|
+
// committed only after paging succeeded: a load that fails here gave
|
|
518
|
+
// the model no instructions, so it must not have approved anything.
|
|
519
|
+
// Idempotent: a continuation call grants the same entries again, and
|
|
520
|
+
// the turn's set keeps one copy.
|
|
521
|
+
let grant: ReturnType<NonNullable<typeof context.grantSkillTools>> | undefined
|
|
522
|
+
if (allowed !== undefined && allowed.length > 0 && context.grantSkillTools) {
|
|
523
|
+
grant = context.grantSkillTools({
|
|
524
|
+
skill: skill.metadata.name,
|
|
525
|
+
allowedTools: allowed,
|
|
526
|
+
...(snapshot.skillDirectory ? { skillDirectory: snapshot.skillDirectory } : {}),
|
|
527
|
+
})
|
|
528
|
+
}
|
|
529
|
+
const notice = grantNotice(allowed, grant, context.grantSkillTools !== undefined)
|
|
530
|
+
const page = pageSkillBody({
|
|
531
|
+
snapshot,
|
|
313
532
|
digest,
|
|
314
533
|
start,
|
|
315
|
-
|
|
316
|
-
maxChars,
|
|
534
|
+
notice,
|
|
535
|
+
maxChars: context.maxToolOutputChars,
|
|
317
536
|
})
|
|
318
537
|
if (!page) {
|
|
319
538
|
return {
|
|
320
539
|
success: false,
|
|
321
540
|
output: '',
|
|
322
|
-
error:
|
|
323
|
-
'The model-visible tool-output budget is too small to list skill metadata safely. Increase maxToolOutputChars and retry.',
|
|
541
|
+
error: `The model-visible tool-output budget is too small to read "${input.name}" safely. Increase maxToolOutputChars and retry.`,
|
|
324
542
|
}
|
|
325
543
|
}
|
|
544
|
+
grant?.commit()
|
|
326
545
|
|
|
327
546
|
return {
|
|
328
547
|
success: true,
|
|
329
|
-
output:
|
|
548
|
+
output: page.output,
|
|
330
549
|
data: {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
...(
|
|
550
|
+
skill: skill.metadata.name,
|
|
551
|
+
...(modelDirectory === undefined ? {} : { directory: modelDirectory }),
|
|
552
|
+
...(allowed === undefined ? {} : { allowedTools: allowed }),
|
|
553
|
+
...(grant ? { granted: grant.granted, ignored: grant.ignored } : {}),
|
|
554
|
+
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
334
555
|
},
|
|
335
556
|
}
|
|
336
|
-
}
|
|
557
|
+
},
|
|
558
|
+
})
|
|
559
|
+
}
|
|
337
560
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
// nothing between them to drift.
|
|
341
|
-
const loaded = await context.skills.load(input.name)
|
|
342
|
-
if (!loaded) {
|
|
343
|
-
// Named, with what IS available. A bare "not found" sends the model
|
|
344
|
-
// guessing at spellings, and the manifest it is guessing from is
|
|
345
|
-
// right there in its own prompt.
|
|
346
|
-
const available = context.skills.names()
|
|
347
|
-
return {
|
|
348
|
-
success: false,
|
|
349
|
-
output: '',
|
|
350
|
-
error: `No skill named "${input.name}". Available: ${available.length > 0 ? available.join(', ') : '(none)'}`,
|
|
351
|
-
}
|
|
352
|
-
}
|
|
561
|
+
/** The `skill` tool with no host options: the listing carries the registry's `location`. */
|
|
562
|
+
export const SkillTool = createSkillTool()
|
|
353
563
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// Reachable even though the manifest omits it: the model can name
|
|
358
|
-
// anything, and a check that only filtered the listing would be a
|
|
359
|
-
// menu restriction rather than a kitchen one — the exact defect
|
|
360
|
-
// `allowedTools` had before it was enforced at dispatch.
|
|
361
|
-
return {
|
|
362
|
-
success: false,
|
|
363
|
-
output: '',
|
|
364
|
-
error: `The skill "${input.name}" is ${skillInvocation(skill)}-invocable; it is not for you to run.`,
|
|
365
|
-
}
|
|
366
|
-
}
|
|
564
|
+
function directoryContextOf(sandbox: Sandbox | undefined): SkillDirectoryContext {
|
|
565
|
+
return sandbox ? { sandbox } : {}
|
|
566
|
+
}
|
|
367
567
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
allowedTools: allowed,
|
|
373
|
-
skillDirectory: skill.dirPath,
|
|
374
|
-
invocation,
|
|
375
|
-
}
|
|
376
|
-
const digest = snapshotDigest(snapshot)
|
|
377
|
-
let start = 0
|
|
378
|
-
if (input.cursor !== undefined) {
|
|
379
|
-
const parsed = parseCursor(input.cursor)
|
|
380
|
-
if (
|
|
381
|
-
!parsed ||
|
|
382
|
-
parsed.digest !== digest ||
|
|
383
|
-
parsed.offset >= snapshot.body.length ||
|
|
384
|
-
!isCodePointBoundary(snapshot.body, parsed.offset)
|
|
385
|
-
) {
|
|
386
|
-
return {
|
|
387
|
-
success: false,
|
|
388
|
-
output: '',
|
|
389
|
-
error: `The continuation cursor for "${input.name}" is stale or invalid. Call skill again without a cursor to read the current instructions.`,
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
start = parsed.offset
|
|
393
|
-
}
|
|
568
|
+
/** An empty string names no directory; treated as the resolver saying none. */
|
|
569
|
+
function nonEmpty(directory: string | undefined): string | undefined {
|
|
570
|
+
return directory === undefined || directory === '' ? undefined : directory
|
|
571
|
+
}
|
|
394
572
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
const notice = grantNotice(allowed, grant, context.grantSkillTools !== undefined)
|
|
409
|
-
const page = pageSkillBody({
|
|
410
|
-
snapshot,
|
|
411
|
-
digest,
|
|
412
|
-
start,
|
|
413
|
-
notice,
|
|
414
|
-
maxChars: context.maxToolOutputChars,
|
|
415
|
-
})
|
|
416
|
-
if (!page) {
|
|
417
|
-
return {
|
|
418
|
-
success: false,
|
|
419
|
-
output: '',
|
|
420
|
-
error: `The model-visible tool-output budget is too small to read "${input.name}" safely. Increase maxToolOutputChars and retry.`,
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
grant?.commit()
|
|
424
|
-
|
|
425
|
-
return {
|
|
426
|
-
success: true,
|
|
427
|
-
output: page.output,
|
|
428
|
-
data: {
|
|
429
|
-
skill: skill.metadata.name,
|
|
430
|
-
...(allowed === undefined ? {} : { allowedTools: allowed }),
|
|
431
|
-
...(grant ? { granted: grant.granted, ignored: grant.ignored } : {}),
|
|
432
|
-
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
433
|
-
},
|
|
434
|
-
}
|
|
435
|
-
},
|
|
436
|
-
})
|
|
573
|
+
/**
|
|
574
|
+
* The line a load opens with once a host has said where the skill's files are.
|
|
575
|
+
*
|
|
576
|
+
* The unreachable case is said out loud rather than left blank. A model given
|
|
577
|
+
* no directory for a skill that says "run scripts/render.sh" goes looking for
|
|
578
|
+
* it, and on a sandboxed turn that search can only fail.
|
|
579
|
+
*/
|
|
580
|
+
function directoryHeader(directory: string | undefined): string {
|
|
581
|
+
return directory === undefined
|
|
582
|
+
? "[This skill's directory is not reachable from your tools in this session, so a file these instructions name by a relative path (scripts/, references/, assets/) cannot be opened here. Do not search the filesystem for it; if the task needs one, say so.]\n\n"
|
|
583
|
+
: `[Skill directory: ${directory}. Relative paths in these instructions, such as scripts/, references/ or assets/, are inside it.]\n\n`
|
|
584
|
+
}
|
|
437
585
|
|
|
438
586
|
/**
|
|
439
587
|
* What the model is told about `allowed-tools`.
|
package/src/tools/defineTool.ts
CHANGED
|
@@ -21,6 +21,8 @@ export interface DefineToolOptions<S extends z.ZodType> {
|
|
|
21
21
|
readOnly: boolean | ((input: z.infer<S>) => boolean)
|
|
22
22
|
destructive: boolean | ((input: z.infer<S>) => boolean)
|
|
23
23
|
concurrencySafe: boolean
|
|
24
|
+
/** Whether this exact call sends the screen to the provider; see {@link ToolDefinition.capturesScreen}. */
|
|
25
|
+
capturesScreen?: boolean | ((input: z.infer<S>) => boolean)
|
|
24
26
|
/** Batch ordering boundary; see {@link ToolDefinition.executionBarrier}. */
|
|
25
27
|
executionBarrier?: boolean
|
|
26
28
|
tier?: string
|
|
@@ -65,6 +67,8 @@ export interface DefineToolOptions<S extends z.ZodType> {
|
|
|
65
67
|
commandDialect?: ToolDefinition['commandDialect']
|
|
66
68
|
/** The argument holding a filesystem path; see {@link ToolDefinition.pathArgument}. */
|
|
67
69
|
pathArgument?: string
|
|
70
|
+
/** The argument holding a canonical URL; see {@link ToolDefinition.urlArgument}. */
|
|
71
|
+
urlArgument?: string
|
|
68
72
|
/** The argument asking to leave the sandbox; see {@link ToolDefinition.sandboxEscapeArgument}. */
|
|
69
73
|
sandboxEscapeArgument?: string
|
|
70
74
|
execute(input: z.infer<S>, context: ToolContext): Promise<ToolResult>
|
|
@@ -117,6 +121,7 @@ export function defineTool<S extends z.ZodType>(
|
|
|
117
121
|
...(options.commandArgument !== undefined ? { commandArgument: options.commandArgument } : {}),
|
|
118
122
|
...(options.commandDialect !== undefined ? { commandDialect: options.commandDialect } : {}),
|
|
119
123
|
...(options.pathArgument !== undefined ? { pathArgument: options.pathArgument } : {}),
|
|
124
|
+
...(options.urlArgument !== undefined ? { urlArgument: options.urlArgument } : {}),
|
|
120
125
|
...(options.sandboxEscapeArgument !== undefined
|
|
121
126
|
? { sandboxEscapeArgument: options.sandboxEscapeArgument }
|
|
122
127
|
: {}),
|
|
@@ -136,6 +141,14 @@ export function defineTool<S extends z.ZodType>(
|
|
|
136
141
|
? options.destructive
|
|
137
142
|
: constantDestructive(options.destructive as boolean),
|
|
138
143
|
isConcurrencySafe: () => options.concurrencySafe,
|
|
144
|
+
...(options.capturesScreen !== undefined
|
|
145
|
+
? {
|
|
146
|
+
capturesScreen:
|
|
147
|
+
typeof options.capturesScreen === 'function'
|
|
148
|
+
? options.capturesScreen
|
|
149
|
+
: () => options.capturesScreen as boolean,
|
|
150
|
+
}
|
|
151
|
+
: {}),
|
|
139
152
|
|
|
140
153
|
async execute(input: TInput, context: ToolContext): Promise<ToolResult> {
|
|
141
154
|
try {
|