@capybara-hq/plugin-sdk 0.1.0-rc.1 → 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 +131 -0
- package/dist/config-ui.js +602 -0
- package/dist/ctx.d.ts +3 -1
- package/dist/directory.d.ts +11 -2
- package/dist/extension-point.d.ts +9 -0
- package/dist/extension-point.js +17 -12
- package/dist/file-preview.d.ts +8 -0
- package/dist/hooks.d.ts +14 -4
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -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 +25 -2
- package/dist/plugin-manifest.js +20 -1
- package/dist/sandbox.d.ts +140 -60
- package/dist/sandbox.js +30 -6
- package/dist/secret.d.ts +4 -1
- package/dist/secret.js +5 -2
- 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 +105 -0
- package/dist/web.js +135 -0
- package/package.json +4 -2
- package/schemas/marketplace.v1.schema.json +36 -0
- package/schemas/plugin.v1.schema.json +49 -4
package/dist/web.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** Web search extension point ref (`web-search@1`). */
|
|
2
|
+
export declare const WEB_SEARCH_EXTENSION_POINT = "web-search@1";
|
|
3
|
+
/** Web fetch extension point ref (`web-fetch@1`). */
|
|
4
|
+
export declare const WEB_FETCH_EXTENSION_POINT = "web-fetch@1";
|
|
5
|
+
/** One search hit. */
|
|
6
|
+
export interface WebSearchResult {
|
|
7
|
+
title: string;
|
|
8
|
+
/** Absolute http / https URL. */
|
|
9
|
+
url: string;
|
|
10
|
+
/** Plain text or markdown, trimmed by the provider. */
|
|
11
|
+
snippet?: string;
|
|
12
|
+
/** ISO 8601 date or datetime, when known. */
|
|
13
|
+
publishedAt?: string;
|
|
14
|
+
}
|
|
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
|
+
*/
|
|
19
|
+
export interface WebSearchProvider {
|
|
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;
|
|
25
|
+
search(args: {
|
|
26
|
+
query: string;
|
|
27
|
+
/** Hints only: the kernel filters the results again. */
|
|
28
|
+
allowedDomains?: string[];
|
|
29
|
+
blockedDomains?: string[];
|
|
30
|
+
maxResults: number;
|
|
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;
|
|
40
|
+
signal: AbortSignal;
|
|
41
|
+
}): Promise<{
|
|
42
|
+
results: WebSearchResult[];
|
|
43
|
+
}>;
|
|
44
|
+
}
|
|
45
|
+
/** A fetched page, converted to markdown. */
|
|
46
|
+
export interface WebFetchPage {
|
|
47
|
+
/** After redirects; equal to the requested URL when there were none. */
|
|
48
|
+
finalUrl: string;
|
|
49
|
+
title?: string;
|
|
50
|
+
markdown: string;
|
|
51
|
+
contentType?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A web fetch provider (`web-fetch@1`).
|
|
55
|
+
*
|
|
56
|
+
* The kernel checks the URL it passes and the returned `finalUrl` without DNS: it refuses IP
|
|
57
|
+
* literals in private, loopback, link-local or reserved ranges and single-label or `localhost`
|
|
58
|
+
* names. A provider that fetches from inside the deployment (rather than through a remote
|
|
59
|
+
* service) must also refuse non-public addresses after DNS resolution, for the URL and for every
|
|
60
|
+
* redirect it follows. It may reuse the kernel's rules: {@link isPublicHostname} on
|
|
61
|
+
* `new URL(url).hostname` (never a hand-parsed host), and on each resolved address it connects
|
|
62
|
+
* to (an IPv6 address in brackets, as in a URL).
|
|
63
|
+
*/
|
|
64
|
+
export interface WebFetchProvider {
|
|
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;
|
|
70
|
+
fetch(args: {
|
|
71
|
+
/** Already validated and upgraded by the kernel. */
|
|
72
|
+
url: string;
|
|
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;
|
|
82
|
+
signal: AbortSignal;
|
|
83
|
+
}): Promise<WebFetchPage>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Why a web provider call failed: `not_found` (404 / no content), `blocked` (the site refused the
|
|
87
|
+
* provider), `auth` (bad credentials), `rate_limited`, `unavailable` (provider down, 5xx, timeout),
|
|
88
|
+
* `invalid` (the provider rejected the query or URL).
|
|
89
|
+
*/
|
|
90
|
+
export type WebProviderErrorKind = "not_found" | "blocked" | "auth" | "rate_limited" | "unavailable" | "invalid";
|
|
91
|
+
/** Thrown by web providers; the kernel maps `kind` to fixed, model-visible error text. */
|
|
92
|
+
export declare class WebProviderError extends Error {
|
|
93
|
+
readonly kind: WebProviderErrorKind;
|
|
94
|
+
constructor(message: string, opts: {
|
|
95
|
+
kind: WebProviderErrorKind;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Whether a URL hostname can name a public internet host. Pure, no DNS: false for `localhost`,
|
|
100
|
+
* single-label names, `*.localhost` / `*.local` / `*.internal`, and IP literals (IPv6 in brackets,
|
|
101
|
+
* as in a URL) in private, loopback, link-local, CGNAT, multicast, unspecified, documentation and
|
|
102
|
+
* reserved ranges, including IPv4-mapped IPv6. A name that resolves to a private address is not
|
|
103
|
+
* detected here.
|
|
104
|
+
*/
|
|
105
|
+
export declare function isPublicHostname(host: string): boolean;
|
package/dist/web.js
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/** Web search extension point ref (`web-search@1`). */
|
|
2
|
+
export const WEB_SEARCH_EXTENSION_POINT = "web-search@1";
|
|
3
|
+
/** Web fetch extension point ref (`web-fetch@1`). */
|
|
4
|
+
export const WEB_FETCH_EXTENSION_POINT = "web-fetch@1";
|
|
5
|
+
/** Thrown by web providers; the kernel maps `kind` to fixed, model-visible error text. */
|
|
6
|
+
export class WebProviderError extends Error {
|
|
7
|
+
kind;
|
|
8
|
+
constructor(message, opts) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "WebProviderError";
|
|
11
|
+
this.kind = opts.kind;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function ipv4Octets(host) {
|
|
15
|
+
const m = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(host);
|
|
16
|
+
if (!m)
|
|
17
|
+
return undefined;
|
|
18
|
+
const o = m.slice(1).map(Number);
|
|
19
|
+
return o.every((n) => n <= 255) ? o : undefined;
|
|
20
|
+
}
|
|
21
|
+
function isPublicIpv4(o) {
|
|
22
|
+
const [a, b, c] = o;
|
|
23
|
+
if (a === 0 || a === 10 || a === 127)
|
|
24
|
+
return false;
|
|
25
|
+
if (a === 100 && b >= 64 && b <= 127)
|
|
26
|
+
return false; // CGNAT
|
|
27
|
+
if (a === 169 && b === 254)
|
|
28
|
+
return false;
|
|
29
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
30
|
+
return false;
|
|
31
|
+
if (a === 192 && b === 168)
|
|
32
|
+
return false;
|
|
33
|
+
if (a === 192 && b === 0 && (c === 0 || c === 2))
|
|
34
|
+
return false; // IETF protocol, TEST-NET-1
|
|
35
|
+
if (a === 192 && b === 88 && c === 99)
|
|
36
|
+
return false; // 6to4 relay
|
|
37
|
+
if (a === 198 && (b === 18 || b === 19))
|
|
38
|
+
return false; // benchmarking
|
|
39
|
+
if (a === 198 && b === 51 && c === 100)
|
|
40
|
+
return false; // TEST-NET-2
|
|
41
|
+
if (a === 203 && b === 0 && c === 113)
|
|
42
|
+
return false; // TEST-NET-3
|
|
43
|
+
if (a >= 224)
|
|
44
|
+
return false; // multicast, reserved, broadcast
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
/** Parses an IPv6 literal (no brackets) into eight 16-bit groups, or undefined. */
|
|
48
|
+
function ipv6Groups(host) {
|
|
49
|
+
let s = host;
|
|
50
|
+
const zone = s.indexOf("%");
|
|
51
|
+
if (zone >= 0)
|
|
52
|
+
s = s.slice(0, zone);
|
|
53
|
+
const tail = /(\d+\.\d+\.\d+\.\d+)$/.exec(s);
|
|
54
|
+
if (tail) {
|
|
55
|
+
const o = ipv4Octets(tail[1]);
|
|
56
|
+
if (!o)
|
|
57
|
+
return undefined;
|
|
58
|
+
s = `${s.slice(0, tail.index)}${((o[0] << 8) | o[1]).toString(16)}:${((o[2] << 8) | o[3]).toString(16)}`;
|
|
59
|
+
}
|
|
60
|
+
if (!/^[0-9a-f:]+$/i.test(s) || s.split("::").length > 2)
|
|
61
|
+
return undefined;
|
|
62
|
+
const [head = "", rest] = s.split("::");
|
|
63
|
+
const h = head === "" ? [] : head.split(":");
|
|
64
|
+
const t = rest === undefined || rest === "" ? [] : rest.split(":");
|
|
65
|
+
const parts = [...h, ...t];
|
|
66
|
+
if (!parts.every((p) => /^[0-9a-f]{1,4}$/i.test(p)))
|
|
67
|
+
return undefined;
|
|
68
|
+
let groups;
|
|
69
|
+
if (rest === undefined) {
|
|
70
|
+
if (h.length !== 8)
|
|
71
|
+
return undefined;
|
|
72
|
+
groups = h;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
if (h.length + t.length > 7)
|
|
76
|
+
return undefined;
|
|
77
|
+
groups = [...h, ...new Array(8 - h.length - t.length).fill("0"), ...t];
|
|
78
|
+
}
|
|
79
|
+
return groups.map((g) => Number.parseInt(g, 16));
|
|
80
|
+
}
|
|
81
|
+
function isPublicIpv6(g) {
|
|
82
|
+
const [g0, g1, g2, g3, g4, g5, g6, g7] = g;
|
|
83
|
+
const zeros5 = g0 === 0 && g1 === 0 && g2 === 0 && g3 === 0 && g4 === 0;
|
|
84
|
+
if (zeros5 && g5 === 0 && g6 === 0 && (g7 === 0 || g7 === 1))
|
|
85
|
+
return false; // :: and ::1
|
|
86
|
+
// IPv4-mapped (::ffff:a.b.c.d) and IPv4-compatible (::a.b.c.d): judge the embedded address.
|
|
87
|
+
if (zeros5 && (g5 === 0xffff || g5 === 0)) {
|
|
88
|
+
return isPublicIpv4([g6 >> 8, g6 & 255, g7 >> 8, g7 & 255]);
|
|
89
|
+
}
|
|
90
|
+
if ((g0 & 0xfe00) === 0xfc00)
|
|
91
|
+
return false; // unique local fc00::/7
|
|
92
|
+
if ((g0 & 0xffc0) === 0xfe80)
|
|
93
|
+
return false; // link-local fe80::/10
|
|
94
|
+
if ((g0 & 0xffc0) === 0xfec0)
|
|
95
|
+
return false; // site-local (deprecated)
|
|
96
|
+
if ((g0 & 0xff00) === 0xff00)
|
|
97
|
+
return false; // multicast
|
|
98
|
+
if (g0 === 0x2001 && g1 === 0x0db8)
|
|
99
|
+
return false; // documentation
|
|
100
|
+
if (g0 === 0x0064 && g1 === 0xff9b)
|
|
101
|
+
return isPublicIpv4([g6 >> 8, g6 & 255, g7 >> 8, g7 & 255]); // NAT64
|
|
102
|
+
if (g0 === 0x2002)
|
|
103
|
+
return isPublicIpv4([g1 >> 8, g1 & 255, g2 >> 8, g2 & 255]); // 6to4
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Whether a URL hostname can name a public internet host. Pure, no DNS: false for `localhost`,
|
|
108
|
+
* single-label names, `*.localhost` / `*.local` / `*.internal`, and IP literals (IPv6 in brackets,
|
|
109
|
+
* as in a URL) in private, loopback, link-local, CGNAT, multicast, unspecified, documentation and
|
|
110
|
+
* reserved ranges, including IPv4-mapped IPv6. A name that resolves to a private address is not
|
|
111
|
+
* detected here.
|
|
112
|
+
*/
|
|
113
|
+
export function isPublicHostname(host) {
|
|
114
|
+
let h = host.trim().toLowerCase();
|
|
115
|
+
if (h.endsWith("."))
|
|
116
|
+
h = h.slice(0, -1);
|
|
117
|
+
if (h === "")
|
|
118
|
+
return false;
|
|
119
|
+
if (h.startsWith("[")) {
|
|
120
|
+
if (!h.endsWith("]"))
|
|
121
|
+
return false;
|
|
122
|
+
const g = ipv6Groups(h.slice(1, -1));
|
|
123
|
+
return g !== undefined && isPublicIpv6(g);
|
|
124
|
+
}
|
|
125
|
+
const o = ipv4Octets(h);
|
|
126
|
+
if (o)
|
|
127
|
+
return isPublicIpv4(o);
|
|
128
|
+
if (/^[\d.]+$/.test(h))
|
|
129
|
+
return false; // malformed or shorthand numeric host
|
|
130
|
+
if (!h.includes("."))
|
|
131
|
+
return false;
|
|
132
|
+
if (h === "localhost" || /\.(localhost|local|internal)$/.test(h))
|
|
133
|
+
return false;
|
|
134
|
+
return true;
|
|
135
|
+
}
|
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",
|
|
@@ -310,6 +335,26 @@
|
|
|
310
335
|
"minLength": 3,
|
|
311
336
|
"maxLength": 512,
|
|
312
337
|
"pattern": "^\\.\\/"
|
|
338
|
+
},
|
|
339
|
+
"configSchemas": {
|
|
340
|
+
"type": "object",
|
|
341
|
+
"properties": {
|
|
342
|
+
"deployment": {
|
|
343
|
+
"type": "object",
|
|
344
|
+
"propertyNames": {
|
|
345
|
+
"type": "string"
|
|
346
|
+
},
|
|
347
|
+
"additionalProperties": {}
|
|
348
|
+
},
|
|
349
|
+
"org": {
|
|
350
|
+
"type": "object",
|
|
351
|
+
"propertyNames": {
|
|
352
|
+
"type": "string"
|
|
353
|
+
},
|
|
354
|
+
"additionalProperties": {}
|
|
355
|
+
}
|
|
356
|
+
},
|
|
357
|
+
"additionalProperties": false
|
|
313
358
|
}
|
|
314
359
|
},
|
|
315
360
|
"required": [
|