@assemblyline-agents/mirror 0.1.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,68 @@
1
+ # @assemblyline-agents/mirror
2
+
3
+ Official Assembly Line connection plugin for [Mirror](https://github.com/jasonbadeaux/mirror).
4
+ It gives each authenticated agent user an optional, separately authorized path
5
+ to their mirrored source records and connected accounts.
6
+
7
+ ## Setup
8
+
9
+ Choose a stable public client id for the agent deployment and set:
10
+
11
+ ```sh
12
+ MIRROR_OAUTH_CLIENT_ID=my-assembly-line-agent
13
+ ```
14
+
15
+ Mirror accepts Assembly Line's OAuth Authorization Code flow with mandatory PKCE
16
+ S256. The normal callback is:
17
+
18
+ ```text
19
+ https://YOUR-AGENT-HOST/openeve/connections/callback
20
+ ```
21
+
22
+ The runtime also serves `/assembly-line/connections/callback`; callback-URL
23
+ construction still emits the legacy `/openeve/...` path during the rename
24
+ compatibility window, so register the URI shown above until it flips.
25
+
26
+ The hosted service and MCP endpoint are used by default. Self-hosted
27
+ deployments can set `MIRROR_MCP_URL` and, when OAuth is on a different origin,
28
+ `MIRROR_OAUTH_ISSUER`. `MIRROR_OAUTH_REDIRECT_URI` overrides Assembly Line's normal
29
+ callback only when necessary.
30
+
31
+ ```sh
32
+ assembly-line add mirror agent
33
+ ```
34
+
35
+ The generated connection exposes Mirror reads and hides all write-like tools.
36
+ To permit approval creation, syncs, connection links, registration, or other
37
+ mutations, opt in with an Assembly Line approval policy:
38
+
39
+ ```ts
40
+ import { defineMirrorConnection } from "@assemblyline-agents/mirror";
41
+
42
+ export default defineMirrorConnection({
43
+ access: {
44
+ read: true,
45
+ write: { approval: "always" }
46
+ }
47
+ });
48
+ ```
49
+
50
+ Mirror still enforces its own account grants and exact-action approval system;
51
+ Assembly Line's approval is an additional outer gate.
52
+
53
+ ## Optional Mirror CLI
54
+
55
+ The MCP connection is the default and works without a CLI. If the sandbox
56
+ image already contains the `mirror` executable, opt in to a short-lived CLI
57
+ profile:
58
+
59
+ ```ts
60
+ export default defineMirrorConnection({
61
+ materializeCli: true,
62
+ access: { read: true, write: false }
63
+ });
64
+ ```
65
+
66
+ Assembly Line writes `/root/.mirror/config.json` with mode `0600`. Only the current
67
+ access token is projected. The rotating refresh token stays in the host-side
68
+ grant store and is never written into the sandbox.
@@ -0,0 +1,29 @@
1
+ import { type ConnectionAuthDefinition, type McpPluginConnectionOptions } from "@assemblyline-agents/core";
2
+ export interface MirrorCliMaterializationOptions {
3
+ /** Sandbox path for the projected CLI profile. Defaults to /root/.mirror/config.json. */
4
+ path?: string;
5
+ /** Mirror CLI profile name. Defaults to openeve. */
6
+ profile?: string;
7
+ /** Runtime recorded in the projected profile. Defaults to openeve. */
8
+ runtime?: string;
9
+ /** Mirror API origin. Defaults to the configured MCP endpoint's origin. */
10
+ apiUrl?: string;
11
+ }
12
+ export interface MirrorConnectionOptions extends Omit<McpPluginConnectionOptions, "auth"> {
13
+ auth?: ConnectionAuthDefinition | false;
14
+ /** Stable public OAuth client id shown on Mirror's consent screen. */
15
+ clientId?: string;
16
+ /** Mirror authorization-server origin. Defaults to the MCP endpoint's origin. */
17
+ issuer?: string;
18
+ /** Override OpenEve's normal /openeve/connections/callback URI. */
19
+ redirectUri?: string;
20
+ /**
21
+ * Project the short-lived access token into a Mirror CLI profile.
22
+ * The sandbox image must already contain the `mirror` CLI. Refresh tokens
23
+ * always remain in OpenEve's host-side grant store.
24
+ */
25
+ materializeCli?: boolean | MirrorCliMaterializationOptions;
26
+ }
27
+ export declare function defineMirrorConnection(options: MirrorConnectionOptions): import("@assemblyline-agents/core").McpHttpClientConnectionDefinition;
28
+ export declare const openevePlugin: import("@assemblyline-agents/core").PluginModule;
29
+ //# 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;AAInC,MAAM,WAAW,+BAA+B;IAC9C,yFAAyF;IACzF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,uBAAwB,SAAQ,IAAI,CAAC,0BAA0B,EAAE,MAAM,CAAC;IACvF,IAAI,CAAC,EAAE,wBAAwB,GAAG,KAAK,CAAC;IACxC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,+BAA+B,CAAC;CAC5D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,yEAiDtE;AAED,eAAO,MAAM,aAAa,kDAA0C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,71 @@
1
+ import { connectionPluginMetadata, defineMcpPluginConnection, defineOAuthAuthorization, definePlugin } from "@assemblyline-agents/core";
2
+ const PLUGIN = connectionPluginMetadata("mirror");
3
+ export function defineMirrorConnection(options) {
4
+ const { auth, clientId, issuer, redirectUri, materializeCli, ...connection } = options;
5
+ const definition = defineMcpPluginConnection(PLUGIN, {
6
+ ...connection,
7
+ auth: auth === false
8
+ ? false
9
+ : auth ?? mirrorOAuth({
10
+ ...(clientId ? { clientId } : {}),
11
+ ...(issuer ? { issuer } : {}),
12
+ ...(redirectUri ? { redirectUri } : {}),
13
+ ...(connection.url ? { mcpUrl: connection.url } : {})
14
+ })
15
+ });
16
+ if (materializeCli) {
17
+ const settings = materializeCli === true ? {} : materializeCli;
18
+ const profile = settings.profile?.trim() || "openeve";
19
+ const runtime = settings.runtime?.trim() || "openeve";
20
+ const apiUrl = normalizeIssuer(settings.apiUrl ?? issuer ?? definition.url);
21
+ definition.materialize = {
22
+ files: [{
23
+ path: settings.path?.trim() || "/root/.mirror/config.json",
24
+ content: `${JSON.stringify({
25
+ version: 1,
26
+ currentProfile: profile,
27
+ profiles: {
28
+ [profile]: {
29
+ apiUrl,
30
+ userId: "{{credential.mirror_user_id}}",
31
+ branchId: "{{credential.mirror_branch_id}}",
32
+ bindingId: "{{credential.mirror_binding_id}}",
33
+ bindingToken: "{{token}}",
34
+ runtime
35
+ }
36
+ }
37
+ }, null, 2)}\n`,
38
+ mode: 0o600
39
+ }]
40
+ };
41
+ }
42
+ return definition;
43
+ }
44
+ export const openevePlugin = definePlugin({ connections: [PLUGIN] });
45
+ function mirrorOAuth(input) {
46
+ return ({ env }) => {
47
+ const resolvedClientId = input.clientId?.trim() || env.MIRROR_OAUTH_CLIENT_ID?.trim();
48
+ if (!resolvedClientId) {
49
+ throw new Error("Mirror OAuth requires MIRROR_OAUTH_CLIENT_ID or clientId.");
50
+ }
51
+ const resolvedIssuer = normalizeIssuer(input.issuer
52
+ ?? env.MIRROR_OAUTH_ISSUER
53
+ ?? input.mcpUrl
54
+ ?? env.MIRROR_MCP_URL
55
+ ?? PLUGIN.defaultUrl);
56
+ const resolvedRedirectUri = input.redirectUri?.trim() || env.MIRROR_OAUTH_REDIRECT_URI?.trim();
57
+ return defineOAuthAuthorization({
58
+ displayName: "Mirror",
59
+ authorizeUrl: new URL("/oauth/authorize", resolvedIssuer).toString(),
60
+ tokenUrl: new URL("/oauth/token", resolvedIssuer).toString(),
61
+ clientId: resolvedClientId,
62
+ ...(resolvedRedirectUri ? { redirectUri: resolvedRedirectUri } : {}),
63
+ pkce: true
64
+ });
65
+ };
66
+ }
67
+ function normalizeIssuer(value) {
68
+ const url = new URL(value);
69
+ return url.origin;
70
+ }
71
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@assemblyline-agents/mirror",
3
+ "version": "0.1.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": "0.1.0"
13
+ },
14
+ "description": "Official OpenEve connection plugin for user-scoped Mirror accounts.",
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/openeve.git",
26
+ "directory": "packages/mirror"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/jasonbadeaux/openeve/issues"
30
+ },
31
+ "homepage": "https://github.com/jasonbadeaux/openeve#readme",
32
+ "author": "OpenEve contributors",
33
+ "keywords": [
34
+ "openeve",
35
+ "ai",
36
+ "agents",
37
+ "mirror",
38
+ "mcp",
39
+ "oauth",
40
+ "connected-accounts",
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,34 @@
1
+ ---
2
+ name: mirror
3
+ description: Use a connected Mirror account to inspect the user's allowed connected providers, query mirrored records, perform bounded live reads, and stage approval-gated actions.
4
+ ---
5
+
6
+ # Mirror
7
+
8
+ Mirror is the user's connected-context layer. It holds downstream provider
9
+ credentials and exposes only the providers and accounts granted to this agent.
10
+ Never ask for, print, or store raw provider credentials.
11
+
12
+ Start with `mirror.whoami`, then `mirror.connected_providers`. Inspect each
13
+ lane's access and mirror policy before choosing a tool:
14
+
15
+ - Use `mirror.query_records` for normal recall from a mirrored lane.
16
+ - Use `mirror.get_source` for one exact raw record.
17
+ - Use `mirror.live_read` only for current state or detail absent from the
18
+ mirror.
19
+ - Use `mirror.get_pending_approvals` to inspect unresolved action requests.
20
+
21
+ Keep reads bounded by provider, account, identifiers, dates, and explicit
22
+ limits. Check message authorship metadata rather than inferring who wrote a
23
+ message from its prose.
24
+
25
+ Write-like provider operations, syncs, setup links, agent registration,
26
+ approval creation/redemption, and credential export are classified as writes
27
+ by Assembly Line. Use them only when the connection exposes write authority and its
28
+ approval gate permits the call. Mirror may apply an additional exact-action
29
+ approval before executing a downstream mutation.
30
+
31
+ The MCP tools are the normal Assembly Line connection surface. If the deployment
32
+ owner installed the optional `mirror` CLI and enabled `materializeCli`, the CLI
33
+ may be used inside the sandbox; its profile contains only a short-lived access
34
+ token. Refresh credentials remain on the Assembly Line host.