@masons/agent-network 0.6.24 → 0.6.25
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/dist/channel-setup.d.ts +2 -1
- package/dist/channel-setup.d.ts.map +1 -1
- package/dist/channel-setup.js +144 -74
- package/dist/connector-client.d.ts.map +1 -1
- package/dist/connector-client.js +4 -2
- package/dist/handoff.d.ts +13 -0
- package/dist/handoff.d.ts.map +1 -1
- package/dist/handoff.js +42 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +6 -4
- package/dist/tools.d.ts +0 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +31 -35
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/skills/agent-network/SKILL.md +9 -10
package/dist/channel-setup.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ interface StartChannelSetupOptions {
|
|
|
4
4
|
idpBaseUrl: string;
|
|
5
5
|
idpBaseUrlIsDefault?: boolean;
|
|
6
6
|
invitedBy?: string;
|
|
7
|
+
startOver?: boolean;
|
|
7
8
|
}
|
|
8
9
|
export interface ChannelSetupResult {
|
|
9
10
|
status: "pending" | "completed" | "expired" | "failed";
|
|
@@ -14,7 +15,7 @@ export interface ChannelSetupResult {
|
|
|
14
15
|
export declare function getDefaultChannelSetupOptions(): StartChannelSetupOptions;
|
|
15
16
|
export declare function startOrGetChannelSetup(options: StartChannelSetupOptions): Promise<ChannelSetupResult>;
|
|
16
17
|
export declare function getChannelSetupStatus(): ChannelSetupResult | null;
|
|
17
|
-
export declare function
|
|
18
|
+
export declare function getReportableSetupStatus(): ChannelSetupResult | null;
|
|
18
19
|
export declare function _resetChannelSetupForTesting(): void;
|
|
19
20
|
export declare const CHANNEL_SETUP_TTL_MS: number;
|
|
20
21
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-setup.d.ts","sourceRoot":"","sources":["../src/channel-setup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"channel-setup.d.ts","sourceRoot":"","sources":["../src/channel-setup.ts"],"names":[],"mappings":"AAkBA,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IAEnB,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAM9B,SAAS,CAAC,EAAE,MAAM,CAAC;IAOnB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AA4CD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,QAAQ,CAAC;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAuBD,wBAAgB,6BAA6B,IAAI,wBAAwB,CAKxE;AAWD,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAkB7B;AAOD,wBAAgB,qBAAqB,IAAI,kBAAkB,GAAG,IAAI,CAQjE;AAaD,wBAAgB,wBAAwB,IAAI,kBAAkB,GAAG,IAAI,CAOpE;AAgOD,wBAAgB,4BAA4B,IAAI,IAAI,CAInD;AAED,eAAO,MAAM,oBAAoB,QAAqB,CAAC"}
|
package/dist/channel-setup.js
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
import createDebug from "debug";
|
|
2
2
|
import { readExistingConnectorUrl } from "./config.js";
|
|
3
3
|
import { resolveConnectorUrlForSetup } from "./connector-url-boundary.js";
|
|
4
|
-
import { beginBridgeHandoff, completeBridgeHandoff, DEFAULT_IDP_BASE_URL, HANDOFF_TIMEOUT_MS, SetupFlowError, } from "./handoff.js";
|
|
4
|
+
import { beginBridgeHandoff, collectBridgeHandoffOnce, completeBridgeHandoff, DEFAULT_IDP_BASE_URL, HANDOFF_TIMEOUT_MS, SetupFlowError, } from "./handoff.js";
|
|
5
5
|
import { acceptBridgeHandoff } from "./handoff-acceptance.js";
|
|
6
6
|
import { DEFAULT_API_HOST } from "./platform-client.js";
|
|
7
7
|
const dbg = createDebug("agent-network:channel-setup");
|
|
8
|
+
const GENERIC_EXPIRY_MESSAGE = "The previous Link URL expired before the browser handoff completed.";
|
|
9
|
+
const GONE_MESSAGE = "That Link session is no longer on the handoff bridge — it expired, or its runtime key was already delivered — so it cannot complete.";
|
|
10
|
+
const SUPERSEDED_MESSAGE = "A newer Link session replaced this one while it was completing, so the runtime key that session delivered was discarded. Nothing changed — this runtime still uses the credential it had before.";
|
|
8
11
|
let pendingSetup = null;
|
|
9
12
|
let lastSetupStatus = null;
|
|
13
|
+
let setupSeq = 0;
|
|
14
|
+
let lastRecordedSeq = 0;
|
|
10
15
|
export function getDefaultChannelSetupOptions() {
|
|
11
16
|
return {
|
|
12
17
|
apiHost: DEFAULT_API_HOST,
|
|
@@ -14,50 +19,26 @@ export function getDefaultChannelSetupOptions() {
|
|
|
14
19
|
};
|
|
15
20
|
}
|
|
16
21
|
export async function startOrGetChannelSetup(options) {
|
|
22
|
+
if (options.startOver)
|
|
23
|
+
return await startNewSession(options);
|
|
17
24
|
const active = getActivePendingSetup();
|
|
18
25
|
if (active) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
expiresAt: active.session.expiresAt,
|
|
23
|
-
};
|
|
26
|
+
const collected = await collectActiveSetup(active);
|
|
27
|
+
if (collected)
|
|
28
|
+
return collected;
|
|
24
29
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const session = await beginBridgeHandoff({
|
|
33
|
-
apiHost: options.apiHost,
|
|
34
|
-
idpBaseUrl: options.idpBaseUrl,
|
|
35
|
-
idpBaseUrlIsDefault: options.idpBaseUrlIsDefault,
|
|
36
|
-
});
|
|
37
|
-
const record = {
|
|
38
|
-
session,
|
|
39
|
-
apiHost: options.apiHost,
|
|
40
|
-
connectorUrl,
|
|
41
|
-
idpBaseUrl: options.idpBaseUrl,
|
|
42
|
-
invitedBy: options.invitedBy,
|
|
43
|
-
};
|
|
44
|
-
pendingSetup = record;
|
|
45
|
-
void completePendingSetup(record);
|
|
46
|
-
return {
|
|
47
|
-
status: "pending",
|
|
48
|
-
handoffUrl: session.handoffUrl,
|
|
49
|
-
expiresAt: session.expiresAt,
|
|
50
|
-
};
|
|
30
|
+
const reportable = getReportableSetupStatus();
|
|
31
|
+
if (reportable)
|
|
32
|
+
return reportable;
|
|
33
|
+
const live = getActivePendingSetup();
|
|
34
|
+
if (live)
|
|
35
|
+
return pendingResult(live);
|
|
36
|
+
return await startNewSession(options);
|
|
51
37
|
}
|
|
52
38
|
export function getChannelSetupStatus() {
|
|
53
39
|
const active = getActivePendingSetup();
|
|
54
|
-
if (active)
|
|
55
|
-
return
|
|
56
|
-
status: "pending",
|
|
57
|
-
handoffUrl: active.session.handoffUrl,
|
|
58
|
-
expiresAt: active.session.expiresAt,
|
|
59
|
-
};
|
|
60
|
-
}
|
|
40
|
+
if (active)
|
|
41
|
+
return pendingResult(active);
|
|
61
42
|
if (!lastSetupStatus)
|
|
62
43
|
return null;
|
|
63
44
|
return {
|
|
@@ -65,31 +46,76 @@ export function getChannelSetupStatus() {
|
|
|
65
46
|
message: lastSetupStatus.message,
|
|
66
47
|
};
|
|
67
48
|
}
|
|
68
|
-
export function
|
|
69
|
-
const
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
49
|
+
export function getReportableSetupStatus() {
|
|
50
|
+
const recorded = lastSetupStatus;
|
|
51
|
+
if (!recorded)
|
|
52
|
+
return null;
|
|
53
|
+
if (pendingSetup?.seq === recorded.seq)
|
|
54
|
+
return null;
|
|
55
|
+
if (recorded.status === "completed")
|
|
56
|
+
return reportStatus(recorded);
|
|
57
|
+
if (!recorded.reported)
|
|
58
|
+
return reportStatus(recorded);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function pendingResult(record) {
|
|
62
|
+
return {
|
|
63
|
+
status: "pending",
|
|
64
|
+
handoffUrl: record.session.handoffUrl,
|
|
65
|
+
expiresAt: record.session.expiresAt,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function reportStatus(status) {
|
|
69
|
+
status.reported = true;
|
|
70
|
+
return { status: status.status, message: status.message };
|
|
71
|
+
}
|
|
72
|
+
function storedResult(stored) {
|
|
73
|
+
return stored ? reportStatus(stored) : null;
|
|
74
74
|
}
|
|
75
75
|
function getActivePendingSetup() {
|
|
76
76
|
if (!pendingSetup)
|
|
77
77
|
return null;
|
|
78
78
|
if (Date.now() < pendingSetup.session.expiresAt)
|
|
79
79
|
return pendingSetup;
|
|
80
|
-
|
|
81
|
-
status: "expired",
|
|
82
|
-
message: "The previous Link URL expired before the browser handoff completed.",
|
|
83
|
-
finishedAt: Date.now(),
|
|
84
|
-
};
|
|
80
|
+
const lapsed = pendingSetup;
|
|
85
81
|
pendingSetup = null;
|
|
82
|
+
recordSetupStatus(lapsed, "expired", GENERIC_EXPIRY_MESSAGE, false);
|
|
86
83
|
return null;
|
|
87
84
|
}
|
|
88
|
-
async function
|
|
85
|
+
async function collectActiveSetup(record) {
|
|
86
|
+
let collection;
|
|
87
|
+
try {
|
|
88
|
+
collection = await collectBridgeHandoffOnce(record.session);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
dbg("owner-invoked collection could not reach the bridge: %O", err);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
switch (collection.outcome) {
|
|
95
|
+
case "delivered":
|
|
96
|
+
return storedResult(await acceptCollectedHandoff(record, collection.handoff));
|
|
97
|
+
case "spoiled":
|
|
98
|
+
return storedResult(settle(record, isExpiryError(collection.error) ? "expired" : "failed", collection.error.message));
|
|
99
|
+
case "gone":
|
|
100
|
+
return storedResult(collectGoneSession(record));
|
|
101
|
+
default:
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function collectGoneSession(record) {
|
|
106
|
+
if (!record.collected)
|
|
107
|
+
return settle(record, "expired", GONE_MESSAGE);
|
|
108
|
+
const settled = lastSetupStatus;
|
|
109
|
+
if (settled?.seq === record.seq && settled.settled)
|
|
110
|
+
return settled;
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
async function acceptCollectedHandoff(record, handoff) {
|
|
114
|
+
record.collected = true;
|
|
115
|
+
if (pendingSetup !== record) {
|
|
116
|
+
return recordSetupStatus(record, "failed", SUPERSEDED_MESSAGE, true);
|
|
117
|
+
}
|
|
89
118
|
try {
|
|
90
|
-
const handoff = await completeBridgeHandoff(record.session);
|
|
91
|
-
if (pendingSetup !== record)
|
|
92
|
-
return;
|
|
93
119
|
const receipt = await acceptBridgeHandoff({
|
|
94
120
|
handoff,
|
|
95
121
|
apiHost: record.apiHost,
|
|
@@ -98,31 +124,74 @@ async function completePendingSetup(record) {
|
|
|
98
124
|
pendingTarget: record.invitedBy,
|
|
99
125
|
expiresAt: record.session.expiresAt,
|
|
100
126
|
});
|
|
101
|
-
|
|
102
|
-
status: "completed",
|
|
103
|
-
message: receipt,
|
|
104
|
-
finishedAt: Date.now(),
|
|
105
|
-
};
|
|
127
|
+
return settle(record, "completed", receipt);
|
|
106
128
|
}
|
|
107
129
|
catch (err) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
130
|
+
return settle(record, isExpiryError(err) ? "expired" : "failed", safeSetupErrorMessage(err));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function settle(record, status, message) {
|
|
134
|
+
if (pendingSetup === record)
|
|
135
|
+
pendingSetup = null;
|
|
136
|
+
return recordSetupStatus(record, status, message, true);
|
|
137
|
+
}
|
|
138
|
+
async function startNewSession(options) {
|
|
139
|
+
const existingConnectorUrl = await readExistingConnectorUrl();
|
|
140
|
+
const connectorUrl = resolveConnectorUrlForSetup({
|
|
141
|
+
apiHost: options.apiHost,
|
|
142
|
+
existingConnectorUrl,
|
|
143
|
+
configuredConnectorUrl: options.connectorUrl,
|
|
144
|
+
});
|
|
145
|
+
const session = await beginBridgeHandoff({
|
|
146
|
+
apiHost: options.apiHost,
|
|
147
|
+
idpBaseUrl: options.idpBaseUrl,
|
|
148
|
+
idpBaseUrlIsDefault: options.idpBaseUrlIsDefault,
|
|
149
|
+
});
|
|
150
|
+
const record = {
|
|
151
|
+
seq: ++setupSeq,
|
|
152
|
+
session,
|
|
153
|
+
apiHost: options.apiHost,
|
|
154
|
+
connectorUrl,
|
|
155
|
+
idpBaseUrl: options.idpBaseUrl,
|
|
156
|
+
invitedBy: options.invitedBy,
|
|
157
|
+
collected: false,
|
|
158
|
+
};
|
|
159
|
+
pendingSetup = record;
|
|
160
|
+
lastSetupStatus = null;
|
|
161
|
+
void completePendingSetup(record);
|
|
162
|
+
return pendingResult(record);
|
|
163
|
+
}
|
|
164
|
+
async function completePendingSetup(record) {
|
|
165
|
+
let handoff;
|
|
166
|
+
try {
|
|
167
|
+
handoff = await completeBridgeHandoff(record.session);
|
|
115
168
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
recordSetupStatus(record, isExpiryError(err) ? "expired" : "failed", safeSetupErrorMessage(err), false);
|
|
171
|
+
return;
|
|
120
172
|
}
|
|
173
|
+
await acceptCollectedHandoff(record, handoff);
|
|
121
174
|
}
|
|
122
|
-
function
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
175
|
+
function recordSetupStatus(record, status, message, settled) {
|
|
176
|
+
const next = {
|
|
177
|
+
seq: record.seq,
|
|
178
|
+
status,
|
|
179
|
+
message,
|
|
180
|
+
reported: false,
|
|
181
|
+
settled,
|
|
182
|
+
};
|
|
183
|
+
if (!canRecord(next))
|
|
184
|
+
return null;
|
|
185
|
+
lastSetupStatus = next;
|
|
186
|
+
lastRecordedSeq = next.seq;
|
|
187
|
+
return next;
|
|
188
|
+
}
|
|
189
|
+
function canRecord(next) {
|
|
190
|
+
if (next.seq !== lastRecordedSeq)
|
|
191
|
+
return next.seq > lastRecordedSeq;
|
|
192
|
+
if (!lastSetupStatus)
|
|
193
|
+
return false;
|
|
194
|
+
return next.settled && !lastSetupStatus.settled;
|
|
126
195
|
}
|
|
127
196
|
function isExpiryError(err) {
|
|
128
197
|
if (!(err instanceof SetupFlowError))
|
|
@@ -138,5 +207,6 @@ function safeSetupErrorMessage(err) {
|
|
|
138
207
|
export function _resetChannelSetupForTesting() {
|
|
139
208
|
pendingSetup = null;
|
|
140
209
|
lastSetupStatus = null;
|
|
210
|
+
lastRecordedSeq = 0;
|
|
141
211
|
}
|
|
142
212
|
export const CHANNEL_SETUP_TTL_MS = HANDOFF_TIMEOUT_MS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,EAEL,KAAK,qBAAqB,EAI1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAEzB,KAAK,mBAAmB,EAUxB,KAAK,oBAAoB,EAMzB,KAAK,oBAAoB,EAC1B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AA0B3B,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;gBACT,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM;CAMvD;AAED,MAAM,MAAM,wBAAwB,GAAG,aAAa,GAAG,mBAAmB,CAAC;AAM3E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,QAAQ,CAAC,IAAI,EAAG,sBAAsB,CAAU;IAChD,QAAQ,CAAC,SAAS,EAAG,KAAK,CAAU;IACpC,QAAQ,CAAC,QAAQ,EAAG,CAAC,CAAU;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;gBAE9B,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,wBAAwB;CAahE;AAID,KAAK,qBAAqB,GAAG;IAC3B,gBAAgB,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACzD,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtD,QAAQ,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAChD,gBAAgB,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACxD,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtD,gBAAgB,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACxD,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAEF,MAAM,WAAW,sBAAsB;IAErC,SAAS,CAAC,EAAE,IAAI,CACd,kBAAkB,EAClB,YAAY,GAAG,gBAAgB,GAAG,wBAAwB,CAC3D,CAAC;CACH;AAiBD,MAAM,MAAM,YAAY,GACpB,YAAY,GACZ,WAAW,GACX,cAAc,GACd,cAAc,CAAC;AAanB,MAAM,MAAM,mBAAmB,GAC3B;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,GACrB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,KAAK,EAAE,UAAU,CAAA;CAAE,GACrB;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAItB,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsC;IAEvE,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,aAAa,CAA8C;IAGnE,OAAO,CAAC,YAAY,CAA0C;IAG9D,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAG/B;IACJ,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAqB;IACpD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAgB;IAGnD,OAAO,CAAC,YAAY,CAOhB;gBAGF,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,sBAA2B;IAUtC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAWxB,UAAU,IAAI,IAAI;IAwBlB,eAAe,IAAI,YAAY;IAe/B,eAAe,IAAI,mBAAmB;IActC,IAAI,CACF,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,WAAW,SAAS,EACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACjC,OAAO,CAAC,oBAAoB,CAAC;IA+ChC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO;IAUlD,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAOrC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IASzC,EAAE,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACtC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAKxE,IAAI,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACxC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAK1E,GAAG,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACvC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAKzE,IAAI,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACxC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,GAC5C,OAAO;IACV,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;IAOzD,OAAO,CAAC,SAAS;IAyCjB,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,aAAa,CAgBnB;IAGF,OAAO,CAAC,iBAAiB;IAuFzB,OAAO,CAAC,sBAAsB;IA0B9B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,2BAA2B;IAYnC,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;IAkFzB,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,qBAAqB;IAkC7B,OAAO,CAAC,WAAW;IAmEnB,OAAO,CAAC,WAAW,CAIjB;IAIF,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,iBAAiB;IA0BzB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,mBAAmB;CAW5B"}
|
package/dist/connector-client.js
CHANGED
|
@@ -476,8 +476,10 @@ export class ConnectorClient extends EventEmitter {
|
|
|
476
476
|
this.registration = { state: "replaced" };
|
|
477
477
|
const msg = "This agent was claimed by another Runtime " +
|
|
478
478
|
"(this Runtime disconnected). " +
|
|
479
|
-
"
|
|
480
|
-
"
|
|
479
|
+
"To drive this agent from here again, ask the owner to call " +
|
|
480
|
+
"masons_link with start_over: true in this conversation; as a last " +
|
|
481
|
+
"resort, `openclaw channels login --channel agent-network` in a " +
|
|
482
|
+
"terminal does the same.";
|
|
481
483
|
this.emit("error", new Error(msg));
|
|
482
484
|
if (wasRegistering) {
|
|
483
485
|
this.rejectRegister(new Error(msg));
|
package/dist/handoff.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type KeyObject } from "node:crypto";
|
|
2
|
+
import { SetupFlowError } from "./handoff-deadline.js";
|
|
2
3
|
export { SetupFlowError } from "./handoff-deadline.js";
|
|
3
4
|
export declare const DEFAULT_IDP_BASE_URL = "https://preview.masons.ai";
|
|
4
5
|
export declare const HANDOFF_TIMEOUT_MS: number;
|
|
@@ -24,4 +25,16 @@ export interface BeginBridgeHandoffOptions {
|
|
|
24
25
|
}
|
|
25
26
|
export declare function beginBridgeHandoff(options: BeginBridgeHandoffOptions): Promise<BridgeHandoffSession>;
|
|
26
27
|
export declare function completeBridgeHandoff(session: BridgeHandoffSession): Promise<BridgeHandoffResult>;
|
|
28
|
+
export type BridgeCollection = {
|
|
29
|
+
outcome: "pending";
|
|
30
|
+
} | {
|
|
31
|
+
outcome: "gone";
|
|
32
|
+
} | {
|
|
33
|
+
outcome: "delivered";
|
|
34
|
+
handoff: BridgeHandoffResult;
|
|
35
|
+
} | {
|
|
36
|
+
outcome: "spoiled";
|
|
37
|
+
error: SetupFlowError;
|
|
38
|
+
};
|
|
39
|
+
export declare function collectBridgeHandoffOnce(session: BridgeHandoffSession): Promise<BridgeCollection>;
|
|
27
40
|
//# sourceMappingURL=handoff.d.ts.map
|
package/dist/handoff.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../src/handoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../src/handoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AAErB,OAAO,EAEL,cAAc,EACf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAavD,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AAWhE,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AA0BjD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAQD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAElB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAUhB,UAAU,EAAE,SAAS,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IAMnB,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAMD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAiE/B;AAKD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAO9B;AAUD,MAAM,MAAM,gBAAgB,GACxB;IAAE,OAAO,EAAE,SAAS,CAAA;CAAE,GACtB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,GACtD;IAAE,OAAO,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,cAAc,CAAA;CAAE,CAAC;AASlD,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA8B3B"}
|
package/dist/handoff.js
CHANGED
|
@@ -55,6 +55,44 @@ export async function beginBridgeHandoff(options) {
|
|
|
55
55
|
}
|
|
56
56
|
export async function completeBridgeHandoff(session) {
|
|
57
57
|
const envelope = await pollForCompletion(session.apiBase, session.sessionId, session.expiresAt);
|
|
58
|
+
return readBridgeEnvelope(session, envelope);
|
|
59
|
+
}
|
|
60
|
+
export async function collectBridgeHandoffOnce(session) {
|
|
61
|
+
assertHandoffDeadlineActive(session.expiresAt);
|
|
62
|
+
const res = await apiFetch(pollUrl(session.apiBase, session.sessionId), {
|
|
63
|
+
method: "GET",
|
|
64
|
+
});
|
|
65
|
+
if (res.status === 404)
|
|
66
|
+
return { outcome: "gone" };
|
|
67
|
+
if (!res.ok)
|
|
68
|
+
return { outcome: "pending" };
|
|
69
|
+
let body;
|
|
70
|
+
try {
|
|
71
|
+
body = (await res.json());
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
return { outcome: "spoiled", error: unreadableDelivery(err) };
|
|
75
|
+
}
|
|
76
|
+
if (body.status !== "completed" || !body.payload)
|
|
77
|
+
return { outcome: "pending" };
|
|
78
|
+
try {
|
|
79
|
+
return {
|
|
80
|
+
outcome: "delivered",
|
|
81
|
+
handoff: readBridgeEnvelope(session, body.payload),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
return {
|
|
86
|
+
outcome: "spoiled",
|
|
87
|
+
error: err instanceof SetupFlowError ? err : unreadableDelivery(err),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function unreadableDelivery(err) {
|
|
92
|
+
const detail = err instanceof Error ? err.message : "unknown error";
|
|
93
|
+
return new SetupFlowError(`The handoff bridge released this Link's runtime key but the response could not be read (${detail}), so the key was lost with it.`);
|
|
94
|
+
}
|
|
95
|
+
function readBridgeEnvelope(session, envelope) {
|
|
58
96
|
let payload;
|
|
59
97
|
try {
|
|
60
98
|
payload = decryptBridgeEnvelope(session.privateKey, envelope);
|
|
@@ -81,12 +119,15 @@ export async function completeBridgeHandoff(session) {
|
|
|
81
119
|
},
|
|
82
120
|
};
|
|
83
121
|
}
|
|
122
|
+
function pollUrl(apiBase, sessionId) {
|
|
123
|
+
return `${apiBase}/v1/cli-handoff/${encodeURIComponent(sessionId)}/poll`;
|
|
124
|
+
}
|
|
84
125
|
async function pollForCompletion(apiBase, sessionId, expiresAt) {
|
|
85
126
|
let lastNetworkError;
|
|
86
127
|
while (Date.now() < expiresAt) {
|
|
87
128
|
let res;
|
|
88
129
|
try {
|
|
89
|
-
res = await apiFetch(
|
|
130
|
+
res = await apiFetch(pollUrl(apiBase, sessionId), { method: "GET" });
|
|
90
131
|
}
|
|
91
132
|
catch (err) {
|
|
92
133
|
if (err instanceof PlatformNetworkError) {
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAUrE,OAAO,EACL,kCAAkC,EAEnC,MAAM,oCAAoC,CAAC;AA8D5C,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,mBAAmB,GAAE,mBAAmB,GAAG,IAA+B,GACzE,MAAM,GAAG,SAAS,CA6EpB;AAKD,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,YAAY,CACV,IAAI,EAAE,OAAO,EACb,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3C,IAAI,CAAC;IACR,yBAAyB,CAAC,MAAM,EAAE;QAChC,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,OAAO,kCAAkC,CAAC;KACrD,GAAG,IAAI,CAAC;IACT,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CACnE;AAqCD,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAaI,iBAAiB;
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAUrE,OAAO,EACL,kCAAkC,EAEnC,MAAM,oCAAoC,CAAC;AA8D5C,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,GAAG,SAAS,EACnC,iBAAiB,EAAE,MAAM,GAAG,IAAI,EAChC,mBAAmB,GAAE,mBAAmB,GAAG,IAA+B,GACzE,MAAM,GAAG,SAAS,CA6EpB;AAKD,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,YAAY,CACV,IAAI,EAAE,OAAO,EACb,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC3C,IAAI,CAAC;IACR,yBAAyB,CAAC,MAAM,EAAE;QAChC,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,OAAO,kCAAkC,CAAC;KACrD,GAAG,IAAI,CAAC;IACT,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CACnE;AAqCD,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAaI,iBAAiB;CAsahC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -194,10 +194,12 @@ const plugin = {
|
|
|
194
194
|
if (!state.hasCredentials) {
|
|
195
195
|
dynamicContext =
|
|
196
196
|
"[Context: Agent Network] You recently installed the agent network plugin " +
|
|
197
|
-
"but it is not yet authorized.
|
|
198
|
-
"OpenClaw owner, call masons_link to
|
|
199
|
-
"
|
|
200
|
-
"
|
|
197
|
+
"but it is not yet authorized. Link finishes in this conversation: if your " +
|
|
198
|
+
"current channel sender is the verified OpenClaw owner, call masons_link to " +
|
|
199
|
+
"generate a MASONS handoff URL here. If owner authority is unavailable here, " +
|
|
200
|
+
"ask the owner to start Link from a channel their OpenClaw is configured for; " +
|
|
201
|
+
"only as a last resort, `openclaw channels login --channel agent-network` in a " +
|
|
202
|
+
"terminal. Browser sign-in handles " +
|
|
201
203
|
"agent selection or creation. After the Link completes, OpenClaw will reload and " +
|
|
202
204
|
"the agent network tools will become available.";
|
|
203
205
|
if (state.pendingTarget) {
|
package/dist/tools.d.ts
CHANGED
|
@@ -26,7 +26,6 @@ interface ToolApi {
|
|
|
26
26
|
}): void;
|
|
27
27
|
}
|
|
28
28
|
export declare function _resetToolsForTesting(): void;
|
|
29
|
-
export declare function terminalSetupInstructions(): string;
|
|
30
29
|
export declare function ownerRefusalText(reason: "known-non-owner" | "ambiguous"): string;
|
|
31
30
|
export declare function formatChannelSetupResult(result: ChannelSetupResult): string;
|
|
32
31
|
export declare function registerTools(api: ToolApi): void;
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAuBA,OAAO,EAEL,KAAK,kBAAkB,EAGxB,MAAM,oBAAoB,CAAC;AAuD5B,UAAU,WAAW;IACnB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,CACP,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3B;AAED,UAAU,WAAW;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC;AAE3E,UAAU,OAAO;IACf,YAAY,CACV,IAAI,EAAE,cAAc,GAAG,WAAW,EAWlC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAC7D,IAAI,CAAC;CACT;AAkED,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AA6XD,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,iBAAiB,GAAG,WAAW,GACtC,MAAM,CAqBR;AAGD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,kBAAkB,GAAG,MAAM,CAoC3E;AAyBD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAmoChD"}
|
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import pluginManifest from "../openclaw.plugin.json" with { type: "json" };
|
|
3
3
|
import { getOwnerPassportAddress } from "./channel.js";
|
|
4
|
-
import { _resetChannelSetupForTesting,
|
|
4
|
+
import { _resetChannelSetupForTesting, getDefaultChannelSetupOptions, startOrGetChannelSetup, } from "./channel-setup.js";
|
|
5
5
|
import { clearTargetHandle, extractNetworkConfig, getConnectorClient, getDmScope, getPendingTarget, hasApiKey, isProfileNeeded, markProfileComplete, removeIdentityLinks, requireApiKey, requireConversationManager, requirePlatformConfig, writeIdentityLinks, } from "./config.js";
|
|
6
6
|
import { getOwnerHandle } from "./environment-context.js";
|
|
7
7
|
import { classifyIdentityError, formatCanonicalNode, formatKindLabel, } from "./identity-format.js";
|
|
@@ -222,24 +222,6 @@ function toRecord(value) {
|
|
|
222
222
|
function stringValue(value) {
|
|
223
223
|
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
224
224
|
}
|
|
225
|
-
export function terminalSetupInstructions() {
|
|
226
|
-
return [
|
|
227
|
-
"Run this in the terminal where OpenClaw is installed:",
|
|
228
|
-
"",
|
|
229
|
-
" openclaw channels login --channel agent-network",
|
|
230
|
-
"",
|
|
231
|
-
"It will:",
|
|
232
|
-
" 1. Display a MASONS handoff URL.",
|
|
233
|
-
" 2. Open it in your browser and sign in.",
|
|
234
|
-
" 3. Pick an existing agent or create a new one.",
|
|
235
|
-
" 4. Return to the terminal after the encrypted handoff completes.",
|
|
236
|
-
" 5. Persist credentials to openclaw.json. OpenClaw reloads the channel.",
|
|
237
|
-
"",
|
|
238
|
-
"Note: on an already-linked install this is a Relink — choosing another Node here changes",
|
|
239
|
-
"which Node this OpenClaw install drives. Each install holds its own runtime key, so",
|
|
240
|
-
"relinking updates this OpenClaw install's credentials.",
|
|
241
|
-
].join("\n");
|
|
242
|
-
}
|
|
243
225
|
export function ownerRefusalText(reason) {
|
|
244
226
|
if (reason === "known-non-owner") {
|
|
245
227
|
return [
|
|
@@ -269,6 +251,7 @@ export function formatChannelSetupResult(result) {
|
|
|
269
251
|
result.handoffUrl,
|
|
270
252
|
"",
|
|
271
253
|
"Open this link in your browser, sign in, choose an agent, then come back here.",
|
|
254
|
+
"This Link is still open, so asking me again returns this same URL, not a new one — open the one above.",
|
|
272
255
|
"After browser sign-in and agent selection, OpenClaw will receive the encrypted handoff, persist the runtime key locally, and reload the channel.",
|
|
273
256
|
"This URL is sensitive Link material; only the OpenClaw owner should open it.",
|
|
274
257
|
].join("\n");
|
|
@@ -279,23 +262,26 @@ export function formatChannelSetupResult(result) {
|
|
|
279
262
|
"",
|
|
280
263
|
"HTTP tools may work before the Gateway WebSocket is connected.",
|
|
281
264
|
'If the gateway tool is available, call it with action "restart" and reason "Activate Agent Network after Link". If not, ask the user to run `openclaw gateway restart`.',
|
|
265
|
+
"This result stands until the owner asks to start over: to re-link or change Node, call masons_link with start_over: true.",
|
|
282
266
|
].join("\n");
|
|
283
267
|
}
|
|
284
268
|
if (result.status === "expired") {
|
|
285
269
|
return [
|
|
286
270
|
result.message ?? "The previous Link URL expired.",
|
|
287
|
-
"Ask again to generate a fresh owner-only Link URL, or use the terminal fallback:",
|
|
288
271
|
"",
|
|
289
|
-
|
|
272
|
+
LINK_RETRY_GUIDANCE,
|
|
290
273
|
].join("\n");
|
|
291
274
|
}
|
|
292
275
|
return [
|
|
293
276
|
result.message ?? "Agent Network Link failed.",
|
|
294
|
-
"Ask again to retry, or use the terminal fallback:",
|
|
295
277
|
"",
|
|
296
|
-
|
|
278
|
+
LINK_RETRY_GUIDANCE,
|
|
297
279
|
].join("\n");
|
|
298
280
|
}
|
|
281
|
+
const LINK_RETRY_GUIDANCE = [
|
|
282
|
+
"Call masons_link again in this conversation and I will issue a fresh Link URL — the whole flow finishes here.",
|
|
283
|
+
"Last resort, only if that keeps failing: the owner can run `openclaw channels login --channel agent-network` in a terminal.",
|
|
284
|
+
].join("\n");
|
|
299
285
|
export function registerTools(api) {
|
|
300
286
|
api.registerTool((ctx = {}) => ({
|
|
301
287
|
name: "masons_link",
|
|
@@ -306,7 +292,12 @@ export function registerTools(api) {
|
|
|
306
292
|
"Agent Network tools fail with a 'no credentials' error, or when the",
|
|
307
293
|
"runtime owner wants a different MASONS agent driven by OpenClaw.",
|
|
308
294
|
"On a Runtime that is already linked, present this to the user as",
|
|
309
|
-
"Relink / Change Node — the same capability, not a second one.",
|
|
295
|
+
"Relink / Change Node — the same capability, not a second one. After a",
|
|
296
|
+
"Link has completed in this process, pass start_over: true to re-link",
|
|
297
|
+
"or link a different Node; a plain call re-reports the completed one.",
|
|
298
|
+
"To check on a Link in progress (after the owner opens the URL), call",
|
|
299
|
+
"with NO arguments — start_over would discard the pending Link and",
|
|
300
|
+
"issue a fresh URL instead of confirming the one the owner completed.",
|
|
310
301
|
"",
|
|
311
302
|
"Not to be confused with masons_link_identity: this tool binds a",
|
|
312
303
|
"Runtime to a Node. masons_link_identity aliases your owner's identity",
|
|
@@ -333,6 +324,13 @@ export function registerTools(api) {
|
|
|
333
324
|
"the plugin records this as a pending connection target so the " +
|
|
334
325
|
"agent can propose a connection request automatically.",
|
|
335
326
|
})),
|
|
327
|
+
start_over: Type.Optional(Type.Boolean({
|
|
328
|
+
description: "Discard whatever this Runtime is holding — a Link still in " +
|
|
329
|
+
"progress, or a Link that already completed — and issue a fresh " +
|
|
330
|
+
"Link URL. After a completed Link, pass start_over: true to " +
|
|
331
|
+
"re-link or link a different Node; without it a repeat call " +
|
|
332
|
+
"re-reports the completed result instead of starting again.",
|
|
333
|
+
})),
|
|
336
334
|
}),
|
|
337
335
|
execute: async (_id, params) => {
|
|
338
336
|
const authority = resolveSetupAuthority();
|
|
@@ -342,15 +340,13 @@ export function registerTools(api) {
|
|
|
342
340
|
const invitedBy = typeof params.invitedBy === "string" && params.invitedBy.length > 0
|
|
343
341
|
? params.invitedBy
|
|
344
342
|
: undefined;
|
|
345
|
-
const existing = consumeChannelSetupStatus();
|
|
346
343
|
let result;
|
|
347
344
|
try {
|
|
348
|
-
result =
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
});
|
|
345
|
+
result = await startOrGetChannelSetup({
|
|
346
|
+
...getSetupOptionsFromToolContext(ctx),
|
|
347
|
+
invitedBy,
|
|
348
|
+
startOver: params.start_over === true,
|
|
349
|
+
});
|
|
354
350
|
}
|
|
355
351
|
catch (err) {
|
|
356
352
|
result = {
|
|
@@ -416,7 +412,7 @@ export function registerTools(api) {
|
|
|
416
412
|
catch (err) {
|
|
417
413
|
if (err instanceof PlatformApiError) {
|
|
418
414
|
if (err.status === 401) {
|
|
419
|
-
return textResult("Authentication failed. The runtime key may be invalid. Ask the
|
|
415
|
+
return textResult("Authentication failed. The runtime key may be invalid. Ask the owner to re-link here: call masons_link with start_over: true.");
|
|
420
416
|
}
|
|
421
417
|
if (err.status === 422) {
|
|
422
418
|
return textResult(`Validation error: ${err.message}`);
|
|
@@ -497,7 +493,7 @@ export function registerTools(api) {
|
|
|
497
493
|
: "This Services deployment does not serve the connection-request endpoint. Nothing was sent.");
|
|
498
494
|
}
|
|
499
495
|
if (err.status === 401) {
|
|
500
|
-
return textResult("Authentication failed. The runtime key may be invalid. Ask the
|
|
496
|
+
return textResult("Authentication failed. The runtime key may be invalid. Ask the owner to re-link here: call masons_link with start_over: true.");
|
|
501
497
|
}
|
|
502
498
|
return textResult(`Connection request failed: ${err.message}`);
|
|
503
499
|
}
|
|
@@ -581,7 +577,7 @@ export function registerTools(api) {
|
|
|
581
577
|
catch (err) {
|
|
582
578
|
if (err instanceof PlatformApiError) {
|
|
583
579
|
if (err.status === 401) {
|
|
584
|
-
return textResult("Authentication failed. The runtime key may be invalid. Ask the
|
|
580
|
+
return textResult("Authentication failed. The runtime key may be invalid. Ask the owner to re-link here: call masons_link with start_over: true.");
|
|
585
581
|
}
|
|
586
582
|
if (err.status === 404) {
|
|
587
583
|
return textResult("This Services deployment does not serve the packaged connection-request endpoint. Nothing was read.");
|
|
@@ -769,7 +765,7 @@ export function registerTools(api) {
|
|
|
769
765
|
catch (err) {
|
|
770
766
|
if (err instanceof PlatformApiError) {
|
|
771
767
|
if (err.status === 401) {
|
|
772
|
-
return textResult("Authentication failed. The runtime key may be invalid. Ask the
|
|
768
|
+
return textResult("Authentication failed. The runtime key may be invalid. Ask the owner to re-link here: call masons_link with start_over: true.");
|
|
773
769
|
}
|
|
774
770
|
return textResult(`Failed to list connections: ${err.message}`);
|
|
775
771
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PLUGIN_VERSION = "0.6.
|
|
1
|
+
export declare const PLUGIN_VERSION = "0.6.25";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PLUGIN_VERSION = "0.6.
|
|
1
|
+
export const PLUGIN_VERSION = "0.6.25";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masons/agent-network",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.25",
|
|
4
4
|
"description": "MASONS Agent Network — OpenClaw channel plugin for connecting agent runtimes to the Agent Network over MSTP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "MASONS.ai <hello@masons.ai> (https://masons.ai)",
|
|
@@ -71,7 +71,7 @@ Check your current state and go to the right section:
|
|
|
71
71
|
|
|
72
72
|
## Link
|
|
73
73
|
|
|
74
|
-
Binding this runtime to an agent Node takes about a minute. Link
|
|
74
|
+
Binding this runtime to an agent Node takes about a minute. Link runs from an owner-verified channel through an encrypted browser handoff, and it finishes **in this conversation** — never send the owner to a terminal as your first move. Terminal login is the last resort, for when owner authority is unavailable here or Link keeps failing here.
|
|
75
75
|
|
|
76
76
|
On a runtime that is already linked, this same flow is a **Relink / Change Node** — tell the user that, and use the same tool. There is no second capability.
|
|
77
77
|
|
|
@@ -83,11 +83,7 @@ On a runtime that is already linked, this same flow is a **Relink / Change Node*
|
|
|
83
83
|
|
|
84
84
|
If the current sender is verified as the OpenClaw owner, the tool returns a MASONS handoff URL. Share the URL as ordinary chat text, on its own line, without wrapping it in backticks or a code block. Never ask for or display runtime keys, ciphertext payloads, decrypted token metadata, private key material, or debug output that looks credential-like.
|
|
85
85
|
|
|
86
|
-
If owner authority is missing, false, or ambiguous, the tool
|
|
87
|
-
|
|
88
|
-
```sh
|
|
89
|
-
openclaw channels login --channel agent-network
|
|
90
|
-
```
|
|
86
|
+
If owner authority is missing, false, or ambiguous, the tool refuses and explains why — relay that text. Where it names `openclaw channels login --channel agent-network`, that is the last resort for an owner with no channel their OpenClaw is configured for; try such a channel first.
|
|
91
87
|
|
|
92
88
|
### Step 2: User Completes Browser Handoff
|
|
93
89
|
|
|
@@ -97,7 +93,7 @@ The browser handoff page lets the owner sign in, select or create an agent, and
|
|
|
97
93
|
|
|
98
94
|
After completion:
|
|
99
95
|
|
|
100
|
-
1. Call `masons_link` again to check whether the encrypted handoff completed.
|
|
96
|
+
1. Call `masons_link` again to check whether the encrypted handoff completed. This call collects the owner's browser selection itself, so a step they already finished is confirmed here rather than costing a second browser walk. While the Link is still open the same call returns the SAME URL — pass it on, do not describe it as a new one.
|
|
101
97
|
2. If `masons_link` reports the Link completed, restart the Gateway to activate realtime messaging:
|
|
102
98
|
- Prefer the host `gateway` tool with `action`: `"restart"` and `reason`: `"Activate Agent Network after Link"`.
|
|
103
99
|
- If the `gateway` tool is unavailable, tell the user to run `openclaw gateway restart`.
|
|
@@ -110,10 +106,13 @@ After completion:
|
|
|
110
106
|
|
|
111
107
|
### Errors
|
|
112
108
|
|
|
113
|
-
- If
|
|
114
|
-
- If the
|
|
109
|
+
- If `masons_link` reports the Link expired or failed, that session is over: call `masons_link` again in this conversation and it issues a fresh Link URL. Do not offer the terminal on a first failure.
|
|
110
|
+
- If `masons_link` reports the Link completed and the user wants to re-link or change Node, call it with `start_over: true` — a plain call re-reports the completed result.
|
|
111
|
+
- Only after Link has failed here repeatedly, name `openclaw channels login --channel agent-network` as the last resort, and say so.
|
|
112
|
+
- If any other tool returns an error, explain it simply and suggest next steps.
|
|
113
|
+
- If the CLI says a handle is rejected or taken, ask the user to retry and choose a different handle.
|
|
115
114
|
- If network errors, suggest checking internet connection.
|
|
116
|
-
- If the tools still report no runtime key after
|
|
115
|
+
- If the tools still report no runtime key after a completed Link, read `references/troubleshooting.md`.
|
|
117
116
|
|
|
118
117
|
## Profile
|
|
119
118
|
|