remote-codex 0.11.32 → 0.11.33
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/apps/supervisor-api/dist/index.js +41 -1
- package/apps/supervisor-web/dist/assets/{index-CGHHTNkM.js → index-DIi8wTEY.js} +7 -7
- package/apps/supervisor-web/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/claude/src/runtimeAdapter.test.ts +57 -1
- package/packages/claude/src/runtimeAdapter.ts +72 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
11
11
|
<link rel="manifest" href="/site.webmanifest" />
|
|
12
12
|
<title>Remote Codex</title>
|
|
13
|
-
<script type="module" crossorigin src="/assets/index-
|
|
13
|
+
<script type="module" crossorigin src="/assets/index-DIi8wTEY.js"></script>
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/react-vendor-Dfg_6BLf.js">
|
|
15
15
|
<link rel="modulepreload" crossorigin href="/assets/ui-vendor-CuR8GHb0.js">
|
|
16
16
|
<link rel="modulepreload" crossorigin href="/assets/graph-vendor-DVQUpZ8C.js">
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ interface Query extends AsyncIterable<SDKMessage> {
|
|
|
15
15
|
interrupt(): Promise<void>;
|
|
16
16
|
supportedModels(): Promise<any[]>;
|
|
17
17
|
mcpServerStatus(): Promise<any[]>;
|
|
18
|
+
usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET(): Promise<any>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
function wait(ms = 0) {
|
|
@@ -29,7 +30,7 @@ class FakeQuery implements Query {
|
|
|
29
30
|
|
|
30
31
|
constructor(
|
|
31
32
|
private readonly messages: SDKMessage[],
|
|
32
|
-
private readonly options: { holdOpen?: boolean } = {},
|
|
33
|
+
private readonly options: { holdOpen?: boolean; usage?: Record<string, any> } = {},
|
|
33
34
|
) {}
|
|
34
35
|
|
|
35
36
|
[Symbol.asyncIterator]() {
|
|
@@ -104,6 +105,12 @@ class FakeQuery implements Query {
|
|
|
104
105
|
async getContextUsage(): Promise<any> {
|
|
105
106
|
return {};
|
|
106
107
|
}
|
|
108
|
+
async usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET(): Promise<any> {
|
|
109
|
+
if (!this.options.usage) {
|
|
110
|
+
throw new Error('Structured usage unavailable in this fixture.');
|
|
111
|
+
}
|
|
112
|
+
return this.options.usage;
|
|
113
|
+
}
|
|
107
114
|
async readFile(): Promise<any> {
|
|
108
115
|
return {};
|
|
109
116
|
}
|
|
@@ -208,6 +215,55 @@ function makeAdapter(
|
|
|
208
215
|
}
|
|
209
216
|
|
|
210
217
|
describe('ClaudeRuntimeAdapter', () => {
|
|
218
|
+
it('actively reads Claude subscription windows from the structured usage API', async () => {
|
|
219
|
+
const adapter = makeAdapter(() => new FakeQuery(
|
|
220
|
+
[systemInit(), result()],
|
|
221
|
+
{
|
|
222
|
+
usage: {
|
|
223
|
+
subscription_type: 'max',
|
|
224
|
+
rate_limits_available: true,
|
|
225
|
+
rate_limits: {
|
|
226
|
+
five_hour: {
|
|
227
|
+
utilization: 23,
|
|
228
|
+
resets_at: '2027-01-15T08:00:00.000Z',
|
|
229
|
+
},
|
|
230
|
+
seven_day: {
|
|
231
|
+
utilization: 84,
|
|
232
|
+
resets_at: '2027-01-20T08:00:00.000Z',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
));
|
|
238
|
+
|
|
239
|
+
await adapter.start();
|
|
240
|
+
await adapter.startSession({
|
|
241
|
+
cwd: '/tmp/workspace',
|
|
242
|
+
model: 'sonnet',
|
|
243
|
+
approvalMode: 'guarded',
|
|
244
|
+
sandboxMode: 'workspace-write',
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
await expect(adapter.getSubscriptionUsage()).resolves.toMatchObject({
|
|
248
|
+
provider: 'claude',
|
|
249
|
+
authKind: 'subscription',
|
|
250
|
+
windows: [
|
|
251
|
+
{
|
|
252
|
+
id: 'five_hour',
|
|
253
|
+
label: '5h',
|
|
254
|
+
usedPercent: 23,
|
|
255
|
+
resetsAt: '2027-01-15T08:00:00.000Z',
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: 'seven_day',
|
|
259
|
+
label: '7d',
|
|
260
|
+
usedPercent: 84,
|
|
261
|
+
resetsAt: '2027-01-20T08:00:00.000Z',
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
|
|
211
267
|
it('captures Claude subscription rate-limit windows from SDK events', async () => {
|
|
212
268
|
const adapter = makeAdapter(() => [
|
|
213
269
|
systemInit(),
|
|
@@ -99,6 +99,19 @@ interface Query extends AsyncIterable<SDKMessage> {
|
|
|
99
99
|
interrupt(): Promise<void>;
|
|
100
100
|
supportedModels(): Promise<ModelInfo[]>;
|
|
101
101
|
mcpServerStatus(): Promise<McpServerStatus[]>;
|
|
102
|
+
usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET?(): Promise<SDKUsageResponse>;
|
|
103
|
+
}
|
|
104
|
+
interface SDKUsageWindow {
|
|
105
|
+
utilization: number | null;
|
|
106
|
+
resets_at: string | null;
|
|
107
|
+
}
|
|
108
|
+
interface SDKUsageResponse {
|
|
109
|
+
subscription_type: string | null;
|
|
110
|
+
rate_limits_available: boolean;
|
|
111
|
+
rate_limits: {
|
|
112
|
+
five_hour?: SDKUsageWindow | null;
|
|
113
|
+
seven_day?: SDKUsageWindow | null;
|
|
114
|
+
} | null;
|
|
102
115
|
}
|
|
103
116
|
interface SDKMessage {
|
|
104
117
|
type: string;
|
|
@@ -1239,6 +1252,7 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
1239
1252
|
'five_hour' | 'seven_day',
|
|
1240
1253
|
{ usedPercent: number; resetsAt: string | null }
|
|
1241
1254
|
>();
|
|
1255
|
+
private subscriptionAuthKind: 'subscription' | 'apiKey' | 'unknown' = 'unknown';
|
|
1242
1256
|
private subscriptionUsageObservedAt: string | null = null;
|
|
1243
1257
|
private readonly clientApp: string;
|
|
1244
1258
|
private sdkLoadError: string | null = null;
|
|
@@ -1271,7 +1285,7 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
1271
1285
|
}));
|
|
1272
1286
|
return {
|
|
1273
1287
|
provider: 'claude' as const,
|
|
1274
|
-
authKind:
|
|
1288
|
+
authKind: this.subscriptionAuthKind,
|
|
1275
1289
|
observedAt,
|
|
1276
1290
|
stale: false,
|
|
1277
1291
|
windows,
|
|
@@ -1297,9 +1311,56 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
1297
1311
|
? new Date(info.resetsAt * 1000).toISOString()
|
|
1298
1312
|
: null,
|
|
1299
1313
|
});
|
|
1314
|
+
this.subscriptionAuthKind = 'subscription';
|
|
1300
1315
|
this.subscriptionUsageObservedAt = new Date().toISOString();
|
|
1301
1316
|
}
|
|
1302
1317
|
|
|
1318
|
+
private async captureStructuredSubscriptionUsage(query: Query) {
|
|
1319
|
+
const getUsage = query.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET;
|
|
1320
|
+
if (!getUsage) {
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
try {
|
|
1325
|
+
const usage = await getUsage.call(query);
|
|
1326
|
+
const nextWindows = new Map<
|
|
1327
|
+
'five_hour' | 'seven_day',
|
|
1328
|
+
{ usedPercent: number; resetsAt: string | null }
|
|
1329
|
+
>();
|
|
1330
|
+
const addWindow = (
|
|
1331
|
+
id: 'five_hour' | 'seven_day',
|
|
1332
|
+
window: SDKUsageWindow | null | undefined,
|
|
1333
|
+
) => {
|
|
1334
|
+
if (
|
|
1335
|
+
typeof window?.utilization !== 'number'
|
|
1336
|
+
|| !Number.isFinite(window.utilization)
|
|
1337
|
+
) {
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
nextWindows.set(id, {
|
|
1341
|
+
usedPercent: Math.max(0, Math.min(100, window.utilization)),
|
|
1342
|
+
resetsAt: typeof window.resets_at === 'string' ? window.resets_at : null,
|
|
1343
|
+
});
|
|
1344
|
+
};
|
|
1345
|
+
addWindow('five_hour', usage.rate_limits?.five_hour);
|
|
1346
|
+
addWindow('seven_day', usage.rate_limits?.seven_day);
|
|
1347
|
+
|
|
1348
|
+
this.subscriptionUsageWindows.clear();
|
|
1349
|
+
for (const [id, window] of nextWindows) {
|
|
1350
|
+
this.subscriptionUsageWindows.set(id, window);
|
|
1351
|
+
}
|
|
1352
|
+
this.subscriptionAuthKind = usage.subscription_type
|
|
1353
|
+
? 'subscription'
|
|
1354
|
+
: usage.rate_limits_available
|
|
1355
|
+
? 'subscription'
|
|
1356
|
+
: 'apiKey';
|
|
1357
|
+
this.subscriptionUsageObservedAt = new Date().toISOString();
|
|
1358
|
+
} catch {
|
|
1359
|
+
// This SDK method is experimental. Rate-limit events remain the
|
|
1360
|
+
// compatibility fallback for Claude versions that do not expose it.
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1303
1364
|
private updateToolboxItemsFromSystemInit(message: SDKMessage) {
|
|
1304
1365
|
this.managementSchema.toolboxItems = buildClaudeToolboxItems(
|
|
1305
1366
|
normalizeClaudeSlashCommands(message.slash_commands),
|
|
@@ -1463,9 +1524,14 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
1463
1524
|
let providerSessionId: string | null = null;
|
|
1464
1525
|
let model: string | null = input.model;
|
|
1465
1526
|
const rawMessages: SDKMessage[] = [];
|
|
1527
|
+
let capturedStructuredUsage = false;
|
|
1466
1528
|
try {
|
|
1467
1529
|
for await (const message of query) {
|
|
1468
1530
|
rawMessages.push(message);
|
|
1531
|
+
if (!capturedStructuredUsage) {
|
|
1532
|
+
capturedStructuredUsage = true;
|
|
1533
|
+
await this.captureStructuredSubscriptionUsage(query);
|
|
1534
|
+
}
|
|
1469
1535
|
this.captureRateLimit(message);
|
|
1470
1536
|
if (message.type === 'system' && message.subtype === 'init') {
|
|
1471
1537
|
this.updateToolboxItemsFromSystemInit(message);
|
|
@@ -1755,9 +1821,14 @@ export class ClaudeRuntimeAdapter extends EventEmitter implements AgentRuntime {
|
|
|
1755
1821
|
const rawMessages: SDKMessage[] = [];
|
|
1756
1822
|
let terminalStatus: AgentTurn['status'] | null = null;
|
|
1757
1823
|
let terminalError: string | null = null;
|
|
1824
|
+
let capturedStructuredUsage = false;
|
|
1758
1825
|
try {
|
|
1759
1826
|
for await (const message of state.query) {
|
|
1760
1827
|
rawMessages.push(message);
|
|
1828
|
+
if (!capturedStructuredUsage) {
|
|
1829
|
+
capturedStructuredUsage = true;
|
|
1830
|
+
await this.captureStructuredSubscriptionUsage(state.query);
|
|
1831
|
+
}
|
|
1761
1832
|
this.captureRateLimit(message);
|
|
1762
1833
|
this.consumeMessage(state, message);
|
|
1763
1834
|
const status = queryResultStatus(message);
|