@wenathlan/extension 1.1.13 → 1.1.14
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 +3 -3
- package/dist/index.js +2 -1
- package/dist/index.js.map +2 -2
- package/dist/memory.d.ts.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/extension/dist/background.js +2 -1
- package/extension/dist/background.js.map +2 -2
- package/extension/dist/manifest.json +1 -1
- package/extension/dist/popup.html +1 -1
- package/extension/manifest.json +1 -1
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
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.14**. 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.14 |
|
|
10
10
|
| --- | --- |
|
|
11
11
|
| Active-tab session | The user starts a short-lived session for one HTTPS tab and one origin. |
|
|
12
12
|
| Page observation | The extension captures a bounded semantic inventory of interactive elements and form labels. |
|
|
@@ -40,7 +40,7 @@ The endpoint field intentionally has no default URL. Enter a URL such as `https:
|
|
|
40
40
|
|
|
41
41
|
```json
|
|
42
42
|
{
|
|
43
|
-
"version": "1.1.
|
|
43
|
+
"version": "1.1.14",
|
|
44
44
|
"objective": "User supplied objective",
|
|
45
45
|
"session": { "id": "uuid", "tabid": 1, "origin": "https://example.com" },
|
|
46
46
|
"observation": { "url": "https://example.com/path", "interactive": [] }
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@ var sessionmemory = class {
|
|
|
3
3
|
constructor(adapter) {
|
|
4
4
|
this.adapter = adapter;
|
|
5
5
|
}
|
|
6
|
+
adapter;
|
|
6
7
|
async getconfig() {
|
|
7
8
|
return this.adapter.get("config");
|
|
8
9
|
}
|
|
@@ -83,7 +84,7 @@ function canexecute(input) {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
// version.ts
|
|
86
|
-
var packageversion = "1.1.
|
|
87
|
+
var packageversion = "1.1.14";
|
|
87
88
|
|
|
88
89
|
// types.ts
|
|
89
90
|
var protocolversion = packageversion;
|
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 } 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 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\"]);\nconst allowedactions = new Set<actionkind>([\"observe\", \"inspect\", \"focus\", \"click\", \"type\", \"navigate\"]);\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 kind === \"focus\" ? \"interaction\" : \"read\";\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 ((step.kind === \"click\" || step.kind === \"focus\" || step.kind === \"inspect\" || step.kind === \"type\") && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\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/** 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 if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: \"The action is outside the approved tab or origin.\" };\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", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.13\" 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\";\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\";\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}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: 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 }>;\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", "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 > 20) throw new Error(\"A plan needs between one and twenty 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,
|
|
4
|
+
"sourcesContent": ["import type { agentplan, agentsession, auditevent, diagnosticreport, endpointconfig } 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 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\"]);\nconst allowedactions = new Set<actionkind>([\"observe\", \"inspect\", \"focus\", \"click\", \"type\", \"navigate\"]);\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 kind === \"focus\" ? \"interaction\" : \"read\";\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 ((step.kind === \"click\" || step.kind === \"focus\" || step.kind === \"inspect\" || step.kind === \"type\") && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\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/** 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 if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: \"The action is outside the approved tab or origin.\" };\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", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.14\" 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\";\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\";\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}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: 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 }>;\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", "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 > 20) throw new Error(\"A plan needs between one and twenty 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": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
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,MAAM,YAAY,CAAC;AAExG,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;
|
|
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,MAAM,YAAY,CAAC;AAExG,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,QAAQ,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAkE;IACnG,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAG9C;CACF;AAED,gEAAgE;AAChE,wBAAgB,QAAQ,IAAI,MAAM,CAEjC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const protocolversion: "1.1.
|
|
1
|
+
export declare const protocolversion: "1.1.14";
|
|
2
2
|
export type actionkind = "observe" | "inspect" | "focus" | "click" | "type" | "navigate";
|
|
3
3
|
export type actionrisk = "read" | "interaction" | "sensitive";
|
|
4
4
|
export type planstate = "draft" | "pending" | "approved" | "rejected" | "expired" | "completed" | "cancelled";
|
package/dist/version.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ var sessionmemory = class {
|
|
|
3
3
|
constructor(adapter) {
|
|
4
4
|
this.adapter = adapter;
|
|
5
5
|
}
|
|
6
|
+
adapter;
|
|
6
7
|
async getconfig() {
|
|
7
8
|
return this.adapter.get("config");
|
|
8
9
|
}
|
|
@@ -83,7 +84,7 @@ function canexecute(input) {
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
// version.ts
|
|
86
|
-
var packageversion = "1.1.
|
|
87
|
+
var packageversion = "1.1.14";
|
|
87
88
|
|
|
88
89
|
// types.ts
|
|
89
90
|
var protocolversion = packageversion;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../memory.ts", "../../policy.ts", "../../version.ts", "../../types.ts", "../../protocol.ts", "../background.ts"],
|
|
4
|
-
"sourcesContent": ["import type { agentplan, agentsession, auditevent, diagnosticreport, endpointconfig } 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 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\"]);\nconst allowedactions = new Set<actionkind>([\"observe\", \"inspect\", \"focus\", \"click\", \"type\", \"navigate\"]);\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 kind === \"focus\" ? \"interaction\" : \"read\";\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 ((step.kind === \"click\" || step.kind === \"focus\" || step.kind === \"inspect\" || step.kind === \"type\") && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\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/** 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 if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: \"The action is outside the approved tab or origin.\" };\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", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.13\" 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\";\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\";\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}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: 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 }>;\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", "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 > 20) throw new Error(\"A plan needs between one and twenty 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", "import { randomid, sessionmemory } from \"../memory.js\";\nimport { canexecute, hostpattern, normalizeendpoint } from \"../policy.js\";\nimport { parseproposal, requestbody } from \"../protocol.js\";\nimport type { agentplan, agentsession, auditevent, diagnosticreport, observation, toolstep } from \"../types.js\";\n\nconst sessionduration = 15 * 60 * 1000;\n\nconst chromestorage = {\n async get<T>(key: string): Promise<T | undefined> { return (await chrome.storage.local.get(key))[key] as T | undefined; },\n async set<T>(key: string, value: T): Promise<void> { await chrome.storage.local.set({ [key]: value }); },\n};\nconst memory = new sessionmemory(chromestorage);\n\nfunction extensionpage(sender: chrome.runtime.MessageSender): boolean {\n return sender.id === chrome.runtime.id && Boolean(sender.url?.startsWith(chrome.runtime.getURL(\"\")));\n}\n\nasync function audit(kind: auditevent[\"kind\"], summary: string, extra: Partial<auditevent> = {}): Promise<void> {\n await memory.addaudi({ id: randomid(), kind, at: Date.now(), summary, ...extra });\n}\n\nasync function activecontext(): Promise<{ tab: chrome.tabs.Tab; origin: string }> {\n const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n if (!tab?.id || !tab.url) throw new Error(\"No active web tab is available.\");\n const origin = new URL(tab.url).origin;\n if (!origin.startsWith(\"https://\")) throw new Error(\"Devthink can work with HTTPS pages only.\");\n return { tab, origin };\n}\n\nasync function snapshot(tabid: number): Promise<observation> {\n await chrome.scripting.executeScript({ target: { tabId: tabid }, files: [\"pagebridge.js\"] });\n const result = await chrome.scripting.executeScript({ target: { tabId: tabid }, func: () => {\n const bridge = (globalThis as typeof globalThis & { devthinkbridge?: { capturesnapshot: () => observation } }).devthinkbridge;\n if (!bridge) throw new Error(\"Devthink page bridge is unavailable.\");\n return bridge.capturesnapshot();\n } });\n const value = result[0]?.result;\n if (!value) throw new Error(\"The page did not return an observation.\");\n return value as observation;\n}\n\nasync function startsession(): Promise<agentsession> {\n const { tab, origin } = await activecontext();\n const session: agentsession = { id: randomid(), tabid: tab.id as number, origin, startedat: Date.now(), expiresat: Date.now() + sessionduration };\n await memory.setsession(session);\n await audit(\"session\", `Session started for ${origin}.`, { sessionid: session.id });\n return session;\n}\n\nasync function diagnostic(): Promise<diagnosticreport> {\n const session = await memory.getsession();\n const { tab, origin } = await activecontext();\n if (!session || session.stoppedat || session.expiresat <= Date.now() || session.tabid !== tab.id || session.origin !== origin) throw new Error(\"Start a current session for this active tab before diagnostics.\");\n const observation = await snapshot(session.tabid);\n const report: diagnosticreport = { id: randomid(), sessionid: session.id, origin, capturedat: Date.now(), tabid: session.tabid, title: observation.title, textlength: observation.textlength, interactivecount: observation.interactive.length, formcount: observation.forms.length, bridgeavailable: true };\n await memory.setdiagnostic(report);\n await audit(\"observe\", \"Structured diagnostics captured for the approved active tab.\", { sessionid: session.id });\n return report;\n}\n\nfunction localplan(objective: string, session: agentsession): agentplan {\n const now = Date.now();\n return { id: randomid(), objective, origin: session.origin, steps: [{ id: randomid(), kind: \"observe\", summary: \"Capture a bounded semantic snapshot of the approved active tab.\", risk: \"read\" }], createdat: now, expiresat: now + sessionduration, state: \"pending\" };\n}\n\nasync function propose(objective: string, remote: boolean): Promise<agentplan> {\n if (!objective.trim()) throw new Error(\"An objective is required.\");\n const session = await memory.getsession();\n if (!session || session.stoppedat || session.expiresat <= Date.now()) throw new Error(\"Start a current browser session before requesting a plan.\");\n const { tab, origin } = await activecontext();\n if (session.tabid !== tab.id || session.origin !== origin) throw new Error(\"The selected tab or origin no longer matches the approved session.\");\n const observation = await snapshot(session.tabid);\n const config = await memory.getconfig();\n let plan = localplan(objective.trim(), session);\n if (remote) {\n if (!config) throw new Error(\"Configure an approved HTTPS endpoint before requesting a remote proposal.\");\n const response = await fetch(config.endpoint, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, credentials: \"omit\", body: requestbody({ objective: objective.trim(), session, observation }) });\n if (!response.ok) throw new Error(`Proposal endpoint returned ${response.status}.`);\n plan = parseproposal(await response.json(), session.origin).plan;\n }\n await memory.setplan(plan);\n await audit(\"proposal\", `Plan proposed with ${plan.steps.length} reviewed step${plan.steps.length === 1 ? \"\" : \"s\"}.`, { sessionid: session.id, planid: plan.id });\n return plan;\n}\n\nasync function executestep(stepid: string): Promise<{ ok: boolean; summary: string }> {\n const session = await memory.getsession();\n const plan = await memory.getplan();\n const { tab, origin } = await activecontext();\n const step = plan?.steps.find(candidate => candidate.id === stepid);\n if (!step) throw new Error(\"Reviewed step was not found.\");\n const gate = canexecute({ session, plan, step, tabid: tab.id as number, origin });\n if (!gate.allowed) throw new Error(gate.reason);\n const fresh = await snapshot(tab.id as number);\n if (step.target && !fresh.interactive.some(item => item.selector === step.target)) throw new Error(\"The page changed and the target must be reviewed again.\");\n const result = await chrome.scripting.executeScript({ target: { tabId: tab.id as number }, func: (action: toolstep, expectedorigin: string) => {\n const bridge = (globalThis as typeof globalThis & { devthinkbridge?: { performstep: (input: toolstep, origin: string) => { ok: boolean; summary: string } } }).devthinkbridge;\n if (!bridge) throw new Error(\"Devthink page bridge is unavailable.\");\n return bridge.performstep(action, expectedorigin);\n }, args: [step, origin] });\n const output = result[0]?.result as { ok: boolean; summary: string } | undefined;\n const summary = output?.summary ?? \"The page action returned no result.\";\n await audit(output?.ok ? \"action\" : \"error\", summary, { ...(session ? { sessionid: session.id } : {}), ...(plan ? { planid: plan.id } : {}), stepid });\n return output ?? { ok: false, summary };\n}\n\nasync function handlerequest(message: unknown, sender: chrome.runtime.MessageSender): Promise<unknown> {\n if (!extensionpage(sender)) throw new Error(\"Requests are accepted only from Devthink extension pages.\");\n const input = message as { kind?: string; endpoint?: string; objective?: string; stepid?: string };\n switch (input.kind) {\n case \"configure\": {\n const config = normalizeendpoint(input.endpoint ?? \"\");\n const granted = await chrome.permissions.contains({ origins: [hostpattern(config.origin)] });\n if (!granted) throw new Error(\"The endpoint origin has not received optional permission.\");\n await memory.setconfig(config);\n await audit(\"configure\", `Configured user-selected endpoint ${config.origin}.`);\n return config;\n }\n case \"startsession\": return startsession();\n case \"context\": return { config: await memory.getconfig(), session: await memory.getsession(), plan: await memory.getplan(), diagnostic: await memory.getdiagnostic(), audit: await memory.getaudit() };\n case \"diagnostic\": return diagnostic();\n case \"proposelocal\": return propose(input.objective ?? \"\", false);\n case \"proposeremote\": return propose(input.objective ?? \"\", true);\n case \"approve\": {\n const plan = await memory.getplan();\n if (!plan || plan.state !== \"pending\") throw new Error(\"Only a pending plan can be approved.\");\n const approved = { ...plan, state: \"approved\" as const, approvedat: Date.now() };\n await memory.setplan(approved);\n const current = await memory.getsession();\n await audit(\"approval\", \"The user approved the reviewed plan.\", { ...(current ? { sessionid: current.id } : {}), planid: approved.id });\n return approved;\n }\n case \"reject\": {\n const plan = await memory.getplan();\n if (!plan) throw new Error(\"No plan is available to reject.\");\n const rejected = { ...plan, state: \"rejected\" as const };\n await memory.setplan(rejected);\n const current = await memory.getsession();\n await audit(\"approval\", \"The user rejected the plan.\", { ...(current ? { sessionid: current.id } : {}), planid: rejected.id });\n return rejected;\n }\n case \"execute\": return executestep(input.stepid ?? \"\");\n case \"stop\": {\n const session = await memory.getsession();\n if (session) await memory.setsession({ ...session, stoppedat: Date.now() });\n const plan = await memory.getplan();\n if (plan && [\"pending\", \"approved\"].includes(plan.state)) await memory.setplan({ ...plan, state: \"cancelled\" });\n await audit(\"stop\", \"The user stopped the browser session.\", { ...(session ? { sessionid: session.id } : {}), ...(plan ? { planid: plan.id } : {}) });\n return { stopped: true };\n }\n default: throw new Error(\"Unknown Devthink request.\");\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendresponse) => {\n handlerequest(message, sender).then(value => sendresponse({ ok: true, value })).catch(error => sendresponse({ ok: false, error: error instanceof Error ? error.message : String(error) }));\n return true;\n});\n\nchrome.runtime.onConnect.addListener(port => {\n if (port.name !== \"devthinksidepanel\" || port.sender?.id !== chrome.runtime.id || !port.sender.url?.startsWith(chrome.runtime.getURL(\"\"))) return port.disconnect();\n port.onMessage.addListener(message => { handlerequest(message, port.sender ?? {}).then(value => port.postMessage({ ok: true, value })).catch(error => port.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) })); });\n});\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { agentplan, agentsession, auditevent, diagnosticreport, endpointconfig } 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 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\"]);\nconst allowedactions = new Set<actionkind>([\"observe\", \"inspect\", \"focus\", \"click\", \"type\", \"navigate\"]);\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 kind === \"focus\" ? \"interaction\" : \"read\";\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 ((step.kind === \"click\" || step.kind === \"focus\" || step.kind === \"inspect\" || step.kind === \"type\") && !step.target?.trim()) return { allowed: false, reason: \"A page target is required.\" };\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/** 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 if (!input.session || input.session.stoppedat) return { allowed: false, reason: \"No active browser session exists.\" };\n if (input.session.expiresat <= now) return { allowed: false, reason: \"The browser session has expired.\" };\n if (input.session.tabid !== input.tabid || input.session.origin !== input.origin) return { allowed: false, reason: \"The action is outside the approved tab or origin.\" };\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", "/** Canonical package version synchronized from package.json. */\nexport const packageversion = \"1.1.14\" 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\";\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\";\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}\n\nexport interface agentsession {\n id: string;\n tabid: number;\n origin: string;\n startedat: number;\n expiresat: number;\n stoppedat?: 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 }>;\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", "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 > 20) throw new Error(\"A plan needs between one and twenty 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", "import { randomid, sessionmemory } from \"../memory.js\";\nimport { canexecute, hostpattern, normalizeendpoint } from \"../policy.js\";\nimport { parseproposal, requestbody } from \"../protocol.js\";\nimport type { agentplan, agentsession, auditevent, diagnosticreport, observation, toolstep } from \"../types.js\";\n\nconst sessionduration = 15 * 60 * 1000;\n\nconst chromestorage = {\n async get<T>(key: string): Promise<T | undefined> { return (await chrome.storage.local.get(key))[key] as T | undefined; },\n async set<T>(key: string, value: T): Promise<void> { await chrome.storage.local.set({ [key]: value }); },\n};\nconst memory = new sessionmemory(chromestorage);\n\nfunction extensionpage(sender: chrome.runtime.MessageSender): boolean {\n return sender.id === chrome.runtime.id && Boolean(sender.url?.startsWith(chrome.runtime.getURL(\"\")));\n}\n\nasync function audit(kind: auditevent[\"kind\"], summary: string, extra: Partial<auditevent> = {}): Promise<void> {\n await memory.addaudi({ id: randomid(), kind, at: Date.now(), summary, ...extra });\n}\n\nasync function activecontext(): Promise<{ tab: chrome.tabs.Tab; origin: string }> {\n const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n if (!tab?.id || !tab.url) throw new Error(\"No active web tab is available.\");\n const origin = new URL(tab.url).origin;\n if (!origin.startsWith(\"https://\")) throw new Error(\"Devthink can work with HTTPS pages only.\");\n return { tab, origin };\n}\n\nasync function snapshot(tabid: number): Promise<observation> {\n await chrome.scripting.executeScript({ target: { tabId: tabid }, files: [\"pagebridge.js\"] });\n const result = await chrome.scripting.executeScript({ target: { tabId: tabid }, func: () => {\n const bridge = (globalThis as typeof globalThis & { devthinkbridge?: { capturesnapshot: () => observation } }).devthinkbridge;\n if (!bridge) throw new Error(\"Devthink page bridge is unavailable.\");\n return bridge.capturesnapshot();\n } });\n const value = result[0]?.result;\n if (!value) throw new Error(\"The page did not return an observation.\");\n return value as observation;\n}\n\nasync function startsession(): Promise<agentsession> {\n const { tab, origin } = await activecontext();\n const session: agentsession = { id: randomid(), tabid: tab.id as number, origin, startedat: Date.now(), expiresat: Date.now() + sessionduration };\n await memory.setsession(session);\n await audit(\"session\", `Session started for ${origin}.`, { sessionid: session.id });\n return session;\n}\n\nasync function diagnostic(): Promise<diagnosticreport> {\n const session = await memory.getsession();\n const { tab, origin } = await activecontext();\n if (!session || session.stoppedat || session.expiresat <= Date.now() || session.tabid !== tab.id || session.origin !== origin) throw new Error(\"Start a current session for this active tab before diagnostics.\");\n const observation = await snapshot(session.tabid);\n const report: diagnosticreport = { id: randomid(), sessionid: session.id, origin, capturedat: Date.now(), tabid: session.tabid, title: observation.title, textlength: observation.textlength, interactivecount: observation.interactive.length, formcount: observation.forms.length, bridgeavailable: true };\n await memory.setdiagnostic(report);\n await audit(\"observe\", \"Structured diagnostics captured for the approved active tab.\", { sessionid: session.id });\n return report;\n}\n\nfunction localplan(objective: string, session: agentsession): agentplan {\n const now = Date.now();\n return { id: randomid(), objective, origin: session.origin, steps: [{ id: randomid(), kind: \"observe\", summary: \"Capture a bounded semantic snapshot of the approved active tab.\", risk: \"read\" }], createdat: now, expiresat: now + sessionduration, state: \"pending\" };\n}\n\nasync function propose(objective: string, remote: boolean): Promise<agentplan> {\n if (!objective.trim()) throw new Error(\"An objective is required.\");\n const session = await memory.getsession();\n if (!session || session.stoppedat || session.expiresat <= Date.now()) throw new Error(\"Start a current browser session before requesting a plan.\");\n const { tab, origin } = await activecontext();\n if (session.tabid !== tab.id || session.origin !== origin) throw new Error(\"The selected tab or origin no longer matches the approved session.\");\n const observation = await snapshot(session.tabid);\n const config = await memory.getconfig();\n let plan = localplan(objective.trim(), session);\n if (remote) {\n if (!config) throw new Error(\"Configure an approved HTTPS endpoint before requesting a remote proposal.\");\n const response = await fetch(config.endpoint, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, credentials: \"omit\", body: requestbody({ objective: objective.trim(), session, observation }) });\n if (!response.ok) throw new Error(`Proposal endpoint returned ${response.status}.`);\n plan = parseproposal(await response.json(), session.origin).plan;\n }\n await memory.setplan(plan);\n await audit(\"proposal\", `Plan proposed with ${plan.steps.length} reviewed step${plan.steps.length === 1 ? \"\" : \"s\"}.`, { sessionid: session.id, planid: plan.id });\n return plan;\n}\n\nasync function executestep(stepid: string): Promise<{ ok: boolean; summary: string }> {\n const session = await memory.getsession();\n const plan = await memory.getplan();\n const { tab, origin } = await activecontext();\n const step = plan?.steps.find(candidate => candidate.id === stepid);\n if (!step) throw new Error(\"Reviewed step was not found.\");\n const gate = canexecute({ session, plan, step, tabid: tab.id as number, origin });\n if (!gate.allowed) throw new Error(gate.reason);\n const fresh = await snapshot(tab.id as number);\n if (step.target && !fresh.interactive.some(item => item.selector === step.target)) throw new Error(\"The page changed and the target must be reviewed again.\");\n const result = await chrome.scripting.executeScript({ target: { tabId: tab.id as number }, func: (action: toolstep, expectedorigin: string) => {\n const bridge = (globalThis as typeof globalThis & { devthinkbridge?: { performstep: (input: toolstep, origin: string) => { ok: boolean; summary: string } } }).devthinkbridge;\n if (!bridge) throw new Error(\"Devthink page bridge is unavailable.\");\n return bridge.performstep(action, expectedorigin);\n }, args: [step, origin] });\n const output = result[0]?.result as { ok: boolean; summary: string } | undefined;\n const summary = output?.summary ?? \"The page action returned no result.\";\n await audit(output?.ok ? \"action\" : \"error\", summary, { ...(session ? { sessionid: session.id } : {}), ...(plan ? { planid: plan.id } : {}), stepid });\n return output ?? { ok: false, summary };\n}\n\nasync function handlerequest(message: unknown, sender: chrome.runtime.MessageSender): Promise<unknown> {\n if (!extensionpage(sender)) throw new Error(\"Requests are accepted only from Devthink extension pages.\");\n const input = message as { kind?: string; endpoint?: string; objective?: string; stepid?: string };\n switch (input.kind) {\n case \"configure\": {\n const config = normalizeendpoint(input.endpoint ?? \"\");\n const granted = await chrome.permissions.contains({ origins: [hostpattern(config.origin)] });\n if (!granted) throw new Error(\"The endpoint origin has not received optional permission.\");\n await memory.setconfig(config);\n await audit(\"configure\", `Configured user-selected endpoint ${config.origin}.`);\n return config;\n }\n case \"startsession\": return startsession();\n case \"context\": return { config: await memory.getconfig(), session: await memory.getsession(), plan: await memory.getplan(), diagnostic: await memory.getdiagnostic(), audit: await memory.getaudit() };\n case \"diagnostic\": return diagnostic();\n case \"proposelocal\": return propose(input.objective ?? \"\", false);\n case \"proposeremote\": return propose(input.objective ?? \"\", true);\n case \"approve\": {\n const plan = await memory.getplan();\n if (!plan || plan.state !== \"pending\") throw new Error(\"Only a pending plan can be approved.\");\n const approved = { ...plan, state: \"approved\" as const, approvedat: Date.now() };\n await memory.setplan(approved);\n const current = await memory.getsession();\n await audit(\"approval\", \"The user approved the reviewed plan.\", { ...(current ? { sessionid: current.id } : {}), planid: approved.id });\n return approved;\n }\n case \"reject\": {\n const plan = await memory.getplan();\n if (!plan) throw new Error(\"No plan is available to reject.\");\n const rejected = { ...plan, state: \"rejected\" as const };\n await memory.setplan(rejected);\n const current = await memory.getsession();\n await audit(\"approval\", \"The user rejected the plan.\", { ...(current ? { sessionid: current.id } : {}), planid: rejected.id });\n return rejected;\n }\n case \"execute\": return executestep(input.stepid ?? \"\");\n case \"stop\": {\n const session = await memory.getsession();\n if (session) await memory.setsession({ ...session, stoppedat: Date.now() });\n const plan = await memory.getplan();\n if (plan && [\"pending\", \"approved\"].includes(plan.state)) await memory.setplan({ ...plan, state: \"cancelled\" });\n await audit(\"stop\", \"The user stopped the browser session.\", { ...(session ? { sessionid: session.id } : {}), ...(plan ? { planid: plan.id } : {}) });\n return { stopped: true };\n }\n default: throw new Error(\"Unknown Devthink request.\");\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendresponse) => {\n handlerequest(message, sender).then(value => sendresponse({ ok: true, value })).catch(error => sendresponse({ ok: false, error: error instanceof Error ? error.message : String(error) }));\n return true;\n});\n\nchrome.runtime.onConnect.addListener(port => {\n if (port.name !== \"devthinksidepanel\" || port.sender?.id !== chrome.runtime.id || !port.sender.url?.startsWith(chrome.runtime.getURL(\"\"))) return port.disconnect();\n port.onMessage.addListener(message => { handlerequest(message, port.sender ?? {}).then(value => port.postMessage({ ok: true, value })).catch(error => port.postMessage({ ok: false, error: error instanceof Error ? error.message : String(error) })); });\n});\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Devthink</title><link rel="stylesheet" href="style.css"></head>
|
|
4
|
-
<body><main><header><p class="eyebrow">DEVTHINK 1.1.
|
|
4
|
+
<body><main><header><p class="eyebrow">DEVTHINK 1.1.14</p><h1>Browser bridge</h1><p>Consent is required before page access or action.</p></header><label for="endpoint">Optional agent endpoint</label><input id="endpoint" type="url" inputmode="url" placeholder="https://agent.example/proposal" autocomplete="off"><button id="connect">Approve endpoint origin</button><div class="actions"><button id="session">Start active tab session</button><button id="openpanel" class="secondary">Review plans</button><button id="stop" class="danger">Stop</button></div><p id="status" role="status">Loading session state.</p></main><script type="module" src="popup.js"></script></body>
|
|
5
5
|
</html>
|
package/extension/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wenathlan/extension",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.14",
|
|
4
4
|
"description": "Consent-first browser agent bridge and Manifest V3 extension.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-only",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"chromium"
|
|
22
22
|
],
|
|
23
23
|
"engines": {
|
|
24
|
-
"node": ">=
|
|
24
|
+
"node": ">=26.8.1 <27",
|
|
25
|
+
"npm": ">=12.0.2 <13",
|
|
26
|
+
"bun": ">=1.4.0 <2"
|
|
25
27
|
},
|
|
26
28
|
"main": "./dist/index.js",
|
|
27
29
|
"types": "./dist/index.d.ts",
|
|
@@ -46,16 +48,17 @@
|
|
|
46
48
|
"dependency:updates": "node tests/dependencyupdates.mjs sync",
|
|
47
49
|
"workflow:updates": "node tests/workflowupdates.mjs sync",
|
|
48
50
|
"notes:release": "node tests/release.mjs notes",
|
|
51
|
+
"validate:runtime": "node tests/runtimepolicy.mjs",
|
|
49
52
|
"validate:workflow": "node tests/workflowcheck.mjs && node tests/npmgate.mjs",
|
|
50
|
-
"validate": "pnpm check:metadata && pnpm check && pnpm test && pnpm build && node dist/cli.js manifest && node tests/packageextension.mjs && pnpm validate:workflow",
|
|
53
|
+
"validate": "pnpm check:metadata && pnpm validate:runtime && pnpm check && pnpm test && pnpm build && node dist/cli.js manifest && node tests/packageextension.mjs && pnpm validate:workflow",
|
|
51
54
|
"package": "pnpm build && npm pack --dry-run"
|
|
52
55
|
},
|
|
53
56
|
"devDependencies": {
|
|
54
|
-
"@types/chrome": "^0.
|
|
55
|
-
"@types/node": "^
|
|
56
|
-
"esbuild": "^0.
|
|
57
|
-
"typescript": "^
|
|
58
|
-
"vitest": "^
|
|
57
|
+
"@types/chrome": "^0.2.7",
|
|
58
|
+
"@types/node": "^26.4.0",
|
|
59
|
+
"esbuild": "^0.28.2",
|
|
60
|
+
"typescript": "^7.0.2",
|
|
61
|
+
"vitest": "^4.1.11",
|
|
59
62
|
"yaml": "^2.9.0"
|
|
60
63
|
},
|
|
61
64
|
"packageManager": "pnpm@11.24.0"
|