@capybara-hq/plugin-sdk 0.1.0-rc.2 → 0.1.0-rc.3
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/README.md +1 -1
- package/agent-docs/agent-templates.md +47 -0
- package/agent-docs/concepts.md +58 -0
- package/agent-docs/connector-templates.md +47 -0
- package/agent-docs/extension-points/channel.md +15 -0
- package/agent-docs/extension-points/config-source.md +15 -0
- package/agent-docs/extension-points/connector.md +15 -0
- package/agent-docs/extension-points/counter.md +15 -0
- package/agent-docs/extension-points/directory.md +15 -0
- package/agent-docs/extension-points/file-preview.md +15 -0
- package/agent-docs/extension-points/identity-source.md +15 -0
- package/agent-docs/extension-points/model-provider.md +15 -0
- package/agent-docs/extension-points/object-store.md +15 -0
- package/agent-docs/extension-points/sandbox.md +15 -0
- package/agent-docs/extension-points/secret-store.md +15 -0
- package/agent-docs/extension-points/web-fetch.md +15 -0
- package/agent-docs/extension-points/web-search.md +15 -0
- package/agent-docs/extensions.md +63 -0
- package/agent-docs/plugin-format.md +60 -0
- package/agent-docs/skills.md +44 -0
- package/agent-docs/tool-naming.md +21 -0
- package/dist/agent-template.d.ts +85 -0
- package/dist/agent-template.js +361 -2
- package/dist/config-ui.d.ts +2 -1
- package/dist/config-ui.js +25 -7
- package/dist/ctx.d.ts +3 -1
- package/dist/directory.d.ts +11 -2
- package/dist/extension-point.d.ts +4 -0
- package/dist/extension-point.js +16 -14
- package/dist/file-preview.d.ts +8 -0
- package/dist/hooks.d.ts +11 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/marketplace.d.ts +29 -2
- package/dist/marketplace.js +30 -2
- package/dist/org-access.d.ts +27 -0
- package/dist/org-access.js +35 -0
- package/dist/plugin-manifest.d.ts +15 -2
- package/dist/plugin-manifest.js +11 -1
- package/dist/sandbox.d.ts +140 -60
- package/dist/sandbox.js +30 -6
- package/dist/skill-invocation.d.ts +8 -5
- package/dist/skill-invocation.js +17 -8
- package/dist/skill.d.ts +20 -3
- package/dist/skill.js +28 -6
- package/dist/tool.d.ts +8 -0
- package/dist/ui.d.ts +8 -0
- package/dist/web.d.ts +30 -5
- package/package.json +4 -2
- package/schemas/marketplace.v1.schema.json +36 -0
- package/schemas/plugin.v1.schema.json +29 -4
package/dist/sandbox.js
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Sandbox contract `sandbox@
|
|
2
|
+
* Sandbox contract `sandbox@2`: a single-select, brokered extension point (extensions may not
|
|
3
3
|
* `requires` it; the kernel's `SandboxService` consumes it). The provider implements only the
|
|
4
4
|
* primitives below; the kernel builds `glob` / `grep` / `edit` from `exec` plus `readFile` /
|
|
5
5
|
* `writeFile`.
|
|
6
|
+
*
|
|
7
|
+
* `@2` separates an environment's **file system** from its **instance**: the file system
|
|
8
|
+
* (`createFileSystem`) lives until the environment is deleted (`destroyFileSystem`); instances
|
|
9
|
+
* (`create`) attach to it and come and go (`destroy` drops the instance and keeps the files).
|
|
6
10
|
*/
|
|
7
11
|
/** Sandbox extension point ref. */
|
|
8
|
-
export const SANDBOX_EXTENSION_POINT = "sandbox@
|
|
9
|
-
/**
|
|
12
|
+
export const SANDBOX_EXTENSION_POINT = "sandbox@2";
|
|
13
|
+
/** The roots inside the sandbox the model may access. */
|
|
10
14
|
export const SANDBOX_ROOTS = ["/workspace", "/skills", "/tmp"];
|
|
11
15
|
const MAX_PATH_LENGTH = 4096;
|
|
12
16
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
17
|
+
* The instance is definitely gone on the provider's side (container removed, E2B sandbox expired).
|
|
18
|
+
* `exec` / `readFile` / `writeFile` / `stat` must throw it (not a plain Error) when they find the
|
|
19
|
+
* instance gone; the kernel then rebuilds the instance and retries once. A transient connection
|
|
20
|
+
* failure throws a plain error.
|
|
15
21
|
*/
|
|
16
22
|
export class SandboxGoneError extends Error {
|
|
17
23
|
sandboxGone = true;
|
|
@@ -20,12 +26,30 @@ export class SandboxGoneError extends Error {
|
|
|
20
26
|
this.name = "SandboxGoneError";
|
|
21
27
|
}
|
|
22
28
|
}
|
|
23
|
-
/**
|
|
29
|
+
/** Duck-typed check (not instanceof), so a plugin bundling another plugin-sdk copy still matches. */
|
|
24
30
|
export function isSandboxGoneError(e) {
|
|
25
31
|
return (e instanceof Error &&
|
|
26
32
|
e.name === "SandboxGoneError" &&
|
|
27
33
|
e.sandboxGone === true);
|
|
28
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* The file system is definitely gone on the provider's side (volume removed, E2B sandbox killed).
|
|
37
|
+
* `create` throws it instead of attaching the instance to a new, empty file system; the kernel then
|
|
38
|
+
* reports the environment's files as lost rather than handing out a silently empty workspace.
|
|
39
|
+
*/
|
|
40
|
+
export class FileSystemGoneError extends Error {
|
|
41
|
+
fileSystemGone = true;
|
|
42
|
+
constructor(message, opts) {
|
|
43
|
+
super(message, opts && "cause" in opts ? { cause: opts.cause } : undefined);
|
|
44
|
+
this.name = "FileSystemGoneError";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Duck-typed check (not instanceof), so a plugin bundling another plugin-sdk copy still matches. */
|
|
48
|
+
export function isFileSystemGoneError(e) {
|
|
49
|
+
return (e instanceof Error &&
|
|
50
|
+
e.name === "FileSystemGoneError" &&
|
|
51
|
+
e.fileSystemGone === true);
|
|
52
|
+
}
|
|
29
53
|
/**
|
|
30
54
|
* A holder tag (`exec` argument `tag`, {@link SandboxProvider.killTagged}): the kernel passes its
|
|
31
55
|
* lease tokens (UUIDs). Providers check tags against it before putting them in a command line or a
|
|
@@ -26,13 +26,14 @@ export declare function skillInvocation(frontmatter: Readonly<Record<string, unk
|
|
|
26
26
|
export declare function parseSkillArguments(args: string): string[];
|
|
27
27
|
/**
|
|
28
28
|
* A skill body with its arguments substituted (see the file header), without the wrapper.
|
|
29
|
-
* `skillName` is the resolved skill's bare name
|
|
30
|
-
* `/skills/<skillName>` (a qualified `<plugin>:<name>`
|
|
29
|
+
* `skillName` is the resolved skill's bare name and `digest` its version's `skillDigest`:
|
|
30
|
+
* `${CLAUDE_SKILL_DIR}` becomes `/skills/<skillName>@<digest>` (a qualified `<plugin>:<name>` or a
|
|
31
|
+
* digest that is not 12 lowercase hex digits throws a `TypeError`). `args` is trimmed;
|
|
31
32
|
* more than {@link SKILL_INVOCATION_LIMITS.argumentsMaxChars} characters throw a `RangeError`, and
|
|
32
33
|
* so does a result longer than {@link SKILL_INVOCATION_LIMITS.renderedMaxChars} (checked while
|
|
33
34
|
* substituting, before the long string is built).
|
|
34
35
|
*/
|
|
35
|
-
export declare function renderSkillBody(body: string, invocation: SkillInvocation, args: string, skillName: string): string;
|
|
36
|
+
export declare function renderSkillBody(body: string, invocation: SkillInvocation, args: string, skillName: string, digest: string): string;
|
|
36
37
|
/** Input of {@link renderSkillInvocation}. */
|
|
37
38
|
export interface RenderSkillInvocationInput {
|
|
38
39
|
/**
|
|
@@ -41,10 +42,12 @@ export interface RenderSkillInvocationInput {
|
|
|
41
42
|
*/
|
|
42
43
|
name: string;
|
|
43
44
|
/**
|
|
44
|
-
* The resolved skill's bare name (never `<plugin>:<name>`): its sandbox
|
|
45
|
-
* `/skills/<skillName>/`, used for `${CLAUDE_SKILL_DIR}` and the files line.
|
|
45
|
+
* The resolved skill's bare name (never `<plugin>:<name>`): with `digest`, its sandbox
|
|
46
|
+
* directory `/skills/<skillName>@<digest>/`, used for `${CLAUDE_SKILL_DIR}` and the files line.
|
|
46
47
|
*/
|
|
47
48
|
skillName: string;
|
|
49
|
+
/** The version's `skillDigest` (12 lowercase hex digits). */
|
|
50
|
+
digest: string;
|
|
48
51
|
version: number;
|
|
49
52
|
/** The SKILL.md body (after the frontmatter). */
|
|
50
53
|
body: string;
|
package/dist/skill-invocation.js
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
* The argument rules follow Claude Code (re-checked 2026-10-27): `$ARGUMENTS` is the whole argument
|
|
7
7
|
* string, `$ARGUMENTS[N]` / `$N` are 0-based positional values (a missing one stays as written),
|
|
8
8
|
* `$name` takes its value from frontmatter `arguments` (a missing one becomes empty), `\$` is a
|
|
9
|
-
* literal `$`, `${CLAUDE_SKILL_DIR}` is `/skills/<name>` and every other `${…}` stays as written.
|
|
9
|
+
* literal `$`, `${CLAUDE_SKILL_DIR}` is `/skills/<name>@<digest>` and every other `${…}` stays as written.
|
|
10
10
|
* When the body has no argument placeholder and the arguments are not empty, they are appended as
|
|
11
11
|
* `ARGUMENTS: <args>`. Substituted text is never scanned again. Nothing is executed: shell
|
|
12
12
|
* injections (`` !`cmd` ``) stay text, and the model is told how to run them.
|
|
13
13
|
*/
|
|
14
|
-
import { isSkillName, SKILL_INVOCATION_LIMITS, SKILLS_SANDBOX_ROOT } from "./skill.js";
|
|
14
|
+
import { isSkillName, SKILL_INVOCATION_LIMITS, SKILLS_SANDBOX_ROOT, skillSandboxDir, } from "./skill.js";
|
|
15
15
|
import { argumentHintText, SKILL_ARGUMENT_NAME_RE } from "./skill-keys.js";
|
|
16
16
|
/**
|
|
17
17
|
* The invocation metadata of a SKILL.md frontmatter. Values of the wrong type are ignored here
|
|
@@ -102,17 +102,26 @@ const checkSkillName = (skillName) => {
|
|
|
102
102
|
throw new TypeError(`skillName must be a bare skill name (its directory under ${SKILLS_SANDBOX_ROOT}), got "${skillName}"`);
|
|
103
103
|
}
|
|
104
104
|
};
|
|
105
|
+
const DIGEST_RE = /^[0-9a-f]{12}$/;
|
|
106
|
+
const checkDigest = (digest) => {
|
|
107
|
+
if (typeof digest !== "string" || !DIGEST_RE.test(digest)) {
|
|
108
|
+
throw new TypeError(`digest must be 12 lowercase hex digits (skillDigest), got "${digest}"`);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
105
111
|
const tooLong = () => new RangeError(`the rendered skill must be at most ${SKILL_INVOCATION_LIMITS.renderedMaxChars} characters`);
|
|
106
112
|
/**
|
|
107
113
|
* A skill body with its arguments substituted (see the file header), without the wrapper.
|
|
108
|
-
* `skillName` is the resolved skill's bare name
|
|
109
|
-
* `/skills/<skillName>` (a qualified `<plugin>:<name>`
|
|
114
|
+
* `skillName` is the resolved skill's bare name and `digest` its version's `skillDigest`:
|
|
115
|
+
* `${CLAUDE_SKILL_DIR}` becomes `/skills/<skillName>@<digest>` (a qualified `<plugin>:<name>` or a
|
|
116
|
+
* digest that is not 12 lowercase hex digits throws a `TypeError`). `args` is trimmed;
|
|
110
117
|
* more than {@link SKILL_INVOCATION_LIMITS.argumentsMaxChars} characters throw a `RangeError`, and
|
|
111
118
|
* so does a result longer than {@link SKILL_INVOCATION_LIMITS.renderedMaxChars} (checked while
|
|
112
119
|
* substituting, before the long string is built).
|
|
113
120
|
*/
|
|
114
|
-
export function renderSkillBody(body, invocation, args, skillName) {
|
|
121
|
+
export function renderSkillBody(body, invocation, args, skillName, digest) {
|
|
115
122
|
checkSkillName(skillName);
|
|
123
|
+
checkDigest(digest);
|
|
124
|
+
const dir = skillSandboxDir(skillName, digest);
|
|
116
125
|
const all = trimmedArgs(args);
|
|
117
126
|
const values = parseSkillArguments(all);
|
|
118
127
|
const named = invocation.arguments ?? [];
|
|
@@ -125,7 +134,7 @@ export function renderSkillBody(body, invocation, args, skillName) {
|
|
|
125
134
|
if (m === "\\$")
|
|
126
135
|
return "$";
|
|
127
136
|
if (m === "${CLAUDE_SKILL_DIR}")
|
|
128
|
-
return
|
|
137
|
+
return dir;
|
|
129
138
|
if (m === "$ARGUMENTS") {
|
|
130
139
|
placeholder = true;
|
|
131
140
|
return all;
|
|
@@ -173,14 +182,14 @@ const escapeAttr = (s) => s.replace(/&/g, "&").replace(/"/g, """).repla
|
|
|
173
182
|
*/
|
|
174
183
|
export function renderSkillInvocation(i) {
|
|
175
184
|
const args = trimmedArgs(i.args);
|
|
176
|
-
const body = renderSkillBody(i.body, i.invocation, args, i.skillName).replace(CLOSE_TAG_RE, "<\\/$1");
|
|
185
|
+
const body = renderSkillBody(i.body, i.invocation, args, i.skillName, i.digest).replace(CLOSE_TAG_RE, "<\\/$1");
|
|
177
186
|
const parts = [];
|
|
178
187
|
if (i.lead !== false) {
|
|
179
188
|
parts.push(escapeTags(`The user invoked the skill "${i.name}" with /${i.name}${args === "" ? "" : ` ${args}`}. Follow its instructions for this request.`));
|
|
180
189
|
}
|
|
181
190
|
parts.push(`<skill_invocation name="${escapeAttr(i.name)}" version="${i.version}">\n${body}\n</skill_invocation>`);
|
|
182
191
|
if (i.lines.files === "load") {
|
|
183
|
-
parts.push(`Its files are not in the sandbox yet: call Skill with "${i.name}" to copy them to ${
|
|
192
|
+
parts.push(`Its files are not in the sandbox yet: call Skill with "${i.name}" to copy them to ${skillSandboxDir(i.skillName, i.digest)}/ before running its scripts.`);
|
|
184
193
|
}
|
|
185
194
|
else if (i.lines.files === "unavailable") {
|
|
186
195
|
parts.push("Its other files are not available in this conversation.");
|
package/dist/skill.d.ts
CHANGED
|
@@ -30,12 +30,29 @@ export declare const SKILL_INVOCATION_LIMITS: {
|
|
|
30
30
|
};
|
|
31
31
|
/** 技能入口文件(包根目录,大小写敏感)。 */
|
|
32
32
|
export declare const SKILL_ENTRY_FILE = "SKILL.md";
|
|
33
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* The sandbox root for skills: each skill version is copied (read-only to commands) to
|
|
35
|
+
* `/skills/<name>@<digest>/` ({@link skillSandboxDir}).
|
|
36
|
+
*/
|
|
34
37
|
export declare const SKILLS_SANDBOX_ROOT = "/skills";
|
|
35
38
|
/** 是否为合法的技能名(见文件头的规范说明)。 */
|
|
36
39
|
export declare function isSkillName(s: unknown): s is string;
|
|
37
|
-
/**
|
|
38
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The digest of a skill version's file manifest: the first 12 hex digits of the sha256 of its
|
|
42
|
+
* files sorted by path (JavaScript string order), one `${path} ${size} ${sha256}\n` line each. Two
|
|
43
|
+
* versions with the same files get the same digest, so their sandbox directories coincide; any
|
|
44
|
+
* other change gives a different directory, so two versions of one skill never overwrite each
|
|
45
|
+
* other in a shared file system.
|
|
46
|
+
*/
|
|
47
|
+
export declare function skillDigest(files: {
|
|
48
|
+
path: string;
|
|
49
|
+
size: number;
|
|
50
|
+
sha256: string;
|
|
51
|
+
}[]): string;
|
|
52
|
+
/** A skill version's directory in the sandbox: `/skills/<name>@<digest>` ({@link skillDigest}). */
|
|
53
|
+
export declare function skillSandboxDir(name: string, digest: string): string;
|
|
54
|
+
/** A skill file's path in the sandbox: `/skills/<name>@<digest>/<path>`. */
|
|
55
|
+
export declare function skillSandboxPath(name: string, digest: string, path: string): string;
|
|
39
56
|
/** {@link parseSkillMd} 成功时的结果。 */
|
|
40
57
|
export interface ParsedSkillMd {
|
|
41
58
|
name: string;
|
package/dist/skill.js
CHANGED
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
* whose types are checked because the kernel uses them (`skillInvocation`, phase D). Matching the
|
|
17
17
|
* directory name is not enforced: an uploaded zip's outer directory often has another name (GitHub's
|
|
18
18
|
* `repo-main/`); the skill's name is always the frontmatter `name`, and its sandbox directory is
|
|
19
|
-
* `/skills/<name
|
|
19
|
+
* `/skills/<name>@<digest>/` ({@link skillSandboxDir}, {@link skillDigest}).
|
|
20
20
|
*/
|
|
21
|
+
import { createHash } from "node:crypto";
|
|
21
22
|
import { readFrontmatter } from "./frontmatter.js";
|
|
22
23
|
import { hasControlChars } from "./model.js";
|
|
23
24
|
import { validateSandboxPath } from "./sandbox.js";
|
|
@@ -54,7 +55,10 @@ export const SKILL_INVOCATION_LIMITS = {
|
|
|
54
55
|
};
|
|
55
56
|
/** 技能入口文件(包根目录,大小写敏感)。 */
|
|
56
57
|
export const SKILL_ENTRY_FILE = "SKILL.md";
|
|
57
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* The sandbox root for skills: each skill version is copied (read-only to commands) to
|
|
60
|
+
* `/skills/<name>@<digest>/` ({@link skillSandboxDir}).
|
|
61
|
+
*/
|
|
58
62
|
export const SKILLS_SANDBOX_ROOT = "/skills";
|
|
59
63
|
const NAME_RE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
60
64
|
const XML_TAG_RE = /<\/?[A-Za-z][^<>]*>/;
|
|
@@ -63,9 +67,27 @@ const DRIVE_RE = /^[A-Za-z]:/;
|
|
|
63
67
|
export function isSkillName(s) {
|
|
64
68
|
return typeof s === "string" && s.length <= SKILL_LIMITS.nameMaxChars && NAME_RE.test(s);
|
|
65
69
|
}
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
/**
|
|
71
|
+
* The digest of a skill version's file manifest: the first 12 hex digits of the sha256 of its
|
|
72
|
+
* files sorted by path (JavaScript string order), one `${path} ${size} ${sha256}\n` line each. Two
|
|
73
|
+
* versions with the same files get the same digest, so their sandbox directories coincide; any
|
|
74
|
+
* other change gives a different directory, so two versions of one skill never overwrite each
|
|
75
|
+
* other in a shared file system.
|
|
76
|
+
*/
|
|
77
|
+
export function skillDigest(files) {
|
|
78
|
+
const lines = [...files]
|
|
79
|
+
.sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0))
|
|
80
|
+
.map((f) => `${f.path} ${f.size} ${f.sha256}\n`)
|
|
81
|
+
.join("");
|
|
82
|
+
return createHash("sha256").update(lines).digest("hex").slice(0, 12);
|
|
83
|
+
}
|
|
84
|
+
/** A skill version's directory in the sandbox: `/skills/<name>@<digest>` ({@link skillDigest}). */
|
|
85
|
+
export function skillSandboxDir(name, digest) {
|
|
86
|
+
return `${SKILLS_SANDBOX_ROOT}/${name}@${digest}`;
|
|
87
|
+
}
|
|
88
|
+
/** A skill file's path in the sandbox: `/skills/<name>@<digest>/<path>`. */
|
|
89
|
+
export function skillSandboxPath(name, digest, path) {
|
|
90
|
+
return `${skillSandboxDir(name, digest)}/${path}`;
|
|
69
91
|
}
|
|
70
92
|
const chars = (s) => [...s].length;
|
|
71
93
|
/**
|
|
@@ -179,7 +201,7 @@ function pathProblem(p) {
|
|
|
179
201
|
return "path must not contain '.' or '..' segments";
|
|
180
202
|
}
|
|
181
203
|
// 再按沙箱路径规则核一遍(百分号编码的 `..` 等)
|
|
182
|
-
const errs = validateSandboxPath(skillSandboxPath("skill", p));
|
|
204
|
+
const errs = validateSandboxPath(skillSandboxPath("skill", "000000000000", p));
|
|
183
205
|
return errs[0] ?? null;
|
|
184
206
|
}
|
|
185
207
|
/**
|
package/dist/tool.d.ts
CHANGED
|
@@ -129,6 +129,14 @@ export interface ToolCallContext {
|
|
|
129
129
|
state: unknown;
|
|
130
130
|
answer: FormAnswer | null;
|
|
131
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* The extension's effective deployment config for this org: the platform's deployment config
|
|
134
|
+
* with the org's copy applied to the overridable fields (`orgAccess(…, "override")`), or the
|
|
135
|
+
* platform's config (equal to `ctx.config`) while the org follows it. Use it, not `ctx.config`,
|
|
136
|
+
* for work done for this org. Optional in the type so older extensions compile; the kernel
|
|
137
|
+
* always passes it.
|
|
138
|
+
*/
|
|
139
|
+
config?: unknown;
|
|
132
140
|
}
|
|
133
141
|
export type ToolHandler = (input: unknown, ctx: ToolCallContext) => Promise<ToolResult | InputRequired>;
|
|
134
142
|
/**
|
package/dist/ui.d.ts
CHANGED
|
@@ -175,6 +175,14 @@ export interface UiRenderArgs {
|
|
|
175
175
|
callId: string;
|
|
176
176
|
key?: string;
|
|
177
177
|
};
|
|
178
|
+
/**
|
|
179
|
+
* The extension's effective deployment config for this org: the platform's deployment config
|
|
180
|
+
* with the org's copy applied to the overridable fields (`orgAccess(…, "override")`), or the
|
|
181
|
+
* platform's config (equal to `ctx.config`) while the org follows it. Use it, not `ctx.config`,
|
|
182
|
+
* for work done for this org. Optional in the type so older extensions compile; the kernel
|
|
183
|
+
* always passes it.
|
|
184
|
+
*/
|
|
185
|
+
config?: unknown;
|
|
178
186
|
}
|
|
179
187
|
/** 视图里的按钮或表单提交:`actionId` 来自块;表单提交时带 `answer`。 */
|
|
180
188
|
export interface UiActionArgs extends UiRenderArgs {
|
package/dist/web.d.ts
CHANGED
|
@@ -12,10 +12,16 @@ export interface WebSearchResult {
|
|
|
12
12
|
/** ISO 8601 date or datetime, when known. */
|
|
13
13
|
publishedAt?: string;
|
|
14
14
|
}
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* A web search provider (`web-search@1`). The kernel passes the org's decrypted `orgConfig` and the
|
|
17
|
+
* extension's effective deployment config for the org (`config`).
|
|
18
|
+
*/
|
|
16
19
|
export interface WebSearchProvider {
|
|
17
|
-
/**
|
|
18
|
-
|
|
20
|
+
/**
|
|
21
|
+
* False when this org's config lacks what the provider needs. `config` is the effective
|
|
22
|
+
* deployment config for the org (see `search`'s `config`).
|
|
23
|
+
*/
|
|
24
|
+
configured?(orgConfig: unknown, config?: unknown): boolean;
|
|
19
25
|
search(args: {
|
|
20
26
|
query: string;
|
|
21
27
|
/** Hints only: the kernel filters the results again. */
|
|
@@ -23,6 +29,14 @@ export interface WebSearchProvider {
|
|
|
23
29
|
blockedDomains?: string[];
|
|
24
30
|
maxResults: number;
|
|
25
31
|
orgConfig: unknown;
|
|
32
|
+
/**
|
|
33
|
+
* The extension's effective deployment config for this org: the platform's deployment config
|
|
34
|
+
* with the org's copy applied to the overridable fields (`orgAccess(…, "override")`), or the
|
|
35
|
+
* platform's config (equal to `ctx.config`) while the org follows it. Use it, not `ctx.config`,
|
|
36
|
+
* for work done for this org. Optional in the type so older extensions compile; the kernel
|
|
37
|
+
* always passes it.
|
|
38
|
+
*/
|
|
39
|
+
config?: unknown;
|
|
26
40
|
signal: AbortSignal;
|
|
27
41
|
}): Promise<{
|
|
28
42
|
results: WebSearchResult[];
|
|
@@ -48,12 +62,23 @@ export interface WebFetchPage {
|
|
|
48
62
|
* to (an IPv6 address in brackets, as in a URL).
|
|
49
63
|
*/
|
|
50
64
|
export interface WebFetchProvider {
|
|
51
|
-
/**
|
|
52
|
-
|
|
65
|
+
/**
|
|
66
|
+
* False when this org's config lacks what the provider needs. `config` is the effective
|
|
67
|
+
* deployment config for the org (see `fetch`'s `config`).
|
|
68
|
+
*/
|
|
69
|
+
configured?(orgConfig: unknown, config?: unknown): boolean;
|
|
53
70
|
fetch(args: {
|
|
54
71
|
/** Already validated and upgraded by the kernel. */
|
|
55
72
|
url: string;
|
|
56
73
|
orgConfig: unknown;
|
|
74
|
+
/**
|
|
75
|
+
* The extension's effective deployment config for this org: the platform's deployment config
|
|
76
|
+
* with the org's copy applied to the overridable fields (`orgAccess(…, "override")`), or the
|
|
77
|
+
* platform's config (equal to `ctx.config`) while the org follows it. Use it, not `ctx.config`,
|
|
78
|
+
* for work done for this org. Optional in the type so older extensions compile; the kernel
|
|
79
|
+
* always passes it.
|
|
80
|
+
*/
|
|
81
|
+
config?: unknown;
|
|
57
82
|
signal: AbortSignal;
|
|
58
83
|
}): Promise<WebFetchPage>;
|
|
59
84
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capybara-hq/plugin-sdk",
|
|
3
|
-
"version": "0.1.0-rc.
|
|
3
|
+
"version": "0.1.0-rc.3",
|
|
4
4
|
"description": "Capybara plugin SDK: the types and pure functions plugins are written against",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
18
|
"import": "./dist/index.js",
|
|
19
19
|
"default": "./dist/index.js"
|
|
20
|
-
}
|
|
20
|
+
},
|
|
21
|
+
"./package.json": "./package.json"
|
|
21
22
|
},
|
|
22
23
|
"files": [
|
|
23
24
|
"dist",
|
|
24
25
|
"schemas",
|
|
26
|
+
"agent-docs",
|
|
25
27
|
"README.md",
|
|
26
28
|
"NOTICE"
|
|
27
29
|
],
|
|
@@ -68,6 +68,25 @@
|
|
|
68
68
|
"en"
|
|
69
69
|
]
|
|
70
70
|
},
|
|
71
|
+
"displayName": {
|
|
72
|
+
"type": "object",
|
|
73
|
+
"properties": {
|
|
74
|
+
"zh": {
|
|
75
|
+
"type": "string",
|
|
76
|
+
"minLength": 1,
|
|
77
|
+
"maxLength": 100
|
|
78
|
+
},
|
|
79
|
+
"en": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"minLength": 1,
|
|
82
|
+
"maxLength": 100
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"required": [
|
|
86
|
+
"zh",
|
|
87
|
+
"en"
|
|
88
|
+
]
|
|
89
|
+
},
|
|
71
90
|
"version": {
|
|
72
91
|
"type": "string",
|
|
73
92
|
"maxLength": 256,
|
|
@@ -110,6 +129,23 @@
|
|
|
110
129
|
"maxLength": 2000,
|
|
111
130
|
"pattern": "^https:\\/\\/\\S+$"
|
|
112
131
|
},
|
|
132
|
+
"deprecated": {
|
|
133
|
+
"anyOf": [
|
|
134
|
+
{
|
|
135
|
+
"type": "boolean"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"reason": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"minLength": 1,
|
|
143
|
+
"maxLength": 280
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
},
|
|
113
149
|
"source": {
|
|
114
150
|
"anyOf": [
|
|
115
151
|
{
|
|
@@ -28,10 +28,35 @@
|
|
|
28
28
|
"pattern": "\\S"
|
|
29
29
|
},
|
|
30
30
|
"description": {
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
"anyOf": [
|
|
32
|
+
{
|
|
33
|
+
"type": "string",
|
|
34
|
+
"minLength": 1,
|
|
35
|
+
"maxLength": 1024,
|
|
36
|
+
"pattern": "\\S"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"type": "object",
|
|
40
|
+
"properties": {
|
|
41
|
+
"en": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"minLength": 1,
|
|
44
|
+
"maxLength": 1024,
|
|
45
|
+
"pattern": "\\S"
|
|
46
|
+
},
|
|
47
|
+
"zh": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"minLength": 1,
|
|
50
|
+
"maxLength": 1024,
|
|
51
|
+
"pattern": "\\S"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"required": [
|
|
55
|
+
"en"
|
|
56
|
+
],
|
|
57
|
+
"additionalProperties": false
|
|
58
|
+
}
|
|
59
|
+
]
|
|
35
60
|
},
|
|
36
61
|
"displayName": {
|
|
37
62
|
"type": "object",
|