@byokit/openclaw 0.19.0 → 0.21.0
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 +11 -0
- package/README.md +66 -6
- package/dist/accounts.d.ts +3 -1
- package/dist/accounts.js +30 -9
- package/dist/approvals.js +5 -2
- package/dist/bridge.js +8 -4
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +6 -2
- package/dist/delegations.d.ts +10 -2
- package/dist/delegations.js +83 -18
- package/dist/helpers.d.ts +28 -0
- package/dist/helpers.js +72 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/keys.d.ts +3 -1
- package/dist/keys.js +49 -17
- package/dist/kit.d.ts +13 -1
- package/dist/kit.js +63 -12
- package/dist/runs.d.ts +2 -0
- package/dist/runs.js +30 -11
- package/dist/signin.js +2 -3
- package/dist/testing/fake-gateway.js +47 -6
- package/dist/types.d.ts +24 -2
- package/package.json +1 -1
|
@@ -281,15 +281,45 @@ export function fakeGateway(script, o) {
|
|
|
281
281
|
for (const waiter of run.waiters.splice(0))
|
|
282
282
|
waiter(result);
|
|
283
283
|
};
|
|
284
|
-
const emitRun = (run, stream, data) =>
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
const emitRun = (run, stream, data) => {
|
|
285
|
+
emit('agent', { runId: run.runId, seq: run.seq++, stream, ts: Date.now(), data });
|
|
286
|
+
const child = run.child;
|
|
287
|
+
if (child)
|
|
288
|
+
child.relay = child.relay.then(() => bridgeRequest(child.sock, { kind: 'delegation-event',
|
|
289
|
+
event: { runId: run.runId, sessionKey: run.sessionKey, stream, data } })).catch(() => { });
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* A native `sessions_send` as the engine and plugin play it: the parent's dispatch is tracked before it goes, then the
|
|
293
|
+
* exact target session runs as an engine-created child and the receipt names its run (delegated admission, 5.8).
|
|
294
|
+
*/
|
|
295
|
+
const nativeSend = async (run, parentRunId, input, callId, sock) => {
|
|
296
|
+
const ids = { key: run.sessionKey, runId: parentRunId, callId };
|
|
297
|
+
const prepared = await bridgeRequest(sock, { kind: 'delegation-prepare', ...ids, tool: 'sessions_send', input });
|
|
298
|
+
if (prepared.allow === false)
|
|
299
|
+
return { isError: true, output: String(prepared.reason) };
|
|
300
|
+
const sessionKey = String(input.sessionKey);
|
|
301
|
+
const agentId = /^agent:([^:]+):/.exec(sessionKey)?.[1];
|
|
302
|
+
// Like the pin: a send reaches only a session that already exists (its agent's main excepted).
|
|
303
|
+
const child = agentId && (sessions.has(`${agentId}\n${sessionKey}`) || sessionKey === `agent:${agentId}:main`)
|
|
304
|
+
? startRun({ agentId, sessionKey, message: input.message }, sock, true) : undefined;
|
|
305
|
+
const details = child ? { status: 'accepted', runId: child.runId, sessionKey }
|
|
306
|
+
: { status: 'error', error: `No session found: ${sessionKey}`, sessionKey };
|
|
307
|
+
await bridgeRequest(sock, { kind: 'delegation-receipt', ...ids, result: { details } });
|
|
308
|
+
return { isError: !child, output: JSON.stringify(details) };
|
|
309
|
+
};
|
|
310
|
+
/** The `agent` handler: the run's scripted turn, its `[tool NAME {json}]` calls through the real bridge. An
|
|
311
|
+
* engine-created `child` names its own run on the bridge, as the plugin does with the engine's run id. */
|
|
312
|
+
const startRun = (params, bridgeSock, child = false) => {
|
|
287
313
|
if (params.agentId != null && !agents.has(String(params.agentId)))
|
|
288
314
|
throw new Error(`unknown agent: ${params.agentId}`);
|
|
289
315
|
// Like the engine: the provider/model the run is called on, its own override or the member's (here openai).
|
|
290
316
|
const run = { runId: randomUUID(), agentId: String(params.agentId ?? 'main'), sessionKey: String(params.sessionKey ?? ''), seq: 0,
|
|
291
317
|
provider: String(params.provider ?? 'openai'), model: String(params.model ?? 'gpt-5.1'), waiters: [] };
|
|
292
318
|
runs.set(run.runId, run);
|
|
319
|
+
if (child) {
|
|
320
|
+
run.child = { sock: bridgeSock, relay: Promise.resolve() };
|
|
321
|
+
emitRun(run, 'lifecycle', { phase: 'start' });
|
|
322
|
+
}
|
|
293
323
|
const session = sessionOf(run.agentId, run.sessionKey);
|
|
294
324
|
session.provider = run.provider;
|
|
295
325
|
session.model = run.model;
|
|
@@ -309,13 +339,17 @@ export function fakeGateway(script, o) {
|
|
|
309
339
|
let isError = false;
|
|
310
340
|
if (bridgeSock && !(builtin && table?.gateBuiltins === false)) {
|
|
311
341
|
try {
|
|
312
|
-
const
|
|
342
|
+
const owner = child ? { runId: run.runId } : {};
|
|
343
|
+
const gate = await bridgeRequest(bridgeSock, { kind: 'gate', key: run.sessionKey, tool: call.name, input: call.input, ...owner });
|
|
313
344
|
if (!gate.allow) {
|
|
314
345
|
isError = true;
|
|
315
346
|
output = String(gate.reason ?? 'blocked');
|
|
316
347
|
}
|
|
348
|
+
else if (builtin && call.name === 'sessions_send') {
|
|
349
|
+
({ isError, output } = await nativeSend(run, child ? run.runId : String(params.idempotencyKey ?? ''), call.input, toolCallId, bridgeSock));
|
|
350
|
+
}
|
|
317
351
|
else if (!builtin) {
|
|
318
|
-
const done = await bridgeRequest(bridgeSock, { kind: 'call', key: run.sessionKey, permit: gate.permit, tool: call.name, input: call.input });
|
|
352
|
+
const done = await bridgeRequest(bridgeSock, { kind: 'call', key: run.sessionKey, permit: gate.permit, tool: call.name, input: call.input, ...owner });
|
|
319
353
|
isError = done.ok !== true;
|
|
320
354
|
output = String(done.ok === true ? done.text : done.reason);
|
|
321
355
|
}
|
|
@@ -332,7 +366,14 @@ export function fakeGateway(script, o) {
|
|
|
332
366
|
append(session, { role: 'assistant', content: [{ type: 'text', text }] });
|
|
333
367
|
// The engine sums the run's usage (zero buckets omitted); the fake counts characters.
|
|
334
368
|
run.usage = { input: message.length, output: text.length, total: message.length + text.length };
|
|
335
|
-
setTimeout(() =>
|
|
369
|
+
setTimeout(() => {
|
|
370
|
+
if (run.result || !child)
|
|
371
|
+
return finish(run, { status: 'ok', terminalReply: { text } });
|
|
372
|
+
// A child's lifecycle end, as the engine streams it: `hit the limit` plays the model's usage-limit error.
|
|
373
|
+
const error = /hit the limit/i.test(message) ? 'You have hit your ChatGPT usage limit (plus plan). Try again in ~30 min.' : undefined;
|
|
374
|
+
emitRun(run, 'lifecycle', error ? { phase: 'error', error } : { phase: 'end' });
|
|
375
|
+
finish(run, error ? { status: 'error', error } : { status: 'ok', terminalReply: { text } });
|
|
376
|
+
}, ABORT_WINDOW_MS);
|
|
336
377
|
})();
|
|
337
378
|
}, 0);
|
|
338
379
|
return { runId: run.runId, status: 'accepted' };
|
package/dist/types.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface ToolSpec {
|
|
|
19
19
|
export interface RunRef {
|
|
20
20
|
sessionKey: string;
|
|
21
21
|
member: Member;
|
|
22
|
+
helper?: string;
|
|
22
23
|
meta?: unknown;
|
|
23
24
|
runId?: string;
|
|
24
25
|
agentId?: string;
|
|
@@ -31,11 +32,28 @@ export interface RunRef {
|
|
|
31
32
|
runId: string;
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
/** One of a member's helpers (5.8.3): its own persona and sessions (`sessionPrefix`) on `account`, run by `agentId`, the
|
|
36
|
+
* engine agent already holding that sign-in. */
|
|
37
|
+
export type Helper = {
|
|
38
|
+
member: Member;
|
|
39
|
+
helper: string;
|
|
40
|
+
account: AccountId;
|
|
41
|
+
agentId: string;
|
|
42
|
+
sessionPrefix: string;
|
|
43
|
+
};
|
|
44
|
+
/** An admitted engine-created child (5.8): `tools` is the app-tool subset it may call (the parent's, narrowed). */
|
|
45
|
+
export type DelegatedRun = RunRef & Required<Pick<RunRef, 'runId' | 'agentId' | 'parent' | 'root'>> & {
|
|
46
|
+
tools: string[];
|
|
47
|
+
};
|
|
48
|
+
/** A delegated child's lifecycle (5.8.3 S3): `admitted`, its engine `event`s, then one `ended` whose `reason` is
|
|
49
|
+
* `terminal` (finished), `error` (`message`), `resting` (its helper's account hit its limit and rests `until`) or
|
|
50
|
+
* `cancelled` (aborted by the kit or the engine, or its admission ended). */
|
|
35
51
|
export type DelegatedEvent = {
|
|
36
52
|
type: 'admitted' | 'event' | 'ended';
|
|
37
53
|
run: DelegatedRun;
|
|
38
|
-
reason?: 'terminal' | 'cancelled';
|
|
54
|
+
reason?: 'terminal' | 'error' | 'resting' | 'cancelled';
|
|
55
|
+
until?: number;
|
|
56
|
+
message?: string;
|
|
39
57
|
event?: {
|
|
40
58
|
stream: string;
|
|
41
59
|
data?: Record<string, unknown>;
|
|
@@ -77,6 +95,9 @@ export interface RunSpec<S extends OutputSchema | undefined = OutputSchema | und
|
|
|
77
95
|
tools?: string[];
|
|
78
96
|
/** Exact target engine agent IDs and their app-tool subsets; does not share credentials. */
|
|
79
97
|
delegates?: Record<string, string[]>;
|
|
98
|
+
/** The member's ensured helpers (5.8.3) this run may hand work to, and their app-tool subsets: an exact native send to
|
|
99
|
+
* `agent:<the helper's agent>:h-<helper>:<rest>` is admitted as that helper's run (RunRef.helper). */
|
|
100
|
+
helperDelegates?: Record<string, string[]>;
|
|
80
101
|
register?: boolean;
|
|
81
102
|
}
|
|
82
103
|
export type RunEvent = {
|
|
@@ -181,6 +202,7 @@ export type Approval = {
|
|
|
181
202
|
source: 'gate' | 'exec' | 'plugin' | 'question';
|
|
182
203
|
member: Member;
|
|
183
204
|
sessionKey?: string;
|
|
205
|
+
helper?: string;
|
|
184
206
|
tool?: string;
|
|
185
207
|
summary: string;
|
|
186
208
|
input?: unknown;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.21.0",
|
|
4
4
|
"description": "The OpenClaw runtime kit: the pinned engine's full operator surface with plain-words helpers for members, sign-in, runs and approvals.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|