@scotthuang/agent-knock-knock 0.12.15 → 0.12.16
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/CHANGELOG.md +21 -0
- package/README.md +5 -1
- package/dist/src/cli-core.js +61 -2
- package/dist/src/cli-core.js.map +1 -1
- package/dist/src/command-json-callback-transport.d.ts +38 -0
- package/dist/src/command-json-callback-transport.js +298 -0
- package/dist/src/command-json-callback-transport.js.map +1 -0
- package/dist/src/host-adapter.d.ts +52 -0
- package/dist/src/host-adapter.js +123 -0
- package/dist/src/host-adapter.js.map +1 -0
- package/dist/src/host-bridge-mcp.d.ts +22 -0
- package/dist/src/host-bridge-mcp.js +145 -0
- package/dist/src/host-bridge-mcp.js.map +1 -0
- package/dist/src/host-bridge-tools.d.ts +61 -0
- package/dist/src/host-bridge-tools.js +130 -0
- package/dist/src/host-bridge-tools.js.map +1 -0
- package/dist/src/host-bridge.d.ts +28 -0
- package/dist/src/host-bridge.js +156 -0
- package/dist/src/host-bridge.js.map +1 -0
- package/dist/src/host-lifecycle-service.d.ts +39 -0
- package/dist/src/host-lifecycle-service.js +101 -0
- package/dist/src/host-lifecycle-service.js.map +1 -0
- package/dist/src/host-profile-callback-transport.d.ts +14 -0
- package/dist/src/host-profile-callback-transport.js +70 -0
- package/dist/src/host-profile-callback-transport.js.map +1 -0
- package/dist/src/host-profile-cli-adapter.d.ts +8 -0
- package/dist/src/host-profile-cli-adapter.js +169 -0
- package/dist/src/host-profile-cli-adapter.js.map +1 -0
- package/dist/src/host-profile-runtime.d.ts +55 -0
- package/dist/src/host-profile-runtime.js +152 -0
- package/dist/src/host-profile-runtime.js.map +1 -0
- package/dist/src/host-profile.d.ts +121 -0
- package/dist/src/host-profile.js +723 -0
- package/dist/src/host-profile.js.map +1 -0
- package/dist/src/native-thread-resume-snapshot.js +1 -1
- package/dist/src/native-thread-resume-snapshot.js.map +1 -1
- package/dist/src/openclaw-plugin-command-adapter.d.ts +13 -0
- package/dist/src/openclaw-plugin-command-adapter.js +125 -47
- package/dist/src/openclaw-plugin-command-adapter.js.map +1 -1
- package/dist/src/openclaw-plugin-helpers.js +1 -1
- package/dist/src/openclaw-plugin-helpers.js.map +1 -1
- package/dist/src/openclaw-plugin-supervisor.d.ts +1 -1
- package/dist/src/openclaw-plugin-supervisor.js +44 -72
- package/dist/src/openclaw-plugin-supervisor.js.map +1 -1
- package/dist/src/terminal-command-cli-adapter.js +4 -4
- package/dist/src/terminal-command-cli-adapter.js.map +1 -1
- package/dist/src/terminal-dispatch-presenter.js +1 -1
- package/dist/src/terminal-dispatch-presenter.js.map +1 -1
- package/dist/src/terminal-watch-callback-cli-adapter.d.ts +2 -1
- package/dist/src/terminal-watch-callback-cli-adapter.js +4 -3
- package/dist/src/terminal-watch-callback-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-cli-adapter.d.ts +4 -0
- package/dist/src/terminal-watch-cli-adapter.js +33 -3
- package/dist/src/terminal-watch-cli-adapter.js.map +1 -1
- package/dist/src/terminal-watch-service.d.ts +5 -0
- package/dist/src/terminal-watch-service.js +6 -1
- package/dist/src/terminal-watch-service.js.map +1 -1
- package/dist/src/terminal-watch-store.d.ts +2 -0
- package/dist/src/terminal-watch-store.js +13 -0
- package/dist/src/terminal-watch-store.js.map +1 -1
- package/docs/host-bridge-profiles.md +325 -0
- package/examples/host-profiles/command-json-starter.json +62 -0
- package/package.json +30 -2
- package/schemas/host-profile-v1.schema.json +266 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { parseHostProfileV1 } from "./host-profile.js";
|
|
3
|
+
import { callbackEnvelopeMatchesRoute, parseCallbackRoute } from "./callback-transport.js";
|
|
4
|
+
/*
|
|
5
|
+
* Keep the callback driver behind the canonical transport port. Profile
|
|
6
|
+
* parsing owns untrusted-document validation and is deliberately re-applied
|
|
7
|
+
* here so programmatic callers cannot bypass the same fail-closed contract.
|
|
8
|
+
*/
|
|
9
|
+
export const COMMAND_JSON_CALLBACK_TRANSPORT_KIND = "command_json_v1";
|
|
10
|
+
class CommandJsonAcknowledgementError extends Error {
|
|
11
|
+
errorCode;
|
|
12
|
+
constructor(errorCode, message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "CommandJsonAcknowledgementError";
|
|
15
|
+
this.errorCode = errorCode;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Deliver canonical AKK callback envelopes through one administrator-selected
|
|
20
|
+
* command Profile. The Profile and trusted controller identity are captured at
|
|
21
|
+
* construction time and cannot be supplied by a model-facing delivery call.
|
|
22
|
+
*/
|
|
23
|
+
export function createCommandJsonCallbackTransport(options) {
|
|
24
|
+
const profile = parseHostProfileV1(options.profile, { source: "built_in" });
|
|
25
|
+
const profileId = profile.id;
|
|
26
|
+
const profileRevision = profile.revision;
|
|
27
|
+
const controllerSessionId = requiredNonBlank(options.controllerSessionId, "controller session id");
|
|
28
|
+
const callback = Object.freeze({
|
|
29
|
+
executable: profile.callback.executable,
|
|
30
|
+
arguments: profile.callback.arguments,
|
|
31
|
+
stdin: profile.callback.stdin,
|
|
32
|
+
environmentVariables: profile.callback.environment.allow,
|
|
33
|
+
timeoutMs: profile.callback.timeoutMs,
|
|
34
|
+
maxOutputBytes: profile.callback.maxOutputBytes,
|
|
35
|
+
acknowledgement: profile.callback.acknowledgement
|
|
36
|
+
});
|
|
37
|
+
const now = options.now ?? (() => new Date());
|
|
38
|
+
const environment = options.environment ?? (() => process.env);
|
|
39
|
+
const runSync = options.spawnSync ??
|
|
40
|
+
((executable, arguments_, spawnOptions) => spawnSync(executable, arguments_, spawnOptions));
|
|
41
|
+
return Object.freeze({
|
|
42
|
+
kind: COMMAND_JSON_CALLBACK_TRANSPORT_KIND,
|
|
43
|
+
deliver(input) {
|
|
44
|
+
let route;
|
|
45
|
+
try {
|
|
46
|
+
route = parseCallbackRoute(input.route);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return permanentFailure("command_json_callback_route_invalid");
|
|
50
|
+
}
|
|
51
|
+
if (route.transport !== COMMAND_JSON_CALLBACK_TRANSPORT_KIND) {
|
|
52
|
+
return permanentFailure("unsupported_callback_transport");
|
|
53
|
+
}
|
|
54
|
+
if (route.profile_id !== profileId) {
|
|
55
|
+
return permanentFailure("command_json_callback_profile_mismatch");
|
|
56
|
+
}
|
|
57
|
+
if (route.profile_revision !== profileRevision) {
|
|
58
|
+
return permanentFailure("command_json_callback_profile_revision_mismatch");
|
|
59
|
+
}
|
|
60
|
+
if (route.controller_session_id !== controllerSessionId) {
|
|
61
|
+
return permanentFailure("command_json_controller_session_mismatch");
|
|
62
|
+
}
|
|
63
|
+
if (!callbackEnvelopeMatchesRoute(input.envelope, route)) {
|
|
64
|
+
return permanentFailure("callback_envelope_route_mismatch");
|
|
65
|
+
}
|
|
66
|
+
if (!Number.isSafeInteger(input.attempt.number) ||
|
|
67
|
+
input.attempt.number < 1 ||
|
|
68
|
+
!nonBlank(input.attempt.id)) {
|
|
69
|
+
return permanentFailure("command_json_callback_attempt_invalid");
|
|
70
|
+
}
|
|
71
|
+
let arguments_;
|
|
72
|
+
let stdin;
|
|
73
|
+
let env;
|
|
74
|
+
try {
|
|
75
|
+
const values = interpolationValues(input.envelope, controllerSessionId);
|
|
76
|
+
arguments_ = callback.arguments.map((argument) => interpolate(argument, values, "argument"));
|
|
77
|
+
stdin = interpolate(callback.stdin, values, "stdin");
|
|
78
|
+
env = filteredEnvironment(environment(), callback.environmentVariables);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return permanentFailure("command_json_callback_configuration_error");
|
|
82
|
+
}
|
|
83
|
+
let result;
|
|
84
|
+
try {
|
|
85
|
+
result = runSync(callback.executable, arguments_, {
|
|
86
|
+
encoding: "utf8",
|
|
87
|
+
env,
|
|
88
|
+
input: stdin,
|
|
89
|
+
killSignal: "SIGKILL",
|
|
90
|
+
maxBuffer: callback.maxOutputBytes,
|
|
91
|
+
shell: false,
|
|
92
|
+
timeout: callback.timeoutMs,
|
|
93
|
+
windowsHide: true
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return processExecutionFailure(error, now());
|
|
98
|
+
}
|
|
99
|
+
// A spawn error means the process did not complete inside the bounded
|
|
100
|
+
// execution contract. In particular, stdout emitted before a timeout or
|
|
101
|
+
// output-limit kill cannot prove that the Host finished processing the
|
|
102
|
+
// callback, even when it happens to contain an exact accepted payload.
|
|
103
|
+
if (result.error) {
|
|
104
|
+
return processExecutionFailure(result.error, now());
|
|
105
|
+
}
|
|
106
|
+
const acknowledgement = acknowledgementOutcome({
|
|
107
|
+
callback,
|
|
108
|
+
envelope: input.envelope,
|
|
109
|
+
result,
|
|
110
|
+
now: now()
|
|
111
|
+
});
|
|
112
|
+
if (acknowledgement) {
|
|
113
|
+
if (acknowledgement.disposition === "accepted") {
|
|
114
|
+
try {
|
|
115
|
+
input.reportCheckpoint?.(acknowledgement);
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// The exact command acknowledgement remains authoritative even when
|
|
119
|
+
// the caller cannot persist the optional early checkpoint here.
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return acknowledgement;
|
|
123
|
+
}
|
|
124
|
+
return uncertainFailure(result.status === 0
|
|
125
|
+
? "command_json_callback_acknowledgement_invalid"
|
|
126
|
+
: "command_json_callback_exit_unacknowledged", now());
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function acknowledgementOutcome(input) {
|
|
131
|
+
const stdout = typeof input.result.stdout === "string"
|
|
132
|
+
? input.result.stdout.trim()
|
|
133
|
+
: "";
|
|
134
|
+
if (!stdout)
|
|
135
|
+
return undefined;
|
|
136
|
+
let acknowledgement;
|
|
137
|
+
try {
|
|
138
|
+
acknowledgement = JSON.parse(stdout);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
try {
|
|
144
|
+
const definition = input.callback.acknowledgement;
|
|
145
|
+
const hostDisposition = requiredPointerString(acknowledgement, definition.disposition, "disposition");
|
|
146
|
+
const disposition = Object.hasOwn(definition.disposition.mapping, hostDisposition)
|
|
147
|
+
? definition.disposition.mapping[hostDisposition]
|
|
148
|
+
: undefined;
|
|
149
|
+
if (!disposition) {
|
|
150
|
+
throw new CommandJsonAcknowledgementError("command_json_callback_acknowledgement_disposition_unknown", "callback acknowledgement disposition is not mapped");
|
|
151
|
+
}
|
|
152
|
+
const deliveryId = requiredPointerString(acknowledgement, definition.acknowledgedDeliveryId, "acknowledged delivery id");
|
|
153
|
+
const messageId = requiredPointerString(acknowledgement, definition.acknowledgedMessageId, "acknowledged message id");
|
|
154
|
+
if (deliveryId !== input.envelope.delivery_id ||
|
|
155
|
+
messageId !== input.envelope.event.id) {
|
|
156
|
+
throw new CommandJsonAcknowledgementError("command_json_callback_acknowledgement_identity_mismatch", "callback acknowledgement does not bind the exact delivery and message");
|
|
157
|
+
}
|
|
158
|
+
if (disposition === "accepted") {
|
|
159
|
+
const acceptanceId = requiredPointerString(acknowledgement, definition.acceptanceId, "acceptance id");
|
|
160
|
+
return {
|
|
161
|
+
disposition,
|
|
162
|
+
accepted_at: input.now.toISOString(),
|
|
163
|
+
acceptance_id: acceptanceId,
|
|
164
|
+
evidence: processEvidence(input.result)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
const errorCode = defaultOutcomeErrorCode(disposition);
|
|
168
|
+
if (disposition === "uncertain") {
|
|
169
|
+
return {
|
|
170
|
+
disposition,
|
|
171
|
+
error_code: errorCode,
|
|
172
|
+
observed_at: input.now.toISOString(),
|
|
173
|
+
evidence: processEvidence(input.result)
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
disposition,
|
|
178
|
+
error_code: errorCode,
|
|
179
|
+
evidence: processEvidence(input.result)
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const errorCode = error instanceof CommandJsonAcknowledgementError
|
|
184
|
+
? error.errorCode
|
|
185
|
+
: "command_json_callback_acknowledgement_invalid";
|
|
186
|
+
return uncertainFailure(errorCode, input.now);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function processEvidence(result) {
|
|
190
|
+
return {
|
|
191
|
+
transport: COMMAND_JSON_CALLBACK_TRANSPORT_KIND,
|
|
192
|
+
process_status: result.status,
|
|
193
|
+
...(result.signal ? { process_signal: result.signal } : {})
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
function processExecutionFailure(error, observedAt) {
|
|
197
|
+
const code = errorCode(error);
|
|
198
|
+
if (["ENOENT", "ENOTDIR", "EACCES", "EPERM"].includes(code ?? "")) {
|
|
199
|
+
return permanentFailure("command_json_callback_executable_unavailable");
|
|
200
|
+
}
|
|
201
|
+
return uncertainFailure(code === "ETIMEDOUT" || code === "ERR_CHILD_PROCESS_STDIO_MAXBUFFER" ||
|
|
202
|
+
code === "ENOBUFS"
|
|
203
|
+
? "command_json_callback_execution_limit_uncertain"
|
|
204
|
+
: "command_json_callback_execution_uncertain", observedAt);
|
|
205
|
+
}
|
|
206
|
+
function interpolationValues(envelope, controllerSessionId) {
|
|
207
|
+
const values = new Map();
|
|
208
|
+
const add = (name, value, sensitiveBody = false) => {
|
|
209
|
+
if (value !== undefined) {
|
|
210
|
+
values.set(name, { value: String(value), sensitiveBody });
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
add("controller.session_id", controllerSessionId);
|
|
214
|
+
add("envelope.delivery_id", envelope.delivery_id);
|
|
215
|
+
add("envelope.idempotency_key", envelope.idempotency_key);
|
|
216
|
+
add("envelope.message_id", envelope.event.id);
|
|
217
|
+
add("envelope.body", envelope.event.body, true);
|
|
218
|
+
return values;
|
|
219
|
+
}
|
|
220
|
+
function interpolate(template, values, destination) {
|
|
221
|
+
let malformed = false;
|
|
222
|
+
const rendered = template.replace(/\$\{([^{}]+)\}/gu, (_match, name) => {
|
|
223
|
+
const resolved = values.get(String(name));
|
|
224
|
+
if (!resolved || (destination === "argument" && resolved.sensitiveBody)) {
|
|
225
|
+
malformed = true;
|
|
226
|
+
return "";
|
|
227
|
+
}
|
|
228
|
+
return resolved.value;
|
|
229
|
+
});
|
|
230
|
+
if (malformed || rendered.includes("${")) {
|
|
231
|
+
throw new Error("command_json_v1 interpolation is unsupported or malformed");
|
|
232
|
+
}
|
|
233
|
+
assertNoNullByte(rendered, `command_json_v1 ${destination}`);
|
|
234
|
+
return rendered;
|
|
235
|
+
}
|
|
236
|
+
function filteredEnvironment(source, allowed) {
|
|
237
|
+
const filtered = Object.create(null);
|
|
238
|
+
for (const name of allowed) {
|
|
239
|
+
if (Object.hasOwn(source, name) && source[name] !== undefined) {
|
|
240
|
+
filtered[name] = source[name];
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return filtered;
|
|
244
|
+
}
|
|
245
|
+
function requiredPointerString(document, definition, label) {
|
|
246
|
+
const value = resolveJsonPointer(document, definition.jsonPointer);
|
|
247
|
+
if (!nonBlank(value)) {
|
|
248
|
+
throw new CommandJsonAcknowledgementError("command_json_callback_acknowledgement_invalid", `callback acknowledgement ${label} must be a non-empty string`);
|
|
249
|
+
}
|
|
250
|
+
return value;
|
|
251
|
+
}
|
|
252
|
+
function resolveJsonPointer(document, pointer) {
|
|
253
|
+
if (pointer === "")
|
|
254
|
+
return document;
|
|
255
|
+
let current = document;
|
|
256
|
+
for (const encoded of pointer.slice(1).split("/")) {
|
|
257
|
+
const token = encoded.replace(/~1/gu, "/").replace(/~0/gu, "~");
|
|
258
|
+
if (current === null ||
|
|
259
|
+
typeof current !== "object" ||
|
|
260
|
+
!Object.hasOwn(current, token)) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
current = current[token];
|
|
264
|
+
}
|
|
265
|
+
return current;
|
|
266
|
+
}
|
|
267
|
+
function defaultOutcomeErrorCode(disposition) {
|
|
268
|
+
return `command_json_callback_${disposition}`;
|
|
269
|
+
}
|
|
270
|
+
function permanentFailure(errorCode) {
|
|
271
|
+
return { disposition: "permanent_failure", error_code: errorCode };
|
|
272
|
+
}
|
|
273
|
+
function uncertainFailure(errorCode, observedAt) {
|
|
274
|
+
return {
|
|
275
|
+
disposition: "uncertain",
|
|
276
|
+
error_code: errorCode,
|
|
277
|
+
observed_at: observedAt.toISOString()
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function requiredNonBlank(value, label) {
|
|
281
|
+
if (!nonBlank(value))
|
|
282
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
283
|
+
return value;
|
|
284
|
+
}
|
|
285
|
+
function nonBlank(value) {
|
|
286
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
287
|
+
}
|
|
288
|
+
function assertNoNullByte(value, label) {
|
|
289
|
+
if (value.includes("\0"))
|
|
290
|
+
throw new Error(`${label} contains a null byte`);
|
|
291
|
+
}
|
|
292
|
+
function errorCode(error) {
|
|
293
|
+
if (!error || typeof error !== "object")
|
|
294
|
+
return undefined;
|
|
295
|
+
const value = error.code;
|
|
296
|
+
return typeof value === "string" ? value : undefined;
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=command-json-callback-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-json-callback-transport.js","sourceRoot":"","sources":["../../src/command-json-callback-transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type HostBridgeCommandResult, type HostBridgeToolContext, type HostBridgeToolLogger, type HostBridgeToolResult } from "./host-bridge-tools.js";
|
|
2
|
+
export type { HostBridgeCommandResult, HostBridgeToolContext, HostBridgeToolLogger, HostBridgeToolResult } from "./host-bridge-tools.js";
|
|
3
|
+
export { createTrustedHostProfileRuntime, hostProfileRelayEnvironment } from "./host-profile-runtime.js";
|
|
4
|
+
export type { CreateTrustedHostProfileRuntimeOptions, TrustedHostProfileRuntimeV1 } from "./host-profile-runtime.js";
|
|
5
|
+
/** Stable relay entrypoint for native Host connector packages. */
|
|
6
|
+
export declare const defaultHostAdapterRelayPath: string;
|
|
7
|
+
export interface HostAdapterControllerContext extends HostBridgeToolContext {
|
|
8
|
+
/** Exact Host-owned controller incarnation; never derive this from text. */
|
|
9
|
+
readonly authority: object;
|
|
10
|
+
}
|
|
11
|
+
export type HostAdapterEnvironmentContext = HostBridgeToolContext;
|
|
12
|
+
export interface HostAdapterToolMetadata {
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly description: string;
|
|
15
|
+
readonly inputSchema: Readonly<Record<string, unknown>>;
|
|
16
|
+
}
|
|
17
|
+
export interface HostAdapterCommandMetadata {
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly description: string;
|
|
20
|
+
readonly acceptsArgs: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface HostAdapterLifecycle {
|
|
23
|
+
readonly id: string;
|
|
24
|
+
start(): void;
|
|
25
|
+
stop(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export interface CreateHostAdapterOptions {
|
|
28
|
+
readonly relayPath?: string;
|
|
29
|
+
readonly environmentForContext: (context: HostAdapterEnvironmentContext) => NodeJS.ProcessEnv;
|
|
30
|
+
/** Fixed child environment used by the one Host-owned lifecycle service. */
|
|
31
|
+
readonly lifecycleEnvironment?: NodeJS.ProcessEnv;
|
|
32
|
+
readonly lifecycleIntervalMs?: number;
|
|
33
|
+
readonly pluginConfig?: Readonly<Record<string, unknown>>;
|
|
34
|
+
readonly logger: HostBridgeToolLogger;
|
|
35
|
+
}
|
|
36
|
+
export interface HostAdapter {
|
|
37
|
+
readonly command: HostAdapterCommandMetadata;
|
|
38
|
+
readonly tools: readonly HostAdapterToolMetadata[];
|
|
39
|
+
readonly lifecycle: HostAdapterLifecycle;
|
|
40
|
+
executeCommand(context: HostAdapterControllerContext, args: string, signal?: AbortSignal): Promise<HostBridgeCommandResult>;
|
|
41
|
+
executeTool(context: HostAdapterControllerContext, name: string, toolCallId: string, args: Readonly<Record<string, unknown>>, signal?: AbortSignal): Promise<HostBridgeToolResult>;
|
|
42
|
+
/** Drop private action/snapshot authority when the Host disposes an owner. */
|
|
43
|
+
disposeContext(authority: object): void;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Adapt AKK's established slash command and 16 semantic tools to a native Host.
|
|
47
|
+
*
|
|
48
|
+
* Public metadata is captured exactly once. Executable registries are created
|
|
49
|
+
* lazily per exact Host authority object so private approvals, action offers,
|
|
50
|
+
* resume snapshots, and idempotency identities cannot leak across controllers.
|
|
51
|
+
*/
|
|
52
|
+
export declare function createHostAdapter(options: CreateHostAdapterOptions): HostAdapter;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { createHostBridgeToolRegistry } from "./host-bridge-tools.js";
|
|
2
|
+
import { bindOpenClawRelayEnvironment, bindOpenClawRelayPath, defaultOpenClawRelayPath, withHostBridgeInvocationSignal } from "./openclaw-plugin-command-adapter.js";
|
|
3
|
+
import { createMonitorReconciliationService, MONITOR_SUPERVISOR_INTERVAL_MS } from "./openclaw-plugin-supervisor.js";
|
|
4
|
+
export { createTrustedHostProfileRuntime, hostProfileRelayEnvironment } from "./host-profile-runtime.js";
|
|
5
|
+
/** Stable relay entrypoint for native Host connector packages. */
|
|
6
|
+
export const defaultHostAdapterRelayPath = defaultOpenClawRelayPath;
|
|
7
|
+
const METADATA_CONTEXT = Object.freeze({
|
|
8
|
+
sessionKey: "host-adapter:metadata",
|
|
9
|
+
sessionId: "host-adapter:metadata"
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Adapt AKK's established slash command and 16 semantic tools to a native Host.
|
|
13
|
+
*
|
|
14
|
+
* Public metadata is captured exactly once. Executable registries are created
|
|
15
|
+
* lazily per exact Host authority object so private approvals, action offers,
|
|
16
|
+
* resume snapshots, and idempotency identities cannot leak across controllers.
|
|
17
|
+
*/
|
|
18
|
+
export function createHostAdapter(options) {
|
|
19
|
+
const relayPath = requiredString(options.relayPath ?? defaultHostAdapterRelayPath, "relayPath");
|
|
20
|
+
const pluginConfig = options.pluginConfig ?? {};
|
|
21
|
+
const metadataRegistry = createHostBridgeToolRegistry({
|
|
22
|
+
relayPath,
|
|
23
|
+
relayEnvironment: {},
|
|
24
|
+
pluginConfig,
|
|
25
|
+
logger: options.logger,
|
|
26
|
+
context: METADATA_CONTEXT
|
|
27
|
+
});
|
|
28
|
+
const commandMetadata = immutableMetadataClone({
|
|
29
|
+
name: metadataRegistry.command().name,
|
|
30
|
+
description: metadataRegistry.command().description,
|
|
31
|
+
acceptsArgs: metadataRegistry.command().acceptsArgs
|
|
32
|
+
});
|
|
33
|
+
const toolMetadata = immutableMetadataClone(metadataRegistry.list().map((tool) => ({
|
|
34
|
+
name: tool.name,
|
|
35
|
+
description: tool.description,
|
|
36
|
+
inputSchema: tool.inputSchema
|
|
37
|
+
})));
|
|
38
|
+
const registries = new WeakMap();
|
|
39
|
+
const lifecycleApi = {
|
|
40
|
+
pluginConfig,
|
|
41
|
+
logger: options.logger
|
|
42
|
+
};
|
|
43
|
+
bindOpenClawRelayPath(lifecycleApi, relayPath);
|
|
44
|
+
bindOpenClawRelayEnvironment(lifecycleApi, options.lifecycleEnvironment ?? process.env);
|
|
45
|
+
const lifecycle = createMonitorReconciliationService(lifecycleApi, options.lifecycleIntervalMs ?? MONITOR_SUPERVISOR_INTERVAL_MS);
|
|
46
|
+
const registryFor = (context) => {
|
|
47
|
+
const trusted = trustedControllerContext(context);
|
|
48
|
+
const cached = registries.get(context.authority);
|
|
49
|
+
if (cached) {
|
|
50
|
+
if (cached.context.sessionKey !== trusted.sessionKey ||
|
|
51
|
+
cached.context.sessionId !== trusted.sessionId) {
|
|
52
|
+
throw new Error("Host adapter authority cannot be reused with another controller context");
|
|
53
|
+
}
|
|
54
|
+
return cached.registry;
|
|
55
|
+
}
|
|
56
|
+
const environment = options.environmentForContext(trusted);
|
|
57
|
+
if (!environment || typeof environment !== "object") {
|
|
58
|
+
throw new Error("environmentForContext must return a process environment");
|
|
59
|
+
}
|
|
60
|
+
const registry = createHostBridgeToolRegistry({
|
|
61
|
+
relayPath,
|
|
62
|
+
relayEnvironment: environment,
|
|
63
|
+
pluginConfig,
|
|
64
|
+
logger: options.logger,
|
|
65
|
+
context: trusted
|
|
66
|
+
});
|
|
67
|
+
registries.set(context.authority, { context: trusted, registry });
|
|
68
|
+
return registry;
|
|
69
|
+
};
|
|
70
|
+
return Object.freeze({
|
|
71
|
+
command: commandMetadata,
|
|
72
|
+
tools: toolMetadata,
|
|
73
|
+
lifecycle,
|
|
74
|
+
executeCommand(context, args, signal) {
|
|
75
|
+
return withHostBridgeInvocationSignal(signal, () => registryFor(context).command().execute(args));
|
|
76
|
+
},
|
|
77
|
+
executeTool(context, name, toolCallId, args, signal) {
|
|
78
|
+
return withHostBridgeInvocationSignal(signal, () => registryFor(context).execute(name, toolCallId, args));
|
|
79
|
+
},
|
|
80
|
+
disposeContext(authority) {
|
|
81
|
+
requiredAuthority(authority);
|
|
82
|
+
registries.delete(authority);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function trustedControllerContext(context) {
|
|
87
|
+
requiredAuthority(context?.authority);
|
|
88
|
+
return Object.freeze({
|
|
89
|
+
sessionKey: requiredString(context?.sessionKey, "context.sessionKey"),
|
|
90
|
+
sessionId: requiredString(context?.sessionId, "context.sessionId")
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function requiredAuthority(value) {
|
|
94
|
+
if (value === null ||
|
|
95
|
+
(typeof value !== "object" && typeof value !== "function")) {
|
|
96
|
+
throw new Error("context.authority must be an exact Host-owned object");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function requiredString(value, label) {
|
|
100
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
101
|
+
throw new Error(`${label} is required`);
|
|
102
|
+
}
|
|
103
|
+
return value;
|
|
104
|
+
}
|
|
105
|
+
function immutableMetadataClone(value) {
|
|
106
|
+
return deepFreezeMetadata(structuredClone(value));
|
|
107
|
+
}
|
|
108
|
+
function deepFreezeMetadata(value, seen = new WeakSet()) {
|
|
109
|
+
if (value === null ||
|
|
110
|
+
(typeof value !== "object" && typeof value !== "function")) {
|
|
111
|
+
return value;
|
|
112
|
+
}
|
|
113
|
+
const objectValue = value;
|
|
114
|
+
if (seen.has(objectValue)) {
|
|
115
|
+
return value;
|
|
116
|
+
}
|
|
117
|
+
seen.add(objectValue);
|
|
118
|
+
for (const key of Reflect.ownKeys(objectValue)) {
|
|
119
|
+
deepFreezeMetadata(objectValue[key], seen);
|
|
120
|
+
}
|
|
121
|
+
return Object.freeze(value);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=host-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-adapter.js","sourceRoot":"","sources":["../../src/host-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import type { HostBridgeToolRegistry } from "./host-bridge-tools.js";
|
|
3
|
+
export declare const HOST_BRIDGE_MCP_SERVER_NAME = "agent-knock-knock-host-bridge";
|
|
4
|
+
export interface CreateHostBridgeMcpServerOptions {
|
|
5
|
+
readonly registry: HostBridgeToolRegistry;
|
|
6
|
+
readonly version: string;
|
|
7
|
+
/** Test seam; production callers receive a fresh identity per Bridge. */
|
|
8
|
+
readonly instanceId?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Expose the established AKK semantic tool registry over MCP.
|
|
12
|
+
*
|
|
13
|
+
* The low-level SDK server intentionally does not infer validation from the
|
|
14
|
+
* schemas returned by tools/list, so every schema is compiled once here and
|
|
15
|
+
* enforced again before any semantic tool can execute.
|
|
16
|
+
*/
|
|
17
|
+
export declare function createHostBridgeMcpServer(options: CreateHostBridgeMcpServerOptions): Server;
|
|
18
|
+
export declare function getHostBridgeMcpActiveCallCount(server: Server): number;
|
|
19
|
+
/** Preserve both JSON-RPC request-id type and value inside one Bridge. */
|
|
20
|
+
export declare function hostBridgeToolCallId(instanceId: string, requestId: string | number): string;
|
|
21
|
+
/** Wait until every already accepted MCP tool call has produced a result. */
|
|
22
|
+
export declare function drainHostBridgeMcpCalls(server: Server): Promise<void>;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
|
+
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { AjvJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/ajv";
|
|
5
|
+
export const HOST_BRIDGE_MCP_SERVER_NAME = "agent-knock-knock-host-bridge";
|
|
6
|
+
const MAX_MODEL_ERROR_LENGTH = 1_024;
|
|
7
|
+
const activeCallsByServer = new WeakMap();
|
|
8
|
+
/**
|
|
9
|
+
* Expose the established AKK semantic tool registry over MCP.
|
|
10
|
+
*
|
|
11
|
+
* The low-level SDK server intentionally does not infer validation from the
|
|
12
|
+
* schemas returned by tools/list, so every schema is compiled once here and
|
|
13
|
+
* enforced again before any semantic tool can execute.
|
|
14
|
+
*/
|
|
15
|
+
export function createHostBridgeMcpServer(options) {
|
|
16
|
+
const version = requiredString(options.version, "version");
|
|
17
|
+
const instanceId = requiredString(options.instanceId ?? randomUUID(), "instanceId");
|
|
18
|
+
const descriptors = [...options.registry.list()];
|
|
19
|
+
const validatorProvider = new AjvJsonSchemaValidator();
|
|
20
|
+
const compiledByName = new Map();
|
|
21
|
+
for (const descriptor of descriptors) {
|
|
22
|
+
if (compiledByName.has(descriptor.name)) {
|
|
23
|
+
throw new Error(`duplicate host bridge MCP tool ${descriptor.name}`);
|
|
24
|
+
}
|
|
25
|
+
const validate = validatorProvider.getValidator(descriptor.inputSchema);
|
|
26
|
+
compiledByName.set(descriptor.name, { validate });
|
|
27
|
+
}
|
|
28
|
+
const advertisedTools = descriptors.map((descriptor) => ({
|
|
29
|
+
name: descriptor.name,
|
|
30
|
+
description: descriptor.description,
|
|
31
|
+
inputSchema: descriptor.inputSchema
|
|
32
|
+
}));
|
|
33
|
+
const server = new Server({ name: HOST_BRIDGE_MCP_SERVER_NAME, version }, { capabilities: { tools: {} } });
|
|
34
|
+
const activeCalls = new Set();
|
|
35
|
+
activeCallsByServer.set(server, activeCalls);
|
|
36
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: advertisedTools }));
|
|
37
|
+
server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
38
|
+
const name = request.params.name;
|
|
39
|
+
const compiled = compiledByName.get(name);
|
|
40
|
+
if (!compiled) {
|
|
41
|
+
throw invalidParams(`Unknown host bridge tool: ${name}`);
|
|
42
|
+
}
|
|
43
|
+
if (request.params.task !== undefined ||
|
|
44
|
+
hasLegacyTaskRequest(request.params._meta)) {
|
|
45
|
+
throw invalidParams(`Task execution is not supported for tool: ${name}`);
|
|
46
|
+
}
|
|
47
|
+
const validation = compiled.validate(request.params.arguments ?? {});
|
|
48
|
+
if (!validation.valid) {
|
|
49
|
+
throw invalidParams(`Invalid arguments for ${name}: ${validation.errorMessage}`);
|
|
50
|
+
}
|
|
51
|
+
const execution = executeToolCall(options.registry, name, hostBridgeToolCallId(instanceId, extra.requestId), validation.data);
|
|
52
|
+
activeCalls.add(execution);
|
|
53
|
+
try {
|
|
54
|
+
return await execution;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
activeCalls.delete(execution);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
return server;
|
|
61
|
+
}
|
|
62
|
+
export function getHostBridgeMcpActiveCallCount(server) {
|
|
63
|
+
return activeCallsByServer.get(server)?.size ?? 0;
|
|
64
|
+
}
|
|
65
|
+
/** Preserve both JSON-RPC request-id type and value inside one Bridge. */
|
|
66
|
+
export function hostBridgeToolCallId(instanceId, requestId) {
|
|
67
|
+
if ((typeof requestId !== "string" && typeof requestId !== "number") ||
|
|
68
|
+
(typeof requestId === "number" && !Number.isFinite(requestId))) {
|
|
69
|
+
throw new Error("MCP request id must be a finite number or string");
|
|
70
|
+
}
|
|
71
|
+
return `host-bridge:${JSON.stringify([instanceId, requestId])}`;
|
|
72
|
+
}
|
|
73
|
+
/** Wait until every already accepted MCP tool call has produced a result. */
|
|
74
|
+
export async function drainHostBridgeMcpCalls(server) {
|
|
75
|
+
const activeCalls = activeCallsByServer.get(server);
|
|
76
|
+
while (activeCalls && activeCalls.size > 0) {
|
|
77
|
+
await Promise.allSettled([...activeCalls]);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function executeToolCall(registry, name, toolCallId, args) {
|
|
81
|
+
try {
|
|
82
|
+
const result = await registry.execute(name, toolCallId, args);
|
|
83
|
+
return mapToolResult(result);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: "text", text: modelFacingErrorMessage(error) }],
|
|
88
|
+
isError: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function mapToolResult(result) {
|
|
93
|
+
const mapped = {
|
|
94
|
+
content: [...(result.content ?? [])]
|
|
95
|
+
};
|
|
96
|
+
if (isRecord(result.details)) {
|
|
97
|
+
mapped.structuredContent = result.details;
|
|
98
|
+
}
|
|
99
|
+
if (typeof result.isError === "boolean") {
|
|
100
|
+
mapped.isError = result.isError;
|
|
101
|
+
}
|
|
102
|
+
return mapped;
|
|
103
|
+
}
|
|
104
|
+
function invalidParams(message) {
|
|
105
|
+
return new McpError(ErrorCode.InvalidParams, boundedSingleLine(message));
|
|
106
|
+
}
|
|
107
|
+
function modelFacingErrorMessage(error) {
|
|
108
|
+
const message = error instanceof Error
|
|
109
|
+
? error.message
|
|
110
|
+
: typeof error === "string"
|
|
111
|
+
? error
|
|
112
|
+
: "Tool execution failed.";
|
|
113
|
+
return boundedSingleLine(message) || "Tool execution failed.";
|
|
114
|
+
}
|
|
115
|
+
function boundedSingleLine(value) {
|
|
116
|
+
const sanitized = value
|
|
117
|
+
.replace(/\u001B\[[0-?]*[ -/]*[@-~]/gu, "")
|
|
118
|
+
.replace(/[\u0000-\u001F\u007F-\u009F]/gu, " ")
|
|
119
|
+
.replace(/\s+/gu, " ")
|
|
120
|
+
.trim();
|
|
121
|
+
if (sanitized.length <= MAX_MODEL_ERROR_LENGTH) {
|
|
122
|
+
return sanitized;
|
|
123
|
+
}
|
|
124
|
+
let prefix = "";
|
|
125
|
+
for (const character of sanitized) {
|
|
126
|
+
if (prefix.length + character.length > MAX_MODEL_ERROR_LENGTH - 3) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
prefix += character;
|
|
130
|
+
}
|
|
131
|
+
return `${prefix}...`;
|
|
132
|
+
}
|
|
133
|
+
function hasLegacyTaskRequest(meta) {
|
|
134
|
+
return isRecord(meta) && meta.task !== undefined;
|
|
135
|
+
}
|
|
136
|
+
function requiredString(value, label) {
|
|
137
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
138
|
+
throw new Error(`${label} is required`);
|
|
139
|
+
}
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
function isRecord(value) {
|
|
143
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=host-bridge-mcp.js.map
|