@bridge4dev/runner 0.47.0 → 0.48.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/dist/adapters/codex.js +7 -4
- package/dist/levels.d.ts +49 -0
- package/dist/levels.js +51 -0
- package/dist/supervisor.d.ts +31 -0
- package/dist/supervisor.js +110 -6
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/adapters/codex.js
CHANGED
|
@@ -1157,10 +1157,13 @@ class CodexSession {
|
|
|
1157
1157
|
}
|
|
1158
1158
|
return;
|
|
1159
1159
|
}
|
|
1160
|
-
// #279.
|
|
1161
|
-
//
|
|
1162
|
-
//
|
|
1163
|
-
//
|
|
1160
|
+
// #279. Kept out of `OPT_OUT_NOTIFICATIONS` on purpose, but NOT because
|
|
1161
|
+
// it is rare: Codex sends it after every model request, as often as
|
|
1162
|
+
// `thread/tokenUsage/updated` (production count 56 591 against 57 008,
|
|
1163
|
+
// 05.09.2026 – #366). What keeps it off the wire is the supervisor's
|
|
1164
|
+
// level gate, which forwards a snapshot only when it changed, carries a
|
|
1165
|
+
// refusal (`blocked`), or is older than the resend floor. Opting the
|
|
1166
|
+
// notification out here instead would silence the refusal too.
|
|
1164
1167
|
case 'account/rateLimits/updated': {
|
|
1165
1168
|
this.onRateLimits(params);
|
|
1166
1169
|
return;
|
package/dist/levels.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror of the `#region level-events-mirror` block in
|
|
3
|
+
* `packages/shared/src/constants/realtime.ts` – the DevBridge side is the
|
|
4
|
+
* source of truth, exactly like `agent-registry.ts` mirrors the agent registry
|
|
5
|
+
* and `protocol.ts` mirrors the API's wire types.
|
|
6
|
+
*
|
|
7
|
+
* Copied rather than imported on purpose: this package is published to npm on
|
|
8
|
+
* its own and installed by users who have no DevBridge workspace, so a
|
|
9
|
+
* `@devbridge/shared` import would make the published tarball unresolvable.
|
|
10
|
+
*
|
|
11
|
+
* CHECKED: `levels.test.ts` reads both files and compares the region between
|
|
12
|
+
* the markers character by character. Edit the shared file first, then paste
|
|
13
|
+
* the region here – nothing but the region, and nothing of the region left out.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Level signals on the dev-session stream – frames that carry a whole current
|
|
17
|
+
* value rather than a step of the conversation (#366).
|
|
18
|
+
*
|
|
19
|
+
* `agent_tasks` (#113), `context_usage` and `rate_limits` (#279) are LEVELS:
|
|
20
|
+
* every frame replaces the previous one, so a dropped frame costs freshness and
|
|
21
|
+
* never correctness. In production they were 61 % of every Codex session's
|
|
22
|
+
* rows (57 008 + 56 591 of ~185 000, 05.09.2026) while drawing not one line in
|
|
23
|
+
* the transcript – and each one re-rendered the whole page. So they are treated
|
|
24
|
+
* differently at every hop, and this block is the one place that says how:
|
|
25
|
+
*
|
|
26
|
+
* - the runner sends one only when the value moved (the thresholds below);
|
|
27
|
+
* - the API publishes it as a META frame (no `id:`) and never stores a row;
|
|
28
|
+
* - the dashboard keeps it beside the feed, never in it.
|
|
29
|
+
*
|
|
30
|
+
* Mirrored verbatim into `packages/runner/src/levels.ts` – the runner cannot
|
|
31
|
+
* import this package (it is published to npm on its own). `levels.test.ts`
|
|
32
|
+
* compares the two regions character by character.
|
|
33
|
+
*/
|
|
34
|
+
export declare const LEVEL_EVENT_TYPES: readonly ["agent_tasks", "context_usage", "rate_limits"];
|
|
35
|
+
/**
|
|
36
|
+
* A context-meter move smaller than BOTH of these is not worth a frame. The
|
|
37
|
+
* same pair gates the API's mirror onto the session row, so the ring a reload
|
|
38
|
+
* draws from the row and the ring the live frame draws agree to the percent.
|
|
39
|
+
*/
|
|
40
|
+
export declare const CONTEXT_USAGE_MIN_DELTA_TOKENS = 2000;
|
|
41
|
+
export declare const CONTEXT_USAGE_MIN_DELTA_RATIO = 0.01;
|
|
42
|
+
/**
|
|
43
|
+
* An unchanged plan-usage snapshot is re-sent no more often than this. It is
|
|
44
|
+
* re-sent at all because the limits panel dates its figure by ARRIVAL
|
|
45
|
+
* («updated 12 min ago»): silence would read as staleness. Three minutes is
|
|
46
|
+
* the interval the Claude adapter already probes `/usage` at.
|
|
47
|
+
*/
|
|
48
|
+
export declare const RATE_LIMITS_RESEND_INTERVAL_MS: number;
|
|
49
|
+
//# sourceMappingURL=levels.d.ts.map
|
package/dist/levels.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mirror of the `#region level-events-mirror` block in
|
|
3
|
+
* `packages/shared/src/constants/realtime.ts` – the DevBridge side is the
|
|
4
|
+
* source of truth, exactly like `agent-registry.ts` mirrors the agent registry
|
|
5
|
+
* and `protocol.ts` mirrors the API's wire types.
|
|
6
|
+
*
|
|
7
|
+
* Copied rather than imported on purpose: this package is published to npm on
|
|
8
|
+
* its own and installed by users who have no DevBridge workspace, so a
|
|
9
|
+
* `@devbridge/shared` import would make the published tarball unresolvable.
|
|
10
|
+
*
|
|
11
|
+
* CHECKED: `levels.test.ts` reads both files and compares the region between
|
|
12
|
+
* the markers character by character. Edit the shared file first, then paste
|
|
13
|
+
* the region here – nothing but the region, and nothing of the region left out.
|
|
14
|
+
*/
|
|
15
|
+
// #region level-events-mirror
|
|
16
|
+
/**
|
|
17
|
+
* Level signals on the dev-session stream – frames that carry a whole current
|
|
18
|
+
* value rather than a step of the conversation (#366).
|
|
19
|
+
*
|
|
20
|
+
* `agent_tasks` (#113), `context_usage` and `rate_limits` (#279) are LEVELS:
|
|
21
|
+
* every frame replaces the previous one, so a dropped frame costs freshness and
|
|
22
|
+
* never correctness. In production they were 61 % of every Codex session's
|
|
23
|
+
* rows (57 008 + 56 591 of ~185 000, 05.09.2026) while drawing not one line in
|
|
24
|
+
* the transcript – and each one re-rendered the whole page. So they are treated
|
|
25
|
+
* differently at every hop, and this block is the one place that says how:
|
|
26
|
+
*
|
|
27
|
+
* - the runner sends one only when the value moved (the thresholds below);
|
|
28
|
+
* - the API publishes it as a META frame (no `id:`) and never stores a row;
|
|
29
|
+
* - the dashboard keeps it beside the feed, never in it.
|
|
30
|
+
*
|
|
31
|
+
* Mirrored verbatim into `packages/runner/src/levels.ts` – the runner cannot
|
|
32
|
+
* import this package (it is published to npm on its own). `levels.test.ts`
|
|
33
|
+
* compares the two regions character by character.
|
|
34
|
+
*/
|
|
35
|
+
export const LEVEL_EVENT_TYPES = ['agent_tasks', 'context_usage', 'rate_limits'];
|
|
36
|
+
/**
|
|
37
|
+
* A context-meter move smaller than BOTH of these is not worth a frame. The
|
|
38
|
+
* same pair gates the API's mirror onto the session row, so the ring a reload
|
|
39
|
+
* draws from the row and the ring the live frame draws agree to the percent.
|
|
40
|
+
*/
|
|
41
|
+
export const CONTEXT_USAGE_MIN_DELTA_TOKENS = 2_000;
|
|
42
|
+
export const CONTEXT_USAGE_MIN_DELTA_RATIO = 0.01;
|
|
43
|
+
/**
|
|
44
|
+
* An unchanged plan-usage snapshot is re-sent no more often than this. It is
|
|
45
|
+
* re-sent at all because the limits panel dates its figure by ARRIVAL
|
|
46
|
+
* («updated 12 min ago»): silence would read as staleness. Three minutes is
|
|
47
|
+
* the interval the Claude adapter already probes `/usage` at.
|
|
48
|
+
*/
|
|
49
|
+
export const RATE_LIMITS_RESEND_INTERVAL_MS = 3 * 60 * 1000;
|
|
50
|
+
// #endregion level-events-mirror
|
|
51
|
+
//# sourceMappingURL=levels.js.map
|
package/dist/supervisor.d.ts
CHANGED
|
@@ -109,6 +109,13 @@ export interface SupervisorOptions {
|
|
|
109
109
|
* firing over a working agent (QA-2026-08-16 M-4). Never set in production.
|
|
110
110
|
*/
|
|
111
111
|
emptyTurnSettleMs?: number;
|
|
112
|
+
/**
|
|
113
|
+
* How long an unchanged plan-usage snapshot is held before it is re-sent
|
|
114
|
+
* (#366) – a test seam over `RATE_LIMITS_RESEND_INTERVAL_MS`, for the same
|
|
115
|
+
* reason `emptyTurnSettleMs` exists: the real floor is three minutes and this
|
|
116
|
+
* suite runs on real timers. Never set in production.
|
|
117
|
+
*/
|
|
118
|
+
rateLimitsResendMs?: number;
|
|
112
119
|
}
|
|
113
120
|
export declare class Supervisor {
|
|
114
121
|
private readonly ws;
|
|
@@ -136,6 +143,7 @@ export declare class Supervisor {
|
|
|
136
143
|
private static readonly EMPTY_TURN_SETTLE_MS;
|
|
137
144
|
/** The window actually used — the constant, or a test's own shorter one. */
|
|
138
145
|
private readonly emptyTurnSettleMs;
|
|
146
|
+
private readonly rateLimitsResendMs;
|
|
139
147
|
/** A finished session's journal is kept this long for a late reconnect. */
|
|
140
148
|
private static readonly JOURNAL_TTL_MS;
|
|
141
149
|
/** Backstop: events the API will never accept must not pile up forever. */
|
|
@@ -525,6 +533,29 @@ export declare class Supervisor {
|
|
|
525
533
|
* its timer runs out, and it must end in exactly the way it would have
|
|
526
534
|
* ended immediately. A copy would be two behaviours one edit apart.
|
|
527
535
|
*/
|
|
536
|
+
/**
|
|
537
|
+
* The level gate for the context meter (#366).
|
|
538
|
+
*
|
|
539
|
+
* While a turn is open, a frame goes out only when the meter moved by at
|
|
540
|
+
* least one of the shared thresholds or the window itself changed; the
|
|
541
|
+
* newest held-back value is flushed right before `turn_end`, so the ring at
|
|
542
|
+
* rest is exact. Outside a turn every frame passes – there are only a handful
|
|
543
|
+
* (process start, a model change, and the Claude adapter's own measurement,
|
|
544
|
+
* which resolves AFTER `turn_end`), and each one is news.
|
|
545
|
+
*/
|
|
546
|
+
private forwardContextUsage;
|
|
547
|
+
/** Send the value the gate was holding, if any – strictly before `turn_end`. */
|
|
548
|
+
private flushHeldContextUsage;
|
|
549
|
+
/**
|
|
550
|
+
* The level gate for plan usage (#366).
|
|
551
|
+
*
|
|
552
|
+
* A snapshot goes out when it is the first, when anything but `measuredAt`
|
|
553
|
+
* changed, when it carries a refusal (#258 – always, even twice in a row), or
|
|
554
|
+
* when the one last sent is older than the resend floor. The fingerprint is
|
|
555
|
+
* the whole payload minus the clock, so a field an adapter adds tomorrow is
|
|
556
|
+
* part of it without anybody remembering to list it here.
|
|
557
|
+
*/
|
|
558
|
+
private forwardRateLimits;
|
|
528
559
|
private completeTurn;
|
|
529
560
|
/**
|
|
530
561
|
* Move the session to the status a finished turn leaves it in.
|
package/dist/supervisor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { log } from './log.js';
|
|
4
|
+
import { CONTEXT_USAGE_MIN_DELTA_RATIO, CONTEXT_USAGE_MIN_DELTA_TOKENS, RATE_LIMITS_RESEND_INTERVAL_MS, } from './levels.js';
|
|
4
5
|
import { claimAutoResume, clearAutoResume, pruneAutoResume } from './auto-resume.js';
|
|
5
6
|
import { classifyFailure, isRepeatOfSameFailure, MAX_RETRIES_PER_SESSION, retryDelayMs, } from './adapters/error-policy.js';
|
|
6
7
|
import { evaluateRecipeCommand, maskSecrets, maskString } from './policy.js';
|
|
@@ -58,6 +59,16 @@ function gitPolicyOf(descriptor) {
|
|
|
58
59
|
: {}),
|
|
59
60
|
};
|
|
60
61
|
}
|
|
62
|
+
function freshLevels() {
|
|
63
|
+
return {
|
|
64
|
+
contextSent: null,
|
|
65
|
+
contextHeld: null,
|
|
66
|
+
contextPassNext: false,
|
|
67
|
+
limitsSent: null,
|
|
68
|
+
sent: 0,
|
|
69
|
+
dropped: 0,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
61
72
|
const LAUNCH_REFUSED = { ok: false, reason: 'refused' };
|
|
62
73
|
export class Supervisor {
|
|
63
74
|
ws;
|
|
@@ -85,6 +96,7 @@ export class Supervisor {
|
|
|
85
96
|
static EMPTY_TURN_SETTLE_MS = 25_000;
|
|
86
97
|
/** The window actually used — the constant, or a test's own shorter one. */
|
|
87
98
|
emptyTurnSettleMs;
|
|
99
|
+
rateLimitsResendMs;
|
|
88
100
|
/** A finished session's journal is kept this long for a late reconnect. */
|
|
89
101
|
static JOURNAL_TTL_MS = 72 * 3_600_000;
|
|
90
102
|
/** Backstop: events the API will never accept must not pile up forever. */
|
|
@@ -135,6 +147,7 @@ export class Supervisor {
|
|
|
135
147
|
this.opts = opts;
|
|
136
148
|
this.journals = opts.journals ?? new JournalStore();
|
|
137
149
|
this.emptyTurnSettleMs = opts.emptyTurnSettleMs ?? Supervisor.EMPTY_TURN_SETTLE_MS;
|
|
150
|
+
this.rateLimitsResendMs = opts.rateLimitsResendMs ?? RATE_LIMITS_RESEND_INTERVAL_MS;
|
|
138
151
|
this.verify = new VerifyRunner({
|
|
139
152
|
enabled: opts.verifyEnabled !== false,
|
|
140
153
|
onReport: (report) => {
|
|
@@ -743,6 +756,7 @@ export class Supervisor {
|
|
|
743
756
|
lastReported: descriptor.status,
|
|
744
757
|
costUsd: descriptor.costUsd,
|
|
745
758
|
costBaseUsd: descriptor.costUsd,
|
|
759
|
+
levels: freshLevels(),
|
|
746
760
|
stopRequested: false,
|
|
747
761
|
parkRequested: false,
|
|
748
762
|
pendingMessages: [],
|
|
@@ -1697,12 +1711,101 @@ export class Supervisor {
|
|
|
1697
1711
|
* its timer runs out, and it must end in exactly the way it would have
|
|
1698
1712
|
* ended immediately. A copy would be two behaviours one edit apart.
|
|
1699
1713
|
*/
|
|
1714
|
+
/**
|
|
1715
|
+
* The level gate for the context meter (#366).
|
|
1716
|
+
*
|
|
1717
|
+
* While a turn is open, a frame goes out only when the meter moved by at
|
|
1718
|
+
* least one of the shared thresholds or the window itself changed; the
|
|
1719
|
+
* newest held-back value is flushed right before `turn_end`, so the ring at
|
|
1720
|
+
* rest is exact. Outside a turn every frame passes – there are only a handful
|
|
1721
|
+
* (process start, a model change, and the Claude adapter's own measurement,
|
|
1722
|
+
* which resolves AFTER `turn_end`), and each one is news.
|
|
1723
|
+
*/
|
|
1724
|
+
forwardContextUsage(running, usedTokens, maxTokens) {
|
|
1725
|
+
const levels = running.levels;
|
|
1726
|
+
const frame = { usedTokens, maxTokens };
|
|
1727
|
+
const last = levels.contextSent;
|
|
1728
|
+
const turnOpen = running.lastReported === 'RUNNING';
|
|
1729
|
+
const moved = last === null ? Number.POSITIVE_INFINITY : Math.abs(usedTokens - last.usedTokens);
|
|
1730
|
+
const pass = last === null ||
|
|
1731
|
+
last.maxTokens !== maxTokens ||
|
|
1732
|
+
levels.contextPassNext ||
|
|
1733
|
+
!turnOpen ||
|
|
1734
|
+
moved >= CONTEXT_USAGE_MIN_DELTA_TOKENS ||
|
|
1735
|
+
moved / maxTokens >= CONTEXT_USAGE_MIN_DELTA_RATIO;
|
|
1736
|
+
// Only the newest value is worth keeping; whatever it replaces is gone.
|
|
1737
|
+
if (levels.contextHeld !== null)
|
|
1738
|
+
levels.dropped += 1;
|
|
1739
|
+
if (!pass) {
|
|
1740
|
+
levels.contextHeld = frame;
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
levels.contextHeld = null;
|
|
1744
|
+
levels.contextPassNext = false;
|
|
1745
|
+
levels.contextSent = frame;
|
|
1746
|
+
levels.sent += 1;
|
|
1747
|
+
this.sendEvent(running, 'context_usage', frame);
|
|
1748
|
+
}
|
|
1749
|
+
/** Send the value the gate was holding, if any – strictly before `turn_end`. */
|
|
1750
|
+
flushHeldContextUsage(running) {
|
|
1751
|
+
const levels = running.levels;
|
|
1752
|
+
const held = levels.contextHeld;
|
|
1753
|
+
if (held === null)
|
|
1754
|
+
return;
|
|
1755
|
+
levels.contextHeld = null;
|
|
1756
|
+
// A held value identical to the last one sent is not news – flushing it
|
|
1757
|
+
// would add a frame to every turn and give back half the saving.
|
|
1758
|
+
const sent = levels.contextSent;
|
|
1759
|
+
if (sent !== null && sent.usedTokens === held.usedTokens && sent.maxTokens === held.maxTokens) {
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
levels.contextSent = held;
|
|
1763
|
+
levels.sent += 1;
|
|
1764
|
+
this.sendEvent(running, 'context_usage', held);
|
|
1765
|
+
}
|
|
1766
|
+
/**
|
|
1767
|
+
* The level gate for plan usage (#366).
|
|
1768
|
+
*
|
|
1769
|
+
* A snapshot goes out when it is the first, when anything but `measuredAt`
|
|
1770
|
+
* changed, when it carries a refusal (#258 – always, even twice in a row), or
|
|
1771
|
+
* when the one last sent is older than the resend floor. The fingerprint is
|
|
1772
|
+
* the whole payload minus the clock, so a field an adapter adds tomorrow is
|
|
1773
|
+
* part of it without anybody remembering to list it here.
|
|
1774
|
+
*/
|
|
1775
|
+
forwardRateLimits(running, limits) {
|
|
1776
|
+
const levels = running.levels;
|
|
1777
|
+
const print = JSON.stringify({ ...limits, measuredAt: undefined });
|
|
1778
|
+
const now = Date.now();
|
|
1779
|
+
const last = levels.limitsSent;
|
|
1780
|
+
const pass = last === null ||
|
|
1781
|
+
Boolean(limits.blocked) ||
|
|
1782
|
+
last.print !== print ||
|
|
1783
|
+
now - last.at >= this.rateLimitsResendMs;
|
|
1784
|
+
if (!pass) {
|
|
1785
|
+
levels.dropped += 1;
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
levels.limitsSent = { print, at: now };
|
|
1789
|
+
levels.sent += 1;
|
|
1790
|
+
this.sendEvent(running, 'rate_limits', { ...limits });
|
|
1791
|
+
}
|
|
1700
1792
|
completeTurn(running, descriptor, event) {
|
|
1793
|
+
// #366: the ring at rest must be exact – the value the gate held back
|
|
1794
|
+
// during the turn goes out first, so it is older than `turn_end` by seq.
|
|
1795
|
+
this.flushHeldContextUsage(running);
|
|
1701
1796
|
this.sendEvent(running, 'turn_end', {
|
|
1702
1797
|
ok: event.ok,
|
|
1703
1798
|
errorMessage: event.errorMessage,
|
|
1704
1799
|
...(event.aborted ? { aborted: true } : {}),
|
|
1705
1800
|
});
|
|
1801
|
+
// …and whatever the adapter measures once the turn is over (Claude does,
|
|
1802
|
+
// asynchronously) is news, not a step of the same turn.
|
|
1803
|
+
running.levels.contextPassNext = true;
|
|
1804
|
+
log.info('supervisor: levels', {
|
|
1805
|
+
sessionId: descriptor.id,
|
|
1806
|
+
sent: running.levels.sent,
|
|
1807
|
+
dropped: running.levels.dropped,
|
|
1808
|
+
});
|
|
1706
1809
|
// The session is already on its way out with a status that MEANS
|
|
1707
1810
|
// something — a spent budget, a Stop, a teardown. A turn ending inside
|
|
1708
1811
|
// that window is a consequence of it, and letting the line below
|
|
@@ -2221,17 +2324,17 @@ export class Supervisor {
|
|
|
2221
2324
|
});
|
|
2222
2325
|
return;
|
|
2223
2326
|
case 'context_usage':
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
});
|
|
2327
|
+
// #366. A LEVEL: only a value that moved is worth a frame. The gate
|
|
2328
|
+
// decides before `sendEvent`, so a dropped frame never spends a seq.
|
|
2329
|
+
this.forwardContextUsage(running, event.usedTokens, event.maxTokens);
|
|
2228
2330
|
return;
|
|
2229
2331
|
// #279. A LEVEL signal like `agent_tasks`: every frame carries the whole
|
|
2230
|
-
// snapshot, so the API
|
|
2332
|
+
// snapshot, so the API keeps what arrived rather than merging, and a
|
|
2231
2333
|
// dropped frame costs freshness, never correctness. Account-wide, not
|
|
2232
2334
|
// session-wide — the API files it under the SERVER, not this session.
|
|
2335
|
+
// #366: gated the same way as the context meter, see `forwardRateLimits`.
|
|
2233
2336
|
case 'rate_limits':
|
|
2234
|
-
this.
|
|
2337
|
+
this.forwardRateLimits(running, event.limits);
|
|
2235
2338
|
return;
|
|
2236
2339
|
case 'agent_tasks': {
|
|
2237
2340
|
// Ticket #113. A LEVEL signal: every frame carries the whole live set,
|
|
@@ -3444,6 +3547,7 @@ export class Supervisor {
|
|
|
3444
3547
|
lastReported: descriptor.status === 'REVIEW' ? 'REVIEW' : 'WAITING_INPUT',
|
|
3445
3548
|
costUsd: descriptor.costUsd,
|
|
3446
3549
|
costBaseUsd: descriptor.costUsd,
|
|
3550
|
+
levels: freshLevels(),
|
|
3447
3551
|
stopRequested: false,
|
|
3448
3552
|
parkRequested: false,
|
|
3449
3553
|
pendingMessages: [],
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const RUNNER_VERSION = "0.
|
|
1
|
+
export declare const RUNNER_VERSION = "0.48.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/package.json
CHANGED