@masons/agent-network 0.6.19 → 0.6.21
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.map +1 -1
- package/dist/channel-setup.js +2 -1
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +54 -44
- package/dist/cli-setup.d.ts.map +1 -1
- package/dist/cli-setup.js +18 -4
- package/dist/config-fs.d.ts +1 -1
- package/dist/config-fs.d.ts.map +1 -1
- package/dist/config-fs.js +2 -1
- package/dist/config.d.ts +3 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -2
- package/dist/connector-client.d.ts +35 -4
- package/dist/connector-client.d.ts.map +1 -1
- package/dist/connector-client.js +126 -19
- package/dist/conversation-manager-context.d.ts +4 -0
- package/dist/conversation-manager-context.d.ts.map +1 -0
- package/dist/conversation-manager-context.js +8 -0
- package/dist/conversation-manager.d.ts +29 -4
- package/dist/conversation-manager.d.ts.map +1 -1
- package/dist/conversation-manager.js +163 -14
- package/dist/handoff-deadline.d.ts +4 -0
- package/dist/handoff-deadline.d.ts.map +1 -0
- package/dist/handoff-deadline.js +7 -0
- package/dist/handoff.d.ts +1 -2
- package/dist/handoff.d.ts.map +1 -1
- package/dist/handoff.js +20 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/platform-client.d.ts +1 -0
- package/dist/platform-client.d.ts.map +1 -1
- package/dist/platform-client.js +12 -0
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +49 -30
- package/dist/sent-message-buffer.d.ts +2 -3
- package/dist/sent-message-buffer.d.ts.map +1 -1
- package/dist/sent-message-buffer.js +8 -11
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +101 -7
- package/dist/turn-context.d.ts +0 -4
- package/dist/turn-context.d.ts.map +1 -1
- package/dist/turn-context.js +0 -18
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/ws-heartbeat.d.ts +23 -0
- package/dist/ws-heartbeat.d.ts.map +1 -0
- package/dist/ws-heartbeat.js +63 -0
- package/openclaw.plugin.json +2 -1
- package/package.json +1 -1
- package/skills/agent-network/SKILL.md +9 -0
package/dist/handoff.d.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { type KeyObject } from "node:crypto";
|
|
2
|
+
export { SetupFlowError } from "./handoff-deadline.js";
|
|
2
3
|
export declare const DEFAULT_IDP_BASE_URL = "https://preview.masons.ai";
|
|
3
4
|
export declare const HANDOFF_TIMEOUT_MS: number;
|
|
4
|
-
export declare class SetupFlowError extends Error {
|
|
5
|
-
}
|
|
6
5
|
export interface BridgeHandoffResult {
|
|
7
6
|
token: string;
|
|
8
7
|
agent: {
|
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;AAQrB,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAavD,eAAO,MAAM,oBAAoB,8BAA8B,CAAC;AAiBhE,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AAejD,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;IAClB,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;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAMD,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAsD/B;AAKD,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,mBAAmB,CAAC,CAwC9B"}
|
package/dist/handoff.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createDecipheriv, constants as cryptoConstants, generateKeyPairSync, privateDecrypt, } from "node:crypto";
|
|
2
|
+
import { assertHandoffDeadlineActive, SetupFlowError, } from "./handoff-deadline.js";
|
|
2
3
|
import { apiFetch, PlatformNetworkError } from "./platform-client.js";
|
|
4
|
+
export { SetupFlowError } from "./handoff-deadline.js";
|
|
3
5
|
export const DEFAULT_IDP_BASE_URL = "https://preview.masons.ai";
|
|
4
6
|
const HANDLE_REGEX = /^[a-z][a-z0-9_-]{2,14}$/;
|
|
5
|
-
export const HANDOFF_TIMEOUT_MS =
|
|
7
|
+
export const HANDOFF_TIMEOUT_MS = 10 * 60 * 1000;
|
|
6
8
|
const HANDOFF_POLL_INTERVAL_MS = 2000;
|
|
7
|
-
export class SetupFlowError extends Error {
|
|
8
|
-
}
|
|
9
9
|
export async function beginBridgeHandoff(options) {
|
|
10
10
|
const { publicKey, privateKey } = generateKeyPairSync("rsa", {
|
|
11
11
|
modulusLength: 2048,
|
|
@@ -53,7 +53,7 @@ export async function beginBridgeHandoff(options) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
export async function completeBridgeHandoff(session) {
|
|
56
|
-
const envelope = await pollForCompletion(session.apiBase, session.sessionId);
|
|
56
|
+
const envelope = await pollForCompletion(session.apiBase, session.sessionId, session.expiresAt);
|
|
57
57
|
let payload;
|
|
58
58
|
try {
|
|
59
59
|
payload = decryptBridgeEnvelope(session.privateKey, envelope);
|
|
@@ -62,6 +62,7 @@ export async function completeBridgeHandoff(session) {
|
|
|
62
62
|
const message = err instanceof Error ? err.message : "unknown error";
|
|
63
63
|
throw new SetupFlowError(`Handoff received but could not be decrypted (${message}). The link may have been tampered with — re-run setup. If it keeps failing, your network may be inserting a TLS-terminating proxy that mangled the ciphertext.`);
|
|
64
64
|
}
|
|
65
|
+
assertHandoffDeadlineActive(session.expiresAt);
|
|
65
66
|
if (typeof payload.token !== "string" ||
|
|
66
67
|
!payload.token.startsWith("masons_rt_v1_") ||
|
|
67
68
|
typeof payload.agent?.handle !== "string" ||
|
|
@@ -79,10 +80,9 @@ export async function completeBridgeHandoff(session) {
|
|
|
79
80
|
},
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
|
-
async function pollForCompletion(apiBase, sessionId) {
|
|
83
|
-
const start = Date.now();
|
|
83
|
+
async function pollForCompletion(apiBase, sessionId, expiresAt) {
|
|
84
84
|
let lastNetworkError;
|
|
85
|
-
while (Date.now()
|
|
85
|
+
while (Date.now() < expiresAt) {
|
|
86
86
|
let res;
|
|
87
87
|
try {
|
|
88
88
|
res = await apiFetch(`${apiBase}/v1/cli-handoff/${encodeURIComponent(sessionId)}/poll`, { method: "GET" });
|
|
@@ -90,28 +90,38 @@ async function pollForCompletion(apiBase, sessionId) {
|
|
|
90
90
|
catch (err) {
|
|
91
91
|
if (err instanceof PlatformNetworkError) {
|
|
92
92
|
lastNetworkError = err;
|
|
93
|
-
await
|
|
93
|
+
await sleepBeforeNextPoll(expiresAt);
|
|
94
94
|
continue;
|
|
95
95
|
}
|
|
96
96
|
throw err;
|
|
97
97
|
}
|
|
98
|
+
if (Date.now() >= expiresAt)
|
|
99
|
+
break;
|
|
98
100
|
if (res.status === 404) {
|
|
99
101
|
throw new SetupFlowError("Handoff session expired before the runtime key was delivered. Re-run setup.");
|
|
100
102
|
}
|
|
101
103
|
if (!res.ok) {
|
|
102
|
-
await
|
|
104
|
+
await sleepBeforeNextPoll(expiresAt);
|
|
103
105
|
continue;
|
|
104
106
|
}
|
|
105
107
|
const body = (await res.json());
|
|
108
|
+
if (Date.now() >= expiresAt)
|
|
109
|
+
break;
|
|
106
110
|
if (body.status === "completed" && body.payload) {
|
|
107
111
|
return body.payload;
|
|
108
112
|
}
|
|
109
|
-
await
|
|
113
|
+
await sleepBeforeNextPoll(expiresAt);
|
|
110
114
|
}
|
|
111
115
|
throw new SetupFlowError(lastNetworkError
|
|
112
116
|
? `Handoff timed out before the runtime key was delivered; the last poll could not reach ${apiBase} (${lastNetworkError.message}). Re-run setup; if you're behind a proxy that blocks long-running fetches, retry on a different network.`
|
|
113
117
|
: "Handoff timed out before the runtime key was delivered. Re-run setup; if you're behind a proxy that blocks long-running fetches, retry on a different network.");
|
|
114
118
|
}
|
|
119
|
+
async function sleepBeforeNextPoll(expiresAt) {
|
|
120
|
+
const remainingMs = expiresAt - Date.now();
|
|
121
|
+
if (remainingMs <= 0)
|
|
122
|
+
return;
|
|
123
|
+
await sleep(Math.min(HANDOFF_POLL_INTERVAL_MS, remainingMs));
|
|
124
|
+
}
|
|
115
125
|
function decryptBridgeEnvelope(privateKey, envelope) {
|
|
116
126
|
const wrappedKey = Buffer.from(envelope.wrapped_key, "base64url");
|
|
117
127
|
const iv = Buffer.from(envelope.iv, "base64url");
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { AUTHORIZED_TOKEN_TTL_MS, SETUP_CODE_CHARSET, SETUP_CODE_LENGTH, SETUP_CODE_TTL_MS, } from "./constants.js";
|
|
2
2
|
export type { AgentNetworkAccount } from "./config-schema.js";
|
|
3
|
-
export type { AddressedMessageEvent, DeliveryPendingEvent, DeliverySkipEvent, DeliveryStatusEvent, RegisterAckEvent, SendAckEvent, StructuredErrorEvent, } from "./types.js";
|
|
3
|
+
export type { AddressedMessageEvent, DeliveryPendingEvent, DeliverySkipEvent, DeliveryStatusEvent, ObservedSendAckEvent, RegisterAckEvent, SendAckEvent, StructuredErrorEvent, } from "./types.js";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAIxB,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,GACrB,MAAM,YAAY,CAAC"}
|
|
@@ -87,4 +87,5 @@ export declare function acceptRequest(cfg: PlatformClientConfig, runtimeKey: str
|
|
|
87
87
|
export declare function declineRequest(cfg: PlatformClientConfig, runtimeKey: string, requestId: string): Promise<DeclineRequestResponse>;
|
|
88
88
|
export declare function updateProfile(cfg: PlatformClientConfig, runtimeKey: string, params: UpdateProfileParams): Promise<UpdateProfileResponse>;
|
|
89
89
|
export declare function listConnections(cfg: PlatformClientConfig, runtimeKey: string): Promise<ListConnectionsResponse>;
|
|
90
|
+
export declare function getIdentity(cfg: PlatformClientConfig, runtimeKey: string): Promise<ConnectionNodeRef | null>;
|
|
90
91
|
//# sourceMappingURL=platform-client.d.ts.map
|
|
@@ -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;AAMD,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;
|
|
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
|
@@ -144,3 +144,15 @@ export async function listConnections(cfg, runtimeKey) {
|
|
|
144
144
|
return handleError(res);
|
|
145
145
|
return (await res.json());
|
|
146
146
|
}
|
|
147
|
+
export async function getIdentity(cfg, runtimeKey) {
|
|
148
|
+
const res = await apiFetch(`${baseUrl(cfg)}/me/identity`, {
|
|
149
|
+
headers: { Authorization: `Bearer ${runtimeKey}` },
|
|
150
|
+
});
|
|
151
|
+
if (!res.ok)
|
|
152
|
+
return handleError(res);
|
|
153
|
+
const body = (await res.json().catch(() => null));
|
|
154
|
+
if (!body || body.node === undefined) {
|
|
155
|
+
throw new PlatformApiError(res.status, "malformed_response", "identity response carried no `node` field");
|
|
156
|
+
}
|
|
157
|
+
return body.node;
|
|
158
|
+
}
|
package/dist/plugin.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { ConversationManager } from "./conversation-manager.js";
|
|
1
2
|
import { evaluateServicesRetainedToolPolicy } from "./services-retained-tool-policy.js";
|
|
2
|
-
export declare function buildInteractionContext(
|
|
3
|
+
export declare function buildInteractionContext(messageProvider: string | undefined, turnSenderAddress: string | null, conversationManager?: ConversationManager | null): string | undefined;
|
|
3
4
|
interface OpenClawPluginApi {
|
|
4
5
|
runtime: unknown;
|
|
5
6
|
registerChannel(opts: {
|
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
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;CA8ZhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -2,14 +2,14 @@ import pluginManifest from "../openclaw.plugin.json" with { type: "json" };
|
|
|
2
2
|
import { agentNetworkChannel, consumeIdentityLinkingNudge } from "./channel.js";
|
|
3
3
|
import { login } from "./cli-setup.js";
|
|
4
4
|
import { detectPendingState, getConversationManager, getDmScope, getStateCacheGeneration, initPluginRuntime, } from "./config.js";
|
|
5
|
+
import { getInvocationConversationManager } from "./conversation-manager-context.js";
|
|
5
6
|
import { getAgentIdentity } from "./environment-context.js";
|
|
6
7
|
import { ownerNotesQueue } from "./owner-notes.js";
|
|
7
8
|
import { consumeCurrentTurnIsOwner, consumeCurrentTurnOwnerSignal, } from "./owner-session-state.js";
|
|
8
|
-
import { sentMessageBuffer } from "./sent-message-buffer.js";
|
|
9
9
|
import { isServicesRetainedReplyContext } from "./services-retained-reply-context.js";
|
|
10
10
|
import { evaluateServicesRetainedToolPolicy, SERVICES_RETAINED_TOOL_POLICY_ID, } from "./services-retained-tool-policy.js";
|
|
11
11
|
import { registerTools } from "./tools.js";
|
|
12
|
-
import {
|
|
12
|
+
import { setCurrentTurnChannelId, setCurrentTurnIsOwnerForTools, setCurrentTurnOwnerSignalForTools, } from "./turn-context.js";
|
|
13
13
|
import { getUpdateInfo } from "./update-check.js";
|
|
14
14
|
import { PLUGIN_VERSION } from "./version.js";
|
|
15
15
|
function formatTimeAgo(timestamp) {
|
|
@@ -40,8 +40,8 @@ function drainAndFormatNotes(reportInstruction) {
|
|
|
40
40
|
reportInstruction);
|
|
41
41
|
}
|
|
42
42
|
const MAX_INTERACTIONS = 5;
|
|
43
|
-
export function buildInteractionContext(
|
|
44
|
-
const cm =
|
|
43
|
+
export function buildInteractionContext(messageProvider, turnSenderAddress, conversationManager = getConversationManager()) {
|
|
44
|
+
const cm = conversationManager;
|
|
45
45
|
if (!cm)
|
|
46
46
|
return undefined;
|
|
47
47
|
const conversations = cm.listConversations();
|
|
@@ -60,22 +60,18 @@ export function buildInteractionContext(channelId, turnSender, turnSenderAddress
|
|
|
60
60
|
const when = formatTimeAgo(c.lastMessageAt);
|
|
61
61
|
return `• ${who} — ${initiated} — last activity ${when}`;
|
|
62
62
|
});
|
|
63
|
-
const isNetworkTurn =
|
|
64
|
-
if (isNetworkTurn &&
|
|
65
|
-
const senderConvo = turnSenderAddress
|
|
66
|
-
? conversations.find((c) => c.address === turnSenderAddress)
|
|
67
|
-
: undefined;
|
|
63
|
+
const isNetworkTurn = messageProvider === "agent-network";
|
|
64
|
+
if (isNetworkTurn && turnSenderAddress) {
|
|
65
|
+
const senderConvo = conversations.find((c) => c.address === turnSenderAddress);
|
|
68
66
|
const initiated = senderConvo?.initiatedBy === "local"
|
|
69
67
|
? "You initiated this interaction."
|
|
70
68
|
: "They initiated this interaction.";
|
|
71
|
-
const from =
|
|
72
|
-
? `${
|
|
73
|
-
:
|
|
69
|
+
const from = senderConvo && senderConvo.contact !== turnSenderAddress
|
|
70
|
+
? `${senderConvo.contact} (${turnSenderAddress})`
|
|
71
|
+
: turnSenderAddress;
|
|
74
72
|
return (`${header}\n${lines.join("\n")}\n` +
|
|
75
73
|
`[This turn] From ${from}. ${initiated}\n` +
|
|
76
|
-
|
|
77
|
-
? "Your text reply uses the Services-retained reply authority for this message. "
|
|
78
|
-
: "Your text reply goes to this sender. ") +
|
|
74
|
+
"Your text reply goes to this sender. " +
|
|
79
75
|
"To report to your owner: masons_note_for_owner.");
|
|
80
76
|
}
|
|
81
77
|
if (isNetworkTurn) {
|
|
@@ -88,6 +84,24 @@ export function buildInteractionContext(channelId, turnSender, turnSenderAddress
|
|
|
88
84
|
: "[Active interactions on the network]";
|
|
89
85
|
return `${ownerHeader}\n${lines.join("\n")}`;
|
|
90
86
|
}
|
|
87
|
+
function resolveHookProvider(ctx) {
|
|
88
|
+
return ctx?.messageProvider ?? ctx?.channel;
|
|
89
|
+
}
|
|
90
|
+
function resolveHookSender(ctx, servicesRetained) {
|
|
91
|
+
if (servicesRetained || resolveHookProvider(ctx) !== "agent-network") {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
const senderId = ctx?.senderId;
|
|
95
|
+
return typeof senderId === "string" && senderId.length > 0 ? senderId : null;
|
|
96
|
+
}
|
|
97
|
+
function renderPeer(address, conversationManager) {
|
|
98
|
+
const conversation = conversationManager
|
|
99
|
+
.listConversations()
|
|
100
|
+
.find((entry) => entry.address === address);
|
|
101
|
+
return conversation && conversation.contact !== address
|
|
102
|
+
? `${conversation.contact} (${address})`
|
|
103
|
+
: address;
|
|
104
|
+
}
|
|
91
105
|
const plugin = {
|
|
92
106
|
id: "agent-network",
|
|
93
107
|
version: PLUGIN_VERSION,
|
|
@@ -130,7 +144,8 @@ const plugin = {
|
|
|
130
144
|
"masons_note_for_owner(content, from?) — save a note for your owner's next turn. " +
|
|
131
145
|
"Other network tools: masons_list_requests, masons_send_connection_request, " +
|
|
132
146
|
"masons_accept_request, masons_decline_request, masons_list_connections, " +
|
|
133
|
-
"masons_end_conversation (rare one-shot close signal only)
|
|
147
|
+
"masons_end_conversation (rare one-shot close signal only), " +
|
|
148
|
+
"masons_status (your canonical identity and participation status). " +
|
|
134
149
|
"Always try these tools first for network operations. " +
|
|
135
150
|
"If a tool call fails, report the error to your user — do not silently work around it. " +
|
|
136
151
|
"You interact with multiple entities simultaneously — your owner and agents on the network. " +
|
|
@@ -147,13 +162,15 @@ const plugin = {
|
|
|
147
162
|
"";
|
|
148
163
|
api.on("before_prompt_build", async (_event, ctx) => {
|
|
149
164
|
const hookCtx = ctx;
|
|
150
|
-
const
|
|
165
|
+
const messageProvider = resolveHookProvider(hookCtx);
|
|
166
|
+
const invocationConversationManager = getInvocationConversationManager();
|
|
151
167
|
const turnIsOwner = consumeCurrentTurnIsOwner();
|
|
152
168
|
const turnOwnerSignal = consumeCurrentTurnOwnerSignal();
|
|
153
|
-
const turnSender = consumeCurrentTurnSender();
|
|
154
|
-
const turnSenderAddress = consumeCurrentTurnSenderAddress();
|
|
155
169
|
const servicesRetainedReply = isServicesRetainedReplyContext();
|
|
156
|
-
|
|
170
|
+
const turnSenderAddress = invocationConversationManager
|
|
171
|
+
? resolveHookSender(hookCtx, servicesRetainedReply)
|
|
172
|
+
: null;
|
|
173
|
+
setCurrentTurnChannelId(messageProvider ?? null);
|
|
157
174
|
setCurrentTurnIsOwnerForTools(turnIsOwner);
|
|
158
175
|
setCurrentTurnOwnerSignalForTools(turnOwnerSignal);
|
|
159
176
|
const currentGeneration = getStateCacheGeneration();
|
|
@@ -203,7 +220,7 @@ const plugin = {
|
|
|
203
220
|
state.hasCredentials &&
|
|
204
221
|
!state.needsProfile &&
|
|
205
222
|
!state.pendingTarget) {
|
|
206
|
-
if (
|
|
223
|
+
if (messageProvider === "agent-network") {
|
|
207
224
|
if (turnIsOwner) {
|
|
208
225
|
dynamicContext =
|
|
209
226
|
"[Agent Network — Owner via Passport] Your owner (Principal) is talking to you " +
|
|
@@ -226,12 +243,12 @@ const plugin = {
|
|
|
226
243
|
"on the agent network. Your text reply will be sent to that sender — " +
|
|
227
244
|
"your owner (Principal) will NOT see it. To report something to your owner, " +
|
|
228
245
|
"call masons_note_for_owner.";
|
|
229
|
-
const interactionCtx = buildInteractionContext(
|
|
246
|
+
const interactionCtx = buildInteractionContext(messageProvider, turnSenderAddress, invocationConversationManager);
|
|
230
247
|
if (interactionCtx) {
|
|
231
248
|
dynamicContext += `\n\n${interactionCtx}`;
|
|
232
249
|
}
|
|
233
|
-
if (
|
|
234
|
-
const sentMsgs =
|
|
250
|
+
if (turnSenderAddress && invocationConversationManager) {
|
|
251
|
+
const sentMsgs = invocationConversationManager?.getRecentOutboundContext(turnSenderAddress) ?? [];
|
|
235
252
|
if (sentMsgs.length > 0) {
|
|
236
253
|
const lines = sentMsgs.map((m) => {
|
|
237
254
|
const preview = m.content.length > 500
|
|
@@ -240,7 +257,7 @@ const plugin = {
|
|
|
240
257
|
return `• (${formatTimeAgo(m.timestamp)}): "${preview}"`;
|
|
241
258
|
});
|
|
242
259
|
dynamicContext +=
|
|
243
|
-
`\n\n[Your recent messages to ${
|
|
260
|
+
`\n\n[Your recent messages to ${renderPeer(turnSenderAddress, invocationConversationManager)}]\n` +
|
|
244
261
|
lines.join("\n");
|
|
245
262
|
}
|
|
246
263
|
}
|
|
@@ -261,7 +278,7 @@ const plugin = {
|
|
|
261
278
|
? `${dynamicContext}\n\n${nudge}`
|
|
262
279
|
: nudge;
|
|
263
280
|
}
|
|
264
|
-
const interactionCtx = buildInteractionContext(
|
|
281
|
+
const interactionCtx = buildInteractionContext(messageProvider, null);
|
|
265
282
|
if (interactionCtx) {
|
|
266
283
|
dynamicContext = dynamicContext
|
|
267
284
|
? `${dynamicContext}\n\n${interactionCtx}`
|
|
@@ -287,10 +304,12 @@ const plugin = {
|
|
|
287
304
|
if (state.hasCredentials) {
|
|
288
305
|
const envAgent = getAgentIdentity();
|
|
289
306
|
if (envAgent) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
identityLine
|
|
307
|
+
const registered = envAgent.name
|
|
308
|
+
? `@${envAgent.handle}(${envAgent.name})`
|
|
309
|
+
: `@${envAgent.handle}`;
|
|
310
|
+
const identityLine = `[Identity] The Gateway registered this connection as ${registered}. ` +
|
|
311
|
+
"This is connection-level context, not your canonical network identity — " +
|
|
312
|
+
"for the canonical answer, call masons_status.";
|
|
294
313
|
dynamicContext = dynamicContext
|
|
295
314
|
? `${identityLine}\n\n${dynamicContext}`
|
|
296
315
|
: identityLine;
|
|
@@ -7,9 +7,8 @@ export declare class SentMessageBuffer {
|
|
|
7
7
|
static readonly MAX_PER_CONTACT = 5;
|
|
8
8
|
static readonly TTL_MS: number;
|
|
9
9
|
static readonly MAX_CONTENT_LENGTH = 1000;
|
|
10
|
-
record(
|
|
11
|
-
getRecent(
|
|
10
|
+
record(peerAddress: string, content: string): void;
|
|
11
|
+
getRecent(peerAddress: string): SentMessage[];
|
|
12
12
|
clear(): void;
|
|
13
13
|
}
|
|
14
|
-
export declare const sentMessageBuffer: SentMessageBuffer;
|
|
15
14
|
//# sourceMappingURL=sent-message-buffer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sent-message-buffer.d.ts","sourceRoot":"","sources":["../src/sent-message-buffer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sent-message-buffer.d.ts","sourceRoot":"","sources":["../src/sent-message-buffer.ts"],"names":[],"mappings":"AAsBA,MAAM,WAAW,WAAW;IAE1B,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAoC;IAGnD,MAAM,CAAC,QAAQ,CAAC,eAAe,KAAK;IAEpC,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAsB;IAE5C,MAAM,CAAC,QAAQ,CAAC,kBAAkB,QAAQ;IAM1C,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAgClD,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,EAAE;IAsB7C,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -3,13 +3,12 @@ export class SentMessageBuffer {
|
|
|
3
3
|
static MAX_PER_CONTACT = 5;
|
|
4
4
|
static TTL_MS = 2 * 60 * 60 * 1000;
|
|
5
5
|
static MAX_CONTENT_LENGTH = 1000;
|
|
6
|
-
record(
|
|
6
|
+
record(peerAddress, content) {
|
|
7
7
|
const now = Date.now();
|
|
8
|
-
|
|
9
|
-
let list = this.entries.get(key);
|
|
8
|
+
let list = this.entries.get(peerAddress);
|
|
10
9
|
if (!list) {
|
|
11
10
|
list = [];
|
|
12
|
-
this.entries.set(
|
|
11
|
+
this.entries.set(peerAddress, list);
|
|
13
12
|
}
|
|
14
13
|
const cutoff = now - SentMessageBuffer.TTL_MS;
|
|
15
14
|
const fresh = list.filter((m) => m.timestamp > cutoff);
|
|
@@ -20,21 +19,20 @@ export class SentMessageBuffer {
|
|
|
20
19
|
? `${content.slice(0, SentMessageBuffer.MAX_CONTENT_LENGTH)}...`
|
|
21
20
|
: content;
|
|
22
21
|
fresh.push({ content: stored, timestamp: now });
|
|
23
|
-
this.entries.set(
|
|
22
|
+
this.entries.set(peerAddress, fresh);
|
|
24
23
|
}
|
|
25
|
-
getRecent(
|
|
26
|
-
const
|
|
27
|
-
const list = this.entries.get(key);
|
|
24
|
+
getRecent(peerAddress) {
|
|
25
|
+
const list = this.entries.get(peerAddress);
|
|
28
26
|
if (!list)
|
|
29
27
|
return [];
|
|
30
28
|
const cutoff = Date.now() - SentMessageBuffer.TTL_MS;
|
|
31
29
|
const fresh = list.filter((m) => m.timestamp > cutoff);
|
|
32
30
|
if (fresh.length !== list.length) {
|
|
33
31
|
if (fresh.length === 0) {
|
|
34
|
-
this.entries.delete(
|
|
32
|
+
this.entries.delete(peerAddress);
|
|
35
33
|
}
|
|
36
34
|
else {
|
|
37
|
-
this.entries.set(
|
|
35
|
+
this.entries.set(peerAddress, fresh);
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
return fresh;
|
|
@@ -43,4 +41,3 @@ export class SentMessageBuffer {
|
|
|
43
41
|
this.entries.clear();
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
|
-
export const sentMessageBuffer = new SentMessageBuffer();
|
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":"AA2EA,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;AAoZD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAm5BhD"}
|
package/dist/tools.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { getOwnerPassportAddress } from "./channel.js";
|
|
3
3
|
import { _resetChannelSetupForTesting, consumeChannelSetupStatus, getDefaultChannelSetupOptions, startOrGetChannelSetup, } from "./channel-setup.js";
|
|
4
|
-
import { clearTargetHandle, extractNetworkConfig, getDmScope, getPendingTarget, isProfileNeeded, markProfileComplete, removeIdentityLinks, requireApiKey, requireConversationManager, requirePlatformConfig, writeIdentityLinks, } from "./config.js";
|
|
4
|
+
import { clearTargetHandle, extractNetworkConfig, getConnectorClient, getDmScope, getPendingTarget, hasApiKey, isProfileNeeded, markProfileComplete, removeIdentityLinks, requireApiKey, requireConversationManager, requirePlatformConfig, writeIdentityLinks, } from "./config.js";
|
|
5
5
|
import { getOwnerHandle } from "./environment-context.js";
|
|
6
|
-
import { extractHandleFromAddress } from "./handle-utils.js";
|
|
7
6
|
import { ownerNotesQueue } from "./owner-notes.js";
|
|
8
|
-
import { acceptRequest, declineRequest, listConnections, listRequests, PlatformApiError, PlatformNetworkError, requestConnection, updateProfile, } from "./platform-client.js";
|
|
9
|
-
import { sentMessageBuffer } from "./sent-message-buffer.js";
|
|
7
|
+
import { acceptRequest, declineRequest, getIdentity, listConnections, listRequests, PlatformApiError, PlatformNetworkError, requestConnection, updateProfile, } from "./platform-client.js";
|
|
10
8
|
import { isServicesRetainedReplyContext } from "./services-retained-reply-context.js";
|
|
11
9
|
import { getCurrentTurnChannelId, getCurrentTurnIsOwnerNonConsuming, getCurrentTurnOwnerSignal, } from "./turn-context.js";
|
|
12
10
|
import { getLatestPublishedVersion, getPluginVersion, getUpdateInfo, } from "./update-check.js";
|
|
@@ -63,6 +61,76 @@ function formatConnectionResult(requestIds, status) {
|
|
|
63
61
|
}
|
|
64
62
|
return `Connection request sent. Status: ${status}. The other agent's owner will be notified.`;
|
|
65
63
|
}
|
|
64
|
+
function formatIdentityNode(node) {
|
|
65
|
+
const handlePart = node.handle ? `@${node.handle} — ` : "";
|
|
66
|
+
const canonical = `Identity: ${formatKindLabel(node.kind)}${handlePart}${node.mstpAddress}`;
|
|
67
|
+
if (!node.displayName)
|
|
68
|
+
return canonical;
|
|
69
|
+
return `${canonical}\nDisplay name (presentation supplied by the identity endpoint): ${node.displayName}`;
|
|
70
|
+
}
|
|
71
|
+
const IDENTITY_NO_FALLBACK = "This is not an answer — do not assume any locally-cached handle or name is this Runtime's identity.";
|
|
72
|
+
function formatIdentityError(err) {
|
|
73
|
+
if (err instanceof PlatformApiError) {
|
|
74
|
+
if (err.status === 404) {
|
|
75
|
+
return err.code === "not_found"
|
|
76
|
+
? "Identity: the Node's backing entity is missing or deleted."
|
|
77
|
+
: `Identity: unavailable — the identity endpoint is not available at this host (HTTP 404). ${IDENTITY_NO_FALLBACK}`;
|
|
78
|
+
}
|
|
79
|
+
if (err.status === 401) {
|
|
80
|
+
return "Identity: the runtime key is not valid — the network rejected it. The owner can re-authenticate via masons_setup.";
|
|
81
|
+
}
|
|
82
|
+
if (err.status === 403) {
|
|
83
|
+
return "Identity: refused (HTTP 403) — this runtime key is not permitted to read this Runtime's identity. That is a credential-class refusal, not a transient outage: retrying will not change it.";
|
|
84
|
+
}
|
|
85
|
+
return `Identity: unavailable right now (HTTP ${err.status}: ${err.code}). ${IDENTITY_NO_FALLBACK}`;
|
|
86
|
+
}
|
|
87
|
+
if (err instanceof PlatformNetworkError) {
|
|
88
|
+
return `Identity: unavailable right now. ${networkErrorText(err)} ${IDENTITY_NO_FALLBACK}`;
|
|
89
|
+
}
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
function formatRegistration(outcome) {
|
|
93
|
+
switch (outcome.state) {
|
|
94
|
+
case "accepted":
|
|
95
|
+
return "accepted";
|
|
96
|
+
case "refused":
|
|
97
|
+
return `refused: ${outcome.reason}`;
|
|
98
|
+
case "replaced":
|
|
99
|
+
return "replaced by another Runtime (will not retry)";
|
|
100
|
+
case "none":
|
|
101
|
+
return "none";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function formatReadinessSection() {
|
|
105
|
+
const credentialsLine = hasApiKey()
|
|
106
|
+
? "Credentials: configured"
|
|
107
|
+
: "Credentials: not configured";
|
|
108
|
+
const client = getConnectorClient();
|
|
109
|
+
const channel = client ? client.getChannelState() : "not established";
|
|
110
|
+
const registration = formatRegistration(client ? client.getRegistration() : { state: "none" });
|
|
111
|
+
return [
|
|
112
|
+
credentialsLine,
|
|
113
|
+
`Gateway channel: ${channel}`,
|
|
114
|
+
`Registration (this connection): ${registration}`,
|
|
115
|
+
].join("\n");
|
|
116
|
+
}
|
|
117
|
+
async function resolveIdentitySection() {
|
|
118
|
+
if (!hasApiKey()) {
|
|
119
|
+
return "Identity: no runtime key configured — cannot ask the network who this Runtime is. Run masons_setup first.";
|
|
120
|
+
}
|
|
121
|
+
const cfg = requirePlatformConfig();
|
|
122
|
+
const apiKey = requireApiKey();
|
|
123
|
+
try {
|
|
124
|
+
const node = await getIdentity(cfg, apiKey);
|
|
125
|
+
if (node === null) {
|
|
126
|
+
return "Identity: this Runtime's principal holds no active Node on the network.";
|
|
127
|
+
}
|
|
128
|
+
return formatIdentityNode(node);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
return formatIdentityError(err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
66
134
|
function resolveSetupAuthority() {
|
|
67
135
|
const channelId = getCurrentTurnChannelId();
|
|
68
136
|
if (channelId !== "agent-network") {
|
|
@@ -573,6 +641,18 @@ export function registerTools(api) {
|
|
|
573
641
|
return textResult(`${result.total} connection(s):\n\n${lines.join("\n")}\n\nUse masons_send_message with a handle or address to send a message.`);
|
|
574
642
|
}),
|
|
575
643
|
});
|
|
644
|
+
api.registerTool({
|
|
645
|
+
name: "masons_status",
|
|
646
|
+
description: [
|
|
647
|
+
"Report this Runtime's canonical identity and participation status on the agent network.",
|
|
648
|
+
"Use when the owner asks 'who are you on the network', 'what's your identity', 'are you connected', or 'are you ready'.",
|
|
649
|
+
"",
|
|
650
|
+
"Identity comes ONLY from the platform's own identity endpoint — never from local config, cached REGISTER_ACK context, a pending connection target, or any peer/connection handle. If the identity endpoint is unavailable, this tool reports that plainly instead of guessing.",
|
|
651
|
+
"Readiness reports separate facts — credentials configured, live Gateway channel state, and the current connection's registration outcome — without collapsing them into one 'online' verdict.",
|
|
652
|
+
].join("\n"),
|
|
653
|
+
parameters: Type.Object({}),
|
|
654
|
+
execute: withUpdateNotice(async () => textResult([await resolveIdentitySection(), "", formatReadinessSection()].join("\n"))),
|
|
655
|
+
});
|
|
576
656
|
api.registerTool({
|
|
577
657
|
name: "masons_send_message",
|
|
578
658
|
description: "Send a message to a remote agent on the agent network. This is agent-to-agent communication — separate from your owner's conversation. Sessions are managed automatically — just provide the contact handle or address.",
|
|
@@ -591,11 +671,25 @@ export function registerTools(api) {
|
|
|
591
671
|
const cm = requireConversationManager();
|
|
592
672
|
const to = params.to;
|
|
593
673
|
const content = params.content;
|
|
594
|
-
const handle = extractHandleFromAddress(to);
|
|
595
674
|
const result = await cm.send(to, content);
|
|
596
675
|
if (result.status === "sent") {
|
|
597
|
-
|
|
598
|
-
|
|
676
|
+
if (result.addressedTarget?.basis === "resolved") {
|
|
677
|
+
cm.recordOutboundContext(result.addressedTarget.address, content);
|
|
678
|
+
}
|
|
679
|
+
const reference = result.messageRef
|
|
680
|
+
? ` Message reference: ${JSON.stringify(result.messageRef)}.`
|
|
681
|
+
: "";
|
|
682
|
+
if (result.acknowledgementStatus === "stored") {
|
|
683
|
+
return textResult(`Message durably accepted for delivery.${reference}`);
|
|
684
|
+
}
|
|
685
|
+
if (result.acknowledgementStatus === "delivered") {
|
|
686
|
+
return textResult(`Message handed to the recipient Node; presentation is not confirmed.${reference}`);
|
|
687
|
+
}
|
|
688
|
+
return textResult(`Message accepted with acknowledgement status ${JSON.stringify(result.acknowledgementStatus)}.${reference}`);
|
|
689
|
+
}
|
|
690
|
+
if (result.status === "unknown") {
|
|
691
|
+
console.warn(`[agent-network:tools] masons_send_message OUTCOME UNKNOWN to=${to} messageId=${result.messageId} reason=${result.reason}`);
|
|
692
|
+
return textResult(result.error);
|
|
599
693
|
}
|
|
600
694
|
console.warn(`[agent-network:tools] masons_send_message FAILED to=${to} code=${result.errorCode ?? "(none)"} error=${result.error ?? "(none)"}`);
|
|
601
695
|
return textResult(result.error ??
|
package/dist/turn-context.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { OwnerSignal } from "./owner-session-state.js";
|
|
2
|
-
export declare function setCurrentTurnSender(contact: string | null): void;
|
|
3
|
-
export declare function setCurrentTurnSenderAddress(address: string | null): void;
|
|
4
2
|
export declare function setCurrentTurnChannelId(channelId: string | null): void;
|
|
5
3
|
export declare function setCurrentTurnIsOwnerForTools(value: boolean): void;
|
|
6
4
|
export declare function setCurrentTurnOwnerSignalForTools(signal: OwnerSignal): void;
|
|
7
|
-
export declare function consumeCurrentTurnSender(): string | null;
|
|
8
|
-
export declare function consumeCurrentTurnSenderAddress(): string | null;
|
|
9
5
|
export declare function getCurrentTurnChannelId(): string | null;
|
|
10
6
|
export declare function getCurrentTurnIsOwnerNonConsuming(): boolean;
|
|
11
7
|
export declare function getCurrentTurnOwnerSignal(): OwnerSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-context.d.ts","sourceRoot":"","sources":["../src/turn-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"turn-context.d.ts","sourceRoot":"","sources":["../src/turn-context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAqC5D,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEtE;AAOD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAElE;AAUD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAE3E;AAUD,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAMD,wBAAgB,iCAAiC,IAAI,OAAO,CAE3D;AAOD,wBAAgB,yBAAyB,IAAI,WAAW,CAEvD"}
|
package/dist/turn-context.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
let currentTurnSender = null;
|
|
2
|
-
let currentTurnSenderAddress = null;
|
|
3
1
|
let currentTurnChannelId = null;
|
|
4
2
|
let currentTurnIsOwner = false;
|
|
5
3
|
let currentTurnOwnerSignalForTools = null;
|
|
6
|
-
export function setCurrentTurnSender(contact) {
|
|
7
|
-
currentTurnSender = contact;
|
|
8
|
-
}
|
|
9
|
-
export function setCurrentTurnSenderAddress(address) {
|
|
10
|
-
currentTurnSenderAddress = address;
|
|
11
|
-
}
|
|
12
4
|
export function setCurrentTurnChannelId(channelId) {
|
|
13
5
|
currentTurnChannelId = channelId;
|
|
14
6
|
}
|
|
@@ -18,16 +10,6 @@ export function setCurrentTurnIsOwnerForTools(value) {
|
|
|
18
10
|
export function setCurrentTurnOwnerSignalForTools(signal) {
|
|
19
11
|
currentTurnOwnerSignalForTools = signal;
|
|
20
12
|
}
|
|
21
|
-
export function consumeCurrentTurnSender() {
|
|
22
|
-
const value = currentTurnSender;
|
|
23
|
-
currentTurnSender = null;
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
export function consumeCurrentTurnSenderAddress() {
|
|
27
|
-
const value = currentTurnSenderAddress;
|
|
28
|
-
currentTurnSenderAddress = null;
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
13
|
export function getCurrentTurnChannelId() {
|
|
32
14
|
return currentTurnChannelId;
|
|
33
15
|
}
|