@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.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/agent-docs/agent-templates.md +47 -0
  3. package/agent-docs/concepts.md +58 -0
  4. package/agent-docs/connector-templates.md +47 -0
  5. package/agent-docs/extension-points/channel.md +15 -0
  6. package/agent-docs/extension-points/config-source.md +15 -0
  7. package/agent-docs/extension-points/connector.md +15 -0
  8. package/agent-docs/extension-points/counter.md +15 -0
  9. package/agent-docs/extension-points/directory.md +15 -0
  10. package/agent-docs/extension-points/file-preview.md +15 -0
  11. package/agent-docs/extension-points/identity-source.md +15 -0
  12. package/agent-docs/extension-points/model-provider.md +15 -0
  13. package/agent-docs/extension-points/object-store.md +15 -0
  14. package/agent-docs/extension-points/sandbox.md +15 -0
  15. package/agent-docs/extension-points/secret-store.md +15 -0
  16. package/agent-docs/extension-points/web-fetch.md +15 -0
  17. package/agent-docs/extension-points/web-search.md +15 -0
  18. package/agent-docs/extensions.md +63 -0
  19. package/agent-docs/plugin-format.md +60 -0
  20. package/agent-docs/skills.md +44 -0
  21. package/agent-docs/tool-naming.md +21 -0
  22. package/dist/agent-template.d.ts +85 -0
  23. package/dist/agent-template.js +361 -2
  24. package/dist/config-ui.d.ts +131 -0
  25. package/dist/config-ui.js +602 -0
  26. package/dist/ctx.d.ts +3 -1
  27. package/dist/directory.d.ts +11 -2
  28. package/dist/extension-point.d.ts +9 -0
  29. package/dist/extension-point.js +17 -12
  30. package/dist/file-preview.d.ts +8 -0
  31. package/dist/hooks.d.ts +14 -4
  32. package/dist/index.d.ts +4 -1
  33. package/dist/index.js +4 -1
  34. package/dist/marketplace.d.ts +29 -2
  35. package/dist/marketplace.js +30 -2
  36. package/dist/org-access.d.ts +27 -0
  37. package/dist/org-access.js +35 -0
  38. package/dist/plugin-manifest.d.ts +25 -2
  39. package/dist/plugin-manifest.js +20 -1
  40. package/dist/sandbox.d.ts +140 -60
  41. package/dist/sandbox.js +30 -6
  42. package/dist/secret.d.ts +4 -1
  43. package/dist/secret.js +5 -2
  44. package/dist/skill-invocation.d.ts +8 -5
  45. package/dist/skill-invocation.js +17 -8
  46. package/dist/skill.d.ts +20 -3
  47. package/dist/skill.js +28 -6
  48. package/dist/tool.d.ts +8 -0
  49. package/dist/ui.d.ts +8 -0
  50. package/dist/web.d.ts +105 -0
  51. package/dist/web.js +135 -0
  52. package/package.json +4 -2
  53. package/schemas/marketplace.v1.schema.json +36 -0
  54. 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.1",
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
- "type": "string",
32
- "minLength": 1,
33
- "maxLength": 1024,
34
- "pattern": "\\S"
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": [