@masons/agent-network 0.6.22 → 0.6.24
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 +40 -5
- package/dist/_vendor/runtime-adapter-client/exact-target-presentation.d.ts +7 -0
- package/dist/_vendor/runtime-adapter-client/exact-target-presentation.d.ts.map +1 -0
- package/dist/_vendor/runtime-adapter-client/exact-target-presentation.js +51 -0
- package/dist/_vendor/runtime-adapter-client/index.d.ts +1 -0
- package/dist/_vendor/runtime-adapter-client/index.d.ts.map +1 -1
- package/dist/_vendor/runtime-adapter-client/index.js +1 -0
- package/dist/_vendor/runtime-adapter-client/runtime-adapter-api.d.ts +2 -2
- package/dist/_vendor/runtime-adapter-client/runtime-adapter-api.d.ts.map +1 -1
- package/dist/_vendor/runtime-adapter-client/runtime-adapter-api.js +105 -20
- package/dist/_vendor/runtime-adapter-client/types.d.ts +17 -5
- package/dist/_vendor/runtime-adapter-client/types.d.ts.map +1 -1
- package/dist/_vendor/runtime-adapter-client/types.js +13 -0
- package/dist/_vendor/runtime-adapter-client/work-target.d.ts.map +1 -1
- package/dist/_vendor/runtime-adapter-client/work-target.js +23 -5
- package/dist/channel-setup.d.ts +1 -0
- package/dist/channel-setup.d.ts.map +1 -1
- package/dist/channel-setup.js +4 -3
- package/dist/cli-setup.d.ts.map +1 -1
- package/dist/cli-setup.js +7 -7
- package/dist/config.js +1 -1
- package/dist/handoff-acceptance.js +5 -5
- package/dist/handoff-deadline.js +1 -1
- package/dist/handoff.d.ts +1 -0
- package/dist/handoff.d.ts.map +1 -1
- package/dist/handoff.js +43 -10
- package/dist/platform-client.d.ts +37 -32
- package/dist/platform-client.d.ts.map +1 -1
- package/dist/platform-client.js +42 -29
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +8 -6
- package/dist/tools.d.ts +4 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +293 -111
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/openclaw.plugin.json +6 -5
- package/package.json +1 -1
- package/skills/agent-network/SKILL.md +90 -46
- package/skills/agent-network/references/maintenance.md +3 -3
- package/skills/agent-network/references/troubleshooting.md +71 -13
|
@@ -4,13 +4,19 @@ export function parseRuntimeWorkTargetRef(value) {
|
|
|
4
4
|
const raw = value;
|
|
5
5
|
if (raw.kind !== "projection_endpoint" ||
|
|
6
6
|
typeof raw.projection_endpoint_id !== "string" ||
|
|
7
|
-
raw.projection_endpoint_id.
|
|
7
|
+
raw.projection_endpoint_id.length === 0 ||
|
|
8
|
+
raw.projection_endpoint_id.trim() !== raw.projection_endpoint_id) {
|
|
8
9
|
return null;
|
|
9
10
|
}
|
|
10
|
-
const projectionEndpointId = raw.projection_endpoint_id
|
|
11
|
+
const projectionEndpointId = raw.projection_endpoint_id;
|
|
11
12
|
if (raw.background_exchange_mode === "resident_endpoint") {
|
|
12
|
-
if (raw
|
|
13
|
+
if (!hasExactKeys(raw, [
|
|
14
|
+
"kind",
|
|
15
|
+
"projection_endpoint_id",
|
|
16
|
+
"background_exchange_mode",
|
|
17
|
+
])) {
|
|
13
18
|
return null;
|
|
19
|
+
}
|
|
14
20
|
return {
|
|
15
21
|
kind: "projection_endpoint",
|
|
16
22
|
projection_endpoint_id: projectionEndpointId,
|
|
@@ -20,16 +26,28 @@ export function parseRuntimeWorkTargetRef(value) {
|
|
|
20
26
|
if ((raw.background_exchange_mode === "adapter_managed_turn" ||
|
|
21
27
|
raw.background_exchange_mode === "session_attached_pull") &&
|
|
22
28
|
typeof raw.runtime_session_id === "string" &&
|
|
23
|
-
raw.runtime_session_id.
|
|
29
|
+
raw.runtime_session_id.length > 0 &&
|
|
30
|
+
raw.runtime_session_id.trim() === raw.runtime_session_id &&
|
|
31
|
+
hasExactKeys(raw, [
|
|
32
|
+
"kind",
|
|
33
|
+
"projection_endpoint_id",
|
|
34
|
+
"runtime_session_id",
|
|
35
|
+
"background_exchange_mode",
|
|
36
|
+
])) {
|
|
24
37
|
return {
|
|
25
38
|
kind: "projection_endpoint",
|
|
26
39
|
projection_endpoint_id: projectionEndpointId,
|
|
27
|
-
runtime_session_id: raw.runtime_session_id
|
|
40
|
+
runtime_session_id: raw.runtime_session_id,
|
|
28
41
|
background_exchange_mode: raw.background_exchange_mode,
|
|
29
42
|
};
|
|
30
43
|
}
|
|
31
44
|
return null;
|
|
32
45
|
}
|
|
46
|
+
function hasExactKeys(value, expected) {
|
|
47
|
+
const actual = Object.keys(value).sort();
|
|
48
|
+
return (actual.length === expected.length &&
|
|
49
|
+
[...expected].sort().every((key, index) => actual[index] === key));
|
|
50
|
+
}
|
|
33
51
|
export function isRuntimeWorkTargetRef(value) {
|
|
34
52
|
return parseRuntimeWorkTargetRef(value) !== null;
|
|
35
53
|
}
|
package/dist/channel-setup.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-setup.d.ts","sourceRoot":"","sources":["../src/channel-setup.ts"],"names":[],"mappings":"AAeA,UAAU,wBAAwB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"channel-setup.d.ts","sourceRoot":"","sources":["../src/channel-setup.ts"],"names":[],"mappings":"AAeA,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;CACpB;AA2BD,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;AAOD,wBAAgB,6BAA6B,IAAI,wBAAwB,CAKxE;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CAsC7B;AAED,wBAAgB,qBAAqB,IAAI,kBAAkB,GAAG,IAAI,CAcjE;AAED,wBAAgB,yBAAyB,IAAI,kBAAkB,GAAG,IAAI,CAMrE;AAmFD,wBAAgB,4BAA4B,IAAI,IAAI,CAGnD;AAED,eAAO,MAAM,oBAAoB,QAAqB,CAAC"}
|
package/dist/channel-setup.js
CHANGED
|
@@ -32,6 +32,7 @@ export async function startOrGetChannelSetup(options) {
|
|
|
32
32
|
const session = await beginBridgeHandoff({
|
|
33
33
|
apiHost: options.apiHost,
|
|
34
34
|
idpBaseUrl: options.idpBaseUrl,
|
|
35
|
+
idpBaseUrlIsDefault: options.idpBaseUrlIsDefault,
|
|
35
36
|
});
|
|
36
37
|
const record = {
|
|
37
38
|
session,
|
|
@@ -78,7 +79,7 @@ function getActivePendingSetup() {
|
|
|
78
79
|
return pendingSetup;
|
|
79
80
|
lastSetupStatus = {
|
|
80
81
|
status: "expired",
|
|
81
|
-
message: "The previous
|
|
82
|
+
message: "The previous Link URL expired before the browser handoff completed.",
|
|
82
83
|
finishedAt: Date.now(),
|
|
83
84
|
};
|
|
84
85
|
pendingSetup = null;
|
|
@@ -131,8 +132,8 @@ function isExpiryError(err) {
|
|
|
131
132
|
function safeSetupErrorMessage(err) {
|
|
132
133
|
if (err instanceof SetupFlowError)
|
|
133
134
|
return err.message;
|
|
134
|
-
dbg("
|
|
135
|
-
return "
|
|
135
|
+
dbg("link failed with an unexpected error: %O", err);
|
|
136
|
+
return "Link failed for an unexpected reason; check debug logs.";
|
|
136
137
|
}
|
|
137
138
|
export function _resetChannelSetupForTesting() {
|
|
138
139
|
pendingSetup = null;
|
package/dist/cli-setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-setup.d.ts","sourceRoot":"","sources":["../src/cli-setup.ts"],"names":[],"mappings":"AA8FA,UAAU,eAAe;IACvB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAOD,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"cli-setup.d.ts","sourceRoot":"","sources":["../src/cli-setup.ts"],"names":[],"mappings":"AA8FA,UAAU,eAAe;IACvB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAOD,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAqFD,wBAAsB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+EhE"}
|
package/dist/cli-setup.js
CHANGED
|
@@ -3,14 +3,15 @@ import { ConnectorUrlConfigurationError, resolveConnectorUrlForSetup, } from "./
|
|
|
3
3
|
import { beginBridgeHandoff, completeBridgeHandoff, DEFAULT_IDP_BASE_URL, SetupFlowError, } from "./handoff.js";
|
|
4
4
|
import { acceptBridgeHandoff } from "./handoff-acceptance.js";
|
|
5
5
|
import { DEFAULT_API_HOST, DEFAULT_CONNECTOR_URL, PlatformApiError, } from "./platform-client.js";
|
|
6
|
-
async function serverBridgeHandoffFlow(apiHost, idpBaseUrl, runtime) {
|
|
6
|
+
async function serverBridgeHandoffFlow(apiHost, idpBaseUrl, idpBaseUrlIsDefault, runtime) {
|
|
7
7
|
const session = await beginBridgeHandoff({
|
|
8
8
|
apiHost,
|
|
9
9
|
idpBaseUrl,
|
|
10
|
+
idpBaseUrlIsDefault,
|
|
10
11
|
});
|
|
11
12
|
runtime.writeStdout([
|
|
12
13
|
"",
|
|
13
|
-
"Open this link in your browser to
|
|
14
|
+
"Open this link in your browser to complete the Link:",
|
|
14
15
|
` ${session.handoffUrl}`,
|
|
15
16
|
"",
|
|
16
17
|
"Waiting for the runtime key to be issued and delivered…",
|
|
@@ -23,12 +24,11 @@ async function serverBridgeHandoffFlow(apiHost, idpBaseUrl, runtime) {
|
|
|
23
24
|
}
|
|
24
25
|
export async function login(ctx) {
|
|
25
26
|
const apiHost = typeof ctx.cfg.apiHost === "string" ? ctx.cfg.apiHost : DEFAULT_API_HOST;
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
: DEFAULT_IDP_BASE_URL;
|
|
27
|
+
const configuredIdpBaseUrl = typeof ctx.cfg.idpBaseUrl === "string" ? ctx.cfg.idpBaseUrl : undefined;
|
|
28
|
+
const idpBaseUrl = configuredIdpBaseUrl ?? DEFAULT_IDP_BASE_URL;
|
|
29
29
|
let completed;
|
|
30
30
|
try {
|
|
31
|
-
completed = await serverBridgeHandoffFlow(apiHost, idpBaseUrl, ctx.runtime);
|
|
31
|
+
completed = await serverBridgeHandoffFlow(apiHost, idpBaseUrl, configuredIdpBaseUrl === undefined, ctx.runtime);
|
|
32
32
|
}
|
|
33
33
|
catch (err) {
|
|
34
34
|
if (err instanceof SetupFlowError) {
|
|
@@ -36,7 +36,7 @@ export async function login(ctx) {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
if (err instanceof PlatformApiError) {
|
|
39
|
-
ctx.runtime.error(`
|
|
39
|
+
ctx.runtime.error(`Link failed (HTTP ${err.status} ${err.code}): ${err.message}`);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
throw err;
|
package/dist/config.js
CHANGED
|
@@ -104,7 +104,7 @@ export function requirePlatformConfig() {
|
|
|
104
104
|
}
|
|
105
105
|
export function requireApiKey() {
|
|
106
106
|
if (!storedApiKey) {
|
|
107
|
-
throw new Error("No runtime key configured. Complete
|
|
107
|
+
throw new Error("No runtime key configured. Complete Link first.");
|
|
108
108
|
}
|
|
109
109
|
return storedApiKey;
|
|
110
110
|
}
|
|
@@ -32,20 +32,20 @@ async function refreshCanonicalNode(options) {
|
|
|
32
32
|
throw acceptanceFailure(err, options.apiHost);
|
|
33
33
|
}
|
|
34
34
|
if (node === null) {
|
|
35
|
-
throw new SetupFlowError(`The delivered runtime key is valid, but the network reports no active Node for it to represent, so it was not accepted. ${NOTHING_CHANGED} Choose or create an Agent Node in the console, then re-run
|
|
35
|
+
throw new SetupFlowError(`The delivered runtime key is valid, but the network reports no active Node for it to represent, so it was not accepted. ${NOTHING_CHANGED} Choose or create an Agent Node in the console, then re-run Link.`);
|
|
36
36
|
}
|
|
37
37
|
return node;
|
|
38
38
|
}
|
|
39
39
|
function acceptanceFailure(err, apiHost) {
|
|
40
40
|
switch (classifyIdentityError(err)) {
|
|
41
41
|
case "credential-refused":
|
|
42
|
-
return new SetupFlowError(`The network rejected the runtime key delivered by the browser${httpStatusSuffix(err)}, so it was not accepted. That is a credential-class refusal — retrying will not change it. ${NOTHING_CHANGED} Re-run
|
|
42
|
+
return new SetupFlowError(`The network rejected the runtime key delivered by the browser${httpStatusSuffix(err)}, so it was not accepted. That is a credential-class refusal — retrying will not change it. ${NOTHING_CHANGED} Re-run Link to authorize a new runtime key.`);
|
|
43
43
|
case "entity-missing":
|
|
44
|
-
return new SetupFlowError(`The delivered runtime key authenticates, but the Node it represents has no backing entity on the network — it is missing or deleted — so it was not accepted. ${NOTHING_CHANGED} Choose or create an Agent Node in the console, then re-run
|
|
44
|
+
return new SetupFlowError(`The delivered runtime key authenticates, but the Node it represents has no backing entity on the network — it is missing or deleted — so it was not accepted. ${NOTHING_CHANGED} Choose or create an Agent Node in the console, then re-run Link.`);
|
|
45
45
|
case "endpoint-absent":
|
|
46
|
-
return new SetupFlowError(`This MASONS Services deployment does not serve the identity endpoint (HTTP 404 for GET /v1/me/identity at ${apiHost}), so the delivered runtime key could not be verified and was not accepted. That is a property of this host — an older or self-hosted apps/api — not an expired link. ${NOTHING_CHANGED} Point
|
|
46
|
+
return new SetupFlowError(`This MASONS Services deployment does not serve the identity endpoint (HTTP 404 for GET /v1/me/identity at ${apiHost}), so the delivered runtime key could not be verified and was not accepted. That is a property of this host — an older or self-hosted apps/api — not an expired link. ${NOTHING_CHANGED} Point Link at a Services deployment that serves the identity endpoint, or upgrade this one, then re-run Link.`);
|
|
47
47
|
case "unavailable":
|
|
48
|
-
return new SetupFlowError(`The network could not confirm which Node the delivered runtime key represents (${unavailableDetail(err)}), so it was not accepted. ${NOTHING_CHANGED} Re-run
|
|
48
|
+
return new SetupFlowError(`The network could not confirm which Node the delivered runtime key represents (${unavailableDetail(err)}), so it was not accepted. ${NOTHING_CHANGED} Re-run Link to try again.`);
|
|
49
49
|
default:
|
|
50
50
|
return err;
|
|
51
51
|
}
|
package/dist/handoff-deadline.js
CHANGED
|
@@ -2,6 +2,6 @@ export class SetupFlowError extends Error {
|
|
|
2
2
|
}
|
|
3
3
|
export function assertHandoffDeadlineActive(expiresAt) {
|
|
4
4
|
if (Date.now() >= expiresAt) {
|
|
5
|
-
throw new SetupFlowError("Handoff session expired before the runtime key was delivered. Re-run
|
|
5
|
+
throw new SetupFlowError("Handoff session expired before the runtime key was delivered. Re-run Link.");
|
|
6
6
|
}
|
|
7
7
|
}
|
package/dist/handoff.d.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface BridgeHandoffSession {
|
|
|
20
20
|
export interface BeginBridgeHandoffOptions {
|
|
21
21
|
apiHost: string;
|
|
22
22
|
idpBaseUrl: string;
|
|
23
|
+
idpBaseUrlIsDefault?: boolean;
|
|
23
24
|
}
|
|
24
25
|
export declare function beginBridgeHandoff(options: BeginBridgeHandoffOptions): Promise<BridgeHandoffSession>;
|
|
25
26
|
export declare function completeBridgeHandoff(session: BridgeHandoffSession): Promise<BridgeHandoffResult>;
|
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;AAQrB,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;
|
|
1
|
+
{"version":3,"file":"handoff.d.ts","sourceRoot":"","sources":["../src/handoff.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,SAAS,EAEf,MAAM,aAAa,CAAC;AAQrB,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;IAOhB,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,CA0C9B"}
|
package/dist/handoff.js
CHANGED
|
@@ -15,6 +15,7 @@ export async function beginBridgeHandoff(options) {
|
|
|
15
15
|
.toString("base64url");
|
|
16
16
|
const apiBase = normalizeHttpBase(options.apiHost);
|
|
17
17
|
let sessionId;
|
|
18
|
+
let ownerChoiceUrl;
|
|
18
19
|
try {
|
|
19
20
|
const initRes = await apiFetch(`${apiBase}/v1/cli-handoff/init`, {
|
|
20
21
|
method: "POST",
|
|
@@ -24,25 +25,29 @@ export async function beginBridgeHandoff(options) {
|
|
|
24
25
|
}),
|
|
25
26
|
});
|
|
26
27
|
if (!initRes.ok) {
|
|
27
|
-
throw new SetupFlowError(`
|
|
28
|
+
throw new SetupFlowError(`Link service rejected init (HTTP ${initRes.status}). Retry in a moment; if it persists, check that ${apiBase} is reachable and not behind a proxy that strips the request body.`);
|
|
28
29
|
}
|
|
29
30
|
const initBody = (await initRes.json());
|
|
30
31
|
if (typeof initBody.session_id !== "string" ||
|
|
31
32
|
initBody.session_id.length === 0) {
|
|
32
|
-
throw new SetupFlowError("
|
|
33
|
+
throw new SetupFlowError("Link service returned a malformed response (missing session_id). Retry; if it persists, this is a server-side bug worth reporting.");
|
|
34
|
+
}
|
|
35
|
+
if (typeof initBody.owner_choice_url !== "string" ||
|
|
36
|
+
initBody.owner_choice_url.length === 0) {
|
|
37
|
+
throw new SetupFlowError("The Link service did not return a usable owner_choice_url in the init response (missing, empty, or not a string). Most likely this Services deployment predates the owner_choice_url contract (masons.ai#4320) — upgrade the server, or use a plugin release that predates the contract. This runtime does not compose that address itself.");
|
|
33
38
|
}
|
|
34
39
|
sessionId = initBody.session_id;
|
|
40
|
+
ownerChoiceUrl = initBody.owner_choice_url;
|
|
35
41
|
}
|
|
36
42
|
catch (err) {
|
|
37
43
|
if (err instanceof SetupFlowError)
|
|
38
44
|
throw err;
|
|
39
45
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
40
|
-
throw new SetupFlowError(`Could not reach the
|
|
46
|
+
throw new SetupFlowError(`Could not reach the Link service at ${apiBase} (${message}). Retry in a moment.`);
|
|
41
47
|
}
|
|
42
|
-
const handoffUrl = `${options.idpBaseUrl}/console/handoff?session=${encodeURIComponent(sessionId)}`;
|
|
43
48
|
return {
|
|
44
49
|
sessionId,
|
|
45
|
-
handoffUrl,
|
|
50
|
+
handoffUrl: verifyOwnerChoiceUrl(ownerChoiceUrl, options.idpBaseUrl, options.idpBaseUrlIsDefault ?? false),
|
|
46
51
|
apiBase,
|
|
47
52
|
privateKey,
|
|
48
53
|
expiresAt: Date.now() + HANDOFF_TIMEOUT_MS,
|
|
@@ -56,14 +61,14 @@ export async function completeBridgeHandoff(session) {
|
|
|
56
61
|
}
|
|
57
62
|
catch (err) {
|
|
58
63
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
59
|
-
throw new SetupFlowError(`Handoff received but could not be decrypted (${message}). The link may have been tampered with — re-run
|
|
64
|
+
throw new SetupFlowError(`Handoff received but could not be decrypted (${message}). The link may have been tampered with — re-run Link. If it keeps failing, your network may be inserting a TLS-terminating proxy that mangled the ciphertext.`);
|
|
60
65
|
}
|
|
61
66
|
assertHandoffDeadlineActive(session.expiresAt);
|
|
62
67
|
if (typeof payload.token !== "string" ||
|
|
63
68
|
!RUNTIME_KEY_PATTERN.test(payload.token) ||
|
|
64
69
|
typeof payload.agent?.handle !== "string" ||
|
|
65
70
|
typeof payload.agent?.agentId !== "string") {
|
|
66
|
-
throw new SetupFlowError("Handoff payload did not match the expected shape. Re-run
|
|
71
|
+
throw new SetupFlowError("Handoff payload did not match the expected shape. Re-run Link; if it keeps happening, this is a server-side bug worth reporting.");
|
|
67
72
|
}
|
|
68
73
|
return {
|
|
69
74
|
token: payload.token,
|
|
@@ -94,7 +99,7 @@ async function pollForCompletion(apiBase, sessionId, expiresAt) {
|
|
|
94
99
|
if (Date.now() >= expiresAt)
|
|
95
100
|
break;
|
|
96
101
|
if (res.status === 404) {
|
|
97
|
-
throw new SetupFlowError("Handoff session expired before the runtime key was delivered. Re-run
|
|
102
|
+
throw new SetupFlowError("Handoff session expired before the runtime key was delivered. Re-run Link.");
|
|
98
103
|
}
|
|
99
104
|
if (!res.ok) {
|
|
100
105
|
await sleepBeforeNextPoll(expiresAt);
|
|
@@ -109,8 +114,8 @@ async function pollForCompletion(apiBase, sessionId, expiresAt) {
|
|
|
109
114
|
await sleepBeforeNextPoll(expiresAt);
|
|
110
115
|
}
|
|
111
116
|
throw new SetupFlowError(lastNetworkError
|
|
112
|
-
? `Handoff timed out before the runtime key was delivered; the last poll could not reach ${apiBase} (${lastNetworkError.message}). Re-run
|
|
113
|
-
: "Handoff timed out before the runtime key was delivered. Re-run
|
|
117
|
+
? `Handoff timed out before the runtime key was delivered; the last poll could not reach ${apiBase} (${lastNetworkError.message}). Re-run Link; if you're behind a proxy that blocks long-running fetches, retry on a different network.`
|
|
118
|
+
: "Handoff timed out before the runtime key was delivered. Re-run Link; if you're behind a proxy that blocks long-running fetches, retry on a different network.");
|
|
114
119
|
}
|
|
115
120
|
async function sleepBeforeNextPoll(expiresAt) {
|
|
116
121
|
const remainingMs = expiresAt - Date.now();
|
|
@@ -144,6 +149,34 @@ function decryptBridgeEnvelope(privateKey, envelope) {
|
|
|
144
149
|
]);
|
|
145
150
|
return JSON.parse(plaintext.toString("utf-8"));
|
|
146
151
|
}
|
|
152
|
+
function verifyOwnerChoiceUrl(ownerChoiceUrl, idpBaseUrl, idpBaseUrlIsDefault) {
|
|
153
|
+
const configured = parseAbsoluteUrl(idpBaseUrl);
|
|
154
|
+
if (!configured) {
|
|
155
|
+
throw new SetupFlowError("This Runtime's identity provider (idpBaseUrl) is not an absolute http(s) URL, so the owner-choice address the Link service named cannot be verified. Set idpBaseUrl for this channel to an absolute http(s) URL and re-run Link.");
|
|
156
|
+
}
|
|
157
|
+
const named = parseAbsoluteUrl(ownerChoiceUrl);
|
|
158
|
+
if (!named) {
|
|
159
|
+
throw new SetupFlowError("The Link service named an owner-choice address that is not a valid absolute URL; refusing to direct the owner's browser to it. Retry; if it persists, this is a server-side bug worth reporting.");
|
|
160
|
+
}
|
|
161
|
+
if (named.protocol !== "http:" && named.protocol !== "https:") {
|
|
162
|
+
throw new SetupFlowError(`The Link service named an owner-choice address using the "${named.protocol}" scheme, which is not an address a browser can be sent to; refusing it. Retry; if it persists, this is a server-side bug worth reporting.`);
|
|
163
|
+
}
|
|
164
|
+
if (named.origin !== configured.origin) {
|
|
165
|
+
const anchor = idpBaseUrlIsDefault
|
|
166
|
+
? "the built-in default identity provider (idpBaseUrl is not set)"
|
|
167
|
+
: "your configured identity provider (idpBaseUrl)";
|
|
168
|
+
throw new SetupFlowError(`The Link service named an owner-choice address on ${named.origin}, which is not ${anchor}: ${configured.origin}. Refusing to direct the owner's browser there. If your deployment's identity provider genuinely moved, update idpBaseUrl for this channel. If you did not expect this, do not change configuration — the server may be misdirecting your sign-in; report it.`);
|
|
169
|
+
}
|
|
170
|
+
return named.href;
|
|
171
|
+
}
|
|
172
|
+
function parseAbsoluteUrl(value) {
|
|
173
|
+
try {
|
|
174
|
+
return new URL(value);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
147
180
|
function normalizeHttpBase(apiHost) {
|
|
148
181
|
const trimmed = apiHost.replace(/\/+$/, "");
|
|
149
182
|
if (/^https?:\/\//.test(trimmed))
|
|
@@ -13,10 +13,6 @@ export declare class PlatformNetworkError extends Error {
|
|
|
13
13
|
readonly detail: string;
|
|
14
14
|
constructor(code: "timeout" | "network", detail: string);
|
|
15
15
|
}
|
|
16
|
-
export interface RequestConnectionResponse {
|
|
17
|
-
requestIds: string[];
|
|
18
|
-
status: string;
|
|
19
|
-
}
|
|
20
16
|
export interface ConnectionNodeRef {
|
|
21
17
|
kind: string;
|
|
22
18
|
mstpAddress: string;
|
|
@@ -24,31 +20,43 @@ export interface ConnectionNodeRef {
|
|
|
24
20
|
displayName?: string;
|
|
25
21
|
avatarUrl?: string;
|
|
26
22
|
}
|
|
27
|
-
export
|
|
23
|
+
export type PackagedRequestStatus = "awaiting-your-decision" | "awaiting-counterparty" | "accepted" | "ignored" | "withdrawn";
|
|
24
|
+
export interface PackagedTombstoneCounterparty {
|
|
28
25
|
id: string;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
kind?: string;
|
|
27
|
+
handle?: string;
|
|
28
|
+
mstpAddress?: string;
|
|
29
|
+
tombstone: true;
|
|
30
|
+
}
|
|
31
|
+
export type PackagedCounterparty = ConnectionNodeRef | PackagedTombstoneCounterparty;
|
|
32
|
+
export declare function isPackagedTombstone(c: PackagedCounterparty): c is PackagedTombstoneCounterparty;
|
|
33
|
+
export interface PackagedRequest {
|
|
34
|
+
id: string;
|
|
35
|
+
counterparty: PackagedCounterparty;
|
|
36
|
+
counterpartyProfile?: {
|
|
37
|
+
tagline: string | null;
|
|
38
|
+
} | null;
|
|
39
|
+
status: PackagedRequestStatus;
|
|
40
|
+
shadowed?: true;
|
|
39
41
|
createdAt: string;
|
|
42
|
+
resolvedAt?: string;
|
|
40
43
|
}
|
|
41
44
|
export interface ListRequestsResponse {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
export interface AcceptRequestResponse {
|
|
46
|
-
status: "accepted";
|
|
47
|
-
counterparty: ConnectionNodeRef | null;
|
|
45
|
+
items: PackagedRequest[];
|
|
46
|
+
nextCursor: string | null;
|
|
48
47
|
}
|
|
49
|
-
export interface
|
|
50
|
-
|
|
48
|
+
export interface CreateRequestResult {
|
|
49
|
+
request: PackagedRequest | null;
|
|
50
|
+
created: boolean;
|
|
51
51
|
}
|
|
52
|
+
export type ResolveRequestResult = {
|
|
53
|
+
outcome: "resolved";
|
|
54
|
+
idempotent: boolean;
|
|
55
|
+
request: PackagedRequest | null;
|
|
56
|
+
} | {
|
|
57
|
+
outcome: "already_resolved";
|
|
58
|
+
status: string | null;
|
|
59
|
+
};
|
|
52
60
|
export interface UpdateProfileParams {
|
|
53
61
|
name?: string;
|
|
54
62
|
scope?: string;
|
|
@@ -73,18 +81,15 @@ export interface ListConnectionsResponse {
|
|
|
73
81
|
}>;
|
|
74
82
|
}
|
|
75
83
|
export declare function apiFetch(url: string, init?: RequestInit): Promise<Response>;
|
|
76
|
-
export declare function requestConnection(cfg: PlatformClientConfig, runtimeKey: string,
|
|
77
|
-
targetHandle: string;
|
|
78
|
-
variants: ("distribute" | "receive")[];
|
|
79
|
-
}): Promise<RequestConnectionResponse>;
|
|
84
|
+
export declare function requestConnection(cfg: PlatformClientConfig, runtimeKey: string, targetHandle: string): Promise<CreateRequestResult>;
|
|
80
85
|
export declare function listRequests(cfg: PlatformClientConfig, runtimeKey: string, params?: {
|
|
81
|
-
status?: string;
|
|
82
|
-
direction?: string;
|
|
83
|
-
page?: number;
|
|
84
86
|
limit?: number;
|
|
87
|
+
cursor?: string;
|
|
88
|
+
counterparty?: string;
|
|
85
89
|
}): Promise<ListRequestsResponse>;
|
|
86
|
-
export declare
|
|
87
|
-
export declare
|
|
90
|
+
export declare const acceptRequest: (cfg: PlatformClientConfig, runtimeKey: string, requestId: string) => Promise<ResolveRequestResult>;
|
|
91
|
+
export declare const ignoreRequest: (cfg: PlatformClientConfig, runtimeKey: string, requestId: string) => Promise<ResolveRequestResult>;
|
|
92
|
+
export declare const withdrawRequest: (cfg: PlatformClientConfig, runtimeKey: string, requestId: string) => Promise<ResolveRequestResult>;
|
|
88
93
|
export declare function updateProfile(cfg: PlatformClientConfig, runtimeKey: string, params: UpdateProfileParams): Promise<UpdateProfileResponse>;
|
|
89
94
|
export declare function listConnections(cfg: PlatformClientConfig, runtimeKey: string): Promise<ListConnectionsResponse>;
|
|
90
95
|
export declare function getIdentity(cfg: PlatformClientConfig, runtimeKey: string): Promise<ConnectionNodeRef | null>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform-client.d.ts","sourceRoot":"","sources":["../src/platform-client.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,gBAAgB,0BAA0B,CAAC;AASxD,eAAO,MAAM,qBAAqB,iDACc,CAAC;AAEjD,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EAC5B,OAAO,EAAE,MAAM;CAKlB;AAiBD,qBAAa,oBAAqB,SAAQ,KAAK;aAE3B,IAAI,EAAE,SAAS,GAAG,SAAS;aAE3B,MAAM,EAAE,MAAM;gBAFd,IAAI,EAAE,SAAS,GAAG,SAAS,EAE3B,MAAM,EAAE,MAAM;CAKjC;
|
|
1
|
+
{"version":3,"file":"platform-client.d.ts","sourceRoot":"","sources":["../src/platform-client.ts"],"names":[],"mappings":"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"}
|
package/dist/platform-client.js
CHANGED
|
@@ -20,6 +20,9 @@ export class PlatformNetworkError extends Error {
|
|
|
20
20
|
this.name = "PlatformNetworkError";
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
export function isPackagedTombstone(c) {
|
|
24
|
+
return "tombstone" in c && c.tombstone === true;
|
|
25
|
+
}
|
|
23
26
|
function baseUrl(cfg) {
|
|
24
27
|
const trimmed = cfg.apiHost.replace(/\/+$/, "");
|
|
25
28
|
const origin = /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
@@ -73,31 +76,31 @@ export async function apiFetch(url, init = {}) {
|
|
|
73
76
|
clearTimeout(timer);
|
|
74
77
|
}
|
|
75
78
|
}
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
const REQUESTS_PATH = "/me/connection-requests";
|
|
80
|
+
export async function requestConnection(cfg, runtimeKey, targetHandle) {
|
|
81
|
+
const res = await apiFetch(`${baseUrl(cfg)}${REQUESTS_PATH}`, {
|
|
78
82
|
method: "POST",
|
|
79
83
|
headers: {
|
|
80
84
|
"Content-Type": "application/json",
|
|
81
85
|
Authorization: `Bearer ${runtimeKey}`,
|
|
82
86
|
},
|
|
83
|
-
body: JSON.stringify(
|
|
87
|
+
body: JSON.stringify({ targetHandle }),
|
|
84
88
|
});
|
|
85
89
|
if (!res.ok)
|
|
86
90
|
return handleError(res);
|
|
87
|
-
|
|
91
|
+
const body = (await res.json().catch(() => ({})));
|
|
92
|
+
return { request: body.request ?? null, created: res.status === 201 };
|
|
88
93
|
}
|
|
89
94
|
export async function listRequests(cfg, runtimeKey, params) {
|
|
90
95
|
const query = new URLSearchParams();
|
|
91
|
-
if (params?.status != null)
|
|
92
|
-
query.set("status", params.status);
|
|
93
|
-
if (params?.direction != null)
|
|
94
|
-
query.set("direction", params.direction);
|
|
95
|
-
if (params?.page != null)
|
|
96
|
-
query.set("page", String(params.page));
|
|
97
96
|
if (params?.limit != null)
|
|
98
97
|
query.set("limit", String(params.limit));
|
|
98
|
+
if (params?.cursor != null)
|
|
99
|
+
query.set("cursor", params.cursor);
|
|
100
|
+
if (params?.counterparty != null)
|
|
101
|
+
query.set("counterparty", params.counterparty);
|
|
99
102
|
const qs = query.toString();
|
|
100
|
-
const url = `${baseUrl(cfg)}
|
|
103
|
+
const url = `${baseUrl(cfg)}${REQUESTS_PATH}${qs ? `?${qs}` : ""}`;
|
|
101
104
|
const res = await apiFetch(url, {
|
|
102
105
|
headers: { Authorization: `Bearer ${runtimeKey}` },
|
|
103
106
|
});
|
|
@@ -105,24 +108,34 @@ export async function listRequests(cfg, runtimeKey, params) {
|
|
|
105
108
|
return handleError(res);
|
|
106
109
|
return (await res.json());
|
|
107
110
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
111
|
+
function resolveVerb(verb) {
|
|
112
|
+
return async (cfg, runtimeKey, requestId) => {
|
|
113
|
+
const res = await apiFetch(`${baseUrl(cfg)}${REQUESTS_PATH}/${encodeURIComponent(requestId)}/${verb}`, {
|
|
114
|
+
method: "POST",
|
|
115
|
+
headers: { Authorization: `Bearer ${runtimeKey}` },
|
|
116
|
+
});
|
|
117
|
+
if (res.status === 409) {
|
|
118
|
+
const conflict = (await res.json().catch(() => ({})));
|
|
119
|
+
if (conflict.error === "already_resolved") {
|
|
120
|
+
return {
|
|
121
|
+
outcome: "already_resolved",
|
|
122
|
+
status: typeof conflict.status === "string" ? conflict.status : null,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (!res.ok)
|
|
127
|
+
return handleError(res);
|
|
128
|
+
const body = (await res.json().catch(() => ({})));
|
|
129
|
+
return {
|
|
130
|
+
outcome: "resolved",
|
|
131
|
+
idempotent: body.idempotent === true,
|
|
132
|
+
request: body.request ?? null,
|
|
133
|
+
};
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
export const acceptRequest = resolveVerb("accept");
|
|
137
|
+
export const ignoreRequest = resolveVerb("ignore");
|
|
138
|
+
export const withdrawRequest = resolveVerb("withdraw");
|
|
126
139
|
export async function updateProfile(cfg, runtimeKey, params) {
|
|
127
140
|
const res = await apiFetch(`${baseUrl(cfg)}/me/profile`, {
|
|
128
141
|
method: "PATCH",
|
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;CAoahC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -143,9 +143,11 @@ const plugin = {
|
|
|
143
143
|
"separate from your owner's conversation; " +
|
|
144
144
|
"masons_note_for_owner(content, from?) — save a note for your owner's next turn. " +
|
|
145
145
|
"Other network tools: masons_list_requests, masons_send_connection_request, " +
|
|
146
|
-
"masons_accept_request,
|
|
146
|
+
"masons_accept_request, masons_list_connections, " +
|
|
147
147
|
"masons_end_conversation (rare one-shot close signal only), " +
|
|
148
148
|
"masons_status (your canonical identity and participation status). " +
|
|
149
|
+
"masons_withdraw_request (take back a connection request you sent). " +
|
|
150
|
+
"masons_ignore_request (set aside a connection request awaiting your decision; silent — the sender is not notified). " +
|
|
149
151
|
"Always try these tools first for network operations. " +
|
|
150
152
|
"If a tool call fails, report the error to your user — do not silently work around it. " +
|
|
151
153
|
"You interact with multiple entities simultaneously — your owner and agents on the network. " +
|
|
@@ -193,18 +195,18 @@ const plugin = {
|
|
|
193
195
|
dynamicContext =
|
|
194
196
|
"[Context: Agent Network] You recently installed the agent network plugin " +
|
|
195
197
|
"but it is not yet authorized. If your current channel sender is the verified " +
|
|
196
|
-
"OpenClaw owner, call
|
|
198
|
+
"OpenClaw owner, call masons_link to generate a MASONS handoff URL here. " +
|
|
197
199
|
"If owner authority is unavailable, tell your user to run this terminal fallback: " +
|
|
198
200
|
"`openclaw channels login --channel agent-network`. Browser sign-in handles " +
|
|
199
|
-
"agent selection or creation. After
|
|
201
|
+
"agent selection or creation. After the Link completes, OpenClaw will reload and " +
|
|
200
202
|
"the agent network tools will become available.";
|
|
201
203
|
if (state.pendingTarget) {
|
|
202
|
-
dynamicContext += ` After
|
|
204
|
+
dynamicContext += ` After the Link completes, send a connection request to ${state.pendingTarget} — they invited your user to join.`;
|
|
203
205
|
}
|
|
204
206
|
}
|
|
205
207
|
else if (state.needsProfile) {
|
|
206
208
|
dynamicContext =
|
|
207
|
-
"[Context: Agent Network] You are
|
|
209
|
+
"[Context: Agent Network] You are linked to the agent network, but your agent's profile is empty. " +
|
|
208
210
|
"Generate a profile based on what you know about the user and their agent, then show it to the user for confirmation. " +
|
|
209
211
|
"Once confirmed, call masons_update_profile with all four fields (name, scope, about, audience). " +
|
|
210
212
|
"Without a profile, other agents can't see who you are — " +
|
|
@@ -214,7 +216,7 @@ const plugin = {
|
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
218
|
else if (state.pendingTarget) {
|
|
217
|
-
dynamicContext = `[Context: Agent Network] You are
|
|
219
|
+
dynamicContext = `[Context: Agent Network] You are linked to the agent network. You have a pending connection — call the masons_send_connection_request tool with targetHandle "${state.pendingTarget}" to send a connection request.`;
|
|
218
220
|
}
|
|
219
221
|
if (!dynamicContext &&
|
|
220
222
|
state.hasCredentials &&
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChannelSetupResult } from "./channel-setup.js";
|
|
1
2
|
interface ToolContent {
|
|
2
3
|
content: Array<{
|
|
3
4
|
type: "text";
|
|
@@ -25,6 +26,9 @@ interface ToolApi {
|
|
|
25
26
|
}): void;
|
|
26
27
|
}
|
|
27
28
|
export declare function _resetToolsForTesting(): void;
|
|
29
|
+
export declare function terminalSetupInstructions(): string;
|
|
30
|
+
export declare function ownerRefusalText(reason: "known-non-owner" | "ambiguous"): string;
|
|
31
|
+
export declare function formatChannelSetupResult(result: ChannelSetupResult): string;
|
|
28
32
|
export declare function registerTools(api: ToolApi): void;
|
|
29
33
|
export {};
|
|
30
34
|
//# sourceMappingURL=tools.d.ts.map
|