@assemblyline-agents/margins 2.0.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenEve contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # @assemblyline-agents/margins
2
+
3
+ Official Assembly Line connection plugin for resource-scoped collaborative
4
+ Markdown in Margins. A binding can cover one page, one folder and its
5
+ descendants, or the whole workspace.
6
+
7
+ ## Setup
8
+
9
+ ```sh
10
+ assembly-line add margins agent
11
+ ```
12
+
13
+ No developer OAuth registration or long-lived token environment variable is
14
+ required for the hosted service. In Margins, open the agent invite for the
15
+ page, folder, or workspace, choose **Comment and suggest** or **Edit directly**,
16
+ and paste the generated one-time packet into the agent's chat. Assembly Line
17
+ advertises `margins__pair`, redeems the packet on the host, and stores the
18
+ returned rotating access and refresh credentials outside the model sandbox.
19
+
20
+ For self-hosted Margins, set `MARGINS_MCP_URL` and optionally
21
+ `MARGINS_ISSUER`. Configure stable collaborator identity with
22
+ `MARGINS_AGENT_ID`, `MARGINS_AGENT_NAME`, `MARGINS_AGENT_RUNTIME`, and
23
+ `MARGINS_AGENT_HARNESS`, or pass their equivalents to
24
+ `defineMarginsConnection()`.
25
+
26
+ The generated connection is read-only at Assembly Line's outer policy layer.
27
+ Margins still enforces the packet's own scope and permission. Enable reviewed
28
+ mutations explicitly if the agent should comment, suggest, create pages, or
29
+ edit Markdown:
30
+
31
+ ```ts
32
+ import { defineMarginsConnection } from "@assemblyline-agents/margins";
33
+
34
+ export default defineMarginsConnection({
35
+ agentId: "research-editor",
36
+ agentName: "Research Editor",
37
+ access: {
38
+ read: true,
39
+ write: { approval: "always" }
40
+ }
41
+ });
42
+ ```
43
+
44
+ Comments and suggestions are classified as writes because they mutate shared
45
+ workspace state. Margins applies its own permission check after Assembly Line's
46
+ approval gate; a **Comment and suggest** binding can never edit canonical
47
+ Markdown or create a page.
@@ -0,0 +1,18 @@
1
+ import { type ConnectionAuthDefinition, type McpPluginConnectionOptions } from "@assemblyline-agents/core";
2
+ export interface MarginsConnectionOptions extends Omit<McpPluginConnectionOptions, "auth"> {
3
+ /** Override the refresh-capable authorization contract. Keep the default when using binding packets. */
4
+ auth?: ConnectionAuthDefinition | false;
5
+ /** Margins deployment origin. Defaults to the MCP endpoint's origin. */
6
+ issuer?: string;
7
+ /** Stable agent id recorded in Margins comments, suggestions, edits, and presence. */
8
+ agentId?: string;
9
+ /** Human-readable agent name shown to Margins collaborators. */
10
+ agentName?: string;
11
+ /** Agent runtime recorded with the binding. Defaults to assembly-line. */
12
+ agentRuntime?: string;
13
+ /** Harness recorded with the binding. Defaults to assembly-line. */
14
+ agentHarness?: string;
15
+ }
16
+ export declare function defineMarginsConnection(options: MarginsConnectionOptions): import("@assemblyline-agents/core").McpHttpClientConnectionDefinition;
17
+ export declare const assemblyLinePlugin: import("@assemblyline-agents/core").PluginModule;
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,wBAAwB,EAC7B,KAAK,0BAA0B,EAChC,MAAM,2BAA2B,CAAC;AAKnC,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,0BAA0B,EAAE,MAAM,CAAC;IACxF,wGAAwG;IACxG,IAAI,CAAC,EAAE,wBAAwB,GAAG,KAAK,CAAC;IACxC,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,wBAAwB,yEAiCxE;AAED,eAAO,MAAM,kBAAkB,kDAA0C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,53 @@
1
+ import { connectionPluginMetadata, defineMcpPluginConnection, defineOAuthAuthorization, definePlugin } from "@assemblyline-agents/core";
2
+ import { createMarginsPairingRedeemer } from "./pairing.js";
3
+ const PLUGIN = connectionPluginMetadata("margins");
4
+ export function defineMarginsConnection(options) {
5
+ const { auth, issuer, agentId, agentName, agentRuntime, agentHarness, ...connection } = options;
6
+ const definition = defineMcpPluginConnection(PLUGIN, {
7
+ ...connection,
8
+ auth: auth === false
9
+ ? false
10
+ : auth ?? marginsAuthorization({
11
+ ...(issuer ? { issuer } : {}),
12
+ ...(connection.url ? { mcpUrl: connection.url } : {})
13
+ })
14
+ });
15
+ definition.redeemPairingCode = createMarginsPairingRedeemer(({ env }) => ({
16
+ origin: normalizeIssuer(issuer
17
+ ?? env.MARGINS_ISSUER
18
+ ?? connection.url
19
+ ?? env.MARGINS_MCP_URL
20
+ ?? definition.url),
21
+ agentId: cleanIdentity(agentId ?? env.MARGINS_AGENT_ID) ?? "assembly-line-agent",
22
+ agentName: cleanIdentity(agentName ?? env.MARGINS_AGENT_NAME) ?? "Assembly Line Agent",
23
+ runtime: cleanIdentity(agentRuntime ?? env.MARGINS_AGENT_RUNTIME) ?? "assembly-line",
24
+ harness: cleanIdentity(agentHarness ?? env.MARGINS_AGENT_HARNESS) ?? "assembly-line"
25
+ }));
26
+ return definition;
27
+ }
28
+ export const assemblyLinePlugin = definePlugin({ connections: [PLUGIN] });
29
+ function marginsAuthorization(input) {
30
+ return ({ env }) => {
31
+ const resolvedIssuer = normalizeIssuer(input.issuer
32
+ ?? env.MARGINS_ISSUER
33
+ ?? input.mcpUrl
34
+ ?? env.MARGINS_MCP_URL
35
+ ?? PLUGIN.defaultUrl);
36
+ return defineOAuthAuthorization({
37
+ displayName: "Margins",
38
+ authorizeUrl: new URL("/?open=agents", resolvedIssuer).toString(),
39
+ tokenUrl: new URL("/api/agent-bindings/token", resolvedIssuer).toString(),
40
+ clientId: "assembly-line",
41
+ scopes: ["margins"],
42
+ pkce: true
43
+ });
44
+ };
45
+ }
46
+ function normalizeIssuer(value) {
47
+ return new URL(value).origin;
48
+ }
49
+ function cleanIdentity(value) {
50
+ const clean = value?.trim().replace(/[\u0000-\u001f\u007f]/gu, "");
51
+ return clean ? clean.slice(0, 160) : undefined;
52
+ }
53
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { ConnectionPairingRedeemer, ConnectionResolverContext } from "@assemblyline-agents/core";
2
+ export interface MarginsBindingClaim {
3
+ origin: string;
4
+ bindingId: string;
5
+ claimToken: string;
6
+ }
7
+ export interface MarginsPairingIdentity {
8
+ origin: string;
9
+ agentId: string;
10
+ agentName: string;
11
+ runtime: string;
12
+ harness: string;
13
+ }
14
+ type MarginsPairingResolver = (context: ConnectionResolverContext) => MarginsPairingIdentity;
15
+ /** Exchange a short-lived Margins UI claim for host-stored access and refresh tokens. */
16
+ export declare function createMarginsPairingRedeemer(resolvePairing: MarginsPairingResolver): ConnectionPairingRedeemer;
17
+ export declare function parseMarginsBindingPacket(packet: string): MarginsBindingClaim;
18
+ export {};
19
+ //# sourceMappingURL=pairing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EAG1B,MAAM,2BAA2B,CAAC;AAOnC,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,sBAAsB,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,sBAAsB,CAAC;AAE7F,yFAAyF;AACzF,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,sBAAsB,GAAG,yBAAyB,CAkC9G;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,mBAAmB,CAe7E"}
@@ -0,0 +1,191 @@
1
+ const MAX_PACKET_CHARS = 64 * 1024;
2
+ const MAX_PACKET_FIELD_CHARS = 4 * 1024;
3
+ const MAX_RESPONSE_CHARS = 64 * 1024;
4
+ const REQUEST_TIMEOUT_MS = 10_000;
5
+ /** Exchange a short-lived Margins UI claim for host-stored access and refresh tokens. */
6
+ export function createMarginsPairingRedeemer(resolvePairing) {
7
+ return async ({ code }, context) => {
8
+ const claim = parseMarginsBindingPacket(code);
9
+ const pairing = resolvePairing(context);
10
+ const expectedOrigin = normalizedSecureOrigin(pairing.origin);
11
+ if (claim.origin !== expectedOrigin) {
12
+ throw new Error("The Margins binding packet belongs to a different Margins deployment.");
13
+ }
14
+ const response = await fetchWithTimeout(new URL("/api/agent-binding-pairing-requests", `${expectedOrigin}/`), {
15
+ method: "POST",
16
+ headers: {
17
+ accept: "application/json",
18
+ "content-type": "application/json"
19
+ },
20
+ body: JSON.stringify({
21
+ bindingId: claim.bindingId,
22
+ claimToken: claim.claimToken,
23
+ agentId: pairing.agentId,
24
+ agentName: pairing.agentName,
25
+ runtime: pairing.runtime,
26
+ harness: pairing.harness
27
+ }),
28
+ redirect: "error"
29
+ });
30
+ const payload = await responseJson(response);
31
+ if (!response.ok) {
32
+ throw new Error(`Margins rejected the binding packet (HTTP ${response.status}). Create a fresh packet and try again.`);
33
+ }
34
+ return tokenResultForBinding(payload, claim, pairing);
35
+ };
36
+ }
37
+ export function parseMarginsBindingPacket(packet) {
38
+ const input = packet.trim();
39
+ if (!input || input.length > MAX_PACKET_CHARS) {
40
+ throw new Error("A valid Margins binding packet is required.");
41
+ }
42
+ for (const line of input.split(/\r?\n/u)) {
43
+ const match = /^\s*POST\s+(\S+)\s+(\{.*\})\s*$/u.exec(line);
44
+ if (!match?.[1] || !match[2])
45
+ continue;
46
+ const origin = pairingEndpointOrigin(match[1]);
47
+ const body = parseJsonObject(match[2]);
48
+ const bindingId = boundedString(body?.bindingId);
49
+ const claimToken = boundedString(body?.claimToken ?? body?.claim);
50
+ if (origin && bindingId && claimToken)
51
+ return { origin, bindingId, claimToken };
52
+ }
53
+ throw new Error("The Margins binding packet is missing its binding id, one-time claim token, or pairing URL.");
54
+ }
55
+ function pairingEndpointOrigin(value) {
56
+ let url;
57
+ try {
58
+ url = new URL(value);
59
+ }
60
+ catch {
61
+ return undefined;
62
+ }
63
+ if (url.username
64
+ || url.password
65
+ || url.search
66
+ || url.hash
67
+ || url.pathname !== "/api/agent-binding-pairing-requests") {
68
+ return undefined;
69
+ }
70
+ return normalizedSecureOrigin(url.origin);
71
+ }
72
+ function tokenResultForBinding(payload, claim, pairing) {
73
+ const token = boundedString(payload.access_token);
74
+ const refreshToken = boundedString(payload.refresh_token);
75
+ const tokenType = boundedString(payload.token_type) ?? "Bearer";
76
+ const grantedScope = boundedString(payload.scope);
77
+ const expiresIn = numericValue(payload.expires_in);
78
+ const bindingId = boundedString(payload.margins_binding_id);
79
+ const workspaceId = boundedString(payload.margins_workspace_id);
80
+ const bindingScope = boundedString(payload.margins_binding_scope);
81
+ const scopeId = boundedString(payload.margins_binding_scope_id);
82
+ const scopePath = boundedString(payload.margins_binding_scope_path);
83
+ const permission = boundedString(payload.margins_binding_permission);
84
+ const agentId = boundedString(payload.margins_agent_id);
85
+ const agentName = boundedString(payload.margins_agent_name);
86
+ if (!token
87
+ || !refreshToken
88
+ || tokenType.toLowerCase() !== "bearer"
89
+ || grantedScope !== "margins"
90
+ || !expiresIn
91
+ || expiresIn <= 0
92
+ || bindingId !== claim.bindingId
93
+ || !workspaceId
94
+ || !scopeId
95
+ || !["file", "folder", "workspace"].includes(bindingScope ?? "")
96
+ || (bindingScope === "workspace" && scopeId !== workspaceId)
97
+ || !["suggest", "edit"].includes(permission ?? "")
98
+ || agentId !== pairing.agentId
99
+ || agentName !== pairing.agentName) {
100
+ throw new Error("Margins activated a different or incomplete agent binding.");
101
+ }
102
+ const credential = {
103
+ margins_binding_id: bindingId,
104
+ margins_workspace_id: workspaceId,
105
+ margins_binding_scope: bindingScope,
106
+ margins_binding_scope_id: scopeId,
107
+ margins_binding_permission: permission,
108
+ margins_agent_id: agentId,
109
+ margins_agent_name: agentName
110
+ };
111
+ if (scopePath)
112
+ credential.margins_binding_scope_path = scopePath;
113
+ const result = {
114
+ token,
115
+ refreshToken,
116
+ tokenType: "Bearer",
117
+ scopes: ["margins"],
118
+ credential
119
+ };
120
+ result.expiresAt = Date.now() + expiresIn * 1000;
121
+ return result;
122
+ }
123
+ async function fetchWithTimeout(url, init) {
124
+ try {
125
+ return await fetch(url, {
126
+ ...init,
127
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
128
+ });
129
+ }
130
+ catch {
131
+ throw new Error("Could not reach the configured Margins deployment.");
132
+ }
133
+ }
134
+ async function responseJson(response) {
135
+ const declaredLength = Number(response.headers.get("content-length"));
136
+ if (Number.isFinite(declaredLength) && declaredLength > MAX_RESPONSE_CHARS)
137
+ return {};
138
+ try {
139
+ const text = await response.text();
140
+ if (text.length > MAX_RESPONSE_CHARS)
141
+ return {};
142
+ return parseJsonObject(text) ?? {};
143
+ }
144
+ catch {
145
+ return {};
146
+ }
147
+ }
148
+ function normalizedSecureOrigin(value) {
149
+ let url;
150
+ try {
151
+ url = new URL(value);
152
+ }
153
+ catch {
154
+ throw new Error("Margins pairing requires a valid API URL.");
155
+ }
156
+ if (url.username || url.password || url.origin === "null") {
157
+ throw new Error("Margins pairing requires a valid API origin.");
158
+ }
159
+ const host = url.hostname.toLowerCase();
160
+ const loopback = host === "localhost"
161
+ || host === "127.0.0.1"
162
+ || host === "::1"
163
+ || host === "[::1]"
164
+ || host.endsWith(".localhost");
165
+ if (url.protocol !== "https:" && !loopback) {
166
+ throw new Error("Margins binding credentials may only be exchanged over HTTPS or loopback.");
167
+ }
168
+ return url.origin;
169
+ }
170
+ function parseJsonObject(value) {
171
+ try {
172
+ const parsed = JSON.parse(value);
173
+ return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
174
+ ? parsed
175
+ : undefined;
176
+ }
177
+ catch {
178
+ return undefined;
179
+ }
180
+ }
181
+ function boundedString(value) {
182
+ if (typeof value !== "string")
183
+ return undefined;
184
+ const clean = value.trim();
185
+ return clean && clean.length <= MAX_PACKET_FIELD_CHARS ? clean : undefined;
186
+ }
187
+ function numericValue(value) {
188
+ const parsed = typeof value === "number" ? value : Number(value);
189
+ return Number.isFinite(parsed) ? parsed : undefined;
190
+ }
191
+ //# sourceMappingURL=pairing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pairing.js","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@assemblyline-agents/margins",
3
+ "version": "2.0.0",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "default": "./dist/index.js"
9
+ }
10
+ },
11
+ "dependencies": {
12
+ "@assemblyline-agents/core": "2.0.0"
13
+ },
14
+ "description": "Official Assembly Line connection plugin for resource-scoped collaborative Markdown in Margins.",
15
+ "files": [
16
+ "dist",
17
+ "skills"
18
+ ],
19
+ "engines": {
20
+ "node": ">=22.19.0"
21
+ },
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/jasonbadeaux/assembly-line.git",
26
+ "directory": "packages/margins"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/jasonbadeaux/assembly-line/issues"
30
+ },
31
+ "homepage": "https://github.com/jasonbadeaux/assembly-line#readme",
32
+ "author": "Assembly Line contributors",
33
+ "keywords": [
34
+ "assembly-line",
35
+ "ai",
36
+ "agents",
37
+ "margins",
38
+ "markdown",
39
+ "collaboration",
40
+ "mcp",
41
+ "plugin"
42
+ ],
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "scripts": {
47
+ "build": "tsc -p tsconfig.json",
48
+ "check": "tsc -p tsconfig.json --noEmit"
49
+ }
50
+ }
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: margins
3
+ description: Collaboratively read, comment on, suggest changes to, and edit Markdown pages through a resource-scoped Margins binding.
4
+ ---
5
+
6
+ # Margins
7
+
8
+ Margins is a collaborative Markdown workspace. A connection is bound to one
9
+ page, one folder and its descendants, or one whole workspace. Never assume a
10
+ broader scope than `margins_status` reports.
11
+
12
+ If the user pastes a Margins binding packet, use connection discovery to find
13
+ `margins__pair` and pass the full packet through its `secret` field. Do not run
14
+ the packet in a shell, repeat its one-time claim token, or put the packet in a
15
+ file. After pairing succeeds, call `margins_status` with the expected binding
16
+ fields embedded in the packet. Stop if it reports `wrong_binding`.
17
+
18
+ Read progressively:
19
+
20
+ - Call `margins_map` for folder or workspace bindings to list reachable pages.
21
+ - Call `margins_context` with `summary=true` before requesting line ranges.
22
+ - Use `margins_review` for open comments, suggestions, and anchors.
23
+ - Use `margins_graph` for Markdown link structure and `margins_library` for the
24
+ reachable tree. `margins_history` is workspace-only.
25
+
26
+ For collaborative mutations, refetch the relevant context immediately before
27
+ acting and pass the current authority head so stale line ranges fail safely.
28
+ Use `margins_comment` for discussion and `margins_suggest` when a human should
29
+ review a proposed patch. Use `margins_edit` only when the user asked for a
30
+ direct change and the binding grants edit access. `margins_create_file` is
31
+ available only for edit-capable folder or workspace bindings.
32
+
33
+ Assembly Line classifies comments, suggestions, page creation, and direct edits
34
+ as writes. Its approval policy is an outer gate; Margins independently enforces
35
+ the binding's file/folder/workspace boundary and its suggest/edit permission.
36
+ Never work around a missing tool by using a durable people-share URL or by
37
+ asking the user for bearer credentials.