@wenathlan/extension 1.1.31 → 1.1.32
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 +16 -12
- package/dist/cli.js +23 -2
- package/dist/index.js +95 -13
- package/dist/index.js.map +2 -2
- package/dist/memory.d.ts +9 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/policy.d.ts +6 -2
- package/dist/policy.d.ts.map +1 -1
- package/dist/protocol.d.ts +7 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/types.d.ts +35 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +250 -40
- package/extension/dist/background.js.map +4 -4
- package/extension/dist/manifest.json +7 -1
- package/extension/dist/pagebridge.js +384 -15
- package/extension/dist/pagebridge.js.map +4 -4
- package/extension/dist/popup.html +1 -1
- package/extension/dist/popup.js +15 -0
- package/extension/dist/popup.js.map +2 -2
- package/extension/dist/sidepanel.html +1 -1
- package/extension/dist/sidepanel.js +65 -15
- package/extension/dist/sidepanel.js.map +2 -2
- package/extension/dist/style.css +1 -0
- package/extension/manifest.json +7 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,28 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Devthink is a **consent-first browser-agent bridge** distributed as a TypeScript library and a Chromium Manifest V3 extension. It turns a user-provided browser objective into a bounded, reviewable plan. The user must start the active-tab session and approve the plan before any page action reaches the browser.
|
|
4
4
|
|
|
5
|
-
Version: **1.1.
|
|
5
|
+
Version: **1.1.32**. License: **GPL-3.0-only**. The repository is `wenathlan/extension`; the npm-compatible scoped package identifier is `@wenathlan/extension`.
|
|
6
6
|
|
|
7
7
|
## What it does
|
|
8
8
|
|
|
9
|
-
| Capability | Behavior in 1.1.
|
|
9
|
+
| Capability | Behavior in 1.1.32 |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| Active-tab session | The user starts a short-lived session for one HTTPS tab and one origin. |
|
|
12
|
-
| Page observation | The extension captures
|
|
13
|
-
| Plan proposal | A local plan can be created immediately; an optional user-configured HTTPS endpoint can return a typed plan proposal. |
|
|
11
|
+
| Active-tab session | The user starts a short-lived session for one HTTPS tab and one origin; the session records its origin grants. |
|
|
12
|
+
| Page observation | The extension captures the complete semantic inventory: every interactive element, every form control, every select option and the full page text. |
|
|
13
|
+
| Plan proposal | A local plan can be created immediately; an optional user-configured HTTPS endpoint can return a typed plan proposal of any length. |
|
|
14
14
|
| Review gate | Every remote proposal starts in `pending`; it cannot reach the page bridge before explicit approval. |
|
|
15
|
-
| Browser tools | Reviewed plans
|
|
15
|
+
| Browser tools | Reviewed plans cover sixty three action kinds: pointer, keyboard, drag and drop, upload, form control, page movement, a complete read vocabulary, page mutation under review, reviewed evaluation, and browser-level tab, window, zoom, snapshot and download commands. |
|
|
16
|
+
| Optional capabilities | `tabs`, `downloads`, `clipboardRead` and `clipboardWrite` are optional permissions; browser kinds check their capability, the review panel can request a grant and every grant is audited. |
|
|
17
|
+
| Unlimited by choice | Wait durations, plan size, plan expiry, audit retention and outcome retention carry no code ceilings; every bound is a user choice. |
|
|
18
|
+
| Structured results | Step results carry structured JSON details, rendered in the side panel beside each reviewed step. |
|
|
16
19
|
| Session pause | The user can pause and resume the active session; a paused session blocks every execution and preview while keeping the reviewed plan alive. |
|
|
17
|
-
| Plan progress | Each reviewed step is tracked, completed steps are marked
|
|
20
|
+
| Plan progress | Each reviewed step is tracked with its outcome history, completed steps are marked, plans close automatically once every step has executed, and prior history survives plan replacement. |
|
|
18
21
|
| Stop and audit | The user can stop the session at any time. Configuration, proposals, decisions and results remain in local extension storage. |
|
|
19
22
|
|
|
20
23
|
The project is deliberately **not** a hosted control platform. It does not depend on a provider-specific sandbox, server URL or browser profile. A configured endpoint is optional, has to use HTTPS and receives only the session record and bounded observation required to produce a plan.
|
|
21
24
|
|
|
22
25
|
## Security boundary
|
|
23
26
|
|
|
24
|
-
> Devthink never requests broad host access at installation. The user can grant a single HTTPS origin only after entering it in the extension popup.
|
|
27
|
+
> Devthink never requests broad host access at installation. The user can grant a single HTTPS origin only after entering it in the extension popup, and privileged browser capabilities only as optional permissions requested from the review panel.
|
|
25
28
|
|
|
26
|
-
The default manifest requests `activeTab`, `storage`, `scripting` and `sidePanel
|
|
29
|
+
The default manifest requests `activeTab`, `storage`, `scripting` and `sidePanel`, plus optional permissions for `tabs`, `downloads`, `clipboardRead` and `clipboardWrite` that stay dormant until the user grants them at runtime. It does not request debugger, cookies, history, proxy control, native messaging, web requests, full-time host permissions or credentials. A service worker cannot be relied on for unattended 24-hour agent computation; any such system must be designed, installed and governed separately. [1] [2]
|
|
27
30
|
|
|
28
31
|
Browser actions remain blocked if the session is missing, stopped or expired; the tab or origin changed; the plan was not approved; the plan expired; or the tool proposal is not in the local allowlist. The page bridge checks the origin again immediately before it acts.
|
|
29
32
|
|
|
@@ -42,14 +45,15 @@ The endpoint field intentionally has no default URL. Enter a URL such as `https:
|
|
|
42
45
|
|
|
43
46
|
```json
|
|
44
47
|
{
|
|
45
|
-
"version": "1.1.
|
|
48
|
+
"version": "1.1.32",
|
|
46
49
|
"objective": "User supplied objective",
|
|
47
50
|
"session": { "id": "uuid", "tabid": 1, "origin": "https://example.com" },
|
|
48
|
-
"observation": { "url": "https://example.com/path", "interactive": [] }
|
|
51
|
+
"observation": { "schemaversion": 2, "url": "https://example.com/path", "interactive": [] },
|
|
52
|
+
"capabilities": { "tabs": false, "downloads": false, "clipboardread": false, "clipboardwrite": false }
|
|
49
53
|
}
|
|
50
54
|
```
|
|
51
55
|
|
|
52
|
-
It must return a plan proposal using the same version. Every step needs a human-readable summary. Navigation is restricted to the active session origin, and any unknown or malformed proposal is rejected locally. The endpoint is a planner, not an authority to control the browser.
|
|
56
|
+
It must return a plan proposal using the same version. Every step needs a human-readable summary and may carry a reviewed JSON `options` field. Navigation is restricted to the active session origin, and any unknown or malformed proposal is rejected locally. The endpoint is a planner, not an authority to control the browser.
|
|
53
57
|
|
|
54
58
|
## Library use
|
|
55
59
|
|
package/dist/cli.js
CHANGED
|
@@ -2,19 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
// cli/devthink.ts
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
5
6
|
import { resolve } from "node:path";
|
|
6
|
-
var forbidden = /* @__PURE__ */ new Set(["debugger", "cookies", "webRequest", "history", "bookmarks", "
|
|
7
|
+
var forbidden = /* @__PURE__ */ new Set(["debugger", "cookies", "webRequest", "history", "bookmarks", "nativeMessaging", "proxy", "management"]);
|
|
8
|
+
var allowedoptional = /* @__PURE__ */ new Set(["tabs", "downloads", "clipboardRead", "clipboardWrite"]);
|
|
9
|
+
var pinnedidentitykey = "58e21373cec5ade3e6698da5b36ecc2bf7e7e2f755c6fb5e3a6605b535b93985";
|
|
10
|
+
function decodeidentitykey(key) {
|
|
11
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(key)) throw new Error("The manifest key must be strict base64 without whitespace.");
|
|
12
|
+
if (key.length % 4 !== 0) throw new Error(`The manifest key length ${key.length} is not a multiple of four, so it is not valid base64.`);
|
|
13
|
+
const der = Buffer.from(key, "base64");
|
|
14
|
+
if (der.length < 150 || der.length > 600) throw new Error(`The manifest key decodes to ${der.length} bytes, outside the RSA subject public key range.`);
|
|
15
|
+
if (!der.subarray(0, 2).equals(Buffer.from([48, 130]))) throw new Error("The manifest key does not decode to a DER subject public key sequence.");
|
|
16
|
+
const declared = der.readUInt16BE(2);
|
|
17
|
+
if (declared !== der.length - 4) throw new Error(`The manifest key DER length ${declared} does not match the decoded ${der.length - 4} bytes.`);
|
|
18
|
+
return der;
|
|
19
|
+
}
|
|
7
20
|
async function main() {
|
|
8
21
|
const command = process.argv[2] ?? "help";
|
|
9
22
|
if (command === "manifest") {
|
|
10
23
|
const manifest = JSON.parse(await readFile(resolve("extension/manifest.json"), "utf8"));
|
|
11
24
|
const packagejson = JSON.parse(await readFile(resolve("package.json"), "utf8"));
|
|
12
25
|
const permissions = manifest.permissions ?? [];
|
|
26
|
+
const optional = manifest.optional_permissions ?? [];
|
|
13
27
|
const denied = permissions.filter((permission) => forbidden.has(permission));
|
|
28
|
+
const deniedoptional = optional.filter((permission) => !allowedoptional.has(permission));
|
|
14
29
|
if (manifest.version !== packagejson.version) throw new Error("Manifest version must match package.json.");
|
|
30
|
+
if (!manifest.key) throw new Error("A stable manifest key is required for the extension identity.");
|
|
31
|
+
const identitykey = decodeidentitykey(manifest.key);
|
|
32
|
+
if (identitykey.length !== 294) throw new Error(`The manifest key decodes to ${identitykey.length} bytes; the published Devthink identity key decodes to 294.`);
|
|
33
|
+
const digest = createHash("sha256").update(identitykey).digest("hex");
|
|
34
|
+
if (digest !== pinnedidentitykey) throw new Error(`The manifest identity key digest ${digest} does not match the pinned published key; changing the extension identity must be a reviewed decision.`);
|
|
15
35
|
if ((manifest.host_permissions ?? []).length) throw new Error("Mandatory host permissions are not allowed.");
|
|
16
36
|
if (denied.length) throw new Error(`Forbidden permissions: ${denied.join(", ")}`);
|
|
17
|
-
|
|
37
|
+
if (deniedoptional.length) throw new Error(`Forbidden optional permissions: ${deniedoptional.join(", ")}`);
|
|
38
|
+
console.log(JSON.stringify({ valid: true, version: manifest.version, identitykeybytes: identitykey.length, permissions, optionalpermissions: optional }, null, 2));
|
|
18
39
|
return;
|
|
19
40
|
}
|
|
20
41
|
console.log("Usage: devthink manifest");
|
package/dist/index.js
CHANGED
|
@@ -34,12 +34,37 @@ var sessionmemory = class {
|
|
|
34
34
|
async setprogress(value) {
|
|
35
35
|
return this.adapter.set("progress", value);
|
|
36
36
|
}
|
|
37
|
+
async getcapabilities() {
|
|
38
|
+
return this.adapter.get("capabilities");
|
|
39
|
+
}
|
|
40
|
+
async setcapabilities(value) {
|
|
41
|
+
return this.adapter.set("capabilities", value);
|
|
42
|
+
}
|
|
43
|
+
async getsettings() {
|
|
44
|
+
return this.adapter.get("settings");
|
|
45
|
+
}
|
|
46
|
+
async setsettings(value) {
|
|
47
|
+
return this.adapter.set("settings", value);
|
|
48
|
+
}
|
|
37
49
|
async getaudit() {
|
|
38
50
|
return await this.adapter.get("audit") ?? [];
|
|
39
51
|
}
|
|
52
|
+
async getoutcomes() {
|
|
53
|
+
return await this.adapter.get("outcomes") ?? [];
|
|
54
|
+
}
|
|
55
|
+
/** Records one audit event; retention is a user setting and an absent setting keeps every event. */
|
|
40
56
|
async addaudi(event) {
|
|
41
57
|
const records = await this.getaudit();
|
|
42
|
-
|
|
58
|
+
const combined = [event, ...records];
|
|
59
|
+
const retention = (await this.getsettings())?.auditretention;
|
|
60
|
+
await this.adapter.set("audit", retention === void 0 ? combined : combined.slice(0, retention));
|
|
61
|
+
}
|
|
62
|
+
/** Records one step outcome; retention is a user setting and an absent setting keeps every outcome. */
|
|
63
|
+
async addoutcome(outcome) {
|
|
64
|
+
const records = await this.getoutcomes();
|
|
65
|
+
const combined = [outcome, ...records];
|
|
66
|
+
const retention = (await this.getsettings())?.outcomeretention;
|
|
67
|
+
await this.adapter.set("outcomes", retention === void 0 ? combined : combined.slice(0, retention));
|
|
43
68
|
}
|
|
44
69
|
};
|
|
45
70
|
function randomid() {
|
|
@@ -47,10 +72,12 @@ function randomid() {
|
|
|
47
72
|
}
|
|
48
73
|
|
|
49
74
|
// policy.ts
|
|
50
|
-
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select"]);
|
|
51
|
-
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover"]);
|
|
52
|
-
var
|
|
53
|
-
var
|
|
75
|
+
var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile"]);
|
|
76
|
+
var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset"]);
|
|
77
|
+
var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot"]);
|
|
78
|
+
var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
|
|
79
|
+
var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor"]);
|
|
80
|
+
var valueactions = /* @__PURE__ */ new Set(["presskey", "drag", "drop", "upload", "readattribute", "removeattribute", "waittext", "evaluate", "zoomset", "tabactivate", "tabclose", "tabreload", "windowclose", "windowresize", "tabcreate", "windowcreate", "downloadfile"]);
|
|
54
81
|
function normalizeendpoint(value) {
|
|
55
82
|
const endpoint = new URL(value.trim());
|
|
56
83
|
if (endpoint.protocol !== "https:") throw new Error("Devthink accepts HTTPS endpoints only.");
|
|
@@ -67,16 +94,41 @@ function actionrisk(kind) {
|
|
|
67
94
|
if (sensitiveactions.has(kind)) return "sensitive";
|
|
68
95
|
return interactionactions.has(kind) ? "interaction" : "read";
|
|
69
96
|
}
|
|
97
|
+
function parseoptions(step) {
|
|
98
|
+
if (step.options === void 0) return {};
|
|
99
|
+
let parsed;
|
|
100
|
+
try {
|
|
101
|
+
parsed = JSON.parse(step.options);
|
|
102
|
+
} catch {
|
|
103
|
+
throw new Error("Step options must be a JSON object.");
|
|
104
|
+
}
|
|
105
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Step options must be a JSON object.");
|
|
106
|
+
return parsed;
|
|
107
|
+
}
|
|
70
108
|
function waitduration(step) {
|
|
71
109
|
const requested = step.value ? Number.parseInt(step.value, 10) : 250;
|
|
72
110
|
if (!Number.isFinite(requested) || requested < 0) throw new Error("Wait duration must be zero or a positive number of milliseconds.");
|
|
73
|
-
return
|
|
111
|
+
return requested;
|
|
112
|
+
}
|
|
113
|
+
function isnumericid(value) {
|
|
114
|
+
return typeof value === "string" && /^\d+$/.test(value);
|
|
115
|
+
}
|
|
116
|
+
function numericoption(options, key) {
|
|
117
|
+
return options[key] === void 0 || typeof options[key] === "number" && Number.isFinite(options[key]);
|
|
74
118
|
}
|
|
75
119
|
function validatestep(step, origin) {
|
|
76
120
|
if (!allowedactions.has(step.kind)) return { allowed: false, reason: "Unsupported action kind." };
|
|
77
121
|
if (!step.summary.trim()) return { allowed: false, reason: "A human-readable action summary is required." };
|
|
78
122
|
if (targetactions.has(step.kind) && !step.target?.trim()) return { allowed: false, reason: "A page target is required." };
|
|
123
|
+
if (valueactions.has(step.kind) && !step.value?.trim()) return { allowed: false, reason: "A reviewed value is required." };
|
|
79
124
|
if (step.kind === "select" && !step.value?.trim()) return { allowed: false, reason: "A reviewed option value is required." };
|
|
125
|
+
if (step.kind === "navigate" && !step.value) return { allowed: false, reason: "A navigation URL is required." };
|
|
126
|
+
let options;
|
|
127
|
+
try {
|
|
128
|
+
options = parseoptions(step);
|
|
129
|
+
} catch {
|
|
130
|
+
return { allowed: false, reason: "Step options must be a JSON object." };
|
|
131
|
+
}
|
|
80
132
|
if (step.kind === "wait") {
|
|
81
133
|
try {
|
|
82
134
|
waitduration(step);
|
|
@@ -85,13 +137,37 @@ function validatestep(step, origin) {
|
|
|
85
137
|
}
|
|
86
138
|
}
|
|
87
139
|
if (step.kind === "navigate") {
|
|
88
|
-
if (!step.value) return { allowed: false, reason: "A navigation URL is required." };
|
|
89
140
|
try {
|
|
90
|
-
if (new URL(step.value).origin !== origin) return { allowed: false, reason: "Navigation must remain within the approved origin." };
|
|
141
|
+
if (new URL(step.value ?? "").origin !== origin) return { allowed: false, reason: "Navigation must remain within the approved origin." };
|
|
91
142
|
} catch {
|
|
92
143
|
return { allowed: false, reason: "Navigation URL is invalid." };
|
|
93
144
|
}
|
|
94
145
|
}
|
|
146
|
+
if (step.kind === "tabcreate" || step.kind === "windowcreate" || step.kind === "downloadfile") {
|
|
147
|
+
try {
|
|
148
|
+
const url = new URL(step.value ?? "");
|
|
149
|
+
if (url.protocol !== "https:") return { allowed: false, reason: "The reviewed URL must use HTTPS." };
|
|
150
|
+
} catch {
|
|
151
|
+
return { allowed: false, reason: "The reviewed URL is invalid." };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (step.kind === "tabactivate" || step.kind === "tabclose" || step.kind === "tabreload" || step.kind === "windowclose" || step.kind === "windowresize") {
|
|
155
|
+
if (!isnumericid(step.value)) return { allowed: false, reason: "A numeric browser id is required." };
|
|
156
|
+
}
|
|
157
|
+
if (step.kind === "zoomset") {
|
|
158
|
+
const zoom = Number(step.value);
|
|
159
|
+
if (!Number.isFinite(zoom) || zoom <= 0) return { allowed: false, reason: "The reviewed zoom must be a positive number." };
|
|
160
|
+
}
|
|
161
|
+
if (step.kind === "setattribute" || step.kind === "writestorage") {
|
|
162
|
+
const keyname = step.kind === "setattribute" ? "name" : "key";
|
|
163
|
+
if (typeof options[keyname] !== "string" || !options[keyname].trim()) return { allowed: false, reason: `A reviewed ${keyname} is required in options.` };
|
|
164
|
+
if (typeof options.value !== "string") return { allowed: false, reason: "A reviewed value is required in options." };
|
|
165
|
+
}
|
|
166
|
+
if (step.kind === "windowresize") {
|
|
167
|
+
if (typeof options.width !== "number" || typeof options.height !== "number" || !Number.isFinite(options.width) || !Number.isFinite(options.height)) return { allowed: false, reason: "Reviewed width and height numbers are required in options." };
|
|
168
|
+
}
|
|
169
|
+
if ((step.kind === "scrollpage" || step.kind === "scrollby") && (!numericoption(options, "x") || !numericoption(options, "y"))) return { allowed: false, reason: "Scroll amounts must be numbers in options." };
|
|
170
|
+
if (step.kind === "waitfor" && options.timeout !== void 0 && (typeof options.timeout !== "number" || options.timeout < 0)) return { allowed: false, reason: "The waitfor timeout must be zero or a positive number of milliseconds." };
|
|
95
171
|
return { allowed: true };
|
|
96
172
|
}
|
|
97
173
|
function sessiongate(input) {
|
|
@@ -111,7 +187,7 @@ function canexecute(input) {
|
|
|
111
187
|
}
|
|
112
188
|
|
|
113
189
|
// version.ts
|
|
114
|
-
var packageversion = "1.1.
|
|
190
|
+
var packageversion = "1.1.32";
|
|
115
191
|
|
|
116
192
|
// types.ts
|
|
117
193
|
var protocolversion = packageversion;
|
|
@@ -130,7 +206,7 @@ function parseproposal(value, origin) {
|
|
|
130
206
|
if (root.version !== protocolversion) throw new Error("Unsupported protocol version.");
|
|
131
207
|
const planinput = record(root.plan);
|
|
132
208
|
const stepsinput = planinput.steps;
|
|
133
|
-
if (!Array.isArray(stepsinput) || stepsinput.length === 0
|
|
209
|
+
if (!Array.isArray(stepsinput) || stepsinput.length === 0) throw new Error("A plan needs at least one step.");
|
|
134
210
|
const steps = stepsinput.map((input, index) => {
|
|
135
211
|
const candidate = record(input);
|
|
136
212
|
const kind = text(candidate.kind, `step ${index + 1} kind`);
|
|
@@ -140,33 +216,39 @@ function parseproposal(value, origin) {
|
|
|
140
216
|
summary: text(candidate.summary, `step ${index + 1} summary`),
|
|
141
217
|
risk: actionrisk(kind),
|
|
142
218
|
...typeof candidate.target === "string" ? { target: candidate.target } : {},
|
|
143
|
-
...typeof candidate.value === "string" ? { value: candidate.value } : {}
|
|
219
|
+
...typeof candidate.value === "string" ? { value: candidate.value } : {},
|
|
220
|
+
...typeof candidate.options === "string" ? { options: candidate.options } : {}
|
|
144
221
|
};
|
|
145
222
|
const evaluation = validatestep(step, origin);
|
|
146
223
|
if (!evaluation.allowed) throw new Error(evaluation.reason);
|
|
147
224
|
return step;
|
|
148
225
|
});
|
|
149
226
|
const createdat = Date.now();
|
|
227
|
+
const expiresat = typeof planinput.expiresat === "number" ? planinput.expiresat : createdat + 10 * 60 * 1e3;
|
|
150
228
|
const plan = {
|
|
151
229
|
id: typeof planinput.id === "string" ? planinput.id : crypto.randomUUID(),
|
|
152
230
|
objective: text(planinput.objective, "objective"),
|
|
153
231
|
origin,
|
|
154
232
|
steps,
|
|
155
233
|
createdat,
|
|
156
|
-
expiresat
|
|
234
|
+
expiresat,
|
|
157
235
|
state: "pending"
|
|
158
236
|
};
|
|
159
237
|
if (plan.expiresat <= createdat) throw new Error("Plan expiry must be in the future.");
|
|
160
238
|
return { version: protocolversion, plan };
|
|
161
239
|
}
|
|
162
240
|
function requestbody(input) {
|
|
163
|
-
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation });
|
|
241
|
+
return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
|
|
242
|
+
}
|
|
243
|
+
function outcomeresponse(input) {
|
|
244
|
+
return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome });
|
|
164
245
|
}
|
|
165
246
|
export {
|
|
166
247
|
canexecute,
|
|
167
248
|
actionrisk as deriveactionrisk,
|
|
168
249
|
hostpattern,
|
|
169
250
|
normalizeendpoint,
|
|
251
|
+
outcomeresponse,
|
|
170
252
|
parseproposal,
|
|
171
253
|
protocolversion,
|
|
172
254
|
randomid,
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../memory.ts", "../policy.ts", "../version.ts", "../types.ts", "../protocol.ts"],
|
|
4
|
-
"sourcesContent": ["import type { agentplan, agentsession, auditevent, diagnosticreport, endpointconfig, planprogress } from \"./types.js\";\n\n/** Provides a small storage seam that works in browser, tests and future adapters. */\nexport interface memoryadapter {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n}\n\nexport class sessionmemory {\n constructor(private readonly adapter: memoryadapter) {}\n\n async getconfig(): Promise<endpointconfig | undefined> { return this.adapter.get<endpointconfig>(\"config\"); }\n async setconfig(value: endpointconfig): Promise<void> { return this.adapter.set(\"config\", value); }\n async getsession(): Promise<agentsession | undefined> { return this.adapter.get<agentsession>(\"session\"); }\n async setsession(value: agentsession): Promise<void> { return this.adapter.set(\"session\", value); }\n async getplan(): Promise<agentplan | undefined> { return this.adapter.get<agentplan>(\"plan\"); }\n async setplan(value: agentplan): Promise<void> { return this.adapter.set(\"plan\", value); }\n async getdiagnostic(): Promise<diagnosticreport | undefined> { return this.adapter.get<diagnosticreport>(\"diagnostic\"); }\n async setdiagnostic(value: diagnosticreport): Promise<void> { return this.adapter.set(\"diagnostic\", value); }\n async getprogress(): Promise<planprogress | undefined> { return this.adapter.get<planprogress>(\"progress\"); }\n async setprogress(value: planprogress): Promise<void> { return this.adapter.set(\"progress\", value); }\n async getaudit(): Promise<auditevent[]> { return (await this.adapter.get<auditevent[]>(\"audit\")) ?? []; }\n async addaudi(event: auditevent): Promise<void> {\n const records = await this.getaudit();\n await this.adapter.set(\"audit\", [event, ...records].slice(0, 100));\n }\n}\n\n/** Creates identifiers locally without a network dependency. */\nexport function randomid(): string {\n return crypto.randomUUID();\n}\n", "import type { actionkind, agentplan, agentsession, endpointconfig, policyevaluation, toolstep } from \"./types.js\";\n\nconst sensitiveactions = new Set<actionkind>([\"click\", \"type\", \"navigate\", \"select\"]);\nconst interactionactions = new Set<actionkind>([\"focus\", \"scroll\", \"hover\"]);\nconst allowedactions = new Set<actionkind>([\"observe\", \"inspect\", \"focus\", \"click\", \"type\", \"navigate\", \"scroll\", \"select\", \"hover\", \"extract\", \"wait\"]);\nconst targetactions = new Set<actionkind>([\"inspect\", \"focus\", \"click\", \"type\", \"scroll\", \"select\", \"hover\"]);\n\n/** Normalizes a user supplied HTTPS endpoint without preserving a provider lock-in. */\nexport function normalizeendpoint(value: string): endpointconfig {\n const endpoint = new URL(value.trim());\n if (endpoint.protocol !== \"https:\") throw new Error(\"Devthink accepts HTTPS endpoints only.\");\n if (endpoint.username || endpoint.password) throw new Error(\"Endpoint credentials are not allowed in the URL.\");\n return { endpoint: endpoint.toString(), origin: endpoint.origin, configuredat: Date.now() };\n}\n\n/** Creates the exact optional host pattern requested from Chromium. */\nexport function hostpattern(origin: string): string {\n const parsed = new URL(origin);\n if (parsed.protocol !== \"https:\") throw new Error(\"Only HTTPS origins can be granted.\");\n return `${parsed.origin}/*`;\n}\n\n/** Defines action risk from a fixed local allowlist. */\nexport function actionrisk(kind: actionkind): \"read\" | \"interaction\" | \"sensitive\" {\n if (!allowedactions.has(kind)) throw new Error(\"Unsupported browser action.\");\n if (sensitiveactions.has(kind)) return \"sensitive\";\n return interactionactions.has(kind) ? \"interaction\" : \"read\";\n}\n\n/** Parses the bounded pause duration of a wait step. */\nexport function waitduration(step: toolstep): number {\n const requested = step.value ? Number.parseInt(step.value, 10) : 250;\n if (!Number.isFinite(requested) || requested < 0) throw new Error(\"Wait duration must be zero or a positive number of milliseconds.\");\n return Math.min(requested, 10_000);\n}\n\n/** Validates a single proposal against the active tab origin and local policy. */\nexport function validatestep(step: toolstep, origin: string): policyevaluation {\n if (!allowedactions.has(step.kind)) return { allowed: false, reason: \"Unsupported action kind.\" };\n if (!step.summary.trim()) return { allowed: false, reason: \"A human-readable action summary is required.\" };\n if (targetactions.has(step.kind) && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\n if (step.kind === \"select\" && !step.value?.trim()) return { allowed: false, reason: \"A reviewed option value is required.\" };\n if (step.kind === \"wait\") {\n try { waitduration(step); } catch { return { allowed: false, reason: \"Wait duration must be zero or a positive number of milliseconds.\" }; }\n }\n if (step.kind === \"navigate\") {\n if (!step.value) return { allowed: false, reason: \"A navigation URL is required.\" };\n try {\n if (new URL(step.value).origin !== origin) return { allowed: false, reason: \"Navigation must remain within the approved origin.\" };\n } catch {\n return { allowed: false, reason: \"Navigation URL is invalid.\" };\n }\n }\n return { allowed: true };\n}\n\n/** Shared session gate: a live, unpaused session that still matches the active tab. */\nfunction sessiongate(input: { session: agentsession | undefined; tabid: number; origin: string; now: number; action: string }): policyevaluation {\n if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.pausedat) return { allowed: false, reason: `The browser session is paused and cannot ${input.action}.` };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: `The ${input.action} is outside the approved tab or origin.` };\n return { allowed: true };\n}\n\n/** Applies the consent gate immediately before an action reaches the page bridge. */\nexport function canexecute(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"execute an action\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"The plan has not received explicit approval.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The approved plan has expired.\" };\n return validatestep(input.step, input.origin);\n}\n\n/** Allows a non-mutating, temporary target preview during plan review. */\nexport function canpreview(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"preview a target\" });\n if (!gate.allowed) return gate;\n if (!input.plan || ![\"pending\", \"approved\"].includes(input.plan.state)) return { allowed: false, reason: \"Only a reviewed pending or approved plan can be previewed.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The reviewed plan has expired.\" };\n if (![\"focus\", \"inspect\", \"click\", \"type\", \"scroll\", \"select\", \"hover\"].includes(input.step.kind)) return { allowed: false, reason: \"Only a target-based action can be previewed.\" };\n return validatestep(input.step, input.origin);\n}\n", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.31\" as const;\n", "/** Shared contracts for every Devthink target. */\nimport { packageversion } from \"./version.js\";\n\nexport const protocolversion = packageversion;\n\nexport type actionkind = \"observe\" | \"inspect\" | \"focus\" | \"click\" | \"type\" | \"navigate\" | \"scroll\" | \"select\" | \"hover\" | \"extract\" | \"wait\";\nexport type actionrisk = \"read\" | \"interaction\" | \"sensitive\";\nexport type planstate = \"draft\" | \"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"completed\" | \"cancelled\";\nexport type auditkind = \"configure\" | \"session\" | \"observe\" | \"proposal\" | \"approval\" | \"action\" | \"error\" | \"stop\" | \"pause\" | \"resume\" | \"complete\";\n\nexport interface toolstep {\n id: string;\n kind: actionkind;\n target?: string;\n value?: string;\n summary: string;\n risk: actionrisk;\n}\n\nexport interface agentplan {\n id: string;\n objective: string;\n origin: string;\n steps: toolstep[];\n createdat: number;\n expiresat: number;\n state: planstate;\n approvedat?: number;\n completedat?: number;\n}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: number;\n pausedat?: number;\n}\n\nexport interface endpointconfig {\n endpoint: string;\n origin: string;\n configuredat: number;\n}\n\nexport interface observation {\n url: string;\n title: string;\n textpreview: string;\n textlength: number;\n forms: Array<{ label: string; type: string; name: string; options?: string[] }>;\n interactive: Array<{ selector: string; role: string; label: string }>;\n capturedat: number;\n}\n\nexport interface auditevent {\n id: string;\n kind: auditkind;\n at: number;\n summary: string;\n sessionid?: string;\n planid?: string;\n stepid?: string;\n}\n\nexport interface diagnosticreport {\n id: string;\n sessionid: string;\n origin: string;\n capturedat: number;\n tabid: number;\n title: string;\n textlength: number;\n interactivecount: number;\n formcount: number;\n bridgeavailable: boolean;\n}\n\nexport interface proposalrequest {\n objective: string;\n session: agentsession;\n observation: observation;\n}\n\nexport interface planproposal {\n version: typeof protocolversion;\n plan: agentplan;\n}\n\nexport interface policyevaluation {\n allowed: boolean;\n reason?: string;\n}\n\n/** Tracks which reviewed steps of one plan have already executed locally. */\nexport interface planprogress {\n planid: string;\n completedsteps: string[];\n updatedat: number;\n}\n", "import { actionrisk, validatestep } from \"./policy.js\";\nimport { protocolversion, type agentplan, type planproposal, type proposalrequest, type toolstep } from \"./types.js\";\n\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Protocol message must be an object.\");\n return value as Record<string, unknown>;\n}\n\nfunction text(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`${field} must be a non-empty string.`);\n return value.trim();\n}\n\n/** Validates agent output before it becomes a locally reviewable plan. */\nexport function parseproposal(value: unknown, origin: string): planproposal {\n const root = record(value);\n if (root.version !== protocolversion) throw new Error(\"Unsupported protocol version.\");\n const planinput = record(root.plan);\n const stepsinput = planinput.steps;\n if (!Array.isArray(stepsinput) || stepsinput.length === 0 || stepsinput.length > 50) throw new Error(\"A plan needs between one and fifty steps.\");\n const steps: toolstep[] = stepsinput.map((input, index) => {\n const candidate = record(input);\n const kind = text(candidate.kind, `step ${index + 1} kind`) as toolstep[\"kind\"];\n const step: toolstep = {\n id: typeof candidate.id === \"string\" ? candidate.id : crypto.randomUUID(),\n kind,\n summary: text(candidate.summary, `step ${index + 1} summary`),\n risk: actionrisk(kind),\n ...(typeof candidate.target === \"string\" ? { target: candidate.target } : {}),\n ...(typeof candidate.value === \"string\" ? { value: candidate.value } : {}),\n };\n const evaluation = validatestep(step, origin);\n if (!evaluation.allowed) throw new Error(evaluation.reason);\n return step;\n });\n const createdat = Date.now();\n const plan: agentplan = {\n id: typeof planinput.id === \"string\" ? planinput.id : crypto.randomUUID(),\n objective: text(planinput.objective, \"objective\"),\n origin,\n steps,\n createdat,\n expiresat: Math.min(typeof planinput.expiresat === \"number\" ? planinput.expiresat : createdat + 10 * 60 * 1000, createdat + 30 * 60 * 1000),\n state: \"pending\",\n };\n if (plan.expiresat <= createdat) throw new Error(\"Plan expiry must be in the future.\");\n return { version: protocolversion, plan };\n}\n\n/** Shapes the only data that may be sent to a user-configured agent endpoint. */\nexport function requestbody(input: proposalrequest): string {\n return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation });\n}\n"],
|
|
5
|
-
"mappings": ";AAQO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAA6B,SAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAE7B,MAAM,YAAiD;AAAE,WAAO,KAAK,QAAQ,IAAoB,QAAQ;AAAA,EAAG;AAAA,EAC5G,MAAM,UAAU,OAAsC;AAAE,WAAO,KAAK,QAAQ,IAAI,UAAU,KAAK;AAAA,EAAG;AAAA,EAClG,MAAM,aAAgD;AAAE,WAAO,KAAK,QAAQ,IAAkB,SAAS;AAAA,EAAG;AAAA,EAC1G,MAAM,WAAW,OAAoC;AAAE,WAAO,KAAK,QAAQ,IAAI,WAAW,KAAK;AAAA,EAAG;AAAA,EAClG,MAAM,UAA0C;AAAE,WAAO,KAAK,QAAQ,IAAe,MAAM;AAAA,EAAG;AAAA,EAC9F,MAAM,QAAQ,OAAiC;AAAE,WAAO,KAAK,QAAQ,IAAI,QAAQ,KAAK;AAAA,EAAG;AAAA,EACzF,MAAM,gBAAuD;AAAE,WAAO,KAAK,QAAQ,IAAsB,YAAY;AAAA,EAAG;AAAA,EACxH,MAAM,cAAc,OAAwC;AAAE,WAAO,KAAK,QAAQ,IAAI,cAAc,KAAK;AAAA,EAAG;AAAA,EAC5G,MAAM,cAAiD;AAAE,WAAO,KAAK,QAAQ,IAAkB,UAAU;AAAA,EAAG;AAAA,EAC5G,MAAM,YAAY,OAAoC;AAAE,WAAO,KAAK,QAAQ,IAAI,YAAY,KAAK;AAAA,EAAG;AAAA,EACpG,MAAM,WAAkC;AAAE,WAAQ,MAAM,KAAK,QAAQ,IAAkB,OAAO,KAAM,CAAC;AAAA,EAAG;AAAA,EACxG,MAAM,QAAQ,OAAkC;AAC9C,UAAM,UAAU,MAAM,KAAK,SAAS;AACpC,UAAM,KAAK,QAAQ,IAAI,SAAS,CAAC,
|
|
4
|
+
"sourcesContent": ["import type { agentplan, agentsession, auditevent, capabilityreport, diagnosticreport, endpointconfig, planprogress, runsettings, stepoutcome } from \"./types.js\";\n\n/** Provides a small storage seam that works in browser, tests and future adapters. */\nexport interface memoryadapter {\n get<T>(key: string): Promise<T | undefined>;\n set<T>(key: string, value: T): Promise<void>;\n}\n\nexport class sessionmemory {\n constructor(private readonly adapter: memoryadapter) {}\n\n async getconfig(): Promise<endpointconfig | undefined> { return this.adapter.get<endpointconfig>(\"config\"); }\n async setconfig(value: endpointconfig): Promise<void> { return this.adapter.set(\"config\", value); }\n async getsession(): Promise<agentsession | undefined> { return this.adapter.get<agentsession>(\"session\"); }\n async setsession(value: agentsession): Promise<void> { return this.adapter.set(\"session\", value); }\n async getplan(): Promise<agentplan | undefined> { return this.adapter.get<agentplan>(\"plan\"); }\n async setplan(value: agentplan): Promise<void> { return this.adapter.set(\"plan\", value); }\n async getdiagnostic(): Promise<diagnosticreport | undefined> { return this.adapter.get<diagnosticreport>(\"diagnostic\"); }\n async setdiagnostic(value: diagnosticreport): Promise<void> { return this.adapter.set(\"diagnostic\", value); }\n async getprogress(): Promise<planprogress | undefined> { return this.adapter.get<planprogress>(\"progress\"); }\n async setprogress(value: planprogress): Promise<void> { return this.adapter.set(\"progress\", value); }\n async getcapabilities(): Promise<capabilityreport | undefined> { return this.adapter.get<capabilityreport>(\"capabilities\"); }\n async setcapabilities(value: capabilityreport): Promise<void> { return this.adapter.set(\"capabilities\", value); }\n async getsettings(): Promise<runsettings | undefined> { return this.adapter.get<runsettings>(\"settings\"); }\n async setsettings(value: runsettings): Promise<void> { return this.adapter.set(\"settings\", value); }\n async getaudit(): Promise<auditevent[]> { return (await this.adapter.get<auditevent[]>(\"audit\")) ?? []; }\n async getoutcomes(): Promise<stepoutcome[]> { return (await this.adapter.get<stepoutcome[]>(\"outcomes\")) ?? []; }\n\n /** Records one audit event; retention is a user setting and an absent setting keeps every event. */\n async addaudi(event: auditevent): Promise<void> {\n const records = await this.getaudit();\n const combined = [event, ...records];\n const retention = (await this.getsettings())?.auditretention;\n await this.adapter.set(\"audit\", retention === undefined ? combined : combined.slice(0, retention));\n }\n\n /** Records one step outcome; retention is a user setting and an absent setting keeps every outcome. */\n async addoutcome(outcome: stepoutcome): Promise<void> {\n const records = await this.getoutcomes();\n const combined = [outcome, ...records];\n const retention = (await this.getsettings())?.outcomeretention;\n await this.adapter.set(\"outcomes\", retention === undefined ? combined : combined.slice(0, retention));\n }\n}\n\n/** Creates identifiers locally without a network dependency. */\nexport function randomid(): string {\n return crypto.randomUUID();\n}\n", "import type { actionkind, agentplan, agentsession, endpointconfig, policyevaluation, toolstep } from \"./types.js\";\n\nconst sensitiveactions = new Set<actionkind>([\"click\", \"type\", \"navigate\", \"select\", \"presskey\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"reload\", \"back\", \"forward\", \"writestorage\", \"setattribute\", \"removeattribute\", \"evaluate\", \"tabcreate\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowcreate\", \"windowclose\", \"windowresize\", \"downloadfile\"]);\nconst interactionactions = new Set<actionkind>([\"focus\", \"scroll\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"scrollpage\", \"scrollby\", \"scrollend\", \"scrolltop\", \"fullscreen\", \"zoomset\"]);\nconst readactions = new Set<actionkind>([\"observe\", \"inspect\", \"extract\", \"wait\", \"waitfor\", \"waittext\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"readlinks\", \"readimages\", \"readmeta\", \"readforms\", \"readstorage\", \"highlight\", \"tablist\", \"windowlist\", \"tabsnapshot\"]);\nconst allowedactions = new Set<actionkind>([...sensitiveactions, ...interactionactions, ...readactions]);\nconst targetactions = new Set<actionkind>([\"inspect\", \"focus\", \"click\", \"type\", \"scroll\", \"select\", \"hover\", \"clickdeep\", \"rightclick\", \"doubleclick\", \"drag\", \"drop\", \"upload\", \"clear\", \"check\", \"uncheck\", \"toggle\", \"submit\", \"readattribute\", \"readstyle\", \"readgeometry\", \"readvalue\", \"readtext\", \"readhtml\", \"countelements\", \"readtable\", \"highlight\", \"setattribute\", \"removeattribute\", \"waitfor\"]);\nconst valueactions = new Set<actionkind>([\"presskey\", \"drag\", \"drop\", \"upload\", \"readattribute\", \"removeattribute\", \"waittext\", \"evaluate\", \"zoomset\", \"tabactivate\", \"tabclose\", \"tabreload\", \"windowclose\", \"windowresize\", \"tabcreate\", \"windowcreate\", \"downloadfile\"]);\n\n/** Normalizes a user supplied HTTPS endpoint without preserving a provider lock-in. */\nexport function normalizeendpoint(value: string): endpointconfig {\n const endpoint = new URL(value.trim());\n if (endpoint.protocol !== \"https:\") throw new Error(\"Devthink accepts HTTPS endpoints only.\");\n if (endpoint.username || endpoint.password) throw new Error(\"Endpoint credentials are not allowed in the URL.\");\n return { endpoint: endpoint.toString(), origin: endpoint.origin, configuredat: Date.now() };\n}\n\n/** Creates the exact optional host pattern requested from Chromium. */\nexport function hostpattern(origin: string): string {\n const parsed = new URL(origin);\n if (parsed.protocol !== \"https:\") throw new Error(\"Only HTTPS origins can be granted.\");\n return `${parsed.origin}/*`;\n}\n\n/** Defines action risk from the fixed local allowlist. */\nexport function actionrisk(kind: actionkind): \"read\" | \"interaction\" | \"sensitive\" {\n if (!allowedactions.has(kind)) throw new Error(\"Unsupported browser action.\");\n if (sensitiveactions.has(kind)) return \"sensitive\";\n return interactionactions.has(kind) ? \"interaction\" : \"read\";\n}\n\n/** Parses the reviewed JSON options of a step; malformed payloads are rejected early. */\nexport function parseoptions(step: toolstep): Record<string, unknown> {\n if (step.options === undefined) return {};\n let parsed: unknown;\n try { parsed = JSON.parse(step.options); } catch { throw new Error(\"Step options must be a JSON object.\"); }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) throw new Error(\"Step options must be a JSON object.\");\n return parsed as Record<string, unknown>;\n}\n\n/** Maps an action kind to the optional browser permission it requires, if any. */\nexport function requiredcapability(kind: actionkind): string | undefined {\n if (kind === \"tablist\") return \"tabs\";\n if (kind === \"downloadfile\") return \"downloads\";\n return undefined;\n}\n\n/** Parses the reviewed wait duration of a wait step with no upper bound. */\nexport function waitduration(step: toolstep): number {\n const requested = step.value ? Number.parseInt(step.value, 10) : 250;\n if (!Number.isFinite(requested) || requested < 0) throw new Error(\"Wait duration must be zero or a positive number of milliseconds.\");\n return requested;\n}\n\nfunction isnumericid(value: unknown): value is string {\n return typeof value === \"string\" && /^\\d+$/.test(value);\n}\n\nfunction numericoption(options: Record<string, unknown>, key: string): boolean {\n return options[key] === undefined || (typeof options[key] === \"number\" && Number.isFinite(options[key] as number));\n}\n\n/** Validates a single proposal against the active tab origin and local policy. */\nexport function validatestep(step: toolstep, origin: string): policyevaluation {\n if (!allowedactions.has(step.kind)) return { allowed: false, reason: \"Unsupported action kind.\" };\n if (!step.summary.trim()) return { allowed: false, reason: \"A human-readable action summary is required.\" };\n if (targetactions.has(step.kind) && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\n if (valueactions.has(step.kind) && !step.value?.trim()) return { allowed: false, reason: \"A reviewed value is required.\" };\n if (step.kind === \"select\" && !step.value?.trim()) return { allowed: false, reason: \"A reviewed option value is required.\" };\n if (step.kind === \"navigate\" && !step.value) return { allowed: false, reason: \"A navigation URL is required.\" };\n let options: Record<string, unknown>;\n try { options = parseoptions(step); } catch { return { allowed: false, reason: \"Step options must be a JSON object.\" }; }\n if (step.kind === \"wait\") {\n try { waitduration(step); } catch { return { allowed: false, reason: \"Wait duration must be zero or a positive number of milliseconds.\" }; }\n }\n if (step.kind === \"navigate\") {\n try {\n if (new URL(step.value ?? \"\").origin !== origin) return { allowed: false, reason: \"Navigation must remain within the approved origin.\" };\n } catch {\n return { allowed: false, reason: \"Navigation URL is invalid.\" };\n }\n }\n if (step.kind === \"tabcreate\" || step.kind === \"windowcreate\" || step.kind === \"downloadfile\") {\n try {\n const url = new URL(step.value ?? \"\");\n if (url.protocol !== \"https:\") return { allowed: false, reason: \"The reviewed URL must use HTTPS.\" };\n } catch {\n return { allowed: false, reason: \"The reviewed URL is invalid.\" };\n }\n }\n if (step.kind === \"tabactivate\" || step.kind === \"tabclose\" || step.kind === \"tabreload\" || step.kind === \"windowclose\" || step.kind === \"windowresize\") {\n if (!isnumericid(step.value)) return { allowed: false, reason: \"A numeric browser id is required.\" };\n }\n if (step.kind === \"zoomset\") {\n const zoom = Number(step.value);\n if (!Number.isFinite(zoom) || zoom <= 0) return { allowed: false, reason: \"The reviewed zoom must be a positive number.\" };\n }\n if (step.kind === \"setattribute\" || step.kind === \"writestorage\") {\n const keyname = step.kind === \"setattribute\" ? \"name\" : \"key\";\n if (typeof options[keyname] !== \"string\" || !(options[keyname] as string).trim()) return { allowed: false, reason: `A reviewed ${keyname} is required in options.` };\n if (typeof options.value !== \"string\") return { allowed: false, reason: \"A reviewed value is required in options.\" };\n }\n if (step.kind === \"windowresize\") {\n if (typeof options.width !== \"number\" || typeof options.height !== \"number\" || !Number.isFinite(options.width) || !Number.isFinite(options.height)) return { allowed: false, reason: \"Reviewed width and height numbers are required in options.\" };\n }\n if ((step.kind === \"scrollpage\" || step.kind === \"scrollby\") && (!numericoption(options, \"x\") || !numericoption(options, \"y\"))) return { allowed: false, reason: \"Scroll amounts must be numbers in options.\" };\n if (step.kind === \"waitfor\" && options.timeout !== undefined && (typeof options.timeout !== \"number\" || options.timeout < 0)) return { allowed: false, reason: \"The waitfor timeout must be zero or a positive number of milliseconds.\" };\n return { allowed: true };\n}\n\n/** Shared session gate: a live, unpaused session that still matches the active tab. */\nfunction sessiongate(input: { session: agentsession | undefined; tabid: number; origin: string; now: number; action: string }): policyevaluation {\n if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= input.now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.pausedat) return { allowed: false, reason: `The browser session is paused and cannot ${input.action}.` };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: `The ${input.action} is outside the approved tab or origin.` };\n return { allowed: true };\n}\n\n/** Applies the consent gate immediately before an action reaches the page bridge. */\nexport function canexecute(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"execute an action\" });\n if (!gate.allowed) return gate;\n if (!input.plan || input.plan.state !== \"approved\") return { allowed: false, reason: \"The plan has not received explicit approval.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The approved plan has expired.\" };\n return validatestep(input.step, input.origin);\n}\n\n/** Allows a non-mutating, temporary target preview during plan review. */\nexport function canpreview(input: { session: agentsession | undefined; plan: agentplan | undefined; step: toolstep; tabid: number; origin: string; now?: number }): policyevaluation {\n const now = input.now ?? Date.now();\n const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: \"preview a target\" });\n if (!gate.allowed) return gate;\n if (!input.plan || ![\"pending\", \"approved\"].includes(input.plan.state)) return { allowed: false, reason: \"Only a reviewed pending or approved plan can be previewed.\" };\n if (input.plan.expiresat <= now) return { allowed: false, reason: \"The reviewed plan has expired.\" };\n if (!targetactions.has(input.step.kind)) return { allowed: false, reason: \"Only a target-based action can be previewed.\" };\n return validatestep(input.step, input.origin);\n}\n", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.32\" as const;\n", "/** Shared contracts for every Devthink target. */\nimport { packageversion } from \"./version.js\";\n\nexport const protocolversion = packageversion;\n\n/** Every reviewed action kind. Read kinds observe, interaction kinds move focus, sensitive kinds change page or browser state. */\nexport type actionkind =\n | \"observe\" | \"inspect\" | \"extract\" | \"wait\" | \"waitfor\" | \"waittext\"\n | \"readattribute\" | \"readstyle\" | \"readgeometry\" | \"readvalue\" | \"readtext\" | \"readhtml\"\n | \"countelements\" | \"readtable\" | \"readlinks\" | \"readimages\" | \"readmeta\" | \"readforms\"\n | \"readstorage\" | \"highlight\" | \"tablist\" | \"windowlist\" | \"tabsnapshot\"\n | \"focus\" | \"scroll\" | \"hover\" | \"clickdeep\" | \"rightclick\" | \"doubleclick\"\n | \"scrollpage\" | \"scrollby\" | \"scrollend\" | \"scrolltop\" | \"fullscreen\" | \"zoomset\"\n | \"click\" | \"type\" | \"navigate\" | \"select\" | \"presskey\" | \"drag\" | \"drop\" | \"upload\"\n | \"clear\" | \"check\" | \"uncheck\" | \"toggle\" | \"submit\" | \"reload\" | \"back\" | \"forward\"\n | \"writestorage\" | \"setattribute\" | \"removeattribute\" | \"evaluate\"\n | \"tabcreate\" | \"tabactivate\" | \"tabclose\" | \"tabreload\"\n | \"windowcreate\" | \"windowclose\" | \"windowresize\" | \"downloadfile\";\n\nexport type actionrisk = \"read\" | \"interaction\" | \"sensitive\";\nexport type planstate = \"draft\" | \"pending\" | \"approved\" | \"rejected\" | \"expired\" | \"completed\" | \"cancelled\";\nexport type auditkind = \"configure\" | \"session\" | \"observe\" | \"proposal\" | \"approval\" | \"action\" | \"error\" | \"stop\" | \"pause\" | \"resume\" | \"complete\" | \"capability\" | \"tab\" | \"window\" | \"download\";\n\nexport interface toolstep {\n id: string;\n kind: actionkind;\n target?: string;\n value?: string;\n /** Reviewed JSON parameters such as modifiers, amounts or coordinates. */\n options?: string;\n summary: string;\n risk: actionrisk;\n}\n\nexport interface agentplan {\n id: string;\n objective: string;\n origin: string;\n steps: toolstep[];\n createdat: number;\n expiresat: number;\n state: planstate;\n approvedat?: number;\n completedat?: number;\n}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: number;\n pausedat?: number;\n /** Origins granted to this session; prepared for multi origin work. */\n grants?: string[];\n}\n\nexport interface endpointconfig {\n endpoint: string;\n origin: string;\n configuredat: number;\n}\n\nexport interface observation {\n /** Observation schema version for forward compatibility. */\n schemaversion: number;\n url: string;\n title: string;\n textpreview: string;\n textlength: number;\n forms: Array<{ label: string; type: string; name: string; options?: string[] }>;\n interactive: Array<{ selector: string; role: string; label: string }>;\n capturedat: number;\n}\n\nexport interface auditevent {\n id: string;\n kind: auditkind;\n at: number;\n summary: string;\n sessionid?: string;\n planid?: string;\n stepid?: string;\n}\n\nexport interface diagnosticreport {\n id: string;\n sessionid: string;\n origin: string;\n capturedat: number;\n tabid: number;\n title: string;\n textlength: number;\n interactivecount: number;\n formcount: number;\n bridgeavailable: boolean;\n}\n\n/** Live report of the optional browser capabilities the user has granted. */\nexport interface capabilityreport {\n tabs: boolean;\n downloads: boolean;\n clipboardread: boolean;\n clipboardwrite: boolean;\n reportedat: number;\n}\n\n/** Structured result of one executed step, kept with configurable retention. */\nexport interface stepoutcome {\n stepid: string;\n ok: boolean;\n summary: string;\n details?: Record<string, unknown>;\n at: number;\n}\n\n/** User chosen retention windows; an absent value keeps everything forever. */\nexport interface runsettings {\n auditretention?: number;\n outcomeretention?: number;\n}\n\nexport interface proposalrequest {\n objective: string;\n session: agentsession;\n observation: observation;\n capabilities: capabilityreport;\n}\n\nexport interface planproposal {\n version: typeof protocolversion;\n plan: agentplan;\n}\n\nexport interface policyevaluation {\n allowed: boolean;\n reason?: string;\n}\n\n/** Tracks which reviewed steps of one plan have already executed locally. */\nexport interface planprogress {\n planid: string;\n completedsteps: string[];\n outcomes?: stepoutcome[];\n /** Prior progress snapshots preserved when a new plan replaces the tracked one. */\n prior?: planprogress[];\n updatedat: number;\n}\n", "import { actionrisk, parseoptions, validatestep } from \"./policy.js\";\nimport { protocolversion, type agentplan, type planproposal, type proposalrequest, type stepoutcome, type toolstep } from \"./types.js\";\n\nfunction record(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(\"Protocol message must be an object.\");\n return value as Record<string, unknown>;\n}\n\nfunction text(value: unknown, field: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`${field} must be a non-empty string.`);\n return value.trim();\n}\n\n/** Validates agent output before it becomes a locally reviewable plan. Plans may carry any number of steps. */\nexport function parseproposal(value: unknown, origin: string): planproposal {\n const root = record(value);\n if (root.version !== protocolversion) throw new Error(\"Unsupported protocol version.\");\n const planinput = record(root.plan);\n const stepsinput = planinput.steps;\n if (!Array.isArray(stepsinput) || stepsinput.length === 0) throw new Error(\"A plan needs at least one step.\");\n const steps: toolstep[] = stepsinput.map((input, index) => {\n const candidate = record(input);\n const kind = text(candidate.kind, `step ${index + 1} kind`) as toolstep[\"kind\"];\n const step: toolstep = {\n id: typeof candidate.id === \"string\" ? candidate.id : crypto.randomUUID(),\n kind,\n summary: text(candidate.summary, `step ${index + 1} summary`),\n risk: actionrisk(kind),\n ...(typeof candidate.target === \"string\" ? { target: candidate.target } : {}),\n ...(typeof candidate.value === \"string\" ? { value: candidate.value } : {}),\n ...(typeof candidate.options === \"string\" ? { options: candidate.options } : {}),\n };\n const evaluation = validatestep(step, origin);\n if (!evaluation.allowed) throw new Error(evaluation.reason);\n return step;\n });\n const createdat = Date.now();\n const expiresat = typeof planinput.expiresat === \"number\" ? planinput.expiresat : createdat + 10 * 60 * 1000;\n const plan: agentplan = {\n id: typeof planinput.id === \"string\" ? planinput.id : crypto.randomUUID(),\n objective: text(planinput.objective, \"objective\"),\n origin,\n steps,\n createdat,\n expiresat,\n state: \"pending\",\n };\n if (plan.expiresat <= createdat) throw new Error(\"Plan expiry must be in the future.\");\n return { version: protocolversion, plan };\n}\n\n/** Shapes the only data that may be sent to a user-configured agent endpoint. */\nexport function requestbody(input: proposalrequest): string {\n return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });\n}\n\n/** Wraps one executed step outcome in the versioned response envelope for callers. */\nexport function outcomeresponse(input: { outcome: stepoutcome; plan: agentplan }): string {\n return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/memory.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { agentplan, agentsession, auditevent, diagnosticreport, endpointconfig, planprogress } from "./types.js";
|
|
1
|
+
import type { agentplan, agentsession, auditevent, capabilityreport, diagnosticreport, endpointconfig, planprogress, runsettings, stepoutcome } from "./types.js";
|
|
2
2
|
/** Provides a small storage seam that works in browser, tests and future adapters. */
|
|
3
3
|
export interface memoryadapter {
|
|
4
4
|
get<T>(key: string): Promise<T | undefined>;
|
|
@@ -17,8 +17,16 @@ export declare class sessionmemory {
|
|
|
17
17
|
setdiagnostic(value: diagnosticreport): Promise<void>;
|
|
18
18
|
getprogress(): Promise<planprogress | undefined>;
|
|
19
19
|
setprogress(value: planprogress): Promise<void>;
|
|
20
|
+
getcapabilities(): Promise<capabilityreport | undefined>;
|
|
21
|
+
setcapabilities(value: capabilityreport): Promise<void>;
|
|
22
|
+
getsettings(): Promise<runsettings | undefined>;
|
|
23
|
+
setsettings(value: runsettings): Promise<void>;
|
|
20
24
|
getaudit(): Promise<auditevent[]>;
|
|
25
|
+
getoutcomes(): Promise<stepoutcome[]>;
|
|
26
|
+
/** Records one audit event; retention is a user setting and an absent setting keeps every event. */
|
|
21
27
|
addaudi(event: auditevent): Promise<void>;
|
|
28
|
+
/** Records one step outcome; retention is a user setting and an absent setting keeps every outcome. */
|
|
29
|
+
addoutcome(outcome: stepoutcome): Promise<void>;
|
|
22
30
|
}
|
|
23
31
|
/** Creates identifiers locally without a network dependency. */
|
|
24
32
|
export declare function randomid(): string;
|
package/dist/memory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElK,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5C,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C;AAED,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,OAAO;IAApC,YAA6B,OAAO,EAAE,aAAa,EAAI;IAEjD,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAuD;IACvG,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAA8C;IAC7F,UAAU,IAAI,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAsD;IACrG,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAA+C;IAC7F,OAAO,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAAgD;IACzF,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAA4C;IACpF,aAAa,IAAI,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAA6D;IACnH,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAkD;IACvG,WAAW,IAAI,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAAuD;IACvG,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAgD;IAC/F,eAAe,IAAI,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAA+D;IACvH,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAoD;IAC3G,WAAW,IAAI,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAAsD;IACrG,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAgD;IAC9F,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAkE;IACnG,WAAW,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAsE;IAEjH,oGAAoG;IAC9F,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAK9C;IAED,uGAAuG;IACjG,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpD;CACF;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,MAAM,CAEjC"}
|
package/dist/policy.d.ts
CHANGED
|
@@ -3,9 +3,13 @@ import type { actionkind, agentplan, agentsession, endpointconfig, policyevaluat
|
|
|
3
3
|
export declare function normalizeendpoint(value: string): endpointconfig;
|
|
4
4
|
/** Creates the exact optional host pattern requested from Chromium. */
|
|
5
5
|
export declare function hostpattern(origin: string): string;
|
|
6
|
-
/** Defines action risk from
|
|
6
|
+
/** Defines action risk from the fixed local allowlist. */
|
|
7
7
|
export declare function actionrisk(kind: actionkind): "read" | "interaction" | "sensitive";
|
|
8
|
-
/** Parses the
|
|
8
|
+
/** Parses the reviewed JSON options of a step; malformed payloads are rejected early. */
|
|
9
|
+
export declare function parseoptions(step: toolstep): Record<string, unknown>;
|
|
10
|
+
/** Maps an action kind to the optional browser permission it requires, if any. */
|
|
11
|
+
export declare function requiredcapability(kind: actionkind): string | undefined;
|
|
12
|
+
/** Parses the reviewed wait duration of a wait step with no upper bound. */
|
|
9
13
|
export declare function waitduration(step: toolstep): number;
|
|
10
14
|
/** Validates a single proposal against the active tab origin and local policy. */
|
|
11
15
|
export declare function validatestep(step: toolstep, origin: string): policyevaluation;
|
package/dist/policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AASlH,uFAAuF;AACvF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CAK/D;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAIlD;AAED,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,aAAa,GAAG,WAAW,CAIjF;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMpE;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAIvE;AAED,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAInD;AAUD,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CA6C7E;AAWD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAOnL;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,YAAY,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAQnL"}
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { type planproposal, type proposalrequest } from "./types.js";
|
|
2
|
-
/** Validates agent output before it becomes a locally reviewable plan. */
|
|
1
|
+
import { type agentplan, type planproposal, type proposalrequest, type stepoutcome } from "./types.js";
|
|
2
|
+
/** Validates agent output before it becomes a locally reviewable plan. Plans may carry any number of steps. */
|
|
3
3
|
export declare function parseproposal(value: unknown, origin: string): planproposal;
|
|
4
4
|
/** Shapes the only data that may be sent to a user-configured agent endpoint. */
|
|
5
5
|
export declare function requestbody(input: proposalrequest): string;
|
|
6
|
+
/** Wraps one executed step outcome in the versioned response envelope for callers. */
|
|
7
|
+
export declare function outcomeresponse(input: {
|
|
8
|
+
outcome: stepoutcome;
|
|
9
|
+
plan: agentplan;
|
|
10
|
+
}): string;
|
|
6
11
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/protocol.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../protocol.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../protocol.ts"],"names":[],"mappings":"AACA,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAiB,MAAM,YAAY,CAAC;AAYvI,+GAA+G;AAC/G,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAmC1E;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAE1D;AAED,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAAG,MAAM,CAExF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
export declare const protocolversion: "1.1.
|
|
2
|
-
|
|
1
|
+
export declare const protocolversion: "1.1.32";
|
|
2
|
+
/** Every reviewed action kind. Read kinds observe, interaction kinds move focus, sensitive kinds change page or browser state. */
|
|
3
|
+
export type actionkind = "observe" | "inspect" | "extract" | "wait" | "waitfor" | "waittext" | "readattribute" | "readstyle" | "readgeometry" | "readvalue" | "readtext" | "readhtml" | "countelements" | "readtable" | "readlinks" | "readimages" | "readmeta" | "readforms" | "readstorage" | "highlight" | "tablist" | "windowlist" | "tabsnapshot" | "focus" | "scroll" | "hover" | "clickdeep" | "rightclick" | "doubleclick" | "scrollpage" | "scrollby" | "scrollend" | "scrolltop" | "fullscreen" | "zoomset" | "click" | "type" | "navigate" | "select" | "presskey" | "drag" | "drop" | "upload" | "clear" | "check" | "uncheck" | "toggle" | "submit" | "reload" | "back" | "forward" | "writestorage" | "setattribute" | "removeattribute" | "evaluate" | "tabcreate" | "tabactivate" | "tabclose" | "tabreload" | "windowcreate" | "windowclose" | "windowresize" | "downloadfile";
|
|
3
4
|
export type actionrisk = "read" | "interaction" | "sensitive";
|
|
4
5
|
export type planstate = "draft" | "pending" | "approved" | "rejected" | "expired" | "completed" | "cancelled";
|
|
5
|
-
export type auditkind = "configure" | "session" | "observe" | "proposal" | "approval" | "action" | "error" | "stop" | "pause" | "resume" | "complete";
|
|
6
|
+
export type auditkind = "configure" | "session" | "observe" | "proposal" | "approval" | "action" | "error" | "stop" | "pause" | "resume" | "complete" | "capability" | "tab" | "window" | "download";
|
|
6
7
|
export interface toolstep {
|
|
7
8
|
id: string;
|
|
8
9
|
kind: actionkind;
|
|
9
10
|
target?: string;
|
|
10
11
|
value?: string;
|
|
12
|
+
/** Reviewed JSON parameters such as modifiers, amounts or coordinates. */
|
|
13
|
+
options?: string;
|
|
11
14
|
summary: string;
|
|
12
15
|
risk: actionrisk;
|
|
13
16
|
}
|
|
@@ -30,6 +33,8 @@ export interface agentsession {
|
|
|
30
33
|
expiresat: number;
|
|
31
34
|
stoppedat?: number;
|
|
32
35
|
pausedat?: number;
|
|
36
|
+
/** Origins granted to this session; prepared for multi origin work. */
|
|
37
|
+
grants?: string[];
|
|
33
38
|
}
|
|
34
39
|
export interface endpointconfig {
|
|
35
40
|
endpoint: string;
|
|
@@ -37,6 +42,8 @@ export interface endpointconfig {
|
|
|
37
42
|
configuredat: number;
|
|
38
43
|
}
|
|
39
44
|
export interface observation {
|
|
45
|
+
/** Observation schema version for forward compatibility. */
|
|
46
|
+
schemaversion: number;
|
|
40
47
|
url: string;
|
|
41
48
|
title: string;
|
|
42
49
|
textpreview: string;
|
|
@@ -75,10 +82,32 @@ export interface diagnosticreport {
|
|
|
75
82
|
formcount: number;
|
|
76
83
|
bridgeavailable: boolean;
|
|
77
84
|
}
|
|
85
|
+
/** Live report of the optional browser capabilities the user has granted. */
|
|
86
|
+
export interface capabilityreport {
|
|
87
|
+
tabs: boolean;
|
|
88
|
+
downloads: boolean;
|
|
89
|
+
clipboardread: boolean;
|
|
90
|
+
clipboardwrite: boolean;
|
|
91
|
+
reportedat: number;
|
|
92
|
+
}
|
|
93
|
+
/** Structured result of one executed step, kept with configurable retention. */
|
|
94
|
+
export interface stepoutcome {
|
|
95
|
+
stepid: string;
|
|
96
|
+
ok: boolean;
|
|
97
|
+
summary: string;
|
|
98
|
+
details?: Record<string, unknown>;
|
|
99
|
+
at: number;
|
|
100
|
+
}
|
|
101
|
+
/** User chosen retention windows; an absent value keeps everything forever. */
|
|
102
|
+
export interface runsettings {
|
|
103
|
+
auditretention?: number;
|
|
104
|
+
outcomeretention?: number;
|
|
105
|
+
}
|
|
78
106
|
export interface proposalrequest {
|
|
79
107
|
objective: string;
|
|
80
108
|
session: agentsession;
|
|
81
109
|
observation: observation;
|
|
110
|
+
capabilities: capabilityreport;
|
|
82
111
|
}
|
|
83
112
|
export interface planproposal {
|
|
84
113
|
version: typeof protocolversion;
|
|
@@ -92,6 +121,9 @@ export interface policyevaluation {
|
|
|
92
121
|
export interface planprogress {
|
|
93
122
|
planid: string;
|
|
94
123
|
completedsteps: string[];
|
|
124
|
+
outcomes?: stepoutcome[];
|
|
125
|
+
/** Prior progress snapshots preserved when a new plan replaces the tracked one. */
|
|
126
|
+
prior?: planprogress[];
|
|
95
127
|
updatedat: number;
|
|
96
128
|
}
|
|
97
129
|
//# sourceMappingURL=types.d.ts.map
|