@masons/agent-network 0.6.22 → 0.6.23
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/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 +3 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +226 -72
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/openclaw.plugin.json +2 -1
- package/package.json +1 -1
- package/skills/agent-network/SKILL.md +57 -17
|
@@ -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. " +
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAmFA,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;AAoDD,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAodD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAqlChD"}
|
package/dist/tools.js
CHANGED
|
@@ -5,7 +5,7 @@ import { clearTargetHandle, extractNetworkConfig, getConnectorClient, getDmScope
|
|
|
5
5
|
import { getOwnerHandle } from "./environment-context.js";
|
|
6
6
|
import { classifyIdentityError, formatCanonicalNode, formatKindLabel, } from "./identity-format.js";
|
|
7
7
|
import { ownerNotesQueue } from "./owner-notes.js";
|
|
8
|
-
import { acceptRequest,
|
|
8
|
+
import { acceptRequest, getIdentity, ignoreRequest, isPackagedTombstone, listConnections, listRequests, PlatformApiError, PlatformNetworkError, requestConnection, updateProfile, withdrawRequest, } from "./platform-client.js";
|
|
9
9
|
import { isServicesRetainedReplyContext } from "./services-retained-reply-context.js";
|
|
10
10
|
import { getCurrentTurnChannelId, getCurrentTurnIsOwnerNonConsuming, getCurrentTurnOwnerSignal, } from "./turn-context.js";
|
|
11
11
|
import { getLatestPublishedVersion, getPluginVersion, getUpdateInfo, } from "./update-check.js";
|
|
@@ -47,11 +47,61 @@ function maybeAppendUpdateNotice(result) {
|
|
|
47
47
|
function withUpdateNotice(fn) {
|
|
48
48
|
return async (id, params) => maybeAppendUpdateNotice(await fn(id, params));
|
|
49
49
|
}
|
|
50
|
-
function
|
|
51
|
-
if (
|
|
52
|
-
return
|
|
50
|
+
function counterpartyName(c) {
|
|
51
|
+
if (isPackagedTombstone(c)) {
|
|
52
|
+
return c.handle ? `@${c.handle}` : (c.mstpAddress ?? c.id);
|
|
53
53
|
}
|
|
54
|
-
return
|
|
54
|
+
return c.displayName ?? (c.handle ? `@${c.handle}` : c.mstpAddress);
|
|
55
|
+
}
|
|
56
|
+
function suppressionKey(item) {
|
|
57
|
+
const c = item.counterparty;
|
|
58
|
+
if (isPackagedTombstone(c))
|
|
59
|
+
return `tombstone:${c.mstpAddress ?? c.id}`;
|
|
60
|
+
const address = c.mstpAddress;
|
|
61
|
+
if (!address || address.endsWith("/"))
|
|
62
|
+
return null;
|
|
63
|
+
return address;
|
|
64
|
+
}
|
|
65
|
+
function collapseToCounterpartyGrain(items) {
|
|
66
|
+
const seen = new Set();
|
|
67
|
+
const rows = [];
|
|
68
|
+
for (const item of items) {
|
|
69
|
+
if (item.shadowed)
|
|
70
|
+
continue;
|
|
71
|
+
const key = suppressionKey(item);
|
|
72
|
+
if (key !== null) {
|
|
73
|
+
if (seen.has(key))
|
|
74
|
+
continue;
|
|
75
|
+
seen.add(key);
|
|
76
|
+
}
|
|
77
|
+
rows.push(item);
|
|
78
|
+
}
|
|
79
|
+
return rows;
|
|
80
|
+
}
|
|
81
|
+
function directionLabel(status) {
|
|
82
|
+
if (status === "awaiting-your-decision")
|
|
83
|
+
return "incoming";
|
|
84
|
+
if (status === "awaiting-counterparty")
|
|
85
|
+
return "outgoing";
|
|
86
|
+
return "history";
|
|
87
|
+
}
|
|
88
|
+
function formatAlreadyResolved(status, act) {
|
|
89
|
+
const nothing = `Nothing to ${act} —`;
|
|
90
|
+
if (status == null) {
|
|
91
|
+
return `${nothing} this request is no longer pending.`;
|
|
92
|
+
}
|
|
93
|
+
const terminal = status === "accepted" || status === "ignored" || status === "withdrawn";
|
|
94
|
+
return terminal
|
|
95
|
+
? `${nothing} this request is already resolved as "${status}".`
|
|
96
|
+
: `${nothing} this request is not in a state you can ${act} (status: "${status}").`;
|
|
97
|
+
}
|
|
98
|
+
function formatVerb404(err, verbLabel) {
|
|
99
|
+
return err.code === "not_found"
|
|
100
|
+
? "Request not found, or it is not addressable from your perspective. Use masons_list_requests to see current requests."
|
|
101
|
+
: `This Services deployment does not serve the ${verbLabel} endpoint. Nothing changed — the request is unchanged.`;
|
|
102
|
+
}
|
|
103
|
+
function quoteRejected(value) {
|
|
104
|
+
return `"${typeof value === "string" ? value : JSON.stringify(value)}"`;
|
|
55
105
|
}
|
|
56
106
|
const IDENTITY_NO_FALLBACK = "This is not an answer — do not assume any locally-cached handle or name is this Runtime's identity.";
|
|
57
107
|
function formatIdentityError(err) {
|
|
@@ -417,15 +467,20 @@ export function registerTools(api) {
|
|
|
417
467
|
const targetHandle = params.targetHandle;
|
|
418
468
|
let result;
|
|
419
469
|
try {
|
|
420
|
-
result = await requestConnection(cfg, apiKey,
|
|
421
|
-
targetHandle,
|
|
422
|
-
variants: ["distribute", "receive"],
|
|
423
|
-
});
|
|
470
|
+
result = await requestConnection(cfg, apiKey, targetHandle);
|
|
424
471
|
}
|
|
425
472
|
catch (err) {
|
|
426
473
|
if (err instanceof PlatformApiError) {
|
|
474
|
+
if (err.status === 409 && err.code === "already_connected") {
|
|
475
|
+
if (getPendingTarget()) {
|
|
476
|
+
await clearTargetHandle();
|
|
477
|
+
}
|
|
478
|
+
return textResult(`Already connected with @${targetHandle} — no request needed. Use masons_send_message to reach them.`);
|
|
479
|
+
}
|
|
427
480
|
if (err.status === 404) {
|
|
428
|
-
return textResult(
|
|
481
|
+
return textResult(err.code === "target_not_found"
|
|
482
|
+
? `Agent @${targetHandle} not found. Check the handle and try again.`
|
|
483
|
+
: "This Services deployment does not serve the connection-request endpoint. Nothing was sent.");
|
|
429
484
|
}
|
|
430
485
|
if (err.status === 401) {
|
|
431
486
|
return textResult("Authentication failed. The runtime key may be invalid. Ask the user to run `openclaw channels login --channel agent-network`.");
|
|
@@ -440,35 +495,73 @@ export function registerTools(api) {
|
|
|
440
495
|
if (getPendingTarget()) {
|
|
441
496
|
await clearTargetHandle();
|
|
442
497
|
}
|
|
443
|
-
|
|
498
|
+
const request = result.request;
|
|
499
|
+
if (request === null) {
|
|
500
|
+
return textResult("The network accepted the call but returned no request object — " +
|
|
501
|
+
"the outcome is unknown; use masons_list_requests to check.");
|
|
502
|
+
}
|
|
503
|
+
const who = counterpartyName(request.counterparty);
|
|
504
|
+
if (request.status === "accepted") {
|
|
505
|
+
return textResult(`Connection established with ${who}. They had already requested a connection with you, so sending yours completed it — nothing is pending. You can now send messages using masons_send_message.`);
|
|
506
|
+
}
|
|
507
|
+
if (!result.created) {
|
|
508
|
+
return textResult(`A connection request to ${who} is already pending — no new request was sent.`);
|
|
509
|
+
}
|
|
510
|
+
return textResult(`Connection request sent to ${who}. Status: ${request.status}. The other agent's owner will be notified.`);
|
|
444
511
|
}),
|
|
445
512
|
});
|
|
446
513
|
api.registerTool({
|
|
447
514
|
name: "masons_list_requests",
|
|
448
|
-
description: "List connection requests —
|
|
515
|
+
description: "List connection requests — one entry per counterparty, keyed by the " +
|
|
516
|
+
"request ID every request tool takes. Shows what is awaiting your " +
|
|
517
|
+
"decision, what is awaiting theirs, and resolved history. Each entry " +
|
|
518
|
+
"is that counterparty's latest state; pass counterparty to see every " +
|
|
519
|
+
"row of one pair instead.",
|
|
449
520
|
parameters: Type.Object({
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
521
|
+
direction: Type.Optional(Type.Union([
|
|
522
|
+
Type.Literal("all"),
|
|
523
|
+
Type.Literal("incoming"),
|
|
524
|
+
Type.Literal("outgoing"),
|
|
525
|
+
], {
|
|
526
|
+
description: '"all" (default) — both; "incoming" — awaiting YOUR decision; ' +
|
|
527
|
+
'"outgoing" — awaiting the counterparty. Direction is derived ' +
|
|
528
|
+
"from each request's status; it is not a state you can filter " +
|
|
529
|
+
"the network by.",
|
|
530
|
+
})),
|
|
531
|
+
include_history: Type.Optional(Type.Boolean({
|
|
532
|
+
description: "Include resolved requests (accepted / ignored / withdrawn). " +
|
|
533
|
+
"Default true — pass false for pending requests only.",
|
|
456
534
|
})),
|
|
457
|
-
|
|
458
|
-
description:
|
|
535
|
+
counterparty: Type.Optional(Type.String({
|
|
536
|
+
description: "Handle of one agent — show the full per-pair history with " +
|
|
537
|
+
"@handle — bypasses the one-row-per-counterparty collapse.",
|
|
459
538
|
})),
|
|
460
539
|
}),
|
|
461
540
|
execute: withUpdateNotice(async (_id, params) => {
|
|
462
541
|
const cfg = requirePlatformConfig();
|
|
463
542
|
const apiKey = requireApiKey();
|
|
464
|
-
const
|
|
465
|
-
|
|
543
|
+
const rawDirection = params.direction;
|
|
544
|
+
if (rawDirection !== undefined &&
|
|
545
|
+
rawDirection !== "all" &&
|
|
546
|
+
rawDirection !== "incoming" &&
|
|
547
|
+
rawDirection !== "outgoing") {
|
|
548
|
+
return textResult(`${quoteRejected(rawDirection)} is not a direction — use "all", "incoming", or "outgoing". Nothing was read.`);
|
|
549
|
+
}
|
|
550
|
+
const rawHistory = params.include_history;
|
|
551
|
+
if (rawHistory !== undefined && typeof rawHistory !== "boolean") {
|
|
552
|
+
return textResult(`${quoteRejected(rawHistory)} is not a boolean — include_history takes true or false. Nothing was read.`);
|
|
553
|
+
}
|
|
554
|
+
const direction = rawDirection ?? "all";
|
|
555
|
+
const includeHistory = rawHistory ?? true;
|
|
556
|
+
const rawCounterparty = params.counterparty;
|
|
557
|
+
const counterparty = typeof rawCounterparty === "string"
|
|
558
|
+
? rawCounterparty.replace(/^@/, "").trim() || undefined
|
|
559
|
+
: undefined;
|
|
466
560
|
let result;
|
|
467
561
|
try {
|
|
468
562
|
result = await listRequests(cfg, apiKey, {
|
|
469
|
-
status,
|
|
470
|
-
direction,
|
|
471
563
|
limit: 100,
|
|
564
|
+
...(counterparty ? { counterparty } : {}),
|
|
472
565
|
});
|
|
473
566
|
}
|
|
474
567
|
catch (err) {
|
|
@@ -476,6 +569,9 @@ export function registerTools(api) {
|
|
|
476
569
|
if (err.status === 401) {
|
|
477
570
|
return textResult("Authentication failed. The runtime key may be invalid. Ask the user to run `openclaw channels login --channel agent-network`.");
|
|
478
571
|
}
|
|
572
|
+
if (err.status === 404) {
|
|
573
|
+
return textResult("This Services deployment does not serve the packaged connection-request endpoint. Nothing was read.");
|
|
574
|
+
}
|
|
479
575
|
return textResult(`Failed to list requests: ${err.message}`);
|
|
480
576
|
}
|
|
481
577
|
if (err instanceof PlatformNetworkError) {
|
|
@@ -483,53 +579,57 @@ export function registerTools(api) {
|
|
|
483
579
|
}
|
|
484
580
|
throw err;
|
|
485
581
|
}
|
|
486
|
-
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
: "incoming ";
|
|
492
|
-
return textResult(`No ${dirLabel}${status === "all" ? "" : `${status} `}connection requests.`);
|
|
493
|
-
}
|
|
494
|
-
const lines = result.items.map((item) => {
|
|
495
|
-
const dir = item.direction ?? direction;
|
|
496
|
-
const node = dir === "outgoing" ? item.toNode : item.fromNode;
|
|
497
|
-
const otherName = node?.displayName || node?.handle || "unknown";
|
|
498
|
-
const otherHandle = node?.handle || "unknown";
|
|
499
|
-
const kindLabel = formatKindLabel(node?.kind);
|
|
500
|
-
const dirArrow = dir === "outgoing" ? "→" : "←";
|
|
501
|
-
const parts = [
|
|
502
|
-
`• ${dirArrow} ${kindLabel}${otherName} (@${otherHandle})`,
|
|
503
|
-
` ID: ${item.id} | Variant: ${item.variant} | Status: ${item.status}`,
|
|
504
|
-
];
|
|
505
|
-
if (item.matchmaking?.title) {
|
|
506
|
-
parts.push(` Why: ${item.matchmaking.title}`);
|
|
507
|
-
}
|
|
508
|
-
if (item.matchmaking?.benefit) {
|
|
509
|
-
parts.push(` Benefit: ${item.matchmaking.benefit}`);
|
|
510
|
-
}
|
|
511
|
-
if (item.matchmaking?.scenario) {
|
|
512
|
-
parts.push(` Context: ${item.matchmaking.scenario}`);
|
|
513
|
-
}
|
|
514
|
-
return parts.join("\n");
|
|
582
|
+
const filtered = result.items.filter((item) => {
|
|
583
|
+
const label = directionLabel(item.status);
|
|
584
|
+
if (label === "history")
|
|
585
|
+
return includeHistory;
|
|
586
|
+
return direction === "all" || direction === label;
|
|
515
587
|
});
|
|
516
|
-
const
|
|
517
|
-
?
|
|
518
|
-
:
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
? "\n\nUse masons_accept_request or masons_decline_request with the ID to act on incoming requests."
|
|
588
|
+
const rows = counterparty
|
|
589
|
+
? filtered
|
|
590
|
+
: collapseToCounterpartyGrain(filtered);
|
|
591
|
+
const scope = direction !== "all" &&
|
|
592
|
+
rows.every((item) => directionLabel(item.status) === direction)
|
|
593
|
+
? `${direction} `
|
|
523
594
|
: "";
|
|
524
|
-
|
|
595
|
+
const withWho = counterparty ? ` with @${counterparty}` : "";
|
|
596
|
+
const moreLine = result.nextCursor !== null
|
|
597
|
+
? "\n\nMore requests exist beyond this page — this is the most recent page, not the whole history."
|
|
598
|
+
: "";
|
|
599
|
+
if (rows.length === 0) {
|
|
600
|
+
return textResult(`No ${scope}${includeHistory ? "" : "pending "}connection requests${withWho}.${moreLine}`);
|
|
601
|
+
}
|
|
602
|
+
const lines = rows.map((item) => {
|
|
603
|
+
const node = item.counterparty;
|
|
604
|
+
const label = directionLabel(item.status);
|
|
605
|
+
const arrow = label === "incoming" ? "←" : label === "outgoing" ? "→" : "·";
|
|
606
|
+
const kindLabel = formatKindLabel(node.kind);
|
|
607
|
+
const handle = node.handle ? `@${node.handle}` : "no handle";
|
|
608
|
+
const shadowMark = item.shadowed ? " | shadowed" : "";
|
|
609
|
+
return [
|
|
610
|
+
`• ${arrow} ${kindLabel}${counterpartyName(node)} (${handle})`,
|
|
611
|
+
` ID: ${item.id} | Status: ${item.status} | ${label}${shadowMark}`,
|
|
612
|
+
].join("\n");
|
|
613
|
+
});
|
|
614
|
+
const hints = [];
|
|
615
|
+
if (rows.some((item) => item.status === "awaiting-your-decision")) {
|
|
616
|
+
hints.push("Use masons_accept_request or masons_ignore_request with the ID to act on requests awaiting your decision.");
|
|
617
|
+
}
|
|
618
|
+
if (rows.some((item) => item.status === "awaiting-counterparty")) {
|
|
619
|
+
hints.push("Use masons_withdraw_request with the ID to take back a request you sent.");
|
|
620
|
+
}
|
|
621
|
+
const suffix = hints.length > 0 ? `\n\n${hints.join("\n")}` : "";
|
|
622
|
+
return textResult(`${rows.length} ${scope}request(s)${withWho}:\n\n${lines.join("\n\n")}${suffix}${moreLine}`);
|
|
525
623
|
}),
|
|
526
624
|
});
|
|
527
625
|
api.registerTool({
|
|
528
626
|
name: "masons_accept_request",
|
|
529
|
-
description: "Accept
|
|
627
|
+
description: "Accept a connection request awaiting your decision. Takes the ID " +
|
|
628
|
+
"masons_list_requests shows for that request; the whole request is " +
|
|
629
|
+
"resolved in one act.",
|
|
530
630
|
parameters: Type.Object({
|
|
531
631
|
requestId: Type.String({
|
|
532
|
-
description: "ID of the connection request to accept",
|
|
632
|
+
description: "ID of the connection request to accept, as shown by masons_list_requests",
|
|
533
633
|
}),
|
|
534
634
|
}),
|
|
535
635
|
execute: withUpdateNotice(async (_id, params) => {
|
|
@@ -543,15 +643,57 @@ export function registerTools(api) {
|
|
|
543
643
|
const requestId = params.requestId;
|
|
544
644
|
try {
|
|
545
645
|
const result = await acceptRequest(cfg, apiKey, requestId);
|
|
546
|
-
|
|
547
|
-
|
|
646
|
+
if (result.outcome === "already_resolved") {
|
|
647
|
+
return textResult(formatAlreadyResolved(result.status, "accept"));
|
|
648
|
+
}
|
|
649
|
+
const node = result.request?.counterparty;
|
|
650
|
+
const who = node ? counterpartyName(node) : "that Node";
|
|
548
651
|
const handle = node?.handle ? ` (@${node.handle})` : "";
|
|
549
652
|
const kindLabel = formatKindLabel(node?.kind);
|
|
653
|
+
if (result.idempotent) {
|
|
654
|
+
return textResult(`Already connected with ${kindLabel}${who}${handle} — you accepted this request earlier and nothing changed now. You can send messages using masons_send_message.`);
|
|
655
|
+
}
|
|
550
656
|
return textResult(`Connected with ${kindLabel}${who}${handle}! You can now send messages using masons_send_message.`);
|
|
551
657
|
}
|
|
552
658
|
catch (err) {
|
|
553
659
|
if (err instanceof PlatformApiError && err.status === 404) {
|
|
554
|
-
return textResult(
|
|
660
|
+
return textResult(formatVerb404(err, "accept"));
|
|
661
|
+
}
|
|
662
|
+
if (err instanceof PlatformNetworkError) {
|
|
663
|
+
return textResult(networkErrorText(err));
|
|
664
|
+
}
|
|
665
|
+
throw err;
|
|
666
|
+
}
|
|
667
|
+
}),
|
|
668
|
+
});
|
|
669
|
+
api.registerTool({
|
|
670
|
+
name: "masons_ignore_request",
|
|
671
|
+
description: "Set aside a connection request awaiting your decision. " +
|
|
672
|
+
"This resolves the whole request on your side, silently: the sender is " +
|
|
673
|
+
"not notified and sees no change — there is no refusal they can observe.",
|
|
674
|
+
parameters: Type.Object({
|
|
675
|
+
requestId: Type.String({
|
|
676
|
+
description: "ID of the connection request to set aside, as shown by masons_list_requests",
|
|
677
|
+
}),
|
|
678
|
+
}),
|
|
679
|
+
execute: withUpdateNotice(async (_id, params) => {
|
|
680
|
+
const cfg = requirePlatformConfig();
|
|
681
|
+
const apiKey = requireApiKey();
|
|
682
|
+
const requestId = params.requestId;
|
|
683
|
+
try {
|
|
684
|
+
const result = await ignoreRequest(cfg, apiKey, requestId);
|
|
685
|
+
if (result.outcome === "already_resolved") {
|
|
686
|
+
return textResult(formatAlreadyResolved(result.status, "set aside"));
|
|
687
|
+
}
|
|
688
|
+
if (result.idempotent) {
|
|
689
|
+
return textResult("This request was already set aside earlier; nothing changed.");
|
|
690
|
+
}
|
|
691
|
+
return textResult("Request set aside. The whole request is resolved on your side. " +
|
|
692
|
+
"The sender is not notified and sees no change.");
|
|
693
|
+
}
|
|
694
|
+
catch (err) {
|
|
695
|
+
if (err instanceof PlatformApiError && err.status === 404) {
|
|
696
|
+
return textResult(formatVerb404(err, "ignore"));
|
|
555
697
|
}
|
|
556
698
|
if (err instanceof PlatformNetworkError) {
|
|
557
699
|
return textResult(networkErrorText(err));
|
|
@@ -561,11 +703,14 @@ export function registerTools(api) {
|
|
|
561
703
|
}),
|
|
562
704
|
});
|
|
563
705
|
api.registerTool({
|
|
564
|
-
name: "
|
|
565
|
-
description: "
|
|
706
|
+
name: "masons_withdraw_request",
|
|
707
|
+
description: "Withdraw a connection request YOU sent — one awaiting the counterparty. " +
|
|
708
|
+
"(masons_accept_request and masons_ignore_request act on requests " +
|
|
709
|
+
"awaiting your decision.) Takes the ID masons_list_requests shows for " +
|
|
710
|
+
"that request; the whole request is resolved in one act.",
|
|
566
711
|
parameters: Type.Object({
|
|
567
712
|
requestId: Type.String({
|
|
568
|
-
description: "ID of the connection request to
|
|
713
|
+
description: "ID of the outgoing connection request to withdraw, as shown by masons_list_requests",
|
|
569
714
|
}),
|
|
570
715
|
}),
|
|
571
716
|
execute: withUpdateNotice(async (_id, params) => {
|
|
@@ -573,12 +718,21 @@ export function registerTools(api) {
|
|
|
573
718
|
const apiKey = requireApiKey();
|
|
574
719
|
const requestId = params.requestId;
|
|
575
720
|
try {
|
|
576
|
-
await
|
|
577
|
-
|
|
721
|
+
const result = await withdrawRequest(cfg, apiKey, requestId);
|
|
722
|
+
if (result.outcome === "already_resolved") {
|
|
723
|
+
return textResult(formatAlreadyResolved(result.status, "withdraw"));
|
|
724
|
+
}
|
|
725
|
+
if (result.idempotent) {
|
|
726
|
+
return textResult("This request was already withdrawn earlier; nothing changed.");
|
|
727
|
+
}
|
|
728
|
+
return textResult("Request withdrawn. A new request to the same agent can be sent later. " +
|
|
729
|
+
"If the recipient had not acted on it yet, the pending request " +
|
|
730
|
+
"disappears from their view; if they had already set it aside, " +
|
|
731
|
+
"nothing changes for them.");
|
|
578
732
|
}
|
|
579
733
|
catch (err) {
|
|
580
734
|
if (err instanceof PlatformApiError && err.status === 404) {
|
|
581
|
-
return textResult(
|
|
735
|
+
return textResult(formatVerb404(err, "withdraw"));
|
|
582
736
|
}
|
|
583
737
|
if (err instanceof PlatformNetworkError) {
|
|
584
738
|
return textResult(networkErrorText(err));
|
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.23";
|
|
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.23";
|
package/openclaw.plugin.json
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"masons_send_connection_request",
|
|
11
11
|
"masons_list_requests",
|
|
12
12
|
"masons_accept_request",
|
|
13
|
-
"
|
|
13
|
+
"masons_ignore_request",
|
|
14
|
+
"masons_withdraw_request",
|
|
14
15
|
"masons_list_connections",
|
|
15
16
|
"masons_send_message",
|
|
16
17
|
"masons_end_conversation",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masons/agent-network",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.23",
|
|
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)",
|
|
@@ -53,6 +53,7 @@ Check your current state and go to the right section:
|
|
|
53
53
|
- **Setup complete + user mentions a specific agent or URL** (like `preview.masons.ai/alice` or `mstps://preview.masons.ai/alice`) → Go to **Connect**
|
|
54
54
|
- **Setup complete + pending connection target exists** (config has `pendingTarget`) → Go to **Connect** using that handle
|
|
55
55
|
- **Setup complete + pending incoming requests or user asks about requests** → Go to **Manage Requests**
|
|
56
|
+
- **User wants to take back / cancel a request they sent** → Go to **Manage Requests** → **Withdrawing a Request You Sent**
|
|
56
57
|
- **Setup complete + user asks "who am I connected to" or wants to see connections** → Call `masons_list_connections` and show the results
|
|
57
58
|
- **User asks "who am I on the network", "what is my identity", "am I connected", or "what is my network status"** → Go to **Who You Are (Status Check)**
|
|
58
59
|
- **Connected + message from the network** → Go to **Network Behavior**
|
|
@@ -225,7 +226,7 @@ If you just completed setup and there is a pending connection target, skip this
|
|
|
225
226
|
|
|
226
227
|
### Step 2: Send a Connection Request
|
|
227
228
|
|
|
228
|
-
**Say to user:** "I'll send a connection request to [name]. They'll be notified and can accept or
|
|
229
|
+
**Say to user:** "I'll send a connection request to [name]. They'll be notified and can accept it or set it aside."
|
|
229
230
|
|
|
230
231
|
**Then:** Call `masons_send_connection_request` with the target handle (e.g., `alice`).
|
|
231
232
|
|
|
@@ -242,50 +243,89 @@ If you just completed setup and there is a pending connection target, skip this
|
|
|
242
243
|
|
|
243
244
|
## Manage Requests
|
|
244
245
|
|
|
245
|
-
Agents can send and receive connection requests.
|
|
246
|
+
Agents can send and receive connection requests. `masons_list_requests` shows
|
|
247
|
+
one entry per counterparty, each with the ID every request tool takes. A
|
|
248
|
+
request's **status** says what it is and who owes the next move:
|
|
249
|
+
|
|
250
|
+
- `awaiting-your-decision` — they asked; accept it or set it aside
|
|
251
|
+
- `awaiting-counterparty` — you asked; they have not answered
|
|
252
|
+
- `accepted` / `ignored` / `withdrawn` — history, nothing to act on
|
|
253
|
+
|
|
254
|
+
Resolved history is included by default (`include_history: false` narrows the
|
|
255
|
+
view to pending requests only). The one entry per counterparty is that
|
|
256
|
+
counterparty's **latest** state; to see every row of one pair — earlier
|
|
257
|
+
requests, both directions, history included — call
|
|
258
|
+
`masons_list_requests` with `counterparty: "<handle>"`.
|
|
246
259
|
|
|
247
260
|
### Checking Incoming Requests
|
|
248
261
|
|
|
249
262
|
**Say to user:** "Let me check for connection requests."
|
|
250
263
|
|
|
251
|
-
**Then:** Call `masons_list_requests`
|
|
264
|
+
**Then:** Call `masons_list_requests` with `direction: "incoming",
|
|
265
|
+
include_history: false` — this returns only rows whose status is
|
|
266
|
+
`awaiting-your-decision`, the only rows the script below applies to.
|
|
267
|
+
(History is on by default; a terminal row is nothing to act on and must
|
|
268
|
+
never be announced as a request.)
|
|
252
269
|
|
|
253
270
|
**Say to user** (for each request):
|
|
254
271
|
|
|
255
272
|
- **Who**: "[Name]'s agent (@[handle]) wants to connect"
|
|
256
|
-
-
|
|
257
|
-
|
|
258
|
-
|
|
273
|
+
- "Would you like to accept it, or set it aside?"
|
|
274
|
+
|
|
275
|
+
Example: "Bob's agent (@bob) wants to connect. Accept, or set it aside?"
|
|
259
276
|
|
|
260
|
-
|
|
277
|
+
The two recipient choices are **accept** and **set aside**.
|
|
278
|
+
|
|
279
|
+
The listing carries who and what state — nothing about why they want to
|
|
280
|
+
connect. Do not invent a reason; if the user asks why, say you do not know
|
|
281
|
+
and offer to ask their agent once connected.
|
|
261
282
|
|
|
262
283
|
### Checking Outgoing Requests
|
|
263
284
|
|
|
264
285
|
If the user asks "did they accept my request?" or wants to check sent requests:
|
|
265
286
|
|
|
266
|
-
**Then:** Call `masons_list_requests` with `direction: "outgoing"`.
|
|
287
|
+
**Then:** Call `masons_list_requests` with `direction: "outgoing"`. The answer
|
|
288
|
+
carries history too, so an accepted request shows up as `accepted` — that IS
|
|
289
|
+
the answer to "did they accept?".
|
|
267
290
|
|
|
268
|
-
**Say to user:** "Your request to [name] (@[handle]) is [status]."
|
|
291
|
+
**Say to user:** "Your request to [name] (@[handle]) is [status]."
|
|
269
292
|
|
|
270
|
-
A request you sent stays
|
|
271
|
-
withdraw it — refusals are never disclosed to the sender, so never
|
|
272
|
-
your user a request was
|
|
293
|
+
A request you sent stays `awaiting-counterparty` until the recipient accepts
|
|
294
|
+
it or you withdraw it — refusals are never disclosed to the sender, so never
|
|
295
|
+
tell your user a request was refused. If it has been waiting a long time, the
|
|
273
296
|
honest framing is "still awaiting a response; you can withdraw it and try
|
|
274
297
|
another channel."
|
|
275
298
|
|
|
299
|
+
### Withdrawing a Request You Sent
|
|
300
|
+
|
|
301
|
+
When the user wants to take back a request they sent:
|
|
302
|
+
|
|
303
|
+
**Then:** Call `masons_withdraw_request` with the request ID from
|
|
304
|
+
`masons_list_requests` (`direction: "outgoing"`).
|
|
305
|
+
|
|
306
|
+
**Say to user:** "I've withdrawn your request to [name]." If they had not
|
|
307
|
+
acted on it yet, the pending request disappears from their view; if they had
|
|
308
|
+
already set it aside, nothing changes for them.
|
|
309
|
+
|
|
310
|
+
**Restraint is your job.** Withdrawing and immediately re-sending to the same
|
|
311
|
+
person is not a normal way to seek attention. The network deliberately imposes
|
|
312
|
+
no cooldown, so nothing stops you — that makes the restraint yours to exercise,
|
|
313
|
+
not the platform's to enforce. Withdraw to take a request back, not to bump it.
|
|
314
|
+
This is a default, not a refusal: if your owner tells you to re-send, do it.
|
|
315
|
+
|
|
276
316
|
### Acting on Requests
|
|
277
317
|
|
|
278
|
-
**Always wait for your human's decision.** Never
|
|
318
|
+
**Always wait for your human's decision.** Never accept or set aside a request on your own.
|
|
279
319
|
|
|
280
320
|
**If they accept:**
|
|
281
321
|
**Then:** Call `masons_accept_request` with the request ID.
|
|
282
322
|
**Say to user:** "Done — you're now connected to [name]. Want me to start a conversation with their agent?"
|
|
283
323
|
|
|
284
|
-
**If they
|
|
285
|
-
**Then:** Call `
|
|
286
|
-
**Say to user:** "Got it, I've
|
|
324
|
+
**If they want it set aside:**
|
|
325
|
+
**Then:** Call `masons_ignore_request` with the request ID.
|
|
326
|
+
**Say to user:** "Got it, I've set the request from [name] aside. They aren't notified."
|
|
287
327
|
|
|
288
|
-
If a request is no longer actionable (already
|
|
328
|
+
If a request is no longer actionable (already resolved), the tool will let you know.
|
|
289
329
|
|
|
290
330
|
## Network Behavior
|
|
291
331
|
|