@assemblyline-agents/mirror 0.1.0 → 1.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/README.md +16 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/pairing.d.ts +18 -0
- package/dist/pairing.d.ts.map +1 -0
- package/dist/pairing.js +280 -0
- package/dist/pairing.js.map +1 -0
- package/package.json +8 -8
- package/skills/mirror/SKILL.md +6 -0
package/README.md
CHANGED
|
@@ -16,13 +16,9 @@ Mirror accepts Assembly Line's OAuth Authorization Code flow with mandatory PKCE
|
|
|
16
16
|
S256. The normal callback is:
|
|
17
17
|
|
|
18
18
|
```text
|
|
19
|
-
https://YOUR-AGENT-HOST/
|
|
19
|
+
https://YOUR-AGENT-HOST/assembly-line/connections/callback
|
|
20
20
|
```
|
|
21
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
22
|
The hosted service and MCP endpoint are used by default. Self-hosted
|
|
27
23
|
deployments can set `MIRROR_MCP_URL` and, when OAuth is on a different origin,
|
|
28
24
|
`MIRROR_OAUTH_ISSUER`. `MIRROR_OAUTH_REDIRECT_URI` overrides Assembly Line's normal
|
|
@@ -32,6 +28,21 @@ callback only when necessary.
|
|
|
32
28
|
assembly-line add mirror agent
|
|
33
29
|
```
|
|
34
30
|
|
|
31
|
+
## Scoped binding packets
|
|
32
|
+
|
|
33
|
+
For least-privilege setup, create an agent binding in Mirror's Agents UI,
|
|
34
|
+
choose the exact provider accounts it may reach, and paste the generated
|
|
35
|
+
binding packet into the agent's chat. Assembly Line advertises a host-side
|
|
36
|
+
`mirror__pair` connection tool while Mirror is unauthorized. The tool sends
|
|
37
|
+
the packet's one-time claim secret only to the configured Mirror deployment,
|
|
38
|
+
stores the returned access and refresh tokens in the connection grant store,
|
|
39
|
+
and keeps the durable credentials out of the model and sandbox.
|
|
40
|
+
|
|
41
|
+
The packet's API origin must match `MIRROR_OAUTH_ISSUER`, `MIRROR_MCP_URL`, or
|
|
42
|
+
the connection's configured URL. Credential exchange requires HTTPS, except
|
|
43
|
+
for loopback development. OAuth remains available as an alternative account
|
|
44
|
+
authorization path.
|
|
45
|
+
|
|
35
46
|
The generated connection exposes Mirror reads and hides all write-like tools.
|
|
36
47
|
To permit approval creation, syncs, connection links, registration, or other
|
|
37
48
|
mutations, opt in with an Assembly Line approval policy:
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export interface MirrorConnectionOptions extends Omit<McpPluginConnectionOptions
|
|
|
15
15
|
clientId?: string;
|
|
16
16
|
/** Mirror authorization-server origin. Defaults to the MCP endpoint's origin. */
|
|
17
17
|
issuer?: string;
|
|
18
|
-
/** Override
|
|
18
|
+
/** Override the runtime's normal /assembly-line/connections/callback URI. */
|
|
19
19
|
redirectUri?: string;
|
|
20
20
|
/**
|
|
21
21
|
* Project the short-lived access token into a Mirror CLI profile.
|
|
@@ -25,5 +25,5 @@ export interface MirrorConnectionOptions extends Omit<McpPluginConnectionOptions
|
|
|
25
25
|
materializeCli?: boolean | MirrorCliMaterializationOptions;
|
|
26
26
|
}
|
|
27
27
|
export declare function defineMirrorConnection(options: MirrorConnectionOptions): import("@assemblyline-agents/core").McpHttpClientConnectionDefinition;
|
|
28
|
-
export declare const
|
|
28
|
+
export declare const assemblyLinePlugin: import("@assemblyline-agents/core").PluginModule;
|
|
29
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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,+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,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,+BAA+B,CAAC;CAC5D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,yEAwDtE;AAED,eAAO,MAAM,kBAAkB,kDAA0C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { connectionPluginMetadata, defineMcpPluginConnection, defineOAuthAuthorization, definePlugin } from "@assemblyline-agents/core";
|
|
2
|
+
import { createMirrorPairingRedeemer } from "./pairing.js";
|
|
2
3
|
const PLUGIN = connectionPluginMetadata("mirror");
|
|
3
4
|
export function defineMirrorConnection(options) {
|
|
4
5
|
const { auth, clientId, issuer, redirectUri, materializeCli, ...connection } = options;
|
|
@@ -13,6 +14,11 @@ export function defineMirrorConnection(options) {
|
|
|
13
14
|
...(connection.url ? { mcpUrl: connection.url } : {})
|
|
14
15
|
})
|
|
15
16
|
});
|
|
17
|
+
definition.redeemPairingCode = createMirrorPairingRedeemer(({ env }) => normalizeIssuer(issuer
|
|
18
|
+
?? env.MIRROR_OAUTH_ISSUER
|
|
19
|
+
?? connection.url
|
|
20
|
+
?? env.MIRROR_MCP_URL
|
|
21
|
+
?? definition.url));
|
|
16
22
|
if (materializeCli) {
|
|
17
23
|
const settings = materializeCli === true ? {} : materializeCli;
|
|
18
24
|
const profile = settings.profile?.trim() || "openeve";
|
|
@@ -41,7 +47,7 @@ export function defineMirrorConnection(options) {
|
|
|
41
47
|
}
|
|
42
48
|
return definition;
|
|
43
49
|
}
|
|
44
|
-
export const
|
|
50
|
+
export const assemblyLinePlugin = definePlugin({ connections: [PLUGIN] });
|
|
45
51
|
function mirrorOAuth(input) {
|
|
46
52
|
return ({ env }) => {
|
|
47
53
|
const resolvedClientId = input.clientId?.trim() || env.MIRROR_OAUTH_CLIENT_ID?.trim();
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,wBAAwB,EACxB,YAAY,EAGb,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ConnectionPairingRedeemer, ConnectionResolverContext } from "@assemblyline-agents/core";
|
|
2
|
+
interface MirrorBindingClaim {
|
|
3
|
+
origin: string;
|
|
4
|
+
userId: string;
|
|
5
|
+
bindingId: string;
|
|
6
|
+
claimToken: string;
|
|
7
|
+
runtime?: string;
|
|
8
|
+
}
|
|
9
|
+
type MirrorOriginResolver = (context: ConnectionResolverContext) => string;
|
|
10
|
+
/**
|
|
11
|
+
* Builds the host-side redeemer for a Mirror UI binding packet. The packet
|
|
12
|
+
* carries only a one-time claim secret. Mirror releases the durable access and
|
|
13
|
+
* refresh tokens directly to the OpenEve host after the claim is consumed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function createMirrorPairingRedeemer(resolveExpectedOrigin: MirrorOriginResolver): ConnectionPairingRedeemer;
|
|
16
|
+
export declare function parseMirrorBindingPacket(packet: string): MirrorBindingClaim;
|
|
17
|
+
export {};
|
|
18
|
+
//# 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;AAQnC,UAAU,kBAAkB;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,KAAK,oBAAoB,GAAG,CAAC,OAAO,EAAE,yBAAyB,KAAK,MAAM,CAAC;AAE3E;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,qBAAqB,EAAE,oBAAoB,GAAG,yBAAyB,CAqElH;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,CAa3E"}
|
package/dist/pairing.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const MAX_PACKET_CHARS = 64 * 1024;
|
|
2
|
+
const MAX_PACKET_FIELD_CHARS = 4 * 1024;
|
|
3
|
+
const REQUEST_TIMEOUT_MS = 10_000;
|
|
4
|
+
const PAIRING_WAIT_MS = 15_000;
|
|
5
|
+
const POLL_INTERVAL_MS = 250;
|
|
6
|
+
/**
|
|
7
|
+
* Builds the host-side redeemer for a Mirror UI binding packet. The packet
|
|
8
|
+
* carries only a one-time claim secret. Mirror releases the durable access and
|
|
9
|
+
* refresh tokens directly to the OpenEve host after the claim is consumed.
|
|
10
|
+
*/
|
|
11
|
+
export function createMirrorPairingRedeemer(resolveExpectedOrigin) {
|
|
12
|
+
return async ({ code }, context) => {
|
|
13
|
+
const claim = parseMirrorBindingPacket(code);
|
|
14
|
+
const expectedOrigin = normalizedSecureOrigin(resolveExpectedOrigin(context));
|
|
15
|
+
if (claim.origin !== expectedOrigin) {
|
|
16
|
+
throw new Error("The Mirror binding packet belongs to a different Mirror deployment.");
|
|
17
|
+
}
|
|
18
|
+
const createUrl = new URL(`/api/users/${encodeURIComponent(claim.userId)}/agent-binding-pairing-requests`, `${expectedOrigin}/`);
|
|
19
|
+
const created = await requestJson(createUrl, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
accept: "application/json",
|
|
23
|
+
"content-type": "application/json"
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
bindingId: claim.bindingId,
|
|
27
|
+
runtime: claim.runtime ?? "openeve",
|
|
28
|
+
harness: "openeve",
|
|
29
|
+
claimToken: claim.claimToken
|
|
30
|
+
})
|
|
31
|
+
}, "Mirror rejected the binding packet");
|
|
32
|
+
const requestId = boundedString(created.requestId);
|
|
33
|
+
const pollToken = boundedString(created.pollToken);
|
|
34
|
+
if (!requestId || !pollToken) {
|
|
35
|
+
throw new Error("Mirror accepted the binding packet without returning a pairing request.");
|
|
36
|
+
}
|
|
37
|
+
if (created.autoApproved !== true && created.status !== "approved") {
|
|
38
|
+
throw new Error("This Mirror binding packet requires separate approval. Create a fresh one-time packet in Mirror.");
|
|
39
|
+
}
|
|
40
|
+
const tokenUrl = new URL(`/api/users/${encodeURIComponent(claim.userId)}/agent-binding-pairing-requests/${encodeURIComponent(requestId)}/token`, `${expectedOrigin}/`);
|
|
41
|
+
const deadline = Math.min(parseDate(created.expiresAt) ?? Date.now() + PAIRING_WAIT_MS, Date.now() + PAIRING_WAIT_MS);
|
|
42
|
+
while (Date.now() < deadline) {
|
|
43
|
+
const response = await fetchWithTimeout(tokenUrl, {
|
|
44
|
+
method: "GET",
|
|
45
|
+
headers: {
|
|
46
|
+
accept: "application/json",
|
|
47
|
+
authorization: `Bearer ${pollToken}`
|
|
48
|
+
},
|
|
49
|
+
redirect: "error"
|
|
50
|
+
});
|
|
51
|
+
const payload = await responseJson(response);
|
|
52
|
+
if (response.status === 202) {
|
|
53
|
+
await wait(POLL_INTERVAL_MS);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`Mirror could not activate the binding packet (HTTP ${response.status}).`);
|
|
58
|
+
}
|
|
59
|
+
if (payload.status !== "approved") {
|
|
60
|
+
throw new Error("Mirror did not activate the binding packet.");
|
|
61
|
+
}
|
|
62
|
+
return tokenResultForBinding(payload, claim);
|
|
63
|
+
}
|
|
64
|
+
throw new Error("Timed out while Mirror activated the binding packet. Create a fresh packet and try again.");
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export function parseMirrorBindingPacket(packet) {
|
|
68
|
+
const input = packet.trim();
|
|
69
|
+
if (!input || input.length > MAX_PACKET_CHARS) {
|
|
70
|
+
throw new Error("A valid Mirror binding packet is required.");
|
|
71
|
+
}
|
|
72
|
+
const httpClaim = parseHttpClaim(input);
|
|
73
|
+
if (httpClaim)
|
|
74
|
+
return httpClaim;
|
|
75
|
+
const cliClaim = parseCliClaim(input);
|
|
76
|
+
if (cliClaim)
|
|
77
|
+
return cliClaim;
|
|
78
|
+
throw new Error("The Mirror binding packet is missing its binding id, one-time claim token, API URL, or user id.");
|
|
79
|
+
}
|
|
80
|
+
function parseHttpClaim(packet) {
|
|
81
|
+
for (const line of packet.split(/\r?\n/u)) {
|
|
82
|
+
const match = /^\s*POST\s+(\S+)\s+(\{.*\})\s*$/u.exec(line);
|
|
83
|
+
if (!match?.[1] || !match[2])
|
|
84
|
+
continue;
|
|
85
|
+
const endpoint = parsePairingEndpoint(match[1]);
|
|
86
|
+
if (!endpoint)
|
|
87
|
+
continue;
|
|
88
|
+
const body = parseJsonObject(match[2]);
|
|
89
|
+
if (!body)
|
|
90
|
+
continue;
|
|
91
|
+
const bindingId = boundedString(body.bindingId);
|
|
92
|
+
const claimToken = boundedString(body.claimToken ?? body.claim);
|
|
93
|
+
const runtime = boundedString(body.runtime);
|
|
94
|
+
if (!bindingId || !claimToken)
|
|
95
|
+
continue;
|
|
96
|
+
return {
|
|
97
|
+
origin: endpoint.origin,
|
|
98
|
+
userId: endpoint.userId,
|
|
99
|
+
bindingId,
|
|
100
|
+
claimToken,
|
|
101
|
+
...(runtime ? { runtime } : {})
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
function parseCliClaim(packet) {
|
|
107
|
+
for (const line of packet.split(/\r?\n/u)) {
|
|
108
|
+
const words = commandWords(line);
|
|
109
|
+
const bindIndex = words.indexOf("bind");
|
|
110
|
+
if (bindIndex < 0)
|
|
111
|
+
continue;
|
|
112
|
+
const args = words.slice(bindIndex + 1);
|
|
113
|
+
const bindingId = boundedString(flagValue(args, "binding"));
|
|
114
|
+
const claimToken = boundedString(flagValue(args, "claim") ?? flagValue(args, "claim-token"));
|
|
115
|
+
const apiUrl = boundedString(flagValue(args, "api") ?? flagValue(args, "api-url"));
|
|
116
|
+
const userId = boundedString(flagValue(args, "user"));
|
|
117
|
+
const runtime = boundedString(flagValue(args, "runtime"));
|
|
118
|
+
if (!bindingId || !claimToken || !apiUrl || !userId)
|
|
119
|
+
continue;
|
|
120
|
+
return {
|
|
121
|
+
origin: normalizedSecureOrigin(apiUrl),
|
|
122
|
+
userId,
|
|
123
|
+
bindingId,
|
|
124
|
+
claimToken,
|
|
125
|
+
...(runtime ? { runtime } : {})
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
function parsePairingEndpoint(value) {
|
|
131
|
+
let url;
|
|
132
|
+
try {
|
|
133
|
+
url = new URL(value);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (url.username || url.password || url.search || url.hash)
|
|
139
|
+
return null;
|
|
140
|
+
const match = /^\/api\/users\/([^/]+)\/agent-binding-pairing-requests\/?$/u.exec(url.pathname);
|
|
141
|
+
if (!match?.[1])
|
|
142
|
+
return null;
|
|
143
|
+
let userId;
|
|
144
|
+
try {
|
|
145
|
+
userId = decodeURIComponent(match[1]);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
if (!boundedString(userId))
|
|
151
|
+
return null;
|
|
152
|
+
return { origin: normalizedSecureOrigin(url.origin), userId };
|
|
153
|
+
}
|
|
154
|
+
function tokenResultForBinding(payload, claim) {
|
|
155
|
+
const binding = jsonObject(payload.binding);
|
|
156
|
+
const bindingId = boundedString(binding?.bindingId);
|
|
157
|
+
const token = boundedString(binding?.token);
|
|
158
|
+
const refreshToken = boundedString(binding?.refreshToken);
|
|
159
|
+
const branchId = boundedString(binding?.branchId) ?? "default";
|
|
160
|
+
if (!binding || !bindingId || bindingId !== claim.bindingId || !token) {
|
|
161
|
+
throw new Error("Mirror activated a different or incomplete agent binding.");
|
|
162
|
+
}
|
|
163
|
+
const result = {
|
|
164
|
+
token,
|
|
165
|
+
tokenType: "Bearer",
|
|
166
|
+
credential: {
|
|
167
|
+
mirror_user_id: claim.userId,
|
|
168
|
+
mirror_binding_id: bindingId,
|
|
169
|
+
mirror_branch_id: branchId
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
if (refreshToken)
|
|
173
|
+
result.refreshToken = refreshToken;
|
|
174
|
+
const expiresAt = parseDate(binding.expiresAt);
|
|
175
|
+
if (expiresAt)
|
|
176
|
+
result.expiresAt = expiresAt;
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
async function requestJson(url, init, failureMessage) {
|
|
180
|
+
const response = await fetchWithTimeout(url, { ...init, redirect: "error" });
|
|
181
|
+
const payload = await responseJson(response);
|
|
182
|
+
if (!response.ok) {
|
|
183
|
+
throw new Error(`${failureMessage} (HTTP ${response.status}).`);
|
|
184
|
+
}
|
|
185
|
+
return payload;
|
|
186
|
+
}
|
|
187
|
+
async function fetchWithTimeout(url, init) {
|
|
188
|
+
try {
|
|
189
|
+
return await fetch(url, {
|
|
190
|
+
...init,
|
|
191
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
throw new Error("Could not reach the configured Mirror deployment.");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async function responseJson(response) {
|
|
199
|
+
try {
|
|
200
|
+
const value = await response.json();
|
|
201
|
+
return jsonObject(value) ?? {};
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return {};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function normalizedSecureOrigin(value) {
|
|
208
|
+
let url;
|
|
209
|
+
try {
|
|
210
|
+
url = new URL(value);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
throw new Error("Mirror pairing requires a valid API URL.");
|
|
214
|
+
}
|
|
215
|
+
if (url.username || url.password || url.origin === "null") {
|
|
216
|
+
throw new Error("Mirror pairing requires a valid API origin.");
|
|
217
|
+
}
|
|
218
|
+
const host = url.hostname.toLowerCase();
|
|
219
|
+
const loopback = host === "localhost"
|
|
220
|
+
|| host === "127.0.0.1"
|
|
221
|
+
|| host === "::1"
|
|
222
|
+
|| host === "[::1]"
|
|
223
|
+
|| host.endsWith(".localhost");
|
|
224
|
+
if (url.protocol !== "https:" && !loopback) {
|
|
225
|
+
throw new Error("Mirror binding credentials may only be exchanged over HTTPS or loopback.");
|
|
226
|
+
}
|
|
227
|
+
return url.origin;
|
|
228
|
+
}
|
|
229
|
+
function commandWords(line) {
|
|
230
|
+
const words = [];
|
|
231
|
+
const expression = /"((?:\\.|[^"])*)"|'([^']*)'|([^\s]+)/gu;
|
|
232
|
+
for (const match of line.matchAll(expression)) {
|
|
233
|
+
const value = match[1] ?? match[2] ?? match[3];
|
|
234
|
+
if (value !== undefined)
|
|
235
|
+
words.push(value.replace(/\\(["\\])/gu, "$1"));
|
|
236
|
+
}
|
|
237
|
+
return words;
|
|
238
|
+
}
|
|
239
|
+
function flagValue(args, name) {
|
|
240
|
+
const flag = `--${name}`;
|
|
241
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
242
|
+
const value = args[index];
|
|
243
|
+
if (value === flag)
|
|
244
|
+
return args[index + 1];
|
|
245
|
+
if (value?.startsWith(`${flag}=`))
|
|
246
|
+
return value.slice(flag.length + 1);
|
|
247
|
+
}
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
250
|
+
function parseJsonObject(value) {
|
|
251
|
+
try {
|
|
252
|
+
return jsonObject(JSON.parse(value));
|
|
253
|
+
}
|
|
254
|
+
catch {
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function jsonObject(value) {
|
|
259
|
+
return value !== null && typeof value === "object" && !Array.isArray(value)
|
|
260
|
+
? value
|
|
261
|
+
: null;
|
|
262
|
+
}
|
|
263
|
+
function boundedString(value) {
|
|
264
|
+
if (typeof value !== "string")
|
|
265
|
+
return undefined;
|
|
266
|
+
const clean = value.trim();
|
|
267
|
+
return clean && clean.length <= MAX_PACKET_FIELD_CHARS ? clean : undefined;
|
|
268
|
+
}
|
|
269
|
+
function parseDate(value) {
|
|
270
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0)
|
|
271
|
+
return value;
|
|
272
|
+
if (typeof value !== "string")
|
|
273
|
+
return undefined;
|
|
274
|
+
const parsed = Date.parse(value);
|
|
275
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
276
|
+
}
|
|
277
|
+
function wait(ms) {
|
|
278
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
279
|
+
}
|
|
280
|
+
//# 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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assemblyline-agents/mirror",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@assemblyline-agents/core": "
|
|
12
|
+
"@assemblyline-agents/core": "1.0.0"
|
|
13
13
|
},
|
|
14
|
-
"description": "Official
|
|
14
|
+
"description": "Official Assembly Line connection plugin for user-scoped Mirror accounts.",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"skills"
|
|
@@ -22,16 +22,16 @@
|
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/jasonbadeaux/
|
|
25
|
+
"url": "git+https://github.com/jasonbadeaux/assembly-line.git",
|
|
26
26
|
"directory": "packages/mirror"
|
|
27
27
|
},
|
|
28
28
|
"bugs": {
|
|
29
|
-
"url": "https://github.com/jasonbadeaux/
|
|
29
|
+
"url": "https://github.com/jasonbadeaux/assembly-line/issues"
|
|
30
30
|
},
|
|
31
|
-
"homepage": "https://github.com/jasonbadeaux/
|
|
32
|
-
"author": "
|
|
31
|
+
"homepage": "https://github.com/jasonbadeaux/assembly-line#readme",
|
|
32
|
+
"author": "Assembly Line contributors",
|
|
33
33
|
"keywords": [
|
|
34
|
-
"
|
|
34
|
+
"assembly-line",
|
|
35
35
|
"ai",
|
|
36
36
|
"agents",
|
|
37
37
|
"mirror",
|
package/skills/mirror/SKILL.md
CHANGED
|
@@ -9,6 +9,12 @@ Mirror is the user's connected-context layer. It holds downstream provider
|
|
|
9
9
|
credentials and exposes only the providers and accounts granted to this agent.
|
|
10
10
|
Never ask for, print, or store raw provider credentials.
|
|
11
11
|
|
|
12
|
+
If the user pastes a Mirror binding packet, use connection discovery to find
|
|
13
|
+
`mirror__pair` and pass the full packet through its `secret` field. Do not run
|
|
14
|
+
the packet's shell command inside the model sandbox and do not repeat its
|
|
15
|
+
one-time claim token. After pairing succeeds, call `mirror.whoami` to verify
|
|
16
|
+
the binding's resolved scope.
|
|
17
|
+
|
|
12
18
|
Start with `mirror.whoami`, then `mirror.connected_providers`. Inspect each
|
|
13
19
|
lane's access and mirror policy before choosing a tool:
|
|
14
20
|
|