@byokit/openclaw 0.17.0 → 0.18.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 +4 -0
- package/dist/device.d.ts +7 -2
- package/dist/device.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/kit.d.ts +2 -0
- package/dist/kit.js +10 -2
- package/dist/link.js +31 -3
- package/dist/runs.d.ts +21 -1
- package/dist/runs.js +87 -2
- package/dist/types.d.ts +11 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.18.0 (2026-10-18)
|
|
6
|
+
|
|
7
|
+
- Reattach a paired device to a live-kit run by its existing idempotency key: sequenced replay then live events, a bounded journal with typed truncation, and grant-member isolation. Device disconnect does not interrupt the run; engine-restart reconstruction is not included.
|
|
8
|
+
|
|
5
9
|
## 0.17.0 (2026-10-18)
|
|
6
10
|
|
|
7
11
|
- Add opt-in `RunSpec.delegates` for native `sessions_send`/`sessions_spawn` app-tool admission and typed delegated events, retained exact receipts and subtree cancellation. Targets retain their own accounts; helper/person account sharing is not included.
|
package/dist/device.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import type { BrowserDevice, SignInRefusedWhy } from './browser.ts';
|
|
|
2
2
|
import type { DeviceLink } from '@byokit/pair';
|
|
3
3
|
import type { RouteView } from './routes.ts';
|
|
4
4
|
import { type AccountView } from './words.ts';
|
|
5
|
-
import type { Approval, Decision, GatewayEventName, GatewayEventPayload, GatewayMethod, GatewayParams, GatewayResult, KitState, RunEnd, OutputSchema, SchemaOutput, RunEvent, SignInView, AccountRef } from './types.ts';
|
|
5
|
+
import type { Approval, Decision, GatewayEventName, GatewayEventPayload, GatewayMethod, GatewayParams, GatewayResult, KitState, RunEnd, OutputSchema, SchemaOutput, RunEvent, RunFrame, SignInView, AccountRef } from './types.ts';
|
|
6
6
|
export type { GatewayEventName, GatewayEventPayload, GatewayMethod, GatewayParams, GatewayResult } from './types.ts';
|
|
7
|
-
export type { Approval, Decision, KitState, PlanWindow, Route, RunEnd, RunEvent, RunUsage, SignInView, OutputSchema, SchemaOutput } from './types.ts';
|
|
7
|
+
export type { Approval, Decision, KitState, PlanWindow, Route, RunEnd, RunEvent, RunFrame, RunUsage, SignInView, OutputSchema, SchemaOutput } from './types.ts';
|
|
8
8
|
/** One `oc.events` frame: a member's Gateway event, typed by name, or an approval add/resolve (7.2). */
|
|
9
9
|
export type OpenClawLinkEvent = {
|
|
10
10
|
[E in GatewayEventName]: {
|
|
@@ -30,11 +30,13 @@ export type SessionRow = {
|
|
|
30
30
|
/** The frame `oc.run`'s stream ends with: the run's `RunEnd`, beside its events. */
|
|
31
31
|
export type DeviceEndFrame<T = unknown> = {
|
|
32
32
|
type: 'end';
|
|
33
|
+
seq: number;
|
|
33
34
|
end: RunEnd<T>;
|
|
34
35
|
};
|
|
35
36
|
/** `oc.run`'s options beside the message: the member's own session, account, and the kit's run options. */
|
|
36
37
|
export type DeviceRunOptions<S extends OutputSchema | undefined = OutputSchema | undefined> = {
|
|
37
38
|
schema?: S;
|
|
39
|
+
idempotencyKey?: string;
|
|
38
40
|
sessionKey?: string;
|
|
39
41
|
account?: AccountRef | 'default' | 'auto';
|
|
40
42
|
needs?: string[];
|
|
@@ -96,6 +98,9 @@ export type OpenClawDevice = {
|
|
|
96
98
|
signOut(p: string): Promise<void>;
|
|
97
99
|
sessions(): Promise<SessionRow[]>;
|
|
98
100
|
run<const S extends OutputSchema | undefined = undefined>(message: string, o?: DeviceRunOptions<S>): AsyncIterable<DeviceRunEvent | DeviceEndFrame<SchemaOutput<S>>>;
|
|
101
|
+
attach(runId: string, o: {
|
|
102
|
+
fromSeq: number;
|
|
103
|
+
}): AsyncIterable<RunFrame>;
|
|
99
104
|
steer(k: string, t: string, o?: {
|
|
100
105
|
auth?: 'apiKey';
|
|
101
106
|
}): Promise<void>;
|
package/dist/device.js
CHANGED
|
@@ -361,8 +361,9 @@ export function openclawDevice(link) {
|
|
|
361
361
|
await link.request('oc.signout', { provider: p });
|
|
362
362
|
},
|
|
363
363
|
sessions: () => link.request('oc.sessions'),
|
|
364
|
+
attach: (runId, o) => liveStream(() => link.stream('oc.attach', { runId, fromSeq: o.fromSeq })),
|
|
364
365
|
run: (message, o) => {
|
|
365
|
-
const inner = liveStream(() => link.stream('oc.run', { message, ...(o?.sessionKey ? { sessionKey: checkKey(o.sessionKey) } : {}),
|
|
366
|
+
const inner = liveStream(() => link.stream('oc.run', { message, ...(o?.idempotencyKey !== undefined ? { idempotencyKey: o.idempotencyKey } : {}), ...(o?.sessionKey ? { sessionKey: checkKey(o.sessionKey) } : {}),
|
|
366
367
|
...(o?.account !== undefined ? { account: o.account } : {}),
|
|
367
368
|
...(o?.needs !== undefined ? { needs: o.needs } : {}),
|
|
368
369
|
...(o?.model !== undefined ? { model: o.model } : {}), ...(o?.system !== undefined ? { system: o.system } : {}),
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ENGINE_VERSION, OPERATOR_SCOPES, PROTOCOL_VERSION } from './constants.ts';
|
|
2
|
-
export type { Account, AccountId, AccountPick, AccountRef, Approval, CallOptions, ChannelChat, ChannelMessage, Considered, Decision, Defaults, ModelInfo, MoveResult, PickWhy, Room, RoomSpan, RunSelection, SignInState, GatewayEventName, GatewayEventPayload, GatewayMethod, GatewayParams, GatewayResult, GatewayTransport, GateResult, Hello, KitState, KitEventName, KitEventPayload, BrowserPing, LearningCapture, LearningMode, Member, PlanWindow, Route, RunEnd, RunEvent, RunRef, DelegatedRun, DelegatedEvent, RunSpec, OutputSchema, SchemaOutput, RunUsage, ThinkingAsked, ThinkingReport, ThinkingUsed, SignInOptions, SignInView, TelegramChannel, ToolHost, ToolSpec, } from './types.ts';
|
|
2
|
+
export type { Account, AccountId, AccountPick, AccountRef, Approval, CallOptions, ChannelChat, ChannelMessage, Considered, Decision, Defaults, ModelInfo, MoveResult, PickWhy, Room, RoomSpan, RunSelection, SignInState, GatewayEventName, GatewayEventPayload, GatewayMethod, GatewayParams, GatewayResult, GatewayTransport, GateResult, Hello, KitState, KitEventName, KitEventPayload, BrowserPing, LearningCapture, LearningMode, Member, PlanWindow, Route, RunEnd, RunEvent, RunFrame, RunRef, DelegatedRun, DelegatedEvent, RunSpec, OutputSchema, SchemaOutput, RunUsage, ThinkingAsked, ThinkingReport, ThinkingUsed, SignInOptions, SignInView, TelegramChannel, ToolHost, ToolSpec, } from './types.ts';
|
|
3
3
|
export type { GatewayMethods } from './generated/methods.ts';
|
|
4
4
|
export type { JsonValue } from './output.ts';
|
|
5
5
|
export type { RouteFacts, RouteView } from './routes.ts';
|
package/dist/kit.d.ts
CHANGED
|
@@ -64,6 +64,8 @@ export declare class OpenClawKit {
|
|
|
64
64
|
private members?;
|
|
65
65
|
private readonly locks;
|
|
66
66
|
private readonly routeMap;
|
|
67
|
+
private readonly runReplay;
|
|
68
|
+
attach(member: Member, runId: string, fromSeq: number, signal: AbortSignal): AsyncIterable<import("./types.ts").RunFrame>;
|
|
67
69
|
private installs;
|
|
68
70
|
private accountsCtl?;
|
|
69
71
|
private readonly bridge;
|
package/dist/kit.js
CHANGED
|
@@ -18,7 +18,7 @@ import { createAccounts, memberOfAccount } from './accounts.js';
|
|
|
18
18
|
import { createLocks } from './locks.js';
|
|
19
19
|
import { keyAgentId, KEY_PREFIX, MEMBER_ID } from './members.js';
|
|
20
20
|
import { confirmRetainedLogin as confirmLogin, migrateRetainedLogin as migrateLogin } from './migrate.js';
|
|
21
|
-
import { createRuns, signedInProviders } from './runs.js';
|
|
21
|
+
import { createRuns, RunReplay, signedInProviders } from './runs.js';
|
|
22
22
|
import { authStatus, createAuthStatus } from './auth-status.js';
|
|
23
23
|
import { outputSchema } from './output.js';
|
|
24
24
|
import { createKeys } from './keys.js';
|
|
@@ -442,6 +442,10 @@ export class OpenClawKit {
|
|
|
442
442
|
members;
|
|
443
443
|
locks = createLocks();
|
|
444
444
|
routeMap = new Map();
|
|
445
|
+
runReplay = new RunReplay();
|
|
446
|
+
attach(member, runId, fromSeq, signal) {
|
|
447
|
+
return this.runReplay.attach(member, runId, fromSeq, signal);
|
|
448
|
+
}
|
|
445
449
|
installs = Promise.resolve();
|
|
446
450
|
accountsCtl;
|
|
447
451
|
// One bridge and one approval surface per kit: listeners and run registrations survive reconnects (B3).
|
|
@@ -948,6 +952,8 @@ export class OpenClawKit {
|
|
|
948
952
|
});
|
|
949
953
|
}
|
|
950
954
|
closed(why) {
|
|
955
|
+
if (why === 'engine exited')
|
|
956
|
+
this.runReplay.clear();
|
|
951
957
|
// A first start's loop owns an engine exit until it reaches ready; other closes are the transport client's to retry.
|
|
952
958
|
if (this.startRun && !this.reachedReady) {
|
|
953
959
|
if (why === 'engine exited')
|
|
@@ -976,6 +982,7 @@ export class OpenClawKit {
|
|
|
976
982
|
return delay(retryAt - Date.now(), undefined, { signal });
|
|
977
983
|
}
|
|
978
984
|
async stop() {
|
|
985
|
+
this.runReplay.clear();
|
|
979
986
|
this.stopping = true;
|
|
980
987
|
this.reachedReady = false;
|
|
981
988
|
this.startRun?.abort();
|
|
@@ -1311,10 +1318,11 @@ export class OpenClawKit {
|
|
|
1311
1318
|
confirmRetainedLogin(member, source) {
|
|
1312
1319
|
return confirmLogin({ ...this.signInCtx(), seal: this.o.authSeal, log: this.o.log }, member, source);
|
|
1313
1320
|
}
|
|
1314
|
-
// runs (5.8): the facade
|
|
1321
|
+
// runs (5.8): the facade retains the live journal; every dispatch delegates to the O8 module
|
|
1315
1322
|
// with this kit's live transport, member table and bridge (spec item O9).
|
|
1316
1323
|
runs() {
|
|
1317
1324
|
return createRuns({
|
|
1325
|
+
replay: this.runReplay,
|
|
1318
1326
|
request: (method, params, o) => this.request()(method, params, o),
|
|
1319
1327
|
authStatus: this.admission.read,
|
|
1320
1328
|
invalidateAuth: this.admission.invalidate,
|
package/dist/link.js
CHANGED
|
@@ -30,8 +30,9 @@ function memberSessions(result, owns) {
|
|
|
30
30
|
}
|
|
31
31
|
/** `oc.run`'s run options, type-checked; the kit's own checks (account, tool names) still apply. */
|
|
32
32
|
function runOptions(args) {
|
|
33
|
-
const { message, model, account, needs, auth, system, images, thinking, tools, schema } = args;
|
|
33
|
+
const { message, idempotencyKey, model, account, needs, auth, system, images, thinking, tools, schema } = args;
|
|
34
34
|
const ok = typeof message === 'string'
|
|
35
|
+
&& (idempotencyKey === undefined || typeof idempotencyKey === 'string' && idempotencyKey.length > 0)
|
|
35
36
|
&& (model === undefined || typeof model === 'string')
|
|
36
37
|
&& (account === undefined || typeof account === 'string')
|
|
37
38
|
&& (needs === undefined || (Array.isArray(needs) && needs.every((n) => typeof n === 'string')))
|
|
@@ -46,6 +47,7 @@ function runOptions(args) {
|
|
|
46
47
|
outputSchema(schema);
|
|
47
48
|
return {
|
|
48
49
|
message: message,
|
|
50
|
+
...(idempotencyKey === undefined ? {} : { idempotencyKey: idempotencyKey }),
|
|
49
51
|
...(schema === undefined ? {} : { schema: schema }),
|
|
50
52
|
...(model === undefined ? {} : { model: model }),
|
|
51
53
|
...(account === undefined ? {} : { account: account }),
|
|
@@ -561,6 +563,31 @@ export function openclawLink(kit, o) {
|
|
|
561
563
|
}
|
|
562
564
|
return;
|
|
563
565
|
}
|
|
566
|
+
if (req.op === 'oc.attach') {
|
|
567
|
+
if (grant.role === 'view')
|
|
568
|
+
throw refused();
|
|
569
|
+
const args = isRecord(req.args) ? req.args : {};
|
|
570
|
+
if (typeof args.runId !== 'string' || !args.runId.length || !Number.isSafeInteger(args.fromSeq) || args.fromSeq < 0)
|
|
571
|
+
throw refused();
|
|
572
|
+
const controller = new AbortController();
|
|
573
|
+
let frames;
|
|
574
|
+
try {
|
|
575
|
+
frames = kit.attach(member, args.runId, args.fromSeq, controller.signal);
|
|
576
|
+
}
|
|
577
|
+
catch {
|
|
578
|
+
throw refused();
|
|
579
|
+
}
|
|
580
|
+
s.onEnd = () => controller.abort();
|
|
581
|
+
try {
|
|
582
|
+
for await (const frame of frames)
|
|
583
|
+
await s.write(`${JSON.stringify(frame)}\n`);
|
|
584
|
+
s.end();
|
|
585
|
+
}
|
|
586
|
+
finally {
|
|
587
|
+
controller.abort();
|
|
588
|
+
}
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
564
591
|
if (req.op === 'oc.run') {
|
|
565
592
|
if (grant.role === 'view')
|
|
566
593
|
throw refused();
|
|
@@ -579,8 +606,9 @@ export function openclawLink(kit, o) {
|
|
|
579
606
|
tail = tail.then(() => s.write(`${JSON.stringify(frame)}\n`)).catch(() => { });
|
|
580
607
|
};
|
|
581
608
|
try {
|
|
582
|
-
|
|
583
|
-
|
|
609
|
+
let seq = 0;
|
|
610
|
+
const end = await kit.run({ member, sessionKey, ...options }, (e) => { seq = e.seq; send(e); });
|
|
611
|
+
send({ type: 'end', seq: seq + 1, end });
|
|
584
612
|
await tail;
|
|
585
613
|
s.end();
|
|
586
614
|
}
|
package/dist/runs.d.ts
CHANGED
|
@@ -4,14 +4,33 @@ import type { createAccounts } from './accounts.ts';
|
|
|
4
4
|
import type { createLocks } from './locks.ts';
|
|
5
5
|
import { authStatus } from './auth-status.ts';
|
|
6
6
|
import { outputSchema, type OutputSchema, type SchemaOutput } from './output.ts';
|
|
7
|
-
import type { GatewayTransport, Member, RunEnd, RunEvent, RunSpec } from './types.ts';
|
|
7
|
+
import type { GatewayTransport, Member, RunEnd, RunEvent, RunFrame, RunSpec } from './types.ts';
|
|
8
8
|
export declare const USABLE: Set<string>;
|
|
9
9
|
/**
|
|
10
10
|
* The providers a `models.authStatus` answer shows usable (the rule a picked account is checked by), lowercased and
|
|
11
11
|
* unique; undefined while the engine has no prepared status (unknown, not none).
|
|
12
12
|
*/
|
|
13
13
|
export declare function signedInProviders(status: unknown): string[] | undefined;
|
|
14
|
+
type Journal = {
|
|
15
|
+
member: Member;
|
|
16
|
+
frames: Exclude<RunFrame, {
|
|
17
|
+
type: 'truncated';
|
|
18
|
+
}>[];
|
|
19
|
+
done: boolean;
|
|
20
|
+
wake: Set<() => void>;
|
|
21
|
+
};
|
|
22
|
+
/** Live-kit only: bounded history, with readers pulling by cursor rather than growing per-reader queues. */
|
|
23
|
+
export declare class RunReplay {
|
|
24
|
+
private readonly runs;
|
|
25
|
+
begin(member: Member, id: string): Journal | undefined;
|
|
26
|
+
push(row: Journal | undefined, frame: Exclude<RunFrame, {
|
|
27
|
+
type: 'truncated';
|
|
28
|
+
}>): void;
|
|
29
|
+
clear(): void;
|
|
30
|
+
attach(member: Member, id: string, fromSeq: number, signal: AbortSignal): AsyncIterable<RunFrame>;
|
|
31
|
+
}
|
|
14
32
|
export declare function createRuns(ctx: {
|
|
33
|
+
replay?: RunReplay;
|
|
15
34
|
request: GatewayTransport['request'];
|
|
16
35
|
authStatus?: (agentId: string, refresh: boolean, native: boolean) => ReturnType<typeof authStatus>;
|
|
17
36
|
invalidateAuth?: () => void;
|
|
@@ -32,3 +51,4 @@ export declare function createRuns(ctx: {
|
|
|
32
51
|
steer(k: string, t: string): Promise<void>;
|
|
33
52
|
abort(k: string): Promise<void>;
|
|
34
53
|
};
|
|
54
|
+
export {};
|
package/dist/runs.js
CHANGED
|
@@ -71,6 +71,74 @@ function account(model) {
|
|
|
71
71
|
throw new Error(`refused: "${model}" is not a provider/model reference`);
|
|
72
72
|
return { provider, model: model.slice(model.indexOf('/') + 1) }; // the engine lowercases ids
|
|
73
73
|
}
|
|
74
|
+
/** Live-kit only: bounded history, with readers pulling by cursor rather than growing per-reader queues. */
|
|
75
|
+
export class RunReplay {
|
|
76
|
+
runs = new Map();
|
|
77
|
+
begin(member, id) {
|
|
78
|
+
if (this.runs.has(id))
|
|
79
|
+
return undefined; // engine-cache retry must not replace the original stream
|
|
80
|
+
const row = { member, frames: [], done: false, wake: new Set() };
|
|
81
|
+
this.runs.set(id, row);
|
|
82
|
+
return row;
|
|
83
|
+
}
|
|
84
|
+
push(row, frame) {
|
|
85
|
+
if (!row)
|
|
86
|
+
return;
|
|
87
|
+
row.frames.push(frame);
|
|
88
|
+
if (row.frames.length > 32)
|
|
89
|
+
row.frames.shift();
|
|
90
|
+
row.done = frame.type === 'end';
|
|
91
|
+
for (const wake of row.wake)
|
|
92
|
+
wake();
|
|
93
|
+
if (row.done) {
|
|
94
|
+
const completed = [...this.runs].filter(([, r]) => r.done);
|
|
95
|
+
for (const [id] of completed.slice(0, -128))
|
|
96
|
+
this.runs.delete(id);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
clear() {
|
|
100
|
+
for (const row of this.runs.values())
|
|
101
|
+
for (const wake of row.wake)
|
|
102
|
+
wake();
|
|
103
|
+
this.runs.clear();
|
|
104
|
+
}
|
|
105
|
+
attach(member, id, fromSeq, signal) {
|
|
106
|
+
const row = this.runs.get(id);
|
|
107
|
+
if (row && row.member !== member)
|
|
108
|
+
throw new Error('foreign run');
|
|
109
|
+
const runs = this.runs;
|
|
110
|
+
return (async function* () {
|
|
111
|
+
let cursor = fromSeq;
|
|
112
|
+
while (!signal.aborted) {
|
|
113
|
+
if (!row || runs.get(id) !== row) {
|
|
114
|
+
yield { type: 'truncated', reason: 'not-found' };
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const firstSeq = row.frames[0]?.seq ?? 1;
|
|
118
|
+
const lastSeq = row.frames.at(-1)?.seq ?? 0;
|
|
119
|
+
if (cursor < firstSeq - 1 || cursor > lastSeq) {
|
|
120
|
+
yield { type: 'truncated', reason: 'truncated', firstSeq };
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const next = row.frames.find(f => f.seq > cursor);
|
|
124
|
+
if (next) {
|
|
125
|
+
cursor = next.seq;
|
|
126
|
+
yield next;
|
|
127
|
+
if (next.type === 'end')
|
|
128
|
+
return;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (row.done)
|
|
132
|
+
return;
|
|
133
|
+
await new Promise(resolve => {
|
|
134
|
+
const wake = () => { row.wake.delete(wake); signal.removeEventListener('abort', wake); resolve(); };
|
|
135
|
+
row.wake.add(wake);
|
|
136
|
+
signal.addEventListener('abort', wake, { once: true });
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
})();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
74
142
|
export function createRuns(ctx) {
|
|
75
143
|
// The plan window the engine last read for the run's provider: `models.authStatus` answers from its cache without
|
|
76
144
|
// blocking. Nothing reported, or no answer in time, is no window.
|
|
@@ -90,7 +158,7 @@ export function createRuns(ctx) {
|
|
|
90
158
|
ctx.invalidateAuth?.();
|
|
91
159
|
return { ok: false, ...classified, message };
|
|
92
160
|
};
|
|
93
|
-
const
|
|
161
|
+
const execute = async (spec, on, keyAgent, preparedOutput) => {
|
|
94
162
|
// Member boundary first: a member never speaks in another member's session, refused before any request. A key
|
|
95
163
|
// of one of the member's account agents is the member's too; binding below checks the index names it.
|
|
96
164
|
if (!spec.sessionKey.startsWith(`agent:${spec.member}:`) && !(ctx.accounts && !keyAgent && spec.sessionKey.startsWith(`agent:${spec.member}--`)))
|
|
@@ -351,8 +419,25 @@ export function createRuns(ctx) {
|
|
|
351
419
|
releaseDelegation?.();
|
|
352
420
|
}
|
|
353
421
|
};
|
|
422
|
+
const replay = ctx.replay ?? new RunReplay();
|
|
354
423
|
return {
|
|
355
|
-
run,
|
|
424
|
+
run: async (spec, on, keyAgent, preparedOutput) => {
|
|
425
|
+
if (spec.idempotencyKey !== undefined && (typeof spec.idempotencyKey !== 'string' || !spec.idempotencyKey.length))
|
|
426
|
+
throw new Error('refused: idempotencyKey must be a non-empty string');
|
|
427
|
+
const id = spec.idempotencyKey ?? randomUUID();
|
|
428
|
+
const row = replay.begin(spec.member, id);
|
|
429
|
+
let seq = 0;
|
|
430
|
+
const emit = (e) => { const event = { ...e, seq: ++seq }; replay.push(row, event); on?.(event); };
|
|
431
|
+
try {
|
|
432
|
+
const end = await execute({ ...spec, idempotencyKey: id }, emit, keyAgent, preparedOutput);
|
|
433
|
+
replay.push(row, { type: 'end', seq: ++seq, end });
|
|
434
|
+
return end;
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
replay.push(row, { type: 'end', seq: ++seq, end: failure(error instanceof Error ? error.message : String(error)) });
|
|
438
|
+
throw error;
|
|
439
|
+
}
|
|
440
|
+
},
|
|
356
441
|
steer: (k, t) => ctx.request('sessions.steer', { sessionKey: ctx.routes.get(k)?.session ?? k, message: t }),
|
|
357
442
|
abort: async (k) => { await ctx.request('chat.abort', { sessionKey: ctx.routes.get(k)?.session ?? k }); },
|
|
358
443
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -80,6 +80,8 @@ export interface RunSpec<S extends OutputSchema | undefined = OutputSchema | und
|
|
|
80
80
|
register?: boolean;
|
|
81
81
|
}
|
|
82
82
|
export type RunEvent = {
|
|
83
|
+
seq: number;
|
|
84
|
+
} & ({
|
|
83
85
|
type: 'started';
|
|
84
86
|
} | {
|
|
85
87
|
type: 'thinking';
|
|
@@ -103,6 +105,15 @@ export type RunEvent = {
|
|
|
103
105
|
input?: Record<string, unknown>;
|
|
104
106
|
output?: unknown;
|
|
105
107
|
error?: boolean;
|
|
108
|
+
});
|
|
109
|
+
export type RunFrame = RunEvent | {
|
|
110
|
+
type: 'end';
|
|
111
|
+
seq: number;
|
|
112
|
+
end: RunEnd;
|
|
113
|
+
} | {
|
|
114
|
+
type: 'truncated';
|
|
115
|
+
reason: 'truncated' | 'not-found';
|
|
116
|
+
firstSeq?: number;
|
|
106
117
|
};
|
|
107
118
|
/** Token usage of one run as the engine totals it (every model call of the run, compaction included). */
|
|
108
119
|
export type RunUsage = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byokit/openclaw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.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",
|