@dg-kit/safety 1.16.2 → 1.16.3
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/README.md +3 -1
- package/dist/device-command-queue.d.ts +16 -12
- package/dist/device-command-queue.d.ts.map +1 -1
- package/dist/device-command-queue.js +39 -19
- package/dist/device-command-queue.js.map +1 -1
- package/dist/safety-bus.d.ts +12 -0
- package/dist/safety-bus.d.ts.map +1 -1
- package/dist/safety-bus.js +15 -0
- package/dist/safety-bus.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,4 +13,6 @@ npm install @dg-kit/safety
|
|
|
13
13
|
Safety policy is enforced before commands reach a transport. Applications should still expose a
|
|
14
14
|
clear stop control and should not treat account identity as permission to control a device.
|
|
15
15
|
|
|
16
|
-
The package is ESM-only and exports its public API from the package root.
|
|
16
|
+
The package is ESM-only and exports its public API from the package root. Async native-write
|
|
17
|
+
boundaries can use `currentDeviceLeaseSnapshot()` to fence both the current module holder and its
|
|
18
|
+
monotonic epoch, preventing holder-name ABA after a lease transfer.
|
|
@@ -23,38 +23,42 @@ export interface SerialCommandQueueOptions<TCommand, TResult> {
|
|
|
23
23
|
* `emergencyStop`) skip the line entirely: it bumps a generation counter
|
|
24
24
|
* and runs immediately via `run()` rather than `execute()`, and any
|
|
25
25
|
* already-queued-but-not-yet-run task notices its generation is stale and
|
|
26
|
-
* resolves with `skippedResult()` instead of actually executing.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* comment for why).
|
|
26
|
+
* resolves with `skippedResult()` instead of actually executing. The public
|
|
27
|
+
* `interrupt()` method provides the same protection for out-of-band stops,
|
|
28
|
+
* including Opossum's runtime-wide emergency stop.
|
|
30
29
|
*/
|
|
31
30
|
export declare class SerialCommandQueue<TCommand, TResult> {
|
|
32
31
|
private readonly options;
|
|
33
32
|
private tail;
|
|
34
33
|
private generation;
|
|
34
|
+
private activeInterrupt;
|
|
35
35
|
constructor(options: SerialCommandQueueOptions<TCommand, TResult>);
|
|
36
36
|
enqueue(command: TCommand): Promise<TResult>;
|
|
37
|
+
/**
|
|
38
|
+
* Preempts queued work and invalidates an already-running continuation.
|
|
39
|
+
* The interrupt runs immediately; if an older command completes later,
|
|
40
|
+
* the queue runs it once more to restore the safe state.
|
|
41
|
+
*/
|
|
42
|
+
interrupt(run: () => Promise<TResult>, skippedResult: () => Promise<TResult>): Promise<TResult>;
|
|
37
43
|
}
|
|
38
44
|
export declare class DeviceCommandQueue {
|
|
39
45
|
private readonly device;
|
|
40
46
|
private readonly queue;
|
|
41
47
|
constructor(device: DeviceClient);
|
|
42
48
|
enqueue(command: DeviceCommand): Promise<DeviceCommandResult>;
|
|
49
|
+
emergencyStop(): Promise<DeviceCommandResult>;
|
|
43
50
|
}
|
|
44
51
|
/**
|
|
45
|
-
* Serializes Opossum vibration commands
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* variant in its own command union (`vibrate_stop` already exists for that),
|
|
50
|
-
* and the runtime-wide panic button calls `OpossumClient.emergencyStop()`
|
|
51
|
-
* directly (see `AgentRuntime.emergencyStop`), bypassing the queue exactly
|
|
52
|
-
* like Coyote's does.
|
|
52
|
+
* Serializes Opossum vibration commands and exposes an out-of-band emergency
|
|
53
|
+
* interrupt. The interrupt uses the same generation preemption as Coyote, so
|
|
54
|
+
* queued work is skipped and an in-flight write that lands late is followed
|
|
55
|
+
* by another stop instead of restoring vibration.
|
|
53
56
|
*/
|
|
54
57
|
export declare class OpossumCommandQueue {
|
|
55
58
|
private readonly device;
|
|
56
59
|
private readonly queue;
|
|
57
60
|
constructor(device: OpossumClient);
|
|
58
61
|
enqueue(command: OpossumCommand): Promise<OpossumCommandResult>;
|
|
62
|
+
emergencyStop(): Promise<OpossumCommandResult>;
|
|
59
63
|
}
|
|
60
64
|
//# sourceMappingURL=device-command-queue.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-command-queue.d.ts","sourceRoot":"","sources":["../src/device-command-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,MAAM,WAAW,iBAAiB,CAAC,QAAQ,EAAE,OAAO;IAClD,oEAAoE;IACpE,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,6EAA6E;IAC7E,GAAG,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,8EAA8E;IAC9E,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,yBAAyB,CAAC,QAAQ,EAAE,OAAO;IAC1D,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;CAC1D;AAED
|
|
1
|
+
{"version":3,"file":"device-command-queue.d.ts","sourceRoot":"","sources":["../src/device-command-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,MAAM,WAAW,iBAAiB,CAAC,QAAQ,EAAE,OAAO;IAClD,oEAAoE;IACpE,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC,6EAA6E;IAC7E,GAAG,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,8EAA8E;IAC9E,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,yBAAyB,CAAC,QAAQ,EAAE,OAAO;IAC1D,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;CAC1D;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,kBAAkB,CAAC,QAAQ,EAAE,OAAO;IAQnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,IAAI,CAAoC;IAChD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,eAAe,CAGP;gBAEa,OAAO,EAAE,yBAAyB,CAAC,QAAQ,EAAE,OAAO,CAAC;IAE5E,OAAO,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IA0ClD;;;;OAIG;IACG,SAAS,CACb,GAAG,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC3B,aAAa,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,GACpC,OAAO,CAAC,OAAO,CAAC;CAQpB;AAED,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyD;gBAElD,MAAM,EAAE,YAAY;IAoB3C,OAAO,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAI7D,aAAa,IAAI,OAAO,CAAC,mBAAmB,CAAC;CAGpD;AAED;;;;;GAKG;AACH,qBAAa,mBAAmB;IAGlB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2D;gBAEpD,MAAM,EAAE,aAAa;IAM5C,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAI/D,aAAa,IAAI,OAAO,CAAC,oBAAoB,CAAC;CASrD"}
|
|
@@ -7,28 +7,27 @@
|
|
|
7
7
|
* `emergencyStop`) skip the line entirely: it bumps a generation counter
|
|
8
8
|
* and runs immediately via `run()` rather than `execute()`, and any
|
|
9
9
|
* already-queued-but-not-yet-run task notices its generation is stale and
|
|
10
|
-
* resolves with `skippedResult()` instead of actually executing.
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* comment for why).
|
|
10
|
+
* resolves with `skippedResult()` instead of actually executing. The public
|
|
11
|
+
* `interrupt()` method provides the same protection for out-of-band stops,
|
|
12
|
+
* including Opossum's runtime-wide emergency stop.
|
|
14
13
|
*/
|
|
15
14
|
export class SerialCommandQueue {
|
|
16
15
|
options;
|
|
17
16
|
tail = Promise.resolve();
|
|
18
17
|
generation = 0;
|
|
18
|
+
activeInterrupt = null;
|
|
19
19
|
constructor(options) {
|
|
20
20
|
this.options = options;
|
|
21
21
|
}
|
|
22
22
|
async enqueue(command) {
|
|
23
23
|
const interrupt = this.options.priorityInterrupt;
|
|
24
24
|
if (interrupt?.matches(command)) {
|
|
25
|
-
this.
|
|
26
|
-
return interrupt.run(command);
|
|
25
|
+
return this.interrupt(() => interrupt.run(command), interrupt.skippedResult);
|
|
27
26
|
}
|
|
28
27
|
const generation = this.generation;
|
|
29
28
|
const task = this.tail.then(async () => {
|
|
30
|
-
if (
|
|
31
|
-
return
|
|
29
|
+
if (generation !== this.generation && this.activeInterrupt) {
|
|
30
|
+
return this.activeInterrupt.skippedResult();
|
|
32
31
|
}
|
|
33
32
|
const startedAt = this.generation;
|
|
34
33
|
const result = await this.options.execute(command);
|
|
@@ -42,15 +41,28 @@ export class SerialCommandQueue {
|
|
|
42
41
|
// A packet already sent cannot be recalled; what we can do is stop
|
|
43
42
|
// again right after. Emergency stop must be idempotent, so a duplicate
|
|
44
43
|
// stop is safe — a missed one is not.
|
|
45
|
-
if (
|
|
46
|
-
await
|
|
47
|
-
return
|
|
44
|
+
if (startedAt !== this.generation && this.activeInterrupt) {
|
|
45
|
+
await this.activeInterrupt.run(command);
|
|
46
|
+
return this.activeInterrupt.skippedResult();
|
|
48
47
|
}
|
|
49
48
|
return result;
|
|
50
49
|
});
|
|
51
50
|
this.tail = task.then(() => undefined, () => undefined);
|
|
52
51
|
return task;
|
|
53
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Preempts queued work and invalidates an already-running continuation.
|
|
55
|
+
* The interrupt runs immediately; if an older command completes later,
|
|
56
|
+
* the queue runs it once more to restore the safe state.
|
|
57
|
+
*/
|
|
58
|
+
async interrupt(run, skippedResult) {
|
|
59
|
+
this.generation += 1;
|
|
60
|
+
this.activeInterrupt = {
|
|
61
|
+
run: () => run(),
|
|
62
|
+
skippedResult,
|
|
63
|
+
};
|
|
64
|
+
return run();
|
|
65
|
+
}
|
|
54
66
|
}
|
|
55
67
|
export class DeviceCommandQueue {
|
|
56
68
|
device;
|
|
@@ -78,16 +90,15 @@ export class DeviceCommandQueue {
|
|
|
78
90
|
async enqueue(command) {
|
|
79
91
|
return this.queue.enqueue(command);
|
|
80
92
|
}
|
|
93
|
+
async emergencyStop() {
|
|
94
|
+
return this.enqueue({ type: 'emergencyStop' });
|
|
95
|
+
}
|
|
81
96
|
}
|
|
82
97
|
/**
|
|
83
|
-
* Serializes Opossum vibration commands
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
* variant in its own command union (`vibrate_stop` already exists for that),
|
|
88
|
-
* and the runtime-wide panic button calls `OpossumClient.emergencyStop()`
|
|
89
|
-
* directly (see `AgentRuntime.emergencyStop`), bypassing the queue exactly
|
|
90
|
-
* like Coyote's does.
|
|
98
|
+
* Serializes Opossum vibration commands and exposes an out-of-band emergency
|
|
99
|
+
* interrupt. The interrupt uses the same generation preemption as Coyote, so
|
|
100
|
+
* queued work is skipped and an in-flight write that lands late is followed
|
|
101
|
+
* by another stop instead of restoring vibration.
|
|
91
102
|
*/
|
|
92
103
|
export class OpossumCommandQueue {
|
|
93
104
|
device;
|
|
@@ -101,5 +112,14 @@ export class OpossumCommandQueue {
|
|
|
101
112
|
async enqueue(command) {
|
|
102
113
|
return this.queue.enqueue(command);
|
|
103
114
|
}
|
|
115
|
+
async emergencyStop() {
|
|
116
|
+
const stoppedResult = async () => ({
|
|
117
|
+
state: await this.device.getState(),
|
|
118
|
+
});
|
|
119
|
+
return this.queue.interrupt(async () => {
|
|
120
|
+
await this.device.emergencyStop();
|
|
121
|
+
return stoppedResult();
|
|
122
|
+
}, stoppedResult);
|
|
123
|
+
}
|
|
104
124
|
}
|
|
105
125
|
//# sourceMappingURL=device-command-queue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-command-queue.js","sourceRoot":"","sources":["../src/device-command-queue.ts"],"names":[],"mappings":"AAmBA
|
|
1
|
+
{"version":3,"file":"device-command-queue.js","sourceRoot":"","sources":["../src/device-command-queue.ts"],"names":[],"mappings":"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"}
|
package/dist/safety-bus.d.ts
CHANGED
|
@@ -112,6 +112,11 @@ export interface StopAllResult {
|
|
|
112
112
|
error: unknown;
|
|
113
113
|
}[];
|
|
114
114
|
}
|
|
115
|
+
/** Atomic snapshot used by native-write boundaries to reject lease ABA. */
|
|
116
|
+
export interface DeviceLeaseSnapshot {
|
|
117
|
+
holder: string | null;
|
|
118
|
+
epoch: number;
|
|
119
|
+
}
|
|
115
120
|
/** Register a module's device session. Returns an unregister function. */
|
|
116
121
|
export declare function registerSafetySession(session: SafetySession): () => void;
|
|
117
122
|
/** A registered module session, including its optional shell connect action. */
|
|
@@ -157,6 +162,13 @@ export declare function grantDeviceLease(moduleId: string | null): Promise<void>
|
|
|
157
162
|
*/
|
|
158
163
|
export declare function hasDeviceLease(moduleId: string): boolean;
|
|
159
164
|
export declare function currentDeviceLease(): string | null;
|
|
165
|
+
/**
|
|
166
|
+
* Read the holder and its fencing epoch atomically.
|
|
167
|
+
*
|
|
168
|
+
* Consumers that perform asynchronous work must capture this snapshot and
|
|
169
|
+
* compare both fields again immediately before reaching a native write.
|
|
170
|
+
*/
|
|
171
|
+
export declare function currentDeviceLeaseSnapshot(): DeviceLeaseSnapshot;
|
|
160
172
|
/** Subscribe to registry changes (module mount/unmount, lease transfer). */
|
|
161
173
|
export declare function subscribeSafetySessions(listener: () => void): () => void;
|
|
162
174
|
//# sourceMappingURL=safety-bus.d.ts.map
|
package/dist/safety-bus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safety-bus.d.ts","sourceRoot":"","sources":["../src/safety-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,gDAAgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mHAAmH;IACnH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oEAAoE;IACpE,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC3D,4EAA4E;IAC5E,QAAQ,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/D;AAED,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,QAAQ,EAAE,MAAM,OAAO,CAAC;IACxB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,aAAa,EAAE,CAAC;IAChC;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,kFAAkF;IAClF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3D;;;;;;;;;;;;;;;;OAgBG;IACH,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,aAAa;IAC5B,mDAAmD;IACnD,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,EAAE,CAAC;CAC1C;
|
|
1
|
+
{"version":3,"file":"safety-bus.d.ts","sourceRoot":"","sources":["../src/safety-bus.ts"],"names":[],"mappings":"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"}
|
package/dist/safety-bus.js
CHANGED
|
@@ -33,6 +33,11 @@ const listeners = new Set();
|
|
|
33
33
|
* same as disconnecting.
|
|
34
34
|
*/
|
|
35
35
|
let leaseHolder = null;
|
|
36
|
+
/**
|
|
37
|
+
* Monotonic fencing token for the module lease. A holder name alone cannot
|
|
38
|
+
* distinguish agent → chat → agent from one uninterrupted agent lease.
|
|
39
|
+
*/
|
|
40
|
+
let leaseEpoch = 0;
|
|
36
41
|
function notify() {
|
|
37
42
|
for (const l of listeners)
|
|
38
43
|
l();
|
|
@@ -123,6 +128,7 @@ export async function grantDeviceLease(moduleId) {
|
|
|
123
128
|
return;
|
|
124
129
|
const previous = leaseHolder;
|
|
125
130
|
leaseHolder = moduleId;
|
|
131
|
+
leaseEpoch += 1;
|
|
126
132
|
notify();
|
|
127
133
|
if (!previous)
|
|
128
134
|
return;
|
|
@@ -161,6 +167,15 @@ export function hasDeviceLease(moduleId) {
|
|
|
161
167
|
export function currentDeviceLease() {
|
|
162
168
|
return leaseHolder;
|
|
163
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* Read the holder and its fencing epoch atomically.
|
|
172
|
+
*
|
|
173
|
+
* Consumers that perform asynchronous work must capture this snapshot and
|
|
174
|
+
* compare both fields again immediately before reaching a native write.
|
|
175
|
+
*/
|
|
176
|
+
export function currentDeviceLeaseSnapshot() {
|
|
177
|
+
return { holder: leaseHolder, epoch: leaseEpoch };
|
|
178
|
+
}
|
|
164
179
|
/** Subscribe to registry changes (module mount/unmount, lease transfer). */
|
|
165
180
|
export function subscribeSafetySessions(listener) {
|
|
166
181
|
listeners.add(listener);
|
package/dist/safety-bus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safety-bus.js","sourceRoot":"","sources":["../src/safety-bus.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAoFH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;AAExC;;;;;;;GAOG;AACH,IAAI,WAAW,GAAkB,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"safety-bus.js","sourceRoot":"","sources":["../src/safety-bus.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dg-kit/safety",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.3",
|
|
4
4
|
"description": "DG-Lab 设备安全链:策略引擎、默认上限策略、串行命令队列",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "0xNullAI",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"prepublishOnly": "npm run build"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@dg-kit/core": "1.16.
|
|
36
|
-
"@dg-kit/protocol": "1.16.
|
|
35
|
+
"@dg-kit/core": "1.16.3",
|
|
36
|
+
"@dg-kit/protocol": "1.16.3"
|
|
37
37
|
}
|
|
38
38
|
}
|