@threadbase-sh/streamer 1.58.0 → 1.58.1
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/cli.cjs +51 -11
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +51 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +51 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1252,11 +1252,19 @@ var CodexPtyRunner = class {
|
|
|
1252
1252
|
onStatusChange;
|
|
1253
1253
|
onPhaseChange;
|
|
1254
1254
|
onReady;
|
|
1255
|
-
//
|
|
1256
|
-
//
|
|
1255
|
+
// Every Codex prompt the client can answer — startup gates (directory trust,
|
|
1256
|
+
// hooks review), command approvals, and the rate-limit model picker — is
|
|
1257
|
+
// broadcast through this one channel; null dismisses the card once the prompt
|
|
1258
|
+
// leaves the screen.
|
|
1259
|
+
//
|
|
1260
|
+
// Deliberately NOT onLiveQuestion/onLiveQuestionGone, which is Claude's
|
|
1261
|
+
// AskUserQuestion transport. Both channels land on the same mobile
|
|
1262
|
+
// QuestionCard, and the permission one is the correct fit for Codex: its menus
|
|
1263
|
+
// are answered by the option's real on-screen number (parseCodexNumberedOptions
|
|
1264
|
+
// emits `answerKeys: "2\r"`), which is exactly what `permissionIndices` carries
|
|
1265
|
+
// and what AskUserQuestion's down-arrow-count model cannot express. Wiring the
|
|
1266
|
+
// question channel as well would be a second path to the same card.
|
|
1257
1267
|
onPermissionChange;
|
|
1258
|
-
onLiveQuestion;
|
|
1259
|
-
onLiveQuestionGone;
|
|
1260
1268
|
onUserMessage;
|
|
1261
1269
|
log;
|
|
1262
1270
|
// Tracks sessions whose PTY has spawned but Codex hasn't yet reached its
|
|
@@ -1306,8 +1314,6 @@ var CodexPtyRunner = class {
|
|
|
1306
1314
|
this.onPhaseChange = options.onPhaseChange;
|
|
1307
1315
|
this.onReady = options.onReady;
|
|
1308
1316
|
this.onPermissionChange = options.onPermissionChange;
|
|
1309
|
-
this.onLiveQuestion = options.onLiveQuestion;
|
|
1310
|
-
this.onLiveQuestionGone = options.onLiveQuestionGone;
|
|
1311
1317
|
this.onUserMessage = options.onUserMessage;
|
|
1312
1318
|
this.log = options.logger ?? getLogger("codex-pty");
|
|
1313
1319
|
}
|
|
@@ -11346,7 +11352,37 @@ var PairTokenStore = class {
|
|
|
11346
11352
|
expiresInSeconds: Math.floor(this.ttlMs / 1e3)
|
|
11347
11353
|
};
|
|
11348
11354
|
}
|
|
11355
|
+
/**
|
|
11356
|
+
* Whether `consume` would succeed right now, WITHOUT spending the token.
|
|
11357
|
+
*
|
|
11358
|
+
* Exists so a caller can reject a bad token before doing any work, and still
|
|
11359
|
+
* spend the token only once the work has succeeded. A pair token is
|
|
11360
|
+
* single-use and lives 180 seconds, so spending it on a request that then
|
|
11361
|
+
* fails costs the user a whole new QR — and, worse, makes their retry
|
|
11362
|
+
* indistinguishable from an attacker replaying a photographed code, which is
|
|
11363
|
+
* the one signal `design.md` §2.6 designates as replay detection.
|
|
11364
|
+
*
|
|
11365
|
+
* Advisory, not a reservation: it takes no lock and holds nothing. The
|
|
11366
|
+
* authoritative answer is still `consume`'s.
|
|
11367
|
+
*/
|
|
11368
|
+
verify(token) {
|
|
11369
|
+
const result = this.check(token);
|
|
11370
|
+
return result.ok ? { ok: true } : result;
|
|
11371
|
+
}
|
|
11349
11372
|
consume(token) {
|
|
11373
|
+
const result = this.check(token);
|
|
11374
|
+
if (!result.ok) return result;
|
|
11375
|
+
result.record.used = true;
|
|
11376
|
+
return { ok: true };
|
|
11377
|
+
}
|
|
11378
|
+
/**
|
|
11379
|
+
* The shared predicate behind `verify` and `consume`.
|
|
11380
|
+
*
|
|
11381
|
+
* One implementation on purpose: two copies of "is this token usable" is two
|
|
11382
|
+
* places for the expiry or single-use rule to drift, and a drift in this
|
|
11383
|
+
* direction fails open.
|
|
11384
|
+
*/
|
|
11385
|
+
check(token) {
|
|
11350
11386
|
const record2 = this.current;
|
|
11351
11387
|
if (!record2 || record2.token !== token) return { ok: false, reason: "unknown" };
|
|
11352
11388
|
if (Date.now() > record2.expiresAt) {
|
|
@@ -11354,8 +11390,7 @@ var PairTokenStore = class {
|
|
|
11354
11390
|
return { ok: false, reason: "expired" };
|
|
11355
11391
|
}
|
|
11356
11392
|
if (record2.used) return { ok: false, reason: "used" };
|
|
11357
|
-
|
|
11358
|
-
return { ok: true };
|
|
11393
|
+
return { ok: true, record: record2 };
|
|
11359
11394
|
}
|
|
11360
11395
|
peek() {
|
|
11361
11396
|
return this.current;
|
|
@@ -16147,9 +16182,9 @@ var StreamerServer = class {
|
|
|
16147
16182
|
json(res, 400, { error: "Missing token or clientPublicKey" });
|
|
16148
16183
|
return;
|
|
16149
16184
|
}
|
|
16150
|
-
const
|
|
16151
|
-
if (!
|
|
16152
|
-
json(res, 401, { error: `Pair token ${
|
|
16185
|
+
const precheck = this.pairTokens.verify(token);
|
|
16186
|
+
if (!precheck.ok) {
|
|
16187
|
+
json(res, 401, { error: `Pair token ${precheck.reason}` });
|
|
16153
16188
|
return;
|
|
16154
16189
|
}
|
|
16155
16190
|
let sealed;
|
|
@@ -16160,6 +16195,11 @@ var StreamerServer = class {
|
|
|
16160
16195
|
json(res, 400, { error: message });
|
|
16161
16196
|
return;
|
|
16162
16197
|
}
|
|
16198
|
+
const result = this.pairTokens.consume(token);
|
|
16199
|
+
if (!result.ok) {
|
|
16200
|
+
json(res, 401, { error: `Pair token ${result.reason}` });
|
|
16201
|
+
return;
|
|
16202
|
+
}
|
|
16163
16203
|
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
16164
16204
|
this.log.info(`[pair] token exchanged from ${ip} at ${ts}`, {
|
|
16165
16205
|
event: "pair.token_exchanged",
|