@threadbase-sh/streamer 1.69.5 → 1.70.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/api/handlers/sessions.handlers.d.ts +28 -2
- package/dist/api/handlers/sessions.handlers.d.ts.map +1 -1
- package/dist/api/routes/misc.routes.d.ts.map +1 -1
- package/dist/api/routes/sessions.routes.d.ts.map +1 -1
- package/dist/api/types/api-deps.d.ts +1 -0
- package/dist/api/types/api-deps.d.ts.map +1 -1
- package/dist/cli.cjs +1298 -317
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +891 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +890 -49
- package/dist/index.js.map +1 -1
- package/dist/pty-host/protocol.d.ts +21 -4
- package/dist/pty-host/protocol.d.ts.map +1 -1
- package/dist/pty-host/remote-session-runner.d.ts +1 -0
- package/dist/pty-host/remote-session-runner.d.ts.map +1 -1
- package/dist/schemas/prompt.schema.d.ts +113 -0
- package/dist/schemas/prompt.schema.d.ts.map +1 -0
- package/dist/server-wiring.d.ts +22 -0
- package/dist/server-wiring.d.ts.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/services/prompts/promptRegistry.d.ts +99 -0
- package/dist/services/prompts/promptRegistry.d.ts.map +1 -0
- package/dist/services/prompts/ptyPromptAdapter.d.ts +6 -0
- package/dist/services/prompts/ptyPromptAdapter.d.ts.map +1 -0
- package/dist/types.d.ts +4 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -116376,7 +116376,7 @@ var require_query = __commonJS({
|
|
|
116376
116376
|
if (typeof this.text !== "string" && typeof this.name !== "string") {
|
|
116377
116377
|
return new Error("A query must have either text or a name. Supplying neither is unsupported.");
|
|
116378
116378
|
}
|
|
116379
|
-
const previous = connection.parsedStatements[this.name];
|
|
116379
|
+
const previous = connection.parsedStatements[this.name] || connection.submittedNamedStatements[this.name];
|
|
116380
116380
|
if (this.text && previous && this.text !== previous) {
|
|
116381
116381
|
return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`);
|
|
116382
116382
|
}
|
|
@@ -116396,7 +116396,7 @@ var require_query = __commonJS({
|
|
|
116396
116396
|
return null;
|
|
116397
116397
|
}
|
|
116398
116398
|
hasBeenParsed(connection) {
|
|
116399
|
-
return this.name && connection.parsedStatements[this.name];
|
|
116399
|
+
return this.name && (connection.parsedStatements[this.name] || connection.submittedNamedStatements[this.name]);
|
|
116400
116400
|
}
|
|
116401
116401
|
handlePortalSuspended(connection) {
|
|
116402
116402
|
this._getRows(connection, this.rows);
|
|
@@ -116420,6 +116420,9 @@ var require_query = __commonJS({
|
|
|
116420
116420
|
name: this.name,
|
|
116421
116421
|
types: this.types
|
|
116422
116422
|
});
|
|
116423
|
+
if (this.name) {
|
|
116424
|
+
connection.submittedNamedStatements[this.name] = this.text;
|
|
116425
|
+
}
|
|
116423
116426
|
}
|
|
116424
116427
|
try {
|
|
116425
116428
|
connection.bind({
|
|
@@ -117208,7 +117211,7 @@ var require_parser3 = __commonJS({
|
|
|
117208
117211
|
const parameterCount = reader.int16();
|
|
117209
117212
|
const message = new messages_1.ParameterDescriptionMessage(LATEINIT_LENGTH, parameterCount);
|
|
117210
117213
|
for (let i = 0; i < parameterCount; i++) {
|
|
117211
|
-
message.dataTypeIDs[i] = reader.
|
|
117214
|
+
message.dataTypeIDs[i] = reader.uint32();
|
|
117212
117215
|
}
|
|
117213
117216
|
return message;
|
|
117214
117217
|
};
|
|
@@ -117430,6 +117433,7 @@ var require_connection2 = __commonJS({
|
|
|
117430
117433
|
this._keepAlive = config2.keepAlive;
|
|
117431
117434
|
this._keepAliveInitialDelayMillis = config2.keepAliveInitialDelayMillis;
|
|
117432
117435
|
this.parsedStatements = {};
|
|
117436
|
+
this.submittedNamedStatements = {};
|
|
117433
117437
|
this.ssl = config2.ssl || false;
|
|
117434
117438
|
this.sslNegotiation = config2.sslNegotiation || "postgres";
|
|
117435
117439
|
this._ending = false;
|
|
@@ -117987,6 +117991,8 @@ var require_client3 = __commonJS({
|
|
|
117987
117991
|
encoding: this.connectionParameters.client_encoding || "utf8"
|
|
117988
117992
|
});
|
|
117989
117993
|
this._queryQueue = [];
|
|
117994
|
+
this._sentQueryQueue = [];
|
|
117995
|
+
this.pipeline = Boolean(c.pipeline);
|
|
117990
117996
|
this.binary = c.binary || defaults2.binary;
|
|
117991
117997
|
this.processID = null;
|
|
117992
117998
|
this.secretKey = null;
|
|
@@ -118021,6 +118027,8 @@ var require_client3 = __commonJS({
|
|
|
118021
118027
|
enqueueError(activeQuery);
|
|
118022
118028
|
this._activeQuery = null;
|
|
118023
118029
|
}
|
|
118030
|
+
this._sentQueryQueue.forEach(enqueueError);
|
|
118031
|
+
this._sentQueryQueue.length = 0;
|
|
118024
118032
|
this._queryQueue.forEach(enqueueError);
|
|
118025
118033
|
this._queryQueue.length = 0;
|
|
118026
118034
|
}
|
|
@@ -118263,6 +118271,9 @@ var require_client3 = __commonJS({
|
|
|
118263
118271
|
return;
|
|
118264
118272
|
}
|
|
118265
118273
|
this._activeQuery = null;
|
|
118274
|
+
if (activeQuery.name) {
|
|
118275
|
+
delete this.connection.submittedNamedStatements[activeQuery.name];
|
|
118276
|
+
}
|
|
118266
118277
|
activeQuery.handleError(msg, this.connection);
|
|
118267
118278
|
}
|
|
118268
118279
|
_handleRowDescription(msg) {
|
|
@@ -118319,6 +118330,7 @@ var require_client3 = __commonJS({
|
|
|
118319
118330
|
}
|
|
118320
118331
|
if (activeQuery.name) {
|
|
118321
118332
|
this.connection.parsedStatements[activeQuery.name] = activeQuery.text;
|
|
118333
|
+
delete this.connection.submittedNamedStatements[activeQuery.name];
|
|
118322
118334
|
}
|
|
118323
118335
|
}
|
|
118324
118336
|
_handleCopyInResponse(msg) {
|
|
@@ -118385,6 +118397,9 @@ var require_client3 = __commonJS({
|
|
|
118385
118397
|
});
|
|
118386
118398
|
} else if (client._queryQueue.indexOf(query) !== -1) {
|
|
118387
118399
|
client._queryQueue.splice(client._queryQueue.indexOf(query), 1);
|
|
118400
|
+
} else if (client._sentQueryQueue.indexOf(query) !== -1) {
|
|
118401
|
+
query.callback = () => {
|
|
118402
|
+
};
|
|
118388
118403
|
}
|
|
118389
118404
|
}
|
|
118390
118405
|
setTypeParser(oid, format, parseFn) {
|
|
@@ -118403,6 +118418,10 @@ var require_client3 = __commonJS({
|
|
|
118403
118418
|
return utils.escapeLiteral(str);
|
|
118404
118419
|
}
|
|
118405
118420
|
_pulseQueryQueue() {
|
|
118421
|
+
if (this.pipeline) {
|
|
118422
|
+
this._pulsePipelinedQueryQueue();
|
|
118423
|
+
return;
|
|
118424
|
+
}
|
|
118406
118425
|
if (this.readyForQuery === true) {
|
|
118407
118426
|
this._activeQuery = this._queryQueue.shift();
|
|
118408
118427
|
const activeQuery = this._getActiveQuery();
|
|
@@ -118423,6 +118442,30 @@ var require_client3 = __commonJS({
|
|
|
118423
118442
|
}
|
|
118424
118443
|
}
|
|
118425
118444
|
}
|
|
118445
|
+
_pulsePipelinedQueryQueue() {
|
|
118446
|
+
if (!this._connected || !this._queryable) {
|
|
118447
|
+
return;
|
|
118448
|
+
}
|
|
118449
|
+
while (this._queryQueue.length > 0) {
|
|
118450
|
+
const query = this._queryQueue.shift();
|
|
118451
|
+
this.hasExecuted = true;
|
|
118452
|
+
const queryError = query.submit(this.connection);
|
|
118453
|
+
if (queryError) {
|
|
118454
|
+
process.nextTick(() => {
|
|
118455
|
+
query.handleError(queryError, this.connection);
|
|
118456
|
+
});
|
|
118457
|
+
continue;
|
|
118458
|
+
}
|
|
118459
|
+
this._sentQueryQueue.push(query);
|
|
118460
|
+
}
|
|
118461
|
+
if (this.readyForQuery && !this._activeQuery && this._sentQueryQueue.length > 0) {
|
|
118462
|
+
this._activeQuery = this._sentQueryQueue.shift();
|
|
118463
|
+
this.readyForQuery = false;
|
|
118464
|
+
}
|
|
118465
|
+
if (!this._activeQuery && this._sentQueryQueue.length === 0 && this._queryQueue.length === 0 && this.hasExecuted) {
|
|
118466
|
+
this.emit("drain");
|
|
118467
|
+
}
|
|
118468
|
+
}
|
|
118426
118469
|
query(config2, values, callback) {
|
|
118427
118470
|
let query;
|
|
118428
118471
|
let result;
|
|
@@ -118466,6 +118509,9 @@ var require_client3 = __commonJS({
|
|
|
118466
118509
|
const index = this._queryQueue.indexOf(query);
|
|
118467
118510
|
if (index > -1) {
|
|
118468
118511
|
this._queryQueue.splice(index, 1);
|
|
118512
|
+
} else if (this.pipeline) {
|
|
118513
|
+
this.connection.stream.destroy();
|
|
118514
|
+
return;
|
|
118469
118515
|
}
|
|
118470
118516
|
this._pulseQueryQueue();
|
|
118471
118517
|
}, readTimeout);
|
|
@@ -118492,7 +118538,7 @@ var require_client3 = __commonJS({
|
|
|
118492
118538
|
});
|
|
118493
118539
|
return result;
|
|
118494
118540
|
}
|
|
118495
|
-
if (this._queryQueue.length > 0) {
|
|
118541
|
+
if (this._queryQueue.length > 0 && !this.pipeline) {
|
|
118496
118542
|
queryQueueLengthDeprecationNotice();
|
|
118497
118543
|
}
|
|
118498
118544
|
this._queryQueue.push(query);
|
|
@@ -118518,7 +118564,11 @@ var require_client3 = __commonJS({
|
|
|
118518
118564
|
return this._Promise.resolve();
|
|
118519
118565
|
}
|
|
118520
118566
|
}
|
|
118521
|
-
if (
|
|
118567
|
+
if (!this._queryable) {
|
|
118568
|
+
this.connection.stream.destroy();
|
|
118569
|
+
} else if (this.pipeline && (this._getActiveQuery() || this._sentQueryQueue.length > 0 || this._queryQueue.length > 0)) {
|
|
118570
|
+
this.once("drain", () => this.connection.end());
|
|
118571
|
+
} else if (this._getActiveQuery()) {
|
|
118522
118572
|
this.connection.stream.destroy();
|
|
118523
118573
|
} else {
|
|
118524
118574
|
this.connection.end();
|
|
@@ -119008,7 +119058,7 @@ var require_query2 = __commonJS({
|
|
|
119008
119058
|
sourceFunction: "routine"
|
|
119009
119059
|
};
|
|
119010
119060
|
NativeQuery.prototype.handleError = function(err) {
|
|
119011
|
-
const fields = this.native.pq.resultErrorFields();
|
|
119061
|
+
const fields = this.native && this.native.pq.resultErrorFields();
|
|
119012
119062
|
if (fields) {
|
|
119013
119063
|
for (const key in fields) {
|
|
119014
119064
|
const normalizedFieldName = errorFieldMap[key] || key;
|
|
@@ -119142,6 +119192,8 @@ var require_client4 = __commonJS({
|
|
|
119142
119192
|
this._connecting = false;
|
|
119143
119193
|
this._connected = false;
|
|
119144
119194
|
this._queryable = true;
|
|
119195
|
+
this.pipeline = Boolean(config2.pipeline);
|
|
119196
|
+
this._pipelineInFlight = false;
|
|
119145
119197
|
const cp = this.connectionParameters = new ConnectionParameters(config2);
|
|
119146
119198
|
if (config2.nativeConnectionString) cp.nativeConnectionString = config2.nativeConnectionString;
|
|
119147
119199
|
this.user = cp.user;
|
|
@@ -119285,7 +119337,7 @@ var require_client4 = __commonJS({
|
|
|
119285
119337
|
});
|
|
119286
119338
|
return result;
|
|
119287
119339
|
}
|
|
119288
|
-
if (this._queryQueue.length > 0) {
|
|
119340
|
+
if (this._queryQueue.length > 0 && !this.pipeline) {
|
|
119289
119341
|
queryQueueLengthDeprecationNotice();
|
|
119290
119342
|
}
|
|
119291
119343
|
this._queryQueue.push(query);
|
|
@@ -119307,14 +119359,21 @@ var require_client4 = __commonJS({
|
|
|
119307
119359
|
cb2 = (err) => err ? reject(err) : resolve4();
|
|
119308
119360
|
});
|
|
119309
119361
|
}
|
|
119310
|
-
|
|
119311
|
-
self2.
|
|
119312
|
-
|
|
119313
|
-
|
|
119314
|
-
|
|
119315
|
-
|
|
119362
|
+
const doEnd = function() {
|
|
119363
|
+
self2.native.end(function() {
|
|
119364
|
+
self2._connected = false;
|
|
119365
|
+
self2._errorAllQueries(new Error("Connection terminated"));
|
|
119366
|
+
process.nextTick(() => {
|
|
119367
|
+
self2.emit("end");
|
|
119368
|
+
if (cb2) cb2();
|
|
119369
|
+
});
|
|
119316
119370
|
});
|
|
119317
|
-
}
|
|
119371
|
+
};
|
|
119372
|
+
if (this.pipeline && (this._pipelineInFlight || this._queryQueue.length > 0)) {
|
|
119373
|
+
this.once("drain", doEnd);
|
|
119374
|
+
} else {
|
|
119375
|
+
doEnd();
|
|
119376
|
+
}
|
|
119318
119377
|
return result;
|
|
119319
119378
|
};
|
|
119320
119379
|
Client2.prototype._hasActiveQuery = function() {
|
|
@@ -119324,6 +119383,9 @@ var require_client4 = __commonJS({
|
|
|
119324
119383
|
if (!this._connected) {
|
|
119325
119384
|
return;
|
|
119326
119385
|
}
|
|
119386
|
+
if (this.pipeline && !initialConnection) {
|
|
119387
|
+
return this._pulsePipelinedQueryQueue();
|
|
119388
|
+
}
|
|
119327
119389
|
if (this._hasActiveQuery()) {
|
|
119328
119390
|
return;
|
|
119329
119391
|
}
|
|
@@ -119341,6 +119403,69 @@ var require_client4 = __commonJS({
|
|
|
119341
119403
|
self2._pulseQueryQueue();
|
|
119342
119404
|
});
|
|
119343
119405
|
};
|
|
119406
|
+
Client2.prototype._pulsePipelinedQueryQueue = function() {
|
|
119407
|
+
if (!this._connected || this._pipelineInFlight) {
|
|
119408
|
+
return;
|
|
119409
|
+
}
|
|
119410
|
+
if (this._queryQueue.length === 0) {
|
|
119411
|
+
if (this.hasExecuted) {
|
|
119412
|
+
this.emit("drain");
|
|
119413
|
+
}
|
|
119414
|
+
return;
|
|
119415
|
+
}
|
|
119416
|
+
this._pipelineInFlight = true;
|
|
119417
|
+
const self2 = this;
|
|
119418
|
+
const queries = [];
|
|
119419
|
+
const nativeQueries = [];
|
|
119420
|
+
const utils = require_utils5();
|
|
119421
|
+
while (this._queryQueue.length > 0) {
|
|
119422
|
+
const query = this._queryQueue.shift();
|
|
119423
|
+
this.hasExecuted = true;
|
|
119424
|
+
nativeQueries.push(query);
|
|
119425
|
+
const values = query.values ? query.values.map(utils.prepareValue) : null;
|
|
119426
|
+
const pipelineEntry = { text: query.text, name: query.name };
|
|
119427
|
+
if (values) {
|
|
119428
|
+
pipelineEntry.values = values;
|
|
119429
|
+
}
|
|
119430
|
+
if (query.name && this.namedQueries[query.name]) {
|
|
119431
|
+
pipelineEntry._alreadyPrepared = true;
|
|
119432
|
+
}
|
|
119433
|
+
queries.push(pipelineEntry);
|
|
119434
|
+
}
|
|
119435
|
+
this.native.pipeline(queries, function(err, results) {
|
|
119436
|
+
self2._pipelineInFlight = false;
|
|
119437
|
+
if (err) {
|
|
119438
|
+
for (let i = 0; i < nativeQueries.length; i++) {
|
|
119439
|
+
const q2 = nativeQueries[i];
|
|
119440
|
+
q2.native = self2.native;
|
|
119441
|
+
q2.handleError(err);
|
|
119442
|
+
}
|
|
119443
|
+
self2._pulsePipelinedQueryQueue();
|
|
119444
|
+
return;
|
|
119445
|
+
}
|
|
119446
|
+
for (let i = 0; i < nativeQueries.length; i++) {
|
|
119447
|
+
const q2 = nativeQueries[i];
|
|
119448
|
+
const r = results[i];
|
|
119449
|
+
q2.native = self2.native;
|
|
119450
|
+
if (r.err) {
|
|
119451
|
+
q2.handleError(r.err);
|
|
119452
|
+
} else {
|
|
119453
|
+
if (q2.name) {
|
|
119454
|
+
self2.namedQueries[q2.name] = q2.text;
|
|
119455
|
+
}
|
|
119456
|
+
q2.state = "end";
|
|
119457
|
+
q2.emit("end", r.result);
|
|
119458
|
+
if (q2.callback) {
|
|
119459
|
+
q2.callback(null, r.result);
|
|
119460
|
+
}
|
|
119461
|
+
}
|
|
119462
|
+
setImmediate(function() {
|
|
119463
|
+
q2.emit("_done");
|
|
119464
|
+
});
|
|
119465
|
+
}
|
|
119466
|
+
self2._pulsePipelinedQueryQueue();
|
|
119467
|
+
});
|
|
119468
|
+
};
|
|
119344
119469
|
Client2.prototype.cancel = function(query) {
|
|
119345
119470
|
if (this._activeQuery === query) {
|
|
119346
119471
|
this.native.cancel(function() {
|
|
@@ -120610,7 +120735,7 @@ var PTY_HOST_PROTOCOL_VERSION, SESSION_DATE_FIELDS, LineDecoder;
|
|
|
120610
120735
|
var init_protocol = __esm({
|
|
120611
120736
|
"src/pty-host/protocol.ts"() {
|
|
120612
120737
|
"use strict";
|
|
120613
|
-
PTY_HOST_PROTOCOL_VERSION =
|
|
120738
|
+
PTY_HOST_PROTOCOL_VERSION = 4;
|
|
120614
120739
|
SESSION_DATE_FIELDS = [
|
|
120615
120740
|
"startedAt",
|
|
120616
120741
|
"completedAt",
|
|
@@ -120690,8 +120815,12 @@ var init_remote_session_runner = __esm({
|
|
|
120690
120815
|
}
|
|
120691
120816
|
throw new PtyHostProtocolMismatchError(status.protocolVersion, PTY_HOST_PROTOCOL_VERSION);
|
|
120692
120817
|
}
|
|
120693
|
-
await runner.request({ type: "subscribe" });
|
|
120818
|
+
const subscribed = await runner.request({ type: "subscribe" });
|
|
120694
120819
|
runner.refreshMirror(status);
|
|
120820
|
+
runner.restorePromptSnapshots({
|
|
120821
|
+
...status,
|
|
120822
|
+
promptSnapshots: subscribed.promptSnapshots ?? status.promptSnapshots
|
|
120823
|
+
});
|
|
120695
120824
|
return runner;
|
|
120696
120825
|
}
|
|
120697
120826
|
constructor(transport, options) {
|
|
@@ -120784,6 +120913,19 @@ var init_remote_session_runner = __esm({
|
|
|
120784
120913
|
this.pids.set(session.id, entry.pid);
|
|
120785
120914
|
}
|
|
120786
120915
|
}
|
|
120916
|
+
restorePromptSnapshots(status) {
|
|
120917
|
+
for (const snapshot of status.promptSnapshots ?? []) {
|
|
120918
|
+
if (snapshot.kind === "permission") {
|
|
120919
|
+
this.options.onPermissionChange?.(snapshot.sessionId, snapshot.gate, snapshot.occurrenceId);
|
|
120920
|
+
} else {
|
|
120921
|
+
this.options.onLiveQuestion?.(
|
|
120922
|
+
snapshot.sessionId,
|
|
120923
|
+
snapshot.questions,
|
|
120924
|
+
snapshot.occurrenceId
|
|
120925
|
+
);
|
|
120926
|
+
}
|
|
120927
|
+
}
|
|
120928
|
+
}
|
|
120787
120929
|
async heartbeat(state, timeoutMs = HOST_HEARTBEAT_REQUEST_TIMEOUT_MS) {
|
|
120788
120930
|
await this.request({ type: "heartbeat", ...state }, timeoutMs);
|
|
120789
120931
|
}
|
|
@@ -120838,13 +120980,13 @@ var init_remote_session_runner = __esm({
|
|
|
120838
120980
|
break;
|
|
120839
120981
|
}
|
|
120840
120982
|
case "permission-change":
|
|
120841
|
-
this.options.onPermissionChange?.(event.sessionId, event.gate);
|
|
120983
|
+
this.options.onPermissionChange?.(event.sessionId, event.gate, event.occurrenceId);
|
|
120842
120984
|
break;
|
|
120843
120985
|
case "phase-change":
|
|
120844
120986
|
this.options.onPhaseChange?.(event.sessionId, event.phase);
|
|
120845
120987
|
break;
|
|
120846
120988
|
case "live-question":
|
|
120847
|
-
this.options.onLiveQuestion?.(event.sessionId, event.questions);
|
|
120989
|
+
this.options.onLiveQuestion?.(event.sessionId, event.questions, event.occurrenceId);
|
|
120848
120990
|
break;
|
|
120849
120991
|
case "live-question-gone":
|
|
120850
120992
|
this.options.onLiveQuestionGone?.(event.sessionId);
|
|
@@ -128466,12 +128608,15 @@ __export(host_exports, {
|
|
|
128466
128608
|
HOST_ORPHAN_SWEEP_MS: () => HOST_ORPHAN_SWEEP_MS,
|
|
128467
128609
|
SessionHost: () => SessionHost
|
|
128468
128610
|
});
|
|
128469
|
-
var HOST_IDLE_SWEEP_MS, HOST_IDLE_AFTER_MS, HOST_HEARTBEAT_TIMEOUT_MS, HOST_ORPHAN_SWEEP_MS, SessionHost;
|
|
128611
|
+
var import_node_crypto8, HOST_IDLE_SWEEP_MS, HOST_IDLE_AFTER_MS, HOST_HEARTBEAT_TIMEOUT_MS, HOST_ORPHAN_SWEEP_MS, SessionHost;
|
|
128470
128612
|
var init_host = __esm({
|
|
128471
128613
|
"src/pty-host/host.ts"() {
|
|
128472
128614
|
"use strict";
|
|
128615
|
+
import_node_crypto8 = require("crypto");
|
|
128473
128616
|
init_live_session_manager();
|
|
128474
128617
|
init_logger();
|
|
128618
|
+
init_detectPermissionGate();
|
|
128619
|
+
init_detectQuestionFromScreen();
|
|
128475
128620
|
init_protocol();
|
|
128476
128621
|
HOST_IDLE_SWEEP_MS = 5 * 60 * 1e3;
|
|
128477
128622
|
HOST_IDLE_AFTER_MS = 6 * 60 * 60 * 1e3;
|
|
@@ -128493,6 +128638,7 @@ var init_host = __esm({
|
|
|
128493
128638
|
orphanTimer = null;
|
|
128494
128639
|
onOrphaned;
|
|
128495
128640
|
orphaned = false;
|
|
128641
|
+
promptSnapshots = /* @__PURE__ */ new Map();
|
|
128496
128642
|
constructor(options = {}) {
|
|
128497
128643
|
this.log = options.logger ?? getLogger("pty-host");
|
|
128498
128644
|
this.idleAfterMs = options.idleAfterMs ?? HOST_IDLE_AFTER_MS;
|
|
@@ -128505,12 +128651,55 @@ var init_host = __esm({
|
|
|
128505
128651
|
this.lastAgentChunkAt.set(sessionId, Date.now());
|
|
128506
128652
|
this.emit({ type: "event", event: "output", sessionId, data });
|
|
128507
128653
|
},
|
|
128508
|
-
onStatusChange: (session) =>
|
|
128654
|
+
onStatusChange: (session) => {
|
|
128655
|
+
if (session.status === "idle") this.promptSnapshots.delete(session.id);
|
|
128656
|
+
this.emit({ type: "event", event: "status-change", session });
|
|
128657
|
+
},
|
|
128509
128658
|
onReady: (session) => this.emit({ type: "event", event: "ready", session }),
|
|
128510
|
-
onPermissionChange: (sessionId, gate) =>
|
|
128659
|
+
onPermissionChange: (sessionId, gate) => {
|
|
128660
|
+
const prior = this.promptSnapshots.get(sessionId);
|
|
128661
|
+
if (gate === null) {
|
|
128662
|
+
this.promptSnapshots.delete(sessionId);
|
|
128663
|
+
this.emit({
|
|
128664
|
+
type: "event",
|
|
128665
|
+
event: "permission-change",
|
|
128666
|
+
sessionId,
|
|
128667
|
+
gate,
|
|
128668
|
+
...prior ? { occurrenceId: prior.occurrenceId } : {}
|
|
128669
|
+
});
|
|
128670
|
+
return;
|
|
128671
|
+
}
|
|
128672
|
+
const occurrenceId = prior?.kind === "permission" && permissionGateKey(prior.gate) === permissionGateKey(gate) ? prior.occurrenceId : (0, import_node_crypto8.randomUUID)();
|
|
128673
|
+
this.promptSnapshots.set(sessionId, {
|
|
128674
|
+
kind: "permission",
|
|
128675
|
+
sessionId,
|
|
128676
|
+
occurrenceId,
|
|
128677
|
+
gate
|
|
128678
|
+
});
|
|
128679
|
+
this.emit({
|
|
128680
|
+
type: "event",
|
|
128681
|
+
event: "permission-change",
|
|
128682
|
+
sessionId,
|
|
128683
|
+
gate,
|
|
128684
|
+
occurrenceId
|
|
128685
|
+
});
|
|
128686
|
+
},
|
|
128511
128687
|
onPhaseChange: (sessionId, phase) => this.emit({ type: "event", event: "phase-change", sessionId, phase }),
|
|
128512
|
-
onLiveQuestion: (sessionId, questions) =>
|
|
128513
|
-
|
|
128688
|
+
onLiveQuestion: (sessionId, questions) => {
|
|
128689
|
+
const prior = this.promptSnapshots.get(sessionId);
|
|
128690
|
+
const occurrenceId = prior?.kind === "question" && questionContentKey(prior.questions) === questionContentKey(questions) ? prior.occurrenceId : (0, import_node_crypto8.randomUUID)();
|
|
128691
|
+
this.promptSnapshots.set(sessionId, {
|
|
128692
|
+
kind: "question",
|
|
128693
|
+
sessionId,
|
|
128694
|
+
occurrenceId,
|
|
128695
|
+
questions
|
|
128696
|
+
});
|
|
128697
|
+
this.emit({ type: "event", event: "live-question", sessionId, questions, occurrenceId });
|
|
128698
|
+
},
|
|
128699
|
+
onLiveQuestionGone: (sessionId) => {
|
|
128700
|
+
this.promptSnapshots.delete(sessionId);
|
|
128701
|
+
this.emit({ type: "event", event: "live-question-gone", sessionId });
|
|
128702
|
+
},
|
|
128514
128703
|
onUserMessage: (sessionId, text, ts2) => this.emit({ type: "event", event: "user-message", sessionId, text, ts: ts2 })
|
|
128515
128704
|
});
|
|
128516
128705
|
this.idleTimer = setInterval(() => this.reapIdle(), options.idleSweepMs ?? HOST_IDLE_SWEEP_MS);
|
|
@@ -128579,11 +128768,12 @@ var init_host = __esm({
|
|
|
128579
128768
|
event: "pty_host.streamer_subscribed",
|
|
128580
128769
|
subscribers: this.subscribers.size
|
|
128581
128770
|
});
|
|
128582
|
-
return {};
|
|
128771
|
+
return { promptSnapshots: [...this.promptSnapshots.values()] };
|
|
128583
128772
|
case "status":
|
|
128584
128773
|
return {
|
|
128585
128774
|
protocolVersion: PTY_HOST_PROTOCOL_VERSION,
|
|
128586
|
-
sessions: this.runner.listSessions().map((session) => this.toHostSession(session))
|
|
128775
|
+
sessions: this.runner.listSessions().map((session) => this.toHostSession(session)),
|
|
128776
|
+
promptSnapshots: [...this.promptSnapshots.values()]
|
|
128587
128777
|
};
|
|
128588
128778
|
case "heartbeat":
|
|
128589
128779
|
this.heartbeatLeases.set(transport, Date.now());
|
|
@@ -128641,6 +128831,7 @@ var init_host = __esm({
|
|
|
128641
128831
|
}
|
|
128642
128832
|
forget(sessionId) {
|
|
128643
128833
|
this.lastAgentChunkAt.delete(sessionId);
|
|
128834
|
+
this.promptSnapshots.delete(sessionId);
|
|
128644
128835
|
}
|
|
128645
128836
|
/**
|
|
128646
128837
|
* Release PTYs whose agent has been silent past the threshold.
|
|
@@ -132718,13 +132909,13 @@ var checkOptionalParameter = (path2) => {
|
|
|
132718
132909
|
if (segment !== "" && !/\:/.test(segment)) {
|
|
132719
132910
|
basePath += "/" + segment;
|
|
132720
132911
|
} else if (/\:/.test(segment)) {
|
|
132721
|
-
if (
|
|
132912
|
+
if (segment.charCodeAt(segment.length - 1) === 63) {
|
|
132722
132913
|
if (results.length === 0 && basePath === "") {
|
|
132723
132914
|
results.push("/");
|
|
132724
132915
|
} else {
|
|
132725
132916
|
results.push(basePath);
|
|
132726
132917
|
}
|
|
132727
|
-
const optionalSegment = segment.
|
|
132918
|
+
const optionalSegment = segment.slice(0, -1);
|
|
132728
132919
|
basePath += "/" + optionalSegment;
|
|
132729
132920
|
results.push(basePath);
|
|
132730
132921
|
} else {
|
|
@@ -132734,18 +132925,16 @@ var checkOptionalParameter = (path2) => {
|
|
|
132734
132925
|
});
|
|
132735
132926
|
return results.filter((v2, i, a) => a.indexOf(v2) === i);
|
|
132736
132927
|
};
|
|
132928
|
+
var tryDecodeURIComponent = (str) => str.indexOf("%") !== -1 ? tryDecode(str, decodeURIComponent_) : str;
|
|
132737
132929
|
var _decodeURI = (value) => {
|
|
132738
|
-
if (!/[%+]/.test(value)) {
|
|
132739
|
-
return value;
|
|
132740
|
-
}
|
|
132741
132930
|
if (value.indexOf("+") !== -1) {
|
|
132742
132931
|
value = value.replace(/\+/g, " ");
|
|
132743
132932
|
}
|
|
132744
|
-
return
|
|
132933
|
+
return tryDecodeURIComponent(value);
|
|
132745
132934
|
};
|
|
132746
132935
|
var _getQueryParam = (url2, key, multiple) => {
|
|
132747
132936
|
let encoded;
|
|
132748
|
-
if (!multiple && key &&
|
|
132937
|
+
if (!multiple && key && key.indexOf("%") === -1 && key.indexOf("+") === -1) {
|
|
132749
132938
|
let keyIndex2 = url2.indexOf("?", 8);
|
|
132750
132939
|
if (keyIndex2 === -1) {
|
|
132751
132940
|
return void 0;
|
|
@@ -132817,7 +133006,6 @@ var getQueryParams = (url2, key) => {
|
|
|
132817
133006
|
var decodeURIComponent_ = decodeURIComponent;
|
|
132818
133007
|
|
|
132819
133008
|
// node_modules/hono/dist/request.js
|
|
132820
|
-
var tryDecodeURIComponent = (str) => tryDecode(str, decodeURIComponent_);
|
|
132821
133009
|
var HonoRequest = class {
|
|
132822
133010
|
/**
|
|
132823
133011
|
* `.raw` can get the raw Request object.
|
|
@@ -132856,7 +133044,6 @@ var HonoRequest = class {
|
|
|
132856
133044
|
this.raw = request;
|
|
132857
133045
|
this.path = path2;
|
|
132858
133046
|
this.#matchResult = matchResult;
|
|
132859
|
-
this.#validatedData = {};
|
|
132860
133047
|
}
|
|
132861
133048
|
param(key) {
|
|
132862
133049
|
return key ? this.#getDecodedParam(key) : this.#getAllDecodedParams();
|
|
@@ -132864,7 +133051,7 @@ var HonoRequest = class {
|
|
|
132864
133051
|
#getDecodedParam(key) {
|
|
132865
133052
|
const paramKey = this.#matchResult[0][this.routeIndex][1][key];
|
|
132866
133053
|
const param = this.#getParamValue(paramKey);
|
|
132867
|
-
return param &&
|
|
133054
|
+
return param && tryDecodeURIComponent(param);
|
|
132868
133055
|
}
|
|
132869
133056
|
#getAllDecodedParams() {
|
|
132870
133057
|
const decoded = {};
|
|
@@ -132872,7 +133059,7 @@ var HonoRequest = class {
|
|
|
132872
133059
|
for (const key of keys) {
|
|
132873
133060
|
const value = this.#getParamValue(this.#matchResult[0][this.routeIndex][1][key]);
|
|
132874
133061
|
if (value !== void 0) {
|
|
132875
|
-
decoded[key] =
|
|
133062
|
+
decoded[key] = tryDecodeURIComponent(value);
|
|
132876
133063
|
}
|
|
132877
133064
|
}
|
|
132878
133065
|
return decoded;
|
|
@@ -132905,8 +133092,7 @@ var HonoRequest = class {
|
|
|
132905
133092
|
if (cachedBody) {
|
|
132906
133093
|
return cachedBody;
|
|
132907
133094
|
}
|
|
132908
|
-
const anyCachedKey
|
|
132909
|
-
if (anyCachedKey) {
|
|
133095
|
+
for (const anyCachedKey in bodyCache) {
|
|
132910
133096
|
return bodyCache[anyCachedKey].then((body) => {
|
|
132911
133097
|
if (anyCachedKey === "json") {
|
|
132912
133098
|
body = JSON.stringify(body);
|
|
@@ -133009,10 +133195,11 @@ var HonoRequest = class {
|
|
|
133009
133195
|
* @param data - The validated data to add.
|
|
133010
133196
|
*/
|
|
133011
133197
|
addValidatedData(target, data) {
|
|
133012
|
-
|
|
133198
|
+
;
|
|
133199
|
+
(this.#validatedData ??= {})[target] = data;
|
|
133013
133200
|
}
|
|
133014
133201
|
valid(target) {
|
|
133015
|
-
return this.#validatedData[target];
|
|
133202
|
+
return this.#validatedData?.[target];
|
|
133016
133203
|
}
|
|
133017
133204
|
/**
|
|
133018
133205
|
* `.url()` can get the request url strings.
|
|
@@ -133343,6 +133530,10 @@ var Context = class {
|
|
|
133343
133530
|
* c.header('X-Message', 'Hello!')
|
|
133344
133531
|
* c.header('Content-Type', 'text/plain')
|
|
133345
133532
|
*
|
|
133533
|
+
* // Append multiple headers using the append option (e.g. Vary)
|
|
133534
|
+
* c.header('Vary', 'Accept-Encoding', { append: true })
|
|
133535
|
+
* c.header('Vary', 'User-Agent', { append: true })
|
|
133536
|
+
*
|
|
133346
133537
|
* return c.body('Thank you for coming')
|
|
133347
133538
|
* })
|
|
133348
133539
|
* ```
|
|
@@ -133414,11 +133605,11 @@ var Context = class {
|
|
|
133414
133605
|
return Object.fromEntries(this.#var);
|
|
133415
133606
|
}
|
|
133416
133607
|
#newResponse(data, arg, headers) {
|
|
133417
|
-
|
|
133418
|
-
if (typeof arg === "object" &&
|
|
133419
|
-
|
|
133420
|
-
for (const [key, value] of
|
|
133421
|
-
if (key
|
|
133608
|
+
let responseHeaders = this.#res ? new Headers(this.#res.headers) : this.#preparedHeaders;
|
|
133609
|
+
if (typeof arg === "object" && arg.headers) {
|
|
133610
|
+
responseHeaders ??= new Headers();
|
|
133611
|
+
for (const [key, value] of new Headers(arg.headers)) {
|
|
133612
|
+
if (key === "set-cookie") {
|
|
133422
133613
|
responseHeaders.append(key, value);
|
|
133423
133614
|
} else {
|
|
133424
133615
|
responseHeaders.set(key, value);
|
|
@@ -133426,19 +133617,34 @@ var Context = class {
|
|
|
133426
133617
|
}
|
|
133427
133618
|
}
|
|
133428
133619
|
if (headers) {
|
|
133429
|
-
|
|
133430
|
-
|
|
133431
|
-
|
|
133432
|
-
|
|
133433
|
-
|
|
133434
|
-
|
|
133435
|
-
|
|
133620
|
+
if (!responseHeaders) {
|
|
133621
|
+
let count = 0;
|
|
133622
|
+
for (const k2 in headers) {
|
|
133623
|
+
if (++count > 1 || typeof headers[k2] !== "string") {
|
|
133624
|
+
responseHeaders = new Headers();
|
|
133625
|
+
break;
|
|
133626
|
+
}
|
|
133627
|
+
}
|
|
133628
|
+
}
|
|
133629
|
+
if (responseHeaders) {
|
|
133630
|
+
for (const k2 in headers) {
|
|
133631
|
+
const v2 = headers[k2];
|
|
133632
|
+
if (typeof v2 === "string") {
|
|
133633
|
+
responseHeaders.set(k2, v2);
|
|
133634
|
+
} else {
|
|
133635
|
+
responseHeaders.delete(k2);
|
|
133636
|
+
for (const v22 of v2) {
|
|
133637
|
+
responseHeaders.append(k2, v22);
|
|
133638
|
+
}
|
|
133436
133639
|
}
|
|
133437
133640
|
}
|
|
133438
133641
|
}
|
|
133439
133642
|
}
|
|
133440
133643
|
const status = typeof arg === "number" ? arg : arg?.status ?? this.#status;
|
|
133441
|
-
return createResponseInstance(data, {
|
|
133644
|
+
return createResponseInstance(data, {
|
|
133645
|
+
status,
|
|
133646
|
+
headers: responseHeaders ?? headers
|
|
133647
|
+
});
|
|
133442
133648
|
}
|
|
133443
133649
|
newResponse = (...args) => this.#newResponse(...args);
|
|
133444
133650
|
/**
|
|
@@ -133551,7 +133757,7 @@ var Context = class {
|
|
|
133551
133757
|
// node_modules/hono/dist/router.js
|
|
133552
133758
|
var METHOD_NAME_ALL = "ALL";
|
|
133553
133759
|
var METHOD_NAME_ALL_LOWERCASE = "all";
|
|
133554
|
-
var METHODS = ["get", "post", "put", "delete", "options", "patch"];
|
|
133760
|
+
var METHODS = ["get", "post", "put", "delete", "options", "patch", "query"];
|
|
133555
133761
|
var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is already built.";
|
|
133556
133762
|
var UnsupportedPathError = class extends Error {
|
|
133557
133763
|
};
|
|
@@ -133578,6 +133784,7 @@ var Hono = class _Hono {
|
|
|
133578
133784
|
delete;
|
|
133579
133785
|
options;
|
|
133580
133786
|
patch;
|
|
133787
|
+
query;
|
|
133581
133788
|
all;
|
|
133582
133789
|
on;
|
|
133583
133790
|
use;
|
|
@@ -133877,8 +134084,8 @@ var Hono = class _Hono {
|
|
|
133877
134084
|
* @see {@link https://hono.dev/docs/api/hono#fetch}
|
|
133878
134085
|
*
|
|
133879
134086
|
* @param {Request} request - request Object of request
|
|
133880
|
-
* @param {Env}
|
|
133881
|
-
* @param {ExecutionContext} - context of execution
|
|
134087
|
+
* @param {Env} env - env Object
|
|
134088
|
+
* @param {ExecutionContext} executionCtx - context of execution
|
|
133882
134089
|
* @returns {Response | Promise<Response>} response of request
|
|
133883
134090
|
*
|
|
133884
134091
|
*/
|
|
@@ -133970,7 +134177,7 @@ function compareKey(a, b2) {
|
|
|
133970
134177
|
return 1;
|
|
133971
134178
|
}
|
|
133972
134179
|
if (a === ONLY_WILDCARD_REG_EXP_STR || a === TAIL_WILDCARD_REG_EXP_STR) {
|
|
133973
|
-
return 1;
|
|
134180
|
+
return b2 === TAIL_WILDCARD_REG_EXP_STR ? -1 : 1;
|
|
133974
134181
|
} else if (b2 === ONLY_WILDCARD_REG_EXP_STR || b2 === TAIL_WILDCARD_REG_EXP_STR) {
|
|
133975
134182
|
return -1;
|
|
133976
134183
|
}
|
|
@@ -133982,76 +134189,75 @@ function compareKey(a, b2) {
|
|
|
133982
134189
|
return a.length === b2.length ? a < b2 ? -1 : 1 : b2.length - a.length;
|
|
133983
134190
|
}
|
|
133984
134191
|
var Node = class _Node {
|
|
134192
|
+
// handler index of a dynamic path, or -1 for a static path terminal
|
|
133985
134193
|
#index;
|
|
133986
134194
|
#varIndex;
|
|
133987
134195
|
#children = /* @__PURE__ */ Object.create(null);
|
|
133988
|
-
insert(tokens, index, paramMap, context,
|
|
133989
|
-
|
|
133990
|
-
|
|
133991
|
-
|
|
133992
|
-
}
|
|
133993
|
-
|
|
133994
|
-
|
|
133995
|
-
|
|
133996
|
-
|
|
133997
|
-
|
|
133998
|
-
|
|
133999
|
-
|
|
134000
|
-
|
|
134001
|
-
|
|
134002
|
-
|
|
134003
|
-
|
|
134004
|
-
|
|
134005
|
-
|
|
134006
|
-
|
|
134007
|
-
|
|
134008
|
-
}
|
|
134009
|
-
|
|
134010
|
-
if (
|
|
134011
|
-
|
|
134012
|
-
|
|
134013
|
-
|
|
134014
|
-
|
|
134015
|
-
|
|
134016
|
-
|
|
134017
|
-
|
|
134018
|
-
|
|
134019
|
-
|
|
134020
|
-
|
|
134021
|
-
|
|
134022
|
-
return;
|
|
134196
|
+
insert(tokens, index, paramMap, context, isStatic) {
|
|
134197
|
+
let node = this;
|
|
134198
|
+
for (let i = 0, len = tokens.length; i < len; i++) {
|
|
134199
|
+
const token = tokens[i];
|
|
134200
|
+
const pattern = token.length === 1 ? token === "*" ? i === len - 1 ? ["", "", ONLY_WILDCARD_REG_EXP_STR] : ["", "", LABEL_REG_EXP_STR] : null : token === "/*" ? ["", "", TAIL_WILDCARD_REG_EXP_STR] : token.match(/^\:([^\{\}]+)(?:\{(.+)\})?$/);
|
|
134201
|
+
let nextNode;
|
|
134202
|
+
if (pattern) {
|
|
134203
|
+
const name = pattern[1];
|
|
134204
|
+
let regexpStr = pattern[2] || LABEL_REG_EXP_STR;
|
|
134205
|
+
if (name && pattern[2]) {
|
|
134206
|
+
if (regexpStr === ".*") {
|
|
134207
|
+
throw PATH_ERROR;
|
|
134208
|
+
}
|
|
134209
|
+
regexpStr = regexpStr.replace(/^\((?!\?:)(?=[^)]+\)$)/, "(?:");
|
|
134210
|
+
if (/\((?!\?:)/.test(regexpStr)) {
|
|
134211
|
+
throw PATH_ERROR;
|
|
134212
|
+
}
|
|
134213
|
+
if (regexpStr.length === 1 && regExpMetaChars.has(regexpStr)) {
|
|
134214
|
+
throw PATH_ERROR;
|
|
134215
|
+
}
|
|
134216
|
+
}
|
|
134217
|
+
nextNode = node.#children[regexpStr];
|
|
134218
|
+
if (!nextNode) {
|
|
134219
|
+
if (regexpStr !== ONLY_WILDCARD_REG_EXP_STR && regexpStr !== TAIL_WILDCARD_REG_EXP_STR) {
|
|
134220
|
+
for (const k2 in node.#children) {
|
|
134221
|
+
if (
|
|
134222
|
+
// a single-char pattern coexists with single-char literals as a literal does
|
|
134223
|
+
(regexpStr.length > 1 || k2.length > 1) && k2 !== ONLY_WILDCARD_REG_EXP_STR && k2 !== TAIL_WILDCARD_REG_EXP_STR
|
|
134224
|
+
) {
|
|
134225
|
+
throw PATH_ERROR;
|
|
134226
|
+
}
|
|
134227
|
+
}
|
|
134228
|
+
}
|
|
134229
|
+
nextNode = node.#children[regexpStr] = new _Node();
|
|
134023
134230
|
}
|
|
134024
|
-
node = this.#children[regexpStr] = new _Node();
|
|
134025
134231
|
if (name !== "") {
|
|
134026
|
-
|
|
134232
|
+
nextNode.#varIndex ??= context.varIndex++;
|
|
134233
|
+
paramMap.push([name, nextNode.#varIndex]);
|
|
134027
134234
|
}
|
|
134028
|
-
}
|
|
134029
|
-
|
|
134030
|
-
|
|
134031
|
-
|
|
134032
|
-
|
|
134033
|
-
|
|
134034
|
-
|
|
134035
|
-
|
|
134036
|
-
|
|
134037
|
-
)) {
|
|
134038
|
-
throw PATH_ERROR;
|
|
134039
|
-
}
|
|
134040
|
-
if (pathErrorCheckOnly) {
|
|
134041
|
-
return;
|
|
134235
|
+
} else {
|
|
134236
|
+
nextNode = node.#children[token];
|
|
134237
|
+
if (!nextNode) {
|
|
134238
|
+
for (const k2 in node.#children) {
|
|
134239
|
+
if (k2.length > 1 && k2 !== ONLY_WILDCARD_REG_EXP_STR && k2 !== TAIL_WILDCARD_REG_EXP_STR) {
|
|
134240
|
+
throw PATH_ERROR;
|
|
134241
|
+
}
|
|
134242
|
+
}
|
|
134243
|
+
nextNode = node.#children[token] = new _Node();
|
|
134042
134244
|
}
|
|
134043
|
-
node = this.#children[token] = new _Node();
|
|
134044
134245
|
}
|
|
134246
|
+
node = nextNode;
|
|
134247
|
+
}
|
|
134248
|
+
if (node.#index !== void 0) {
|
|
134249
|
+
throw PATH_ERROR;
|
|
134045
134250
|
}
|
|
134046
|
-
node
|
|
134251
|
+
node.#index = isStatic ? -1 : index;
|
|
134047
134252
|
}
|
|
134048
134253
|
buildRegExpStr() {
|
|
134049
134254
|
const childKeys = Object.keys(this.#children).sort(compareKey);
|
|
134050
134255
|
const strList = childKeys.map((k2) => {
|
|
134051
134256
|
const c = this.#children[k2];
|
|
134052
|
-
|
|
134053
|
-
|
|
134054
|
-
|
|
134257
|
+
const childStr = c.buildRegExpStr();
|
|
134258
|
+
return childStr === "" ? "" : (typeof c.#varIndex === "number" ? `(${k2})@${c.#varIndex}` : regExpMetaChars.has(k2) ? `\\${k2}` : k2) + childStr;
|
|
134259
|
+
}).filter(Boolean);
|
|
134260
|
+
if (typeof this.#index === "number" && this.#index !== -1) {
|
|
134055
134261
|
strList.unshift(`#${this.#index}`);
|
|
134056
134262
|
}
|
|
134057
134263
|
if (strList.length === 0) {
|
|
@@ -134068,12 +134274,20 @@ var Node = class _Node {
|
|
|
134068
134274
|
var Trie = class {
|
|
134069
134275
|
#context = { varIndex: 0 };
|
|
134070
134276
|
#root = new Node();
|
|
134071
|
-
|
|
134277
|
+
#index = 0;
|
|
134278
|
+
// dynamic path -> [handler index, param assoc]; static paths are not registered
|
|
134279
|
+
paths = /* @__PURE__ */ Object.create(null);
|
|
134280
|
+
insert(path2, isStatic) {
|
|
134281
|
+
if (isStatic) {
|
|
134282
|
+
this.#root.insert(path2.split(""), 0, [], this.#context, true);
|
|
134283
|
+
return;
|
|
134284
|
+
}
|
|
134072
134285
|
const paramAssoc = [];
|
|
134073
134286
|
const groups = [];
|
|
134287
|
+
let markedPath = path2;
|
|
134074
134288
|
for (let i = 0; ; ) {
|
|
134075
134289
|
let replaced = false;
|
|
134076
|
-
|
|
134290
|
+
markedPath = markedPath.replace(/\{[^}]+\}/g, (m2) => {
|
|
134077
134291
|
const mark = `@\\${i}`;
|
|
134078
134292
|
groups[i] = [mark, m2];
|
|
134079
134293
|
i++;
|
|
@@ -134084,7 +134298,7 @@ var Trie = class {
|
|
|
134084
134298
|
break;
|
|
134085
134299
|
}
|
|
134086
134300
|
}
|
|
134087
|
-
const tokens =
|
|
134301
|
+
const tokens = markedPath.match(/(?::[^\/]+)|(?:\/\*$)|./g) || [];
|
|
134088
134302
|
for (let i = groups.length - 1; i >= 0; i--) {
|
|
134089
134303
|
const [mark] = groups[i];
|
|
134090
134304
|
for (let j2 = tokens.length - 1; j2 >= 0; j2--) {
|
|
@@ -134094,8 +134308,8 @@ var Trie = class {
|
|
|
134094
134308
|
}
|
|
134095
134309
|
}
|
|
134096
134310
|
}
|
|
134097
|
-
this.#root.insert(tokens, index, paramAssoc, this.#context,
|
|
134098
|
-
|
|
134311
|
+
this.#root.insert(tokens, this.#index, paramAssoc, this.#context, false);
|
|
134312
|
+
this.paths[path2] = [this.#index++, paramAssoc];
|
|
134099
134313
|
}
|
|
134100
134314
|
buildRegExp() {
|
|
134101
134315
|
let regexp = this.#root.buildRegExpStr();
|
|
@@ -134121,7 +134335,6 @@ var Trie = class {
|
|
|
134121
134335
|
};
|
|
134122
134336
|
|
|
134123
134337
|
// node_modules/hono/dist/router/reg-exp-router/router.js
|
|
134124
|
-
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
134125
134338
|
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
134126
134339
|
function buildWildcardRegExp(path2) {
|
|
134127
134340
|
return wildcardRegExpCache[path2] ??= new RegExp(
|
|
@@ -134134,63 +134347,6 @@ function buildWildcardRegExp(path2) {
|
|
|
134134
134347
|
function clearWildcardRegExpCache() {
|
|
134135
134348
|
wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
134136
134349
|
}
|
|
134137
|
-
function buildMatcherFromPreprocessedRoutes(routes) {
|
|
134138
|
-
const trie = new Trie();
|
|
134139
|
-
const handlerData = [];
|
|
134140
|
-
if (routes.length === 0) {
|
|
134141
|
-
return nullMatcher;
|
|
134142
|
-
}
|
|
134143
|
-
const routesWithStaticPathFlag = routes.map(
|
|
134144
|
-
(route) => [!/\*|\/:/.test(route[0]), ...route]
|
|
134145
|
-
).sort(
|
|
134146
|
-
([isStaticA, pathA], [isStaticB, pathB]) => isStaticA ? 1 : isStaticB ? -1 : pathA.length - pathB.length
|
|
134147
|
-
);
|
|
134148
|
-
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
134149
|
-
for (let i = 0, j2 = -1, len = routesWithStaticPathFlag.length; i < len; i++) {
|
|
134150
|
-
const [pathErrorCheckOnly, path2, handlers] = routesWithStaticPathFlag[i];
|
|
134151
|
-
if (pathErrorCheckOnly) {
|
|
134152
|
-
staticMap[path2] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
134153
|
-
} else {
|
|
134154
|
-
j2++;
|
|
134155
|
-
}
|
|
134156
|
-
let paramAssoc;
|
|
134157
|
-
try {
|
|
134158
|
-
paramAssoc = trie.insert(path2, j2, pathErrorCheckOnly);
|
|
134159
|
-
} catch (e) {
|
|
134160
|
-
throw e === PATH_ERROR ? new UnsupportedPathError(path2) : e;
|
|
134161
|
-
}
|
|
134162
|
-
if (pathErrorCheckOnly) {
|
|
134163
|
-
continue;
|
|
134164
|
-
}
|
|
134165
|
-
handlerData[j2] = handlers.map(([h, paramCount]) => {
|
|
134166
|
-
const paramIndexMap = /* @__PURE__ */ Object.create(null);
|
|
134167
|
-
paramCount -= 1;
|
|
134168
|
-
for (; paramCount >= 0; paramCount--) {
|
|
134169
|
-
const [key, value] = paramAssoc[paramCount];
|
|
134170
|
-
paramIndexMap[key] = value;
|
|
134171
|
-
}
|
|
134172
|
-
return [h, paramIndexMap];
|
|
134173
|
-
});
|
|
134174
|
-
}
|
|
134175
|
-
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
134176
|
-
for (let i = 0, len = handlerData.length; i < len; i++) {
|
|
134177
|
-
for (let j2 = 0, len2 = handlerData[i].length; j2 < len2; j2++) {
|
|
134178
|
-
const map2 = handlerData[i][j2]?.[1];
|
|
134179
|
-
if (!map2) {
|
|
134180
|
-
continue;
|
|
134181
|
-
}
|
|
134182
|
-
const keys = Object.keys(map2);
|
|
134183
|
-
for (let k2 = 0, len3 = keys.length; k2 < len3; k2++) {
|
|
134184
|
-
map2[keys[k2]] = paramReplacementMap[map2[keys[k2]]];
|
|
134185
|
-
}
|
|
134186
|
-
}
|
|
134187
|
-
}
|
|
134188
|
-
const handlerMap = [];
|
|
134189
|
-
for (const i in indexReplacementMap) {
|
|
134190
|
-
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
134191
|
-
}
|
|
134192
|
-
return [regexp, handlerMap, staticMap];
|
|
134193
|
-
}
|
|
134194
134350
|
function findMiddleware(middleware, path2) {
|
|
134195
134351
|
if (!middleware) {
|
|
134196
134352
|
return void 0;
|
|
@@ -134206,9 +134362,18 @@ var RegExpRouter = class {
|
|
|
134206
134362
|
name = "RegExpRouter";
|
|
134207
134363
|
#middleware;
|
|
134208
134364
|
#routes;
|
|
134365
|
+
#tries;
|
|
134209
134366
|
constructor() {
|
|
134210
134367
|
this.#middleware = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
134211
134368
|
this.#routes = { [METHOD_NAME_ALL]: /* @__PURE__ */ Object.create(null) };
|
|
134369
|
+
this.#tries = { [METHOD_NAME_ALL]: new Trie() };
|
|
134370
|
+
}
|
|
134371
|
+
#insertPath(method, path2) {
|
|
134372
|
+
try {
|
|
134373
|
+
this.#tries[method].insert(path2, !/\*|\/:/.test(path2));
|
|
134374
|
+
} catch (e) {
|
|
134375
|
+
throw e === PATH_ERROR ? new UnsupportedPathError(path2) : e;
|
|
134376
|
+
}
|
|
134212
134377
|
}
|
|
134213
134378
|
add(method, path2, handler) {
|
|
134214
134379
|
const middleware = this.#middleware;
|
|
@@ -134217,11 +134382,12 @@ var RegExpRouter = class {
|
|
|
134217
134382
|
throw new Error(MESSAGE_MATCHER_IS_ALREADY_BUILT);
|
|
134218
134383
|
}
|
|
134219
134384
|
if (!middleware[method]) {
|
|
134220
|
-
;
|
|
134385
|
+
this.#tries[method] = new Trie();
|
|
134221
134386
|
[middleware, routes].forEach((handlerMap) => {
|
|
134222
134387
|
handlerMap[method] = /* @__PURE__ */ Object.create(null);
|
|
134223
134388
|
Object.keys(handlerMap[METHOD_NAME_ALL]).forEach((p2) => {
|
|
134224
134389
|
handlerMap[method][p2] = [...handlerMap[METHOD_NAME_ALL][p2]];
|
|
134390
|
+
this.#insertPath(method, p2);
|
|
134225
134391
|
});
|
|
134226
134392
|
});
|
|
134227
134393
|
}
|
|
@@ -134231,13 +134397,12 @@ var RegExpRouter = class {
|
|
|
134231
134397
|
const paramCount = (path2.match(/\/:/g) || []).length;
|
|
134232
134398
|
if (/\*$/.test(path2)) {
|
|
134233
134399
|
const re2 = buildWildcardRegExp(path2);
|
|
134234
|
-
|
|
134235
|
-
|
|
134236
|
-
|
|
134237
|
-
|
|
134238
|
-
|
|
134239
|
-
|
|
134240
|
-
}
|
|
134400
|
+
Object.keys(middleware).forEach((m2) => {
|
|
134401
|
+
if ((method === METHOD_NAME_ALL || method === m2) && !middleware[m2][path2]) {
|
|
134402
|
+
this.#insertPath(m2, path2);
|
|
134403
|
+
middleware[m2][path2] = findMiddleware(middleware[m2], path2) || findMiddleware(middleware[METHOD_NAME_ALL], path2) || [];
|
|
134404
|
+
}
|
|
134405
|
+
});
|
|
134241
134406
|
Object.keys(middleware).forEach((m2) => {
|
|
134242
134407
|
if (method === METHOD_NAME_ALL || method === m2) {
|
|
134243
134408
|
Object.keys(middleware[m2]).forEach((p2) => {
|
|
@@ -134259,9 +134424,12 @@ var RegExpRouter = class {
|
|
|
134259
134424
|
const path22 = paths[i];
|
|
134260
134425
|
Object.keys(routes).forEach((m2) => {
|
|
134261
134426
|
if (method === METHOD_NAME_ALL || method === m2) {
|
|
134262
|
-
routes[m2][path22]
|
|
134263
|
-
|
|
134264
|
-
|
|
134427
|
+
if (!routes[m2][path22]) {
|
|
134428
|
+
this.#insertPath(m2, path22);
|
|
134429
|
+
routes[m2][path22] = [
|
|
134430
|
+
...findMiddleware(middleware[m2], path22) || findMiddleware(middleware[METHOD_NAME_ALL], path22) || []
|
|
134431
|
+
];
|
|
134432
|
+
}
|
|
134265
134433
|
routes[m2][path22].push([handler, paramCount - len + i + 1]);
|
|
134266
134434
|
}
|
|
134267
134435
|
});
|
|
@@ -134273,29 +134441,54 @@ var RegExpRouter = class {
|
|
|
134273
134441
|
Object.keys(this.#routes).concat(Object.keys(this.#middleware)).forEach((method) => {
|
|
134274
134442
|
matchers[method] ||= this.#buildMatcher(method);
|
|
134275
134443
|
});
|
|
134276
|
-
this.#middleware = this.#routes = void 0;
|
|
134444
|
+
this.#middleware = this.#routes = this.#tries = void 0;
|
|
134277
134445
|
clearWildcardRegExpCache();
|
|
134278
134446
|
return matchers;
|
|
134279
134447
|
}
|
|
134280
134448
|
#buildMatcher(method) {
|
|
134281
|
-
const
|
|
134282
|
-
|
|
134283
|
-
|
|
134284
|
-
|
|
134285
|
-
|
|
134286
|
-
|
|
134287
|
-
|
|
134288
|
-
|
|
134289
|
-
|
|
134290
|
-
|
|
134291
|
-
|
|
134449
|
+
const middleware = this.#middleware[method];
|
|
134450
|
+
const routes = this.#routes[method];
|
|
134451
|
+
const trie = this.#tries[method];
|
|
134452
|
+
const staticMap = /* @__PURE__ */ Object.create(null);
|
|
134453
|
+
const handlerData = [];
|
|
134454
|
+
[middleware, routes].forEach((r) => {
|
|
134455
|
+
for (const path2 in r) {
|
|
134456
|
+
const handlers = r[path2];
|
|
134457
|
+
const pathData = trie.paths[path2];
|
|
134458
|
+
if (!pathData) {
|
|
134459
|
+
staticMap[path2] = [handlers.map(([h]) => [h, /* @__PURE__ */ Object.create(null)]), emptyParam];
|
|
134460
|
+
continue;
|
|
134461
|
+
}
|
|
134462
|
+
const paramAssoc = pathData[1];
|
|
134463
|
+
handlerData[pathData[0]] = handlers.map(([h, paramCount]) => {
|
|
134464
|
+
const paramIndexMap = /* @__PURE__ */ Object.create(null);
|
|
134465
|
+
paramCount -= 1;
|
|
134466
|
+
for (; paramCount >= 0; paramCount--) {
|
|
134467
|
+
const [key, value] = paramAssoc[paramCount];
|
|
134468
|
+
paramIndexMap[key] = value;
|
|
134469
|
+
}
|
|
134470
|
+
return [h, paramIndexMap];
|
|
134471
|
+
});
|
|
134292
134472
|
}
|
|
134293
134473
|
});
|
|
134294
|
-
|
|
134295
|
-
|
|
134296
|
-
|
|
134297
|
-
|
|
134474
|
+
const [regexp, indexReplacementMap, paramReplacementMap] = trie.buildRegExp();
|
|
134475
|
+
for (let i = 0, len = handlerData.length; i < len; i++) {
|
|
134476
|
+
for (let j2 = 0, len2 = handlerData[i].length; j2 < len2; j2++) {
|
|
134477
|
+
const map2 = handlerData[i][j2]?.[1];
|
|
134478
|
+
if (!map2) {
|
|
134479
|
+
continue;
|
|
134480
|
+
}
|
|
134481
|
+
const keys = Object.keys(map2);
|
|
134482
|
+
for (let k2 = 0, len3 = keys.length; k2 < len3; k2++) {
|
|
134483
|
+
map2[keys[k2]] = paramReplacementMap[map2[keys[k2]]];
|
|
134484
|
+
}
|
|
134485
|
+
}
|
|
134486
|
+
}
|
|
134487
|
+
const handlerMap = [];
|
|
134488
|
+
for (const i in indexReplacementMap) {
|
|
134489
|
+
handlerMap[i] = handlerData[indexReplacementMap[i]];
|
|
134298
134490
|
}
|
|
134491
|
+
return [regexp, handlerMap, staticMap];
|
|
134299
134492
|
}
|
|
134300
134493
|
};
|
|
134301
134494
|
|
|
@@ -134356,76 +134549,51 @@ var SmartRouter = class {
|
|
|
134356
134549
|
|
|
134357
134550
|
// node_modules/hono/dist/router/trie-router/node.js
|
|
134358
134551
|
var emptyParams = /* @__PURE__ */ Object.create(null);
|
|
134359
|
-
var
|
|
134360
|
-
for (const _2 in children) {
|
|
134361
|
-
return true;
|
|
134362
|
-
}
|
|
134363
|
-
return false;
|
|
134364
|
-
};
|
|
134552
|
+
var order = 0;
|
|
134365
134553
|
var Node2 = class _Node2 {
|
|
134366
|
-
#methods;
|
|
134367
|
-
#children;
|
|
134368
|
-
#patterns;
|
|
134369
|
-
#
|
|
134554
|
+
#methods = [];
|
|
134555
|
+
#children = /* @__PURE__ */ Object.create(null);
|
|
134556
|
+
#patterns = [];
|
|
134557
|
+
#pattern;
|
|
134370
134558
|
#params = emptyParams;
|
|
134371
|
-
constructor(method, handler, children) {
|
|
134372
|
-
this.#children = children || /* @__PURE__ */ Object.create(null);
|
|
134373
|
-
this.#methods = [];
|
|
134374
|
-
if (method && handler) {
|
|
134375
|
-
const m2 = /* @__PURE__ */ Object.create(null);
|
|
134376
|
-
m2[method] = { handler, possibleKeys: [], score: 0 };
|
|
134377
|
-
this.#methods = [m2];
|
|
134378
|
-
}
|
|
134379
|
-
this.#patterns = [];
|
|
134380
|
-
}
|
|
134381
134559
|
insert(method, path2, handler) {
|
|
134382
|
-
this.#order = ++this.#order;
|
|
134383
134560
|
let curNode = this;
|
|
134384
134561
|
const parts = splitRoutingPath(path2);
|
|
134385
|
-
const possibleKeys =
|
|
134386
|
-
|
|
134387
|
-
|
|
134388
|
-
const nextP = parts[i
|
|
134389
|
-
const pattern = getPattern(p2, nextP);
|
|
134390
|
-
const
|
|
134391
|
-
|
|
134392
|
-
|
|
134393
|
-
|
|
134394
|
-
|
|
134395
|
-
|
|
134396
|
-
continue;
|
|
134562
|
+
const possibleKeys = /* @__PURE__ */ new Set();
|
|
134563
|
+
let i = 0;
|
|
134564
|
+
for (const p2 of parts) {
|
|
134565
|
+
const nextP = parts[++i];
|
|
134566
|
+
const pattern = getPattern(p2, nextP) || (nextP === void 0 && p2 && p2.indexOf("*") === p2.length - 1 ? p2 : null);
|
|
134567
|
+
const isParam = Array.isArray(pattern);
|
|
134568
|
+
const key = isParam ? pattern[0] : pattern || p2;
|
|
134569
|
+
const child = curNode.#children[key] ||= new _Node2();
|
|
134570
|
+
if (pattern && !child.#pattern) {
|
|
134571
|
+
child.#pattern = pattern;
|
|
134572
|
+
curNode.#patterns.push(child);
|
|
134397
134573
|
}
|
|
134398
|
-
curNode
|
|
134399
|
-
if (
|
|
134400
|
-
|
|
134401
|
-
possibleKeys.push(pattern[1]);
|
|
134574
|
+
curNode = child;
|
|
134575
|
+
if (isParam) {
|
|
134576
|
+
possibleKeys.add(pattern[1]);
|
|
134402
134577
|
}
|
|
134403
|
-
curNode = curNode.#children[key];
|
|
134404
134578
|
}
|
|
134405
134579
|
curNode.#methods.push({
|
|
134406
134580
|
[method]: {
|
|
134407
134581
|
handler,
|
|
134408
|
-
possibleKeys: possibleKeys
|
|
134409
|
-
score:
|
|
134582
|
+
possibleKeys: [...possibleKeys],
|
|
134583
|
+
score: ++order
|
|
134410
134584
|
}
|
|
134411
134585
|
});
|
|
134412
|
-
return curNode;
|
|
134413
134586
|
}
|
|
134414
134587
|
#pushHandlerSets(handlerSets, node, method, nodeParams, params) {
|
|
134415
134588
|
for (let i = 0, len = node.#methods.length; i < len; i++) {
|
|
134416
134589
|
const m2 = node.#methods[i];
|
|
134417
134590
|
const handlerSet = m2[method] || m2[METHOD_NAME_ALL];
|
|
134418
|
-
|
|
134419
|
-
if (handlerSet !== void 0) {
|
|
134591
|
+
if (handlerSet) {
|
|
134420
134592
|
handlerSet.params = /* @__PURE__ */ Object.create(null);
|
|
134421
134593
|
handlerSets.push(handlerSet);
|
|
134422
|
-
|
|
134423
|
-
|
|
134424
|
-
|
|
134425
|
-
const processed = processedSet[handlerSet.score];
|
|
134426
|
-
handlerSet.params[key] = params?.[key] && !processed ? params[key] : nodeParams[key] ?? params?.[key];
|
|
134427
|
-
processedSet[handlerSet.score] = true;
|
|
134428
|
-
}
|
|
134594
|
+
for (let i2 = 0, len2 = handlerSet.possibleKeys.length; i2 < len2; i2++) {
|
|
134595
|
+
const key = handlerSet.possibleKeys[i2];
|
|
134596
|
+
handlerSet.params[key] = params?.[key] && !i2 ? params[key] : nodeParams[key] ?? params?.[key];
|
|
134429
134597
|
}
|
|
134430
134598
|
}
|
|
134431
134599
|
}
|
|
@@ -134457,33 +134625,33 @@ var Node2 = class _Node2 {
|
|
|
134457
134625
|
tempNodes.push(nextNode);
|
|
134458
134626
|
}
|
|
134459
134627
|
}
|
|
134460
|
-
for (
|
|
134461
|
-
const pattern =
|
|
134628
|
+
for (const child of node.#patterns) {
|
|
134629
|
+
const pattern = child.#pattern;
|
|
134462
134630
|
const params = node.#params === emptyParams ? {} : { ...node.#params };
|
|
134463
|
-
if (pattern === "
|
|
134464
|
-
|
|
134465
|
-
|
|
134466
|
-
|
|
134467
|
-
|
|
134468
|
-
|
|
134631
|
+
if (typeof pattern === "string") {
|
|
134632
|
+
if (pattern === "*" || part.startsWith(pattern.slice(0, -1))) {
|
|
134633
|
+
this.#pushHandlerSets(handlerSets, child, method, node.#params);
|
|
134634
|
+
if (pattern === "*") {
|
|
134635
|
+
child.#params = params;
|
|
134636
|
+
tempNodes.push(child);
|
|
134637
|
+
}
|
|
134469
134638
|
}
|
|
134470
134639
|
continue;
|
|
134471
134640
|
}
|
|
134472
|
-
const [
|
|
134473
|
-
if (!part &&
|
|
134641
|
+
const [, name, matcher] = pattern;
|
|
134642
|
+
if (!part && matcher === true) {
|
|
134474
134643
|
continue;
|
|
134475
134644
|
}
|
|
134476
|
-
|
|
134477
|
-
|
|
134478
|
-
|
|
134479
|
-
partOffsets = new Array(len);
|
|
134645
|
+
if (matcher !== true) {
|
|
134646
|
+
if (!partOffsets) {
|
|
134647
|
+
partOffsets = [];
|
|
134480
134648
|
let offset = path2[0] === "/" ? 1 : 0;
|
|
134481
134649
|
for (let p2 = 0; p2 < len; p2++) {
|
|
134482
134650
|
partOffsets[p2] = offset;
|
|
134483
134651
|
offset += parts[p2].length + 1;
|
|
134484
134652
|
}
|
|
134485
134653
|
}
|
|
134486
|
-
const restPathString = path2.
|
|
134654
|
+
const restPathString = path2.slice(partOffsets[i]);
|
|
134487
134655
|
const m2 = matcher.exec(restPathString);
|
|
134488
134656
|
if (m2) {
|
|
134489
134657
|
params[name] = m2[0];
|
|
@@ -134497,11 +134665,12 @@ var Node2 = class _Node2 {
|
|
|
134497
134665
|
params
|
|
134498
134666
|
);
|
|
134499
134667
|
}
|
|
134500
|
-
|
|
134668
|
+
for (const _2 in child.#children) {
|
|
134501
134669
|
child.#params = params;
|
|
134502
|
-
const componentCount = m2[0].match(/\//)?.length ?? 0;
|
|
134670
|
+
const componentCount = m2[0].match(/\//g)?.length ?? 0;
|
|
134503
134671
|
const targetCurNodes = curNodesQueue[componentCount] ||= [];
|
|
134504
134672
|
targetCurNodes.push(child);
|
|
134673
|
+
break;
|
|
134505
134674
|
}
|
|
134506
134675
|
continue;
|
|
134507
134676
|
}
|
|
@@ -134529,7 +134698,7 @@ var Node2 = class _Node2 {
|
|
|
134529
134698
|
const shifted = curNodesQueue.shift();
|
|
134530
134699
|
curNodes = shifted ? tempNodes.concat(shifted) : tempNodes;
|
|
134531
134700
|
}
|
|
134532
|
-
if (handlerSets
|
|
134701
|
+
if (handlerSets[1]) {
|
|
134533
134702
|
handlerSets.sort((a, b2) => {
|
|
134534
134703
|
return a.score - b2.score;
|
|
134535
134704
|
});
|
|
@@ -134541,19 +134710,11 @@ var Node2 = class _Node2 {
|
|
|
134541
134710
|
// node_modules/hono/dist/router/trie-router/router.js
|
|
134542
134711
|
var TrieRouter = class {
|
|
134543
134712
|
name = "TrieRouter";
|
|
134544
|
-
#node;
|
|
134545
|
-
constructor() {
|
|
134546
|
-
this.#node = new Node2();
|
|
134547
|
-
}
|
|
134713
|
+
#node = new Node2();
|
|
134548
134714
|
add(method, path2, handler) {
|
|
134549
|
-
const
|
|
134550
|
-
|
|
134551
|
-
for (let i = 0, len = results.length; i < len; i++) {
|
|
134552
|
-
this.#node.insert(method, results[i], handler);
|
|
134553
|
-
}
|
|
134554
|
-
return;
|
|
134715
|
+
for (const result of checkOptionalParameter(path2) || [path2]) {
|
|
134716
|
+
this.#node.insert(method, result, handler);
|
|
134555
134717
|
}
|
|
134556
|
-
this.#node.insert(method, path2, handler);
|
|
134557
134718
|
}
|
|
134558
134719
|
match(method, path2) {
|
|
134559
134720
|
return this.#node.search(method, path2);
|
|
@@ -136057,7 +136218,13 @@ var createMiscRoutes = (deps) => {
|
|
|
136057
136218
|
// the box is starved. Additive capability flag only — live readings stay
|
|
136058
136219
|
// off this polled endpoint. Absent means an older server that never
|
|
136059
136220
|
// samples. Informational: pressure never holds, kills, or refuses sessions.
|
|
136060
|
-
hostPressure: true
|
|
136221
|
+
hostPressure: true,
|
|
136222
|
+
// Provider-neutral prompt contract: normalized prompt events, opaque ids
|
|
136223
|
+
// and the atomic /prompt/answer route. A prompt_snapshot on subscribe
|
|
136224
|
+
// carries RETAINED prompts, terminal ones included — render on `state`,
|
|
136225
|
+
// not on presence — and an answer retry after that retention window is
|
|
136226
|
+
// answered 404 prompt_not_found rather than the recorded outcome.
|
|
136227
|
+
promptContract: { schemaVersion: 1, atomicAnswer: true }
|
|
136061
136228
|
});
|
|
136062
136229
|
});
|
|
136063
136230
|
app.get("/api/profiles", (c) => c.json([]));
|
|
@@ -136555,6 +136722,10 @@ var createSessionRoutes = (deps) => {
|
|
|
136555
136722
|
await deps.handleSendAnswer(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
136556
136723
|
return alreadyHandled6();
|
|
136557
136724
|
});
|
|
136725
|
+
app.post("/:id/prompt/answer", async (c) => {
|
|
136726
|
+
await deps.handlePromptAnswer(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
136727
|
+
return alreadyHandled6();
|
|
136728
|
+
});
|
|
136558
136729
|
app.post("/:id/permission/answer", async (c) => {
|
|
136559
136730
|
await deps.handlePermissionAnswer(c.req.param("id"), c.env.incoming, c.env.outgoing);
|
|
136560
136731
|
return alreadyHandled6();
|
|
@@ -140738,10 +140909,10 @@ function watch(paths, options = {}) {
|
|
|
140738
140909
|
var chokidar_default = { watch, FSWatcher };
|
|
140739
140910
|
|
|
140740
140911
|
// node_modules/@threadbase-sh/scanner/dist/index.js
|
|
140741
|
-
function applySort(metas,
|
|
140912
|
+
function applySort(metas, order2) {
|
|
140742
140913
|
const out = [...metas];
|
|
140743
140914
|
const tie = (a, b2) => a.id.localeCompare(b2.id);
|
|
140744
|
-
switch (
|
|
140915
|
+
switch (order2) {
|
|
140745
140916
|
case "recent":
|
|
140746
140917
|
out.sort((a, b2) => b2.timestamp.localeCompare(a.timestamp) || tie(a, b2));
|
|
140747
140918
|
break;
|
|
@@ -146251,7 +146422,7 @@ function parseSessionListQuery(url2) {
|
|
|
146251
146422
|
if (!VALID_ORDERS.includes(orderRaw)) {
|
|
146252
146423
|
return { error: `order must be asc or desc` };
|
|
146253
146424
|
}
|
|
146254
|
-
const
|
|
146425
|
+
const order2 = orderRaw;
|
|
146255
146426
|
const statusRaw = url2.searchParams.get("status");
|
|
146256
146427
|
let status;
|
|
146257
146428
|
if (statusRaw) {
|
|
@@ -146264,7 +146435,7 @@ function parseSessionListQuery(url2) {
|
|
|
146264
146435
|
status = parts;
|
|
146265
146436
|
}
|
|
146266
146437
|
const cursor = url2.searchParams.get("cursor") ?? void 0;
|
|
146267
|
-
return { query: { limit, sortBy, order, status, cursor } };
|
|
146438
|
+
return { query: { limit, sortBy, order: order2, status, cursor } };
|
|
146268
146439
|
}
|
|
146269
146440
|
function readBody2(req) {
|
|
146270
146441
|
return new Promise((resolve4, reject) => {
|
|
@@ -147672,6 +147843,522 @@ async function readGitBranch2(dir) {
|
|
|
147672
147843
|
// src/api/handlers/sessions.handlers.ts
|
|
147673
147844
|
init_providers();
|
|
147674
147845
|
init_pty_shared();
|
|
147846
|
+
|
|
147847
|
+
// src/schemas/prompt.schema.ts
|
|
147848
|
+
init_zod();
|
|
147849
|
+
var PROMPT_SCHEMA_VERSION = 1;
|
|
147850
|
+
var OpaqueIdSchema = external_exports.string().trim().min(1).max(200);
|
|
147851
|
+
var MeaningfulStringSchema = external_exports.string().trim().min(1);
|
|
147852
|
+
var PromptOptionSchema = external_exports.object({
|
|
147853
|
+
optionId: OpaqueIdSchema,
|
|
147854
|
+
label: MeaningfulStringSchema,
|
|
147855
|
+
description: external_exports.string().optional(),
|
|
147856
|
+
preview: external_exports.string().optional()
|
|
147857
|
+
});
|
|
147858
|
+
var PromptQuestionSchema = external_exports.object({
|
|
147859
|
+
questionId: OpaqueIdSchema,
|
|
147860
|
+
text: MeaningfulStringSchema,
|
|
147861
|
+
header: external_exports.string().optional(),
|
|
147862
|
+
inputMode: external_exports.enum(["single", "multi", "text"]),
|
|
147863
|
+
options: external_exports.array(PromptOptionSchema),
|
|
147864
|
+
allowOther: external_exports.boolean(),
|
|
147865
|
+
secret: external_exports.union([external_exports.boolean(), external_exports.literal("unknown")])
|
|
147866
|
+
}).superRefine((question, ctx) => {
|
|
147867
|
+
const optionIds = question.options.map((option) => option.optionId);
|
|
147868
|
+
if (new Set(optionIds).size !== optionIds.length) {
|
|
147869
|
+
ctx.addIssue({
|
|
147870
|
+
code: "custom",
|
|
147871
|
+
message: "optionId values must be unique",
|
|
147872
|
+
path: ["options"]
|
|
147873
|
+
});
|
|
147874
|
+
}
|
|
147875
|
+
if (question.inputMode === "text" && question.options.length !== 0) {
|
|
147876
|
+
ctx.addIssue({
|
|
147877
|
+
code: "custom",
|
|
147878
|
+
message: "text questions cannot carry options",
|
|
147879
|
+
path: ["options"]
|
|
147880
|
+
});
|
|
147881
|
+
}
|
|
147882
|
+
if (question.inputMode !== "text" && question.options.length === 0) {
|
|
147883
|
+
ctx.addIssue({
|
|
147884
|
+
code: "custom",
|
|
147885
|
+
message: "select questions require options",
|
|
147886
|
+
path: ["options"]
|
|
147887
|
+
});
|
|
147888
|
+
}
|
|
147889
|
+
});
|
|
147890
|
+
var TERMINAL_PROMPT_STATES = /* @__PURE__ */ new Set(["resolved", "cancelled", "expired", "unavailable"]);
|
|
147891
|
+
var PromptSchema = external_exports.object({
|
|
147892
|
+
schemaVersion: external_exports.literal(PROMPT_SCHEMA_VERSION),
|
|
147893
|
+
sessionId: OpaqueIdSchema,
|
|
147894
|
+
promptId: OpaqueIdSchema,
|
|
147895
|
+
revision: external_exports.number().int().positive(),
|
|
147896
|
+
state: external_exports.enum(["open", "updated", "resolved", "cancelled", "expired", "unavailable"]),
|
|
147897
|
+
terminalReason: MeaningfulStringSchema.optional(),
|
|
147898
|
+
intent: external_exports.enum(["approval", "question"]),
|
|
147899
|
+
title: external_exports.string().optional(),
|
|
147900
|
+
message: external_exports.string().optional(),
|
|
147901
|
+
detail: external_exports.string().optional(),
|
|
147902
|
+
questions: external_exports.array(PromptQuestionSchema).min(1),
|
|
147903
|
+
answerRequirement: external_exports.enum(["blocking", "non_blocking", "unknown"]),
|
|
147904
|
+
expiresAt: external_exports.string().datetime({ offset: true }).nullable(),
|
|
147905
|
+
provenance: external_exports.object({
|
|
147906
|
+
source: external_exports.enum(["provider", "screen", "transcript", "synthetic"]),
|
|
147907
|
+
confidence: external_exports.enum(["authoritative", "inferred"])
|
|
147908
|
+
})
|
|
147909
|
+
}).superRefine((prompt, ctx) => {
|
|
147910
|
+
if (![prompt.title, prompt.message, prompt.detail].some((value) => value?.trim())) {
|
|
147911
|
+
ctx.addIssue({
|
|
147912
|
+
code: "custom",
|
|
147913
|
+
message: "prompt requires a meaningful title, message, or detail",
|
|
147914
|
+
path: ["message"]
|
|
147915
|
+
});
|
|
147916
|
+
}
|
|
147917
|
+
const questionIds = prompt.questions.map((question) => question.questionId);
|
|
147918
|
+
if (new Set(questionIds).size !== questionIds.length) {
|
|
147919
|
+
ctx.addIssue({
|
|
147920
|
+
code: "custom",
|
|
147921
|
+
message: "questionId values must be unique",
|
|
147922
|
+
path: ["questions"]
|
|
147923
|
+
});
|
|
147924
|
+
}
|
|
147925
|
+
const optionIds = prompt.questions.flatMap(
|
|
147926
|
+
(question) => question.options.map((option) => option.optionId)
|
|
147927
|
+
);
|
|
147928
|
+
if (new Set(optionIds).size !== optionIds.length) {
|
|
147929
|
+
ctx.addIssue({
|
|
147930
|
+
code: "custom",
|
|
147931
|
+
message: "optionId values must be unique within a prompt",
|
|
147932
|
+
path: ["questions"]
|
|
147933
|
+
});
|
|
147934
|
+
}
|
|
147935
|
+
const terminal = TERMINAL_PROMPT_STATES.has(prompt.state);
|
|
147936
|
+
if (terminal !== (prompt.terminalReason !== void 0)) {
|
|
147937
|
+
ctx.addIssue({
|
|
147938
|
+
code: "custom",
|
|
147939
|
+
message: terminal ? "terminal prompts require terminalReason" : "actionable prompts cannot carry terminalReason",
|
|
147940
|
+
path: ["terminalReason"]
|
|
147941
|
+
});
|
|
147942
|
+
}
|
|
147943
|
+
});
|
|
147944
|
+
var OptionResponseSchema = external_exports.object({
|
|
147945
|
+
questionId: OpaqueIdSchema,
|
|
147946
|
+
optionIds: external_exports.array(OpaqueIdSchema).min(1).refine((ids) => new Set(ids).size === ids.length, "optionIds must be unique"),
|
|
147947
|
+
text: external_exports.never().optional()
|
|
147948
|
+
});
|
|
147949
|
+
var TextResponseSchema = external_exports.object({
|
|
147950
|
+
questionId: OpaqueIdSchema,
|
|
147951
|
+
text: external_exports.string(),
|
|
147952
|
+
optionIds: external_exports.never().optional()
|
|
147953
|
+
});
|
|
147954
|
+
var PromptResponseSchema = external_exports.union([OptionResponseSchema, TextResponseSchema]);
|
|
147955
|
+
var PromptAnswerSchema = external_exports.object({
|
|
147956
|
+
promptId: OpaqueIdSchema,
|
|
147957
|
+
revision: external_exports.number().int().positive(),
|
|
147958
|
+
responses: external_exports.array(PromptResponseSchema).min(1),
|
|
147959
|
+
idempotencyKey: OpaqueIdSchema
|
|
147960
|
+
}).superRefine((answer, ctx) => {
|
|
147961
|
+
const questionIds = answer.responses.map((response) => response.questionId);
|
|
147962
|
+
if (new Set(questionIds).size !== questionIds.length) {
|
|
147963
|
+
ctx.addIssue({
|
|
147964
|
+
code: "custom",
|
|
147965
|
+
message: "each questionId can be answered only once",
|
|
147966
|
+
path: ["responses"]
|
|
147967
|
+
});
|
|
147968
|
+
}
|
|
147969
|
+
});
|
|
147970
|
+
|
|
147971
|
+
// src/services/prompts/promptRegistry.ts
|
|
147972
|
+
var import_node_crypto5 = require("crypto");
|
|
147973
|
+
var PROMPT_TERMINAL_RETENTION_MS = 10 * 60 * 1e3;
|
|
147974
|
+
var PROMPT_MAX_RECORDS_PER_SESSION = 200;
|
|
147975
|
+
var MAX_TIMEOUT_MS = 2147483647;
|
|
147976
|
+
function copyPrompt(prompt) {
|
|
147977
|
+
return {
|
|
147978
|
+
...prompt,
|
|
147979
|
+
questions: prompt.questions.map((question) => ({
|
|
147980
|
+
...question,
|
|
147981
|
+
options: question.options.map((option) => ({ ...option }))
|
|
147982
|
+
})),
|
|
147983
|
+
provenance: { ...prompt.provenance }
|
|
147984
|
+
};
|
|
147985
|
+
}
|
|
147986
|
+
function terminalError(state) {
|
|
147987
|
+
switch (state) {
|
|
147988
|
+
case "resolved":
|
|
147989
|
+
return "already_resolved";
|
|
147990
|
+
case "expired":
|
|
147991
|
+
return "prompt_expired";
|
|
147992
|
+
case "cancelled":
|
|
147993
|
+
return "prompt_cancelled";
|
|
147994
|
+
case "unavailable":
|
|
147995
|
+
return "prompt_unavailable";
|
|
147996
|
+
}
|
|
147997
|
+
}
|
|
147998
|
+
var PromptRegistry = class {
|
|
147999
|
+
bySession = /* @__PURE__ */ new Map();
|
|
148000
|
+
byId = /* @__PURE__ */ new Map();
|
|
148001
|
+
sequences = /* @__PURE__ */ new Map();
|
|
148002
|
+
createId;
|
|
148003
|
+
emit;
|
|
148004
|
+
onExpire;
|
|
148005
|
+
now;
|
|
148006
|
+
terminalRetentionMs;
|
|
148007
|
+
maxRecordsPerSession;
|
|
148008
|
+
constructor(options = {}) {
|
|
148009
|
+
this.createId = options.createId ?? import_node_crypto5.randomUUID;
|
|
148010
|
+
this.emit = options.emit;
|
|
148011
|
+
this.onExpire = options.onExpire;
|
|
148012
|
+
this.now = options.now ?? Date.now;
|
|
148013
|
+
this.terminalRetentionMs = options.terminalRetentionMs ?? PROMPT_TERMINAL_RETENTION_MS;
|
|
148014
|
+
this.maxRecordsPerSession = options.maxRecordsPerSession ?? PROMPT_MAX_RECORDS_PER_SESSION;
|
|
148015
|
+
}
|
|
148016
|
+
open(draft, adapter, promptId = this.createId()) {
|
|
148017
|
+
this.prune(draft.sessionId);
|
|
148018
|
+
const held = this.byId.get(promptId);
|
|
148019
|
+
if (held && (held.prompt.state === "open" || held.prompt.state === "updated")) {
|
|
148020
|
+
throw new Error(`Prompt id already exists: ${promptId}`);
|
|
148021
|
+
}
|
|
148022
|
+
const id = held ? this.createId() : promptId;
|
|
148023
|
+
const prompt = PromptSchema.parse({
|
|
148024
|
+
...draft,
|
|
148025
|
+
schemaVersion: PROMPT_SCHEMA_VERSION,
|
|
148026
|
+
promptId: id,
|
|
148027
|
+
revision: 1,
|
|
148028
|
+
state: "open",
|
|
148029
|
+
questions: draft.questions.map((question) => ({
|
|
148030
|
+
...question,
|
|
148031
|
+
questionId: this.createId(),
|
|
148032
|
+
options: question.options.map((option) => ({ ...option, optionId: this.createId() }))
|
|
148033
|
+
})),
|
|
148034
|
+
provenance: { ...draft.provenance }
|
|
148035
|
+
});
|
|
148036
|
+
const entry = {
|
|
148037
|
+
prompt,
|
|
148038
|
+
adapter,
|
|
148039
|
+
queue: Promise.resolve(),
|
|
148040
|
+
inFlight: /* @__PURE__ */ new Map(),
|
|
148041
|
+
outcomes: /* @__PURE__ */ new Map()
|
|
148042
|
+
};
|
|
148043
|
+
const session = this.bySession.get(prompt.sessionId) ?? /* @__PURE__ */ new Map();
|
|
148044
|
+
session.set(prompt.promptId, entry);
|
|
148045
|
+
this.bySession.set(prompt.sessionId, session);
|
|
148046
|
+
this.byId.set(prompt.promptId, entry);
|
|
148047
|
+
this.publish(entry);
|
|
148048
|
+
this.scheduleExpiration(entry);
|
|
148049
|
+
this.enforceCap(prompt.sessionId);
|
|
148050
|
+
return copyPrompt(prompt);
|
|
148051
|
+
}
|
|
148052
|
+
update(promptId, draft, adapter) {
|
|
148053
|
+
const entry = this.requireEntry(promptId);
|
|
148054
|
+
this.expireIfDue(entry, this.now());
|
|
148055
|
+
if (entry.prompt.sessionId !== draft.sessionId) throw new Error("Prompt session cannot change");
|
|
148056
|
+
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") {
|
|
148057
|
+
throw new Error(`Cannot update terminal prompt ${promptId}`);
|
|
148058
|
+
}
|
|
148059
|
+
if (entry.prompt.questions.length !== draft.questions.length) {
|
|
148060
|
+
throw new Error("Prompt question cardinality cannot change during an update");
|
|
148061
|
+
}
|
|
148062
|
+
const questions = draft.questions.map((question, questionIndex) => {
|
|
148063
|
+
const prior = entry.prompt.questions[questionIndex];
|
|
148064
|
+
if (prior.options.length !== question.options.length) {
|
|
148065
|
+
throw new Error("Prompt option cardinality cannot change during an update");
|
|
148066
|
+
}
|
|
148067
|
+
return {
|
|
148068
|
+
...question,
|
|
148069
|
+
questionId: prior.questionId,
|
|
148070
|
+
options: question.options.map((option, optionIndex) => ({
|
|
148071
|
+
...option,
|
|
148072
|
+
optionId: prior.options[optionIndex].optionId
|
|
148073
|
+
}))
|
|
148074
|
+
};
|
|
148075
|
+
});
|
|
148076
|
+
const prompt = PromptSchema.parse({
|
|
148077
|
+
...draft,
|
|
148078
|
+
schemaVersion: PROMPT_SCHEMA_VERSION,
|
|
148079
|
+
promptId,
|
|
148080
|
+
revision: entry.prompt.revision + 1,
|
|
148081
|
+
state: "updated",
|
|
148082
|
+
questions,
|
|
148083
|
+
provenance: { ...draft.provenance }
|
|
148084
|
+
});
|
|
148085
|
+
entry.prompt = prompt;
|
|
148086
|
+
if (adapter) entry.adapter = adapter;
|
|
148087
|
+
this.publish(entry);
|
|
148088
|
+
this.scheduleExpiration(entry);
|
|
148089
|
+
return copyPrompt(entry.prompt);
|
|
148090
|
+
}
|
|
148091
|
+
transition(promptId, state, reason) {
|
|
148092
|
+
const entry = this.requireEntry(promptId);
|
|
148093
|
+
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") {
|
|
148094
|
+
throw new Error(`Cannot transition terminal prompt ${promptId}`);
|
|
148095
|
+
}
|
|
148096
|
+
entry.prompt = {
|
|
148097
|
+
...entry.prompt,
|
|
148098
|
+
revision: entry.prompt.revision + 1,
|
|
148099
|
+
state,
|
|
148100
|
+
terminalReason: reason
|
|
148101
|
+
};
|
|
148102
|
+
entry.terminalAt = this.now();
|
|
148103
|
+
this.clearExpiration(entry);
|
|
148104
|
+
this.publish(entry);
|
|
148105
|
+
return copyPrompt(entry.prompt);
|
|
148106
|
+
}
|
|
148107
|
+
invalidateSession(sessionId, reason = "session_ended") {
|
|
148108
|
+
const transitioned = [];
|
|
148109
|
+
for (const entry of this.bySession.get(sessionId)?.values() ?? []) {
|
|
148110
|
+
if (entry.prompt.state === "open" || entry.prompt.state === "updated") {
|
|
148111
|
+
transitioned.push(this.transition(entry.prompt.promptId, "unavailable", reason));
|
|
148112
|
+
}
|
|
148113
|
+
}
|
|
148114
|
+
return transitioned;
|
|
148115
|
+
}
|
|
148116
|
+
get(promptId) {
|
|
148117
|
+
const entry = this.byId.get(promptId);
|
|
148118
|
+
if (!entry) return null;
|
|
148119
|
+
this.prune(entry.prompt.sessionId);
|
|
148120
|
+
return this.byId.has(promptId) ? copyPrompt(entry.prompt) : null;
|
|
148121
|
+
}
|
|
148122
|
+
hasActionable(sessionId) {
|
|
148123
|
+
this.prune(sessionId);
|
|
148124
|
+
return [...this.bySession.get(sessionId)?.values() ?? []].some(
|
|
148125
|
+
(entry) => entry.prompt.state === "open" || entry.prompt.state === "updated"
|
|
148126
|
+
);
|
|
148127
|
+
}
|
|
148128
|
+
snapshot(sessionId) {
|
|
148129
|
+
this.prune(sessionId);
|
|
148130
|
+
return {
|
|
148131
|
+
type: "prompt_snapshot",
|
|
148132
|
+
schemaVersion: PROMPT_SCHEMA_VERSION,
|
|
148133
|
+
sessionId,
|
|
148134
|
+
sequence: this.sequences.get(sessionId) ?? 0,
|
|
148135
|
+
prompts: [...this.bySession.get(sessionId)?.values() ?? []].map(
|
|
148136
|
+
(entry) => copyPrompt(entry.prompt)
|
|
148137
|
+
)
|
|
148138
|
+
};
|
|
148139
|
+
}
|
|
148140
|
+
dispose() {
|
|
148141
|
+
for (const entry of this.byId.values()) this.clearExpiration(entry);
|
|
148142
|
+
}
|
|
148143
|
+
answer(sessionId, answer) {
|
|
148144
|
+
this.prune(sessionId);
|
|
148145
|
+
const entry = this.byId.get(answer.promptId);
|
|
148146
|
+
if (!entry || entry.prompt.sessionId !== sessionId) {
|
|
148147
|
+
return Promise.resolve({ ok: false, code: "prompt_not_found" });
|
|
148148
|
+
}
|
|
148149
|
+
this.pruneOutcomes(entry);
|
|
148150
|
+
const recorded = entry.outcomes.get(answer.idempotencyKey);
|
|
148151
|
+
if (recorded) return Promise.resolve(recorded.outcome);
|
|
148152
|
+
const pending = entry.inFlight.get(answer.idempotencyKey);
|
|
148153
|
+
if (pending) return pending;
|
|
148154
|
+
const task = entry.queue.then(() => this.performAnswer(entry, answer));
|
|
148155
|
+
entry.queue = task.then(
|
|
148156
|
+
() => void 0,
|
|
148157
|
+
() => void 0
|
|
148158
|
+
);
|
|
148159
|
+
entry.inFlight.set(answer.idempotencyKey, task);
|
|
148160
|
+
void task.then((outcome) => {
|
|
148161
|
+
entry.inFlight.delete(answer.idempotencyKey);
|
|
148162
|
+
entry.outcomes.set(answer.idempotencyKey, { at: this.now(), outcome });
|
|
148163
|
+
});
|
|
148164
|
+
return task;
|
|
148165
|
+
}
|
|
148166
|
+
async performAnswer(entry, answer) {
|
|
148167
|
+
const prompt = entry.prompt;
|
|
148168
|
+
if (prompt.state !== "open" && prompt.state !== "updated") {
|
|
148169
|
+
return { ok: false, code: terminalError(prompt.state) };
|
|
148170
|
+
}
|
|
148171
|
+
if (this.expireIfDue(entry, this.now())) {
|
|
148172
|
+
return { ok: false, code: "prompt_expired" };
|
|
148173
|
+
}
|
|
148174
|
+
if (prompt.revision !== answer.revision) {
|
|
148175
|
+
return {
|
|
148176
|
+
ok: false,
|
|
148177
|
+
code: "prompt_revision_mismatch",
|
|
148178
|
+
currentRevision: prompt.revision
|
|
148179
|
+
};
|
|
148180
|
+
}
|
|
148181
|
+
const responseError = this.validateResponses(prompt, answer);
|
|
148182
|
+
if (responseError) return { ok: false, code: responseError };
|
|
148183
|
+
if (!entry.adapter) return { ok: false, code: "prompt_unavailable" };
|
|
148184
|
+
let adapterResult;
|
|
148185
|
+
try {
|
|
148186
|
+
adapterResult = await entry.adapter({ prompt: copyPrompt(prompt), answer });
|
|
148187
|
+
} catch {
|
|
148188
|
+
return { ok: false, code: "provider_error" };
|
|
148189
|
+
}
|
|
148190
|
+
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") {
|
|
148191
|
+
return { ok: false, code: terminalError(entry.prompt.state) };
|
|
148192
|
+
}
|
|
148193
|
+
if (entry.prompt.revision !== answer.revision) {
|
|
148194
|
+
return {
|
|
148195
|
+
ok: false,
|
|
148196
|
+
code: "prompt_revision_mismatch",
|
|
148197
|
+
currentRevision: entry.prompt.revision
|
|
148198
|
+
};
|
|
148199
|
+
}
|
|
148200
|
+
if (!adapterResult.ok) {
|
|
148201
|
+
if (adapterResult.terminal) {
|
|
148202
|
+
this.transition(
|
|
148203
|
+
prompt.promptId,
|
|
148204
|
+
adapterResult.terminal.state,
|
|
148205
|
+
adapterResult.terminal.reason
|
|
148206
|
+
);
|
|
148207
|
+
}
|
|
148208
|
+
return { ok: false, code: adapterResult.code };
|
|
148209
|
+
}
|
|
148210
|
+
return { ok: true, prompt: this.transition(prompt.promptId, "resolved", "answered") };
|
|
148211
|
+
}
|
|
148212
|
+
validateResponses(prompt, answer) {
|
|
148213
|
+
const questions = new Map(prompt.questions.map((question) => [question.questionId, question]));
|
|
148214
|
+
for (const response of answer.responses) {
|
|
148215
|
+
if (!questions.has(response.questionId)) return "unknown_question";
|
|
148216
|
+
}
|
|
148217
|
+
if (answer.responses.length !== prompt.questions.length) return "incomplete_answer";
|
|
148218
|
+
const responses = new Map(answer.responses.map((response) => [response.questionId, response]));
|
|
148219
|
+
for (const question of prompt.questions) {
|
|
148220
|
+
const response = responses.get(question.questionId);
|
|
148221
|
+
if (!response) return "incomplete_answer";
|
|
148222
|
+
if (question.inputMode === "text") {
|
|
148223
|
+
if (typeof response.text !== "string") return "incomplete_answer";
|
|
148224
|
+
continue;
|
|
148225
|
+
}
|
|
148226
|
+
const optionIds = response.optionIds;
|
|
148227
|
+
if (!optionIds) return "incomplete_answer";
|
|
148228
|
+
if (question.inputMode === "single" && optionIds.length !== 1) {
|
|
148229
|
+
return "unsupported_prompt_shape";
|
|
148230
|
+
}
|
|
148231
|
+
const known = new Set(question.options.map((option) => option.optionId));
|
|
148232
|
+
if (optionIds.some((optionId) => !known.has(optionId))) return "unknown_option";
|
|
148233
|
+
}
|
|
148234
|
+
return null;
|
|
148235
|
+
}
|
|
148236
|
+
publish(entry) {
|
|
148237
|
+
const sessionId = entry.prompt.sessionId;
|
|
148238
|
+
const sequence = (this.sequences.get(sessionId) ?? 0) + 1;
|
|
148239
|
+
this.sequences.set(sessionId, sequence);
|
|
148240
|
+
this.emit?.({
|
|
148241
|
+
type: "prompt_event",
|
|
148242
|
+
sessionId,
|
|
148243
|
+
sequence,
|
|
148244
|
+
prompt: copyPrompt(entry.prompt)
|
|
148245
|
+
});
|
|
148246
|
+
}
|
|
148247
|
+
scheduleExpiration(entry) {
|
|
148248
|
+
this.clearExpiration(entry);
|
|
148249
|
+
const expiresAt = entry.prompt.expiresAt;
|
|
148250
|
+
if (expiresAt === null) return;
|
|
148251
|
+
const delay = Math.min(MAX_TIMEOUT_MS, Math.max(0, Date.parse(expiresAt) - this.now()));
|
|
148252
|
+
entry.expiryTimer = setTimeout(() => {
|
|
148253
|
+
entry.expiryTimer = void 0;
|
|
148254
|
+
if (!this.expireIfDue(entry, this.now())) this.scheduleExpiration(entry);
|
|
148255
|
+
}, delay);
|
|
148256
|
+
entry.expiryTimer.unref?.();
|
|
148257
|
+
}
|
|
148258
|
+
clearExpiration(entry) {
|
|
148259
|
+
if (entry.expiryTimer) clearTimeout(entry.expiryTimer);
|
|
148260
|
+
entry.expiryTimer = void 0;
|
|
148261
|
+
}
|
|
148262
|
+
expireIfDue(entry, now) {
|
|
148263
|
+
if (entry.prompt.state !== "open" && entry.prompt.state !== "updated") return false;
|
|
148264
|
+
if (entry.prompt.expiresAt === null || now < Date.parse(entry.prompt.expiresAt)) return false;
|
|
148265
|
+
const expired = this.transition(entry.prompt.promptId, "expired", "deadline_elapsed");
|
|
148266
|
+
this.onExpire?.(expired);
|
|
148267
|
+
return true;
|
|
148268
|
+
}
|
|
148269
|
+
requireEntry(promptId) {
|
|
148270
|
+
const entry = this.byId.get(promptId);
|
|
148271
|
+
if (!entry) throw new Error(`Unknown prompt: ${promptId}`);
|
|
148272
|
+
return entry;
|
|
148273
|
+
}
|
|
148274
|
+
prune(sessionId) {
|
|
148275
|
+
const now = this.now();
|
|
148276
|
+
const session = this.bySession.get(sessionId);
|
|
148277
|
+
if (!session) return;
|
|
148278
|
+
for (const [promptId, entry] of session) {
|
|
148279
|
+
this.expireIfDue(entry, now);
|
|
148280
|
+
if (entry.terminalAt !== void 0 && now - entry.terminalAt > this.terminalRetentionMs) {
|
|
148281
|
+
this.clearExpiration(entry);
|
|
148282
|
+
session.delete(promptId);
|
|
148283
|
+
this.byId.delete(promptId);
|
|
148284
|
+
}
|
|
148285
|
+
}
|
|
148286
|
+
if (session.size === 0) this.bySession.delete(sessionId);
|
|
148287
|
+
}
|
|
148288
|
+
enforceCap(sessionId) {
|
|
148289
|
+
const session = this.bySession.get(sessionId);
|
|
148290
|
+
if (!session || session.size <= this.maxRecordsPerSession) return;
|
|
148291
|
+
const terminal = [...session.entries()].filter(([, entry]) => entry.terminalAt !== void 0).sort((a, b2) => (a[1].terminalAt ?? 0) - (b2[1].terminalAt ?? 0));
|
|
148292
|
+
while (session.size > this.maxRecordsPerSession && terminal.length > 0) {
|
|
148293
|
+
const [promptId, entry] = terminal.shift();
|
|
148294
|
+
this.clearExpiration(entry);
|
|
148295
|
+
session.delete(promptId);
|
|
148296
|
+
this.byId.delete(promptId);
|
|
148297
|
+
}
|
|
148298
|
+
}
|
|
148299
|
+
pruneOutcomes(entry) {
|
|
148300
|
+
const now = this.now();
|
|
148301
|
+
for (const [key, recorded] of entry.outcomes) {
|
|
148302
|
+
if (now - recorded.at > this.terminalRetentionMs) entry.outcomes.delete(key);
|
|
148303
|
+
}
|
|
148304
|
+
}
|
|
148305
|
+
};
|
|
148306
|
+
|
|
148307
|
+
// src/services/prompts/ptyPromptAdapter.ts
|
|
148308
|
+
function permissionPromptDraft(sessionId, gate) {
|
|
148309
|
+
if (!gate) throw new Error("Cannot normalize an absent permission gate");
|
|
148310
|
+
const message = gate.prompt?.trim() || "Approval required";
|
|
148311
|
+
return {
|
|
148312
|
+
sessionId,
|
|
148313
|
+
intent: "approval",
|
|
148314
|
+
title: "Approval",
|
|
148315
|
+
message,
|
|
148316
|
+
...gate.detail?.trim() ? { detail: gate.detail } : {},
|
|
148317
|
+
questions: [
|
|
148318
|
+
{
|
|
148319
|
+
text: message,
|
|
148320
|
+
header: "Approval",
|
|
148321
|
+
inputMode: "single",
|
|
148322
|
+
options: gate.options.map((option) => ({ label: option.label })),
|
|
148323
|
+
allowOther: false,
|
|
148324
|
+
secret: "unknown"
|
|
148325
|
+
}
|
|
148326
|
+
],
|
|
148327
|
+
answerRequirement: "unknown",
|
|
148328
|
+
expiresAt: null,
|
|
148329
|
+
provenance: { source: "screen", confidence: "inferred" }
|
|
148330
|
+
};
|
|
148331
|
+
}
|
|
148332
|
+
function questionPromptDraft(sessionId, questions, source) {
|
|
148333
|
+
const first = questions[0];
|
|
148334
|
+
if (!first) throw new Error("Cannot normalize an empty question list");
|
|
148335
|
+
return {
|
|
148336
|
+
sessionId,
|
|
148337
|
+
intent: "question",
|
|
148338
|
+
...first.header.trim() ? { title: first.header } : {},
|
|
148339
|
+
message: first.question,
|
|
148340
|
+
questions: questions.map((question) => ({
|
|
148341
|
+
text: question.question,
|
|
148342
|
+
...question.header.trim() ? { header: question.header } : {},
|
|
148343
|
+
inputMode: question.multiSelect ? "multi" : "single",
|
|
148344
|
+
options: question.options.map((option) => ({
|
|
148345
|
+
label: option.label,
|
|
148346
|
+
...option.description ? { description: option.description } : {},
|
|
148347
|
+
...option.preview ? { preview: option.preview } : {}
|
|
148348
|
+
})),
|
|
148349
|
+
allowOther: false,
|
|
148350
|
+
secret: "unknown"
|
|
148351
|
+
})),
|
|
148352
|
+
answerRequirement: "unknown",
|
|
148353
|
+
expiresAt: null,
|
|
148354
|
+
provenance: {
|
|
148355
|
+
source,
|
|
148356
|
+
confidence: source === "transcript" ? "authoritative" : "inferred"
|
|
148357
|
+
}
|
|
148358
|
+
};
|
|
148359
|
+
}
|
|
148360
|
+
|
|
148361
|
+
// src/api/handlers/sessions.handlers.ts
|
|
147675
148362
|
init_codexScreen();
|
|
147676
148363
|
init_detectPermissionGate();
|
|
147677
148364
|
init_detectQuestionFromScreen();
|
|
@@ -148041,6 +148728,21 @@ function codexSessionActiveBody(outcome) {
|
|
|
148041
148728
|
...outcome.ownerSource != null && { ownerSource: outcome.ownerSource }
|
|
148042
148729
|
};
|
|
148043
148730
|
}
|
|
148731
|
+
function promptAnswerStatus(code) {
|
|
148732
|
+
switch (code) {
|
|
148733
|
+
case "prompt_not_found":
|
|
148734
|
+
return 404;
|
|
148735
|
+
case "provider_error":
|
|
148736
|
+
return 502;
|
|
148737
|
+
case "unknown_question":
|
|
148738
|
+
case "unknown_option":
|
|
148739
|
+
case "incomplete_answer":
|
|
148740
|
+
case "unsupported_prompt_shape":
|
|
148741
|
+
return 400;
|
|
148742
|
+
default:
|
|
148743
|
+
return 409;
|
|
148744
|
+
}
|
|
148745
|
+
}
|
|
148044
148746
|
var SessionHandlers = class {
|
|
148045
148747
|
constructor(deps) {
|
|
148046
148748
|
this.deps = deps;
|
|
@@ -148079,6 +148781,10 @@ var SessionHandlers = class {
|
|
|
148079
148781
|
get pendingQuestions() {
|
|
148080
148782
|
return this.deps.pendingQuestions;
|
|
148081
148783
|
}
|
|
148784
|
+
get promptRegistry() {
|
|
148785
|
+
if (!this.deps.promptRegistry) this.deps.promptRegistry = new PromptRegistry();
|
|
148786
|
+
return this.deps.promptRegistry;
|
|
148787
|
+
}
|
|
148082
148788
|
get pendingQuestionKey() {
|
|
148083
148789
|
return this.deps.pendingQuestionKey;
|
|
148084
148790
|
}
|
|
@@ -148097,6 +148803,13 @@ var SessionHandlers = class {
|
|
|
148097
148803
|
get sessionSubscribers() {
|
|
148098
148804
|
return this.deps.sessionSubscribers;
|
|
148099
148805
|
}
|
|
148806
|
+
// Prompt lifecycle events (question / permission and their cancellations)
|
|
148807
|
+
// carry prompt content and go ONLY to the session's subscribers — never to
|
|
148808
|
+
// every connected socket. A client that subscribes after a prompt opened
|
|
148809
|
+
// gets it from the subscribe replay (server-wiring), not from a broadcast.
|
|
148810
|
+
broadcastToSession(sessionId, message) {
|
|
148811
|
+
this.wsHub.broadcastToClients(this.sessionSubscribers.get(sessionId) ?? [], message);
|
|
148812
|
+
}
|
|
148100
148813
|
get agentConfig() {
|
|
148101
148814
|
return this.deps.agentConfig;
|
|
148102
148815
|
}
|
|
@@ -148590,6 +149303,7 @@ var SessionHandlers = class {
|
|
|
148590
149303
|
json2(res, 400, { error: "Missing input field" });
|
|
148591
149304
|
return;
|
|
148592
149305
|
}
|
|
149306
|
+
this.promptRegistry.hasActionable(sessionId);
|
|
148593
149307
|
const openPrompt = this.pendingPermission.has(sessionId) ? "permission" : this.pendingQuestions.has(sessionId) ? "question" : null;
|
|
148594
149308
|
if (openPrompt) {
|
|
148595
149309
|
this.log.info(`[input.prompt_pending] ${sessionId.slice(0, 8)} kind=${openPrompt}`, {
|
|
@@ -148645,37 +149359,106 @@ var SessionHandlers = class {
|
|
|
148645
149359
|
// the later JSONL flush of the same question is de-duped. We synthesize a
|
|
148646
149360
|
// screen-scoped toolUseId; the JSONL path overwrites pendingQuestions with the
|
|
148647
149361
|
// real toolUseId when it lands, so answering works once JSONL catches up.
|
|
148648
|
-
handleLiveQuestion(sessionId, questions) {
|
|
149362
|
+
handleLiveQuestion(sessionId, questions, occurrenceId) {
|
|
148649
149363
|
const key = questionContentKey(questions);
|
|
148650
149364
|
if (this.pendingQuestionKey.get(sessionId) === key) return;
|
|
148651
149365
|
const toolUseId = `screen:${sessionId}:${key.length}`;
|
|
148652
|
-
this.pendingQuestions.
|
|
149366
|
+
const prior = this.pendingQuestions.get(sessionId);
|
|
149367
|
+
const priorPrompt = prior ? this.promptRegistry.get(prior.promptId) : null;
|
|
149368
|
+
if (priorPrompt?.state === "open" || priorPrompt?.state === "updated") {
|
|
149369
|
+
this.promptRegistry.transition(priorPrompt.promptId, "cancelled", "replaced");
|
|
149370
|
+
}
|
|
149371
|
+
const prompt = this.promptRegistry.open(
|
|
149372
|
+
questionPromptDraft(sessionId, questions, "screen"),
|
|
149373
|
+
this.questionAnswerAdapter(sessionId),
|
|
149374
|
+
occurrenceId
|
|
149375
|
+
);
|
|
149376
|
+
this.pendingQuestions.set(sessionId, {
|
|
149377
|
+
toolUseId,
|
|
149378
|
+
questions,
|
|
149379
|
+
origin: "pty",
|
|
149380
|
+
promptId: prompt.promptId
|
|
149381
|
+
});
|
|
148653
149382
|
this.pendingQuestionKey.set(sessionId, key);
|
|
148654
|
-
this.
|
|
149383
|
+
this.broadcastToSession(sessionId, { type: "question", sessionId, toolUseId, questions });
|
|
149384
|
+
}
|
|
149385
|
+
handleJsonlQuestion(sessionId, toolUseId, questions, origin) {
|
|
149386
|
+
const prior = this.pendingQuestions.get(sessionId);
|
|
149387
|
+
const sameQuestion = prior !== void 0 && questionContentKey(prior.questions) === questionContentKey(questions);
|
|
149388
|
+
let prompt;
|
|
149389
|
+
if (sameQuestion) {
|
|
149390
|
+
const current = this.promptRegistry.get(prior.promptId);
|
|
149391
|
+
prompt = current?.provenance.source === "transcript" ? current : this.promptRegistry.update(
|
|
149392
|
+
prior.promptId,
|
|
149393
|
+
questionPromptDraft(sessionId, questions, "transcript"),
|
|
149394
|
+
this.questionAnswerAdapter(sessionId)
|
|
149395
|
+
);
|
|
149396
|
+
} else {
|
|
149397
|
+
const priorPrompt = prior ? this.promptRegistry.get(prior.promptId) : null;
|
|
149398
|
+
if (priorPrompt?.state === "open" || priorPrompt?.state === "updated") {
|
|
149399
|
+
this.promptRegistry.transition(priorPrompt.promptId, "cancelled", "replaced");
|
|
149400
|
+
}
|
|
149401
|
+
prompt = this.promptRegistry.open(
|
|
149402
|
+
questionPromptDraft(sessionId, questions, "transcript"),
|
|
149403
|
+
this.questionAnswerAdapter(sessionId)
|
|
149404
|
+
);
|
|
149405
|
+
}
|
|
149406
|
+
this.pendingQuestions.set(sessionId, {
|
|
149407
|
+
toolUseId,
|
|
149408
|
+
questions,
|
|
149409
|
+
origin,
|
|
149410
|
+
promptId: prompt.promptId
|
|
149411
|
+
});
|
|
148655
149412
|
}
|
|
148656
149413
|
// Permission gate opened/closed (OSC 777 + scraped options). Broadcasts the
|
|
148657
149414
|
// additive `permission` / `permission_cancelled` events. Mobile answers by
|
|
148658
149415
|
// sending the chosen option index via /input { keys } (e.g. "2\r").
|
|
148659
|
-
handlePermissionChange(sessionId, gate) {
|
|
149416
|
+
handlePermissionChange(sessionId, gate, occurrenceId) {
|
|
148660
149417
|
if (gate === null) {
|
|
148661
|
-
|
|
149418
|
+
const prior2 = this.pendingPermission.get(sessionId);
|
|
149419
|
+
if (!prior2) return;
|
|
149420
|
+
const prompt2 = prior2.promptId ? this.promptRegistry.get(prior2.promptId) : null;
|
|
149421
|
+
if (prompt2?.state === "open" || prompt2?.state === "updated") {
|
|
149422
|
+
this.promptRegistry.transition(prompt2.promptId, "cancelled", "provider_closed");
|
|
149423
|
+
}
|
|
148662
149424
|
this.pendingPermission.delete(sessionId);
|
|
148663
149425
|
this.pendingPermissionKey.delete(sessionId);
|
|
148664
|
-
this.
|
|
149426
|
+
this.broadcastToSession(sessionId, { type: "permission_cancelled", sessionId });
|
|
148665
149427
|
return;
|
|
148666
149428
|
}
|
|
148667
149429
|
const key = permissionContentKey(gate);
|
|
148668
|
-
if (this.pendingPermissionKey.get(sessionId) === key) return;
|
|
148669
149430
|
const prior = this.pendingPermission.get(sessionId);
|
|
148670
|
-
const
|
|
148671
|
-
this.
|
|
149431
|
+
const priorPromptId = prior?.promptId;
|
|
149432
|
+
if (this.pendingPermissionKey.get(sessionId) === key && (occurrenceId === void 0 || prior?.occurrenceId === occurrenceId)) {
|
|
149433
|
+
return;
|
|
149434
|
+
}
|
|
149435
|
+
const samePrompt = prior && priorPromptId !== void 0 && permissionGateKey(prior) === permissionGateKey(gate) && (occurrenceId === void 0 || prior.occurrenceId === occurrenceId);
|
|
149436
|
+
if (prior && !samePrompt) {
|
|
149437
|
+
const priorPrompt = prior.promptId ? this.promptRegistry.get(prior.promptId) : null;
|
|
149438
|
+
if (priorPrompt?.state === "open" || priorPrompt?.state === "updated") {
|
|
149439
|
+
this.promptRegistry.transition(priorPrompt.promptId, "cancelled", "replaced");
|
|
149440
|
+
}
|
|
149441
|
+
}
|
|
149442
|
+
const prompt = gate.options.length === 0 ? null : samePrompt ? this.promptRegistry.get(priorPromptId) : this.promptRegistry.open(
|
|
149443
|
+
permissionPromptDraft(sessionId, gate),
|
|
149444
|
+
this.permissionAnswerAdapter(sessionId),
|
|
149445
|
+
occurrenceId
|
|
149446
|
+
);
|
|
149447
|
+
if (samePrompt && !prompt) throw new Error("Pending permission prompt disappeared");
|
|
149448
|
+
const gateId = prompt?.promptId ?? occurrenceId ?? prior?.gateId ?? (0, import_crypto9.randomUUID)();
|
|
149449
|
+
this.pendingPermission.set(sessionId, {
|
|
149450
|
+
...gate,
|
|
149451
|
+
gateId,
|
|
149452
|
+
...prompt ? { promptId: prompt.promptId } : {},
|
|
149453
|
+
...occurrenceId !== void 0 ? { occurrenceId } : {}
|
|
149454
|
+
});
|
|
148672
149455
|
this.pendingPermissionKey.set(sessionId, key);
|
|
148673
149456
|
const subscriberCount = this.sessionSubscribers.get(sessionId)?.size ?? 0;
|
|
148674
149457
|
this.log.info(
|
|
148675
149458
|
`[ws.broadcast_permission] ${sessionId.slice(0, 8)} subscribers=${subscriberCount}`,
|
|
148676
149459
|
{ event: "ws.broadcast_permission", sessionId, subscriberCount }
|
|
148677
149460
|
);
|
|
148678
|
-
this.
|
|
149461
|
+
this.broadcastToSession(sessionId, {
|
|
148679
149462
|
type: "permission",
|
|
148680
149463
|
sessionId,
|
|
148681
149464
|
...gate.prompt ? { prompt: gate.prompt } : {},
|
|
@@ -148686,6 +149469,107 @@ var SessionHandlers = class {
|
|
|
148686
149469
|
gateId
|
|
148687
149470
|
});
|
|
148688
149471
|
}
|
|
149472
|
+
permissionAnswerAdapter(sessionId) {
|
|
149473
|
+
return async ({ prompt, answer }) => {
|
|
149474
|
+
const gate = this.pendingPermission.get(sessionId);
|
|
149475
|
+
if (!gate || gate.promptId !== prompt.promptId) {
|
|
149476
|
+
return {
|
|
149477
|
+
ok: false,
|
|
149478
|
+
code: "prompt_unavailable",
|
|
149479
|
+
terminal: { state: "unavailable", reason: "provider_prompt_missing" }
|
|
149480
|
+
};
|
|
149481
|
+
}
|
|
149482
|
+
const response = answer.responses[0];
|
|
149483
|
+
const selectedId = response?.optionIds?.[0];
|
|
149484
|
+
const selectedIndex = prompt.questions[0]?.options.findIndex(
|
|
149485
|
+
(option2) => option2.optionId === selectedId
|
|
149486
|
+
);
|
|
149487
|
+
if (selectedIndex === void 0 || selectedIndex < 0) {
|
|
149488
|
+
return { ok: false, code: "unknown_option" };
|
|
149489
|
+
}
|
|
149490
|
+
const option = gate.options[selectedIndex];
|
|
149491
|
+
if (!option) return { ok: false, code: "unknown_option" };
|
|
149492
|
+
const provider = this.sessionStore.getManaged(sessionId)?.provider;
|
|
149493
|
+
if (provider !== CODEX_CLI_PROVIDER && !await this.permissionGateStillOpen(sessionId, permissionGateKey(gate))) {
|
|
149494
|
+
return {
|
|
149495
|
+
ok: false,
|
|
149496
|
+
code: "prompt_cancelled",
|
|
149497
|
+
terminal: { state: "cancelled", reason: "provider_closed" }
|
|
149498
|
+
};
|
|
149499
|
+
}
|
|
149500
|
+
if (this.pendingPermission.get(sessionId)?.promptId !== prompt.promptId) {
|
|
149501
|
+
return { ok: false, code: "prompt_cancelled" };
|
|
149502
|
+
}
|
|
149503
|
+
try {
|
|
149504
|
+
this.ptyManager.sendKeys(
|
|
149505
|
+
sessionId,
|
|
149506
|
+
option.answerKeys ?? permissionAnswerKeys(option.index)
|
|
149507
|
+
);
|
|
149508
|
+
} catch {
|
|
149509
|
+
return { ok: false, code: "provider_error" };
|
|
149510
|
+
}
|
|
149511
|
+
return { ok: true };
|
|
149512
|
+
};
|
|
149513
|
+
}
|
|
149514
|
+
questionAnswerAdapter(sessionId) {
|
|
149515
|
+
return async ({ prompt, answer }) => {
|
|
149516
|
+
const pending = this.pendingQuestions.get(sessionId);
|
|
149517
|
+
if (!pending || pending.promptId !== prompt.promptId) {
|
|
149518
|
+
return {
|
|
149519
|
+
ok: false,
|
|
149520
|
+
code: "prompt_unavailable",
|
|
149521
|
+
terminal: { state: "unavailable", reason: "provider_prompt_missing" }
|
|
149522
|
+
};
|
|
149523
|
+
}
|
|
149524
|
+
const answers = {};
|
|
149525
|
+
for (const question of prompt.questions) {
|
|
149526
|
+
const response = answer.responses.find((item) => item.questionId === question.questionId);
|
|
149527
|
+
if (!response?.optionIds) return { ok: false, code: "unsupported_prompt_shape" };
|
|
149528
|
+
answers[question.text] = response.optionIds.map((optionId) => {
|
|
149529
|
+
const option = question.options.find((item) => item.optionId === optionId);
|
|
149530
|
+
return option?.label ?? "";
|
|
149531
|
+
});
|
|
149532
|
+
}
|
|
149533
|
+
const resolution = resolveAnswer(pending, {
|
|
149534
|
+
toolUseId: pending.toolUseId,
|
|
149535
|
+
answers
|
|
149536
|
+
});
|
|
149537
|
+
if (!resolution.ok) {
|
|
149538
|
+
const code = resolution.reason === "unknown_option" || resolution.reason === "incomplete_answer" || resolution.reason === "unsupported_prompt_shape" ? resolution.reason : "prompt_unavailable";
|
|
149539
|
+
return { ok: false, code };
|
|
149540
|
+
}
|
|
149541
|
+
if (!await this.questionMenuStillOpen(sessionId)) {
|
|
149542
|
+
this.pendingQuestions.delete(sessionId);
|
|
149543
|
+
this.pendingQuestionKey.delete(sessionId);
|
|
149544
|
+
this.broadcastToSession(sessionId, {
|
|
149545
|
+
type: "question_cancelled",
|
|
149546
|
+
sessionId,
|
|
149547
|
+
toolUseId: pending.toolUseId
|
|
149548
|
+
});
|
|
149549
|
+
return {
|
|
149550
|
+
ok: false,
|
|
149551
|
+
code: "prompt_cancelled",
|
|
149552
|
+
terminal: { state: "cancelled", reason: "provider_closed" }
|
|
149553
|
+
};
|
|
149554
|
+
}
|
|
149555
|
+
if (this.pendingQuestions.get(sessionId)?.promptId !== prompt.promptId) {
|
|
149556
|
+
return { ok: false, code: "prompt_cancelled" };
|
|
149557
|
+
}
|
|
149558
|
+
try {
|
|
149559
|
+
this.ptyManager.sendKeys(sessionId, resolution.keys);
|
|
149560
|
+
} catch {
|
|
149561
|
+
return { ok: false, code: "provider_error" };
|
|
149562
|
+
}
|
|
149563
|
+
this.pendingQuestions.delete(sessionId);
|
|
149564
|
+
this.pendingQuestionKey.delete(sessionId);
|
|
149565
|
+
this.broadcastToSession(sessionId, {
|
|
149566
|
+
type: "question_cancelled",
|
|
149567
|
+
sessionId,
|
|
149568
|
+
toolUseId: pending.toolUseId
|
|
149569
|
+
});
|
|
149570
|
+
return { ok: true };
|
|
149571
|
+
};
|
|
149572
|
+
}
|
|
148689
149573
|
/**
|
|
148690
149574
|
* Answer a permission gate — the validated counterpart of POST /:id/input.
|
|
148691
149575
|
*
|
|
@@ -148721,9 +149605,14 @@ var SessionHandlers = class {
|
|
|
148721
149605
|
return;
|
|
148722
149606
|
}
|
|
148723
149607
|
const gateClosed = () => {
|
|
149608
|
+
const pending = this.pendingPermission.get(sessionId);
|
|
149609
|
+
const prompt = pending?.promptId ? this.promptRegistry.get(pending.promptId) : null;
|
|
149610
|
+
if (prompt?.state === "open" || prompt?.state === "updated") {
|
|
149611
|
+
this.promptRegistry.transition(prompt.promptId, "cancelled", "provider_closed");
|
|
149612
|
+
}
|
|
148724
149613
|
this.pendingPermission.delete(sessionId);
|
|
148725
149614
|
this.pendingPermissionKey.delete(sessionId);
|
|
148726
|
-
this.
|
|
149615
|
+
this.broadcastToSession(sessionId, { type: "permission_cancelled", sessionId });
|
|
148727
149616
|
json2(res, 409, { ok: false, reason: "gate_closed" });
|
|
148728
149617
|
};
|
|
148729
149618
|
const gate = this.pendingPermission.get(sessionId);
|
|
@@ -148762,6 +149651,10 @@ var SessionHandlers = class {
|
|
|
148762
149651
|
json2(res, 400, { ok: false, reason: message });
|
|
148763
149652
|
return;
|
|
148764
149653
|
}
|
|
149654
|
+
const normalized = gate.promptId ? this.promptRegistry.get(gate.promptId) : null;
|
|
149655
|
+
if (normalized?.state === "open" || normalized?.state === "updated") {
|
|
149656
|
+
this.promptRegistry.transition(normalized.promptId, "resolved", "answered_legacy");
|
|
149657
|
+
}
|
|
148765
149658
|
json2(res, 200, { ok: true });
|
|
148766
149659
|
}
|
|
148767
149660
|
/**
|
|
@@ -148807,9 +149700,13 @@ var SessionHandlers = class {
|
|
|
148807
149700
|
}
|
|
148808
149701
|
const toolUseId = pending?.toolUseId ?? "";
|
|
148809
149702
|
if (!await this.questionMenuStillOpen(sessionId)) {
|
|
149703
|
+
const prompt = this.promptRegistry.get(pending?.promptId ?? "");
|
|
149704
|
+
if (prompt?.state === "open" || prompt?.state === "updated") {
|
|
149705
|
+
this.promptRegistry.transition(prompt.promptId, "cancelled", "provider_closed");
|
|
149706
|
+
}
|
|
148810
149707
|
this.pendingQuestions.delete(sessionId);
|
|
148811
149708
|
this.pendingQuestionKey.delete(sessionId);
|
|
148812
|
-
this.
|
|
149709
|
+
this.broadcastToSession(sessionId, { type: "question_cancelled", sessionId, toolUseId });
|
|
148813
149710
|
json2(res, 409, { ok: false, reason: "question_gone" });
|
|
148814
149711
|
return;
|
|
148815
149712
|
}
|
|
@@ -148820,10 +149717,41 @@ var SessionHandlers = class {
|
|
|
148820
149717
|
json2(res, 400, { ok: false, reason: message });
|
|
148821
149718
|
return;
|
|
148822
149719
|
}
|
|
149720
|
+
const normalized = this.promptRegistry.get(pending?.promptId ?? "");
|
|
149721
|
+
if (normalized?.state === "open" || normalized?.state === "updated") {
|
|
149722
|
+
this.promptRegistry.transition(normalized.promptId, "resolved", "answered_legacy");
|
|
149723
|
+
}
|
|
148823
149724
|
this.pendingQuestions.delete(sessionId);
|
|
148824
|
-
this.
|
|
149725
|
+
this.broadcastToSession(sessionId, { type: "question_cancelled", sessionId, toolUseId });
|
|
148825
149726
|
json2(res, 200, { ok: true });
|
|
148826
149727
|
}
|
|
149728
|
+
/**
|
|
149729
|
+
* Answer a normalized prompt by its opaque ids.
|
|
149730
|
+
*
|
|
149731
|
+
* Refusals are keyed by `code` — the stable machine taxonomy of the prompt
|
|
149732
|
+
* contract. The released legacy routes (`/answer`, `/permission/answer`) key
|
|
149733
|
+
* theirs by `reason` and keep doing so; a client reads whichever key belongs
|
|
149734
|
+
* to the route it called, and the two vocabularies are not merged.
|
|
149735
|
+
*
|
|
149736
|
+
* Status follows the same split as the legacy routes: a malformed or
|
|
149737
|
+
* unanswerable *request* is 400, a prompt whose *state* refuses the answer is
|
|
149738
|
+
* 409. A retry after PROMPT_TERMINAL_RETENTION_MS answers 404
|
|
149739
|
+
* `prompt_not_found`, not the recorded outcome — the record it would replay
|
|
149740
|
+
* is gone by then.
|
|
149741
|
+
*/
|
|
149742
|
+
async handlePromptAnswer(sessionId, req, res) {
|
|
149743
|
+
const parsed = PromptAnswerSchema.safeParse(await readBody2(req));
|
|
149744
|
+
if (!parsed.success) {
|
|
149745
|
+
json2(res, 400, { ok: false, code: "invalid_prompt_answer" });
|
|
149746
|
+
return;
|
|
149747
|
+
}
|
|
149748
|
+
const outcome = await this.promptRegistry.answer(sessionId, parsed.data);
|
|
149749
|
+
if (outcome.ok) {
|
|
149750
|
+
json2(res, 200, outcome);
|
|
149751
|
+
return;
|
|
149752
|
+
}
|
|
149753
|
+
json2(res, promptAnswerStatus(outcome.code), outcome);
|
|
149754
|
+
}
|
|
148827
149755
|
// Best-effort: a session we don't own a PTY for, or one that raced away
|
|
148828
149756
|
// mid-read, is not ours to veto — say yes and let the write decide.
|
|
148829
149757
|
async questionMenuStillOpen(sessionId) {
|
|
@@ -151168,6 +152096,27 @@ init_capabilities();
|
|
|
151168
152096
|
function wsAllows(principal, required2) {
|
|
151169
152097
|
return principal === null || hasCapability(principal, required2);
|
|
151170
152098
|
}
|
|
152099
|
+
function clearExpiredPendingPrompt(deps, prompt) {
|
|
152100
|
+
const permission = deps.pendingPermission.get(prompt.sessionId);
|
|
152101
|
+
if (permission?.promptId === prompt.promptId) {
|
|
152102
|
+
deps.pendingPermission.delete(prompt.sessionId);
|
|
152103
|
+
deps.pendingPermissionKey.delete(prompt.sessionId);
|
|
152104
|
+
deps.wsHub.broadcastToClients(deps.sessionSubscribers.get(prompt.sessionId) ?? [], {
|
|
152105
|
+
type: "permission_cancelled",
|
|
152106
|
+
sessionId: prompt.sessionId
|
|
152107
|
+
});
|
|
152108
|
+
}
|
|
152109
|
+
const question = deps.pendingQuestions.get(prompt.sessionId);
|
|
152110
|
+
if (question?.promptId === prompt.promptId) {
|
|
152111
|
+
deps.pendingQuestions.delete(prompt.sessionId);
|
|
152112
|
+
deps.pendingQuestionKey.delete(prompt.sessionId);
|
|
152113
|
+
deps.wsHub.broadcastToClients(deps.sessionSubscribers.get(prompt.sessionId) ?? [], {
|
|
152114
|
+
type: "question_cancelled",
|
|
152115
|
+
sessionId: prompt.sessionId,
|
|
152116
|
+
toolUseId: question.toolUseId
|
|
152117
|
+
});
|
|
152118
|
+
}
|
|
152119
|
+
}
|
|
151171
152120
|
function createConversationWatcherEvents(deps) {
|
|
151172
152121
|
return {
|
|
151173
152122
|
onNewLineSpans: (filePath, spans, readFrom, endOffset) => {
|
|
@@ -151290,11 +152239,11 @@ function createLiveSessionOptions(deps) {
|
|
|
151290
152239
|
ts: ts2
|
|
151291
152240
|
});
|
|
151292
152241
|
},
|
|
151293
|
-
onPermissionChange: (sessionId, gate) => {
|
|
151294
|
-
deps.sessionHandlers().handlePermissionChange(sessionId, gate);
|
|
152242
|
+
onPermissionChange: (sessionId, gate, occurrenceId) => {
|
|
152243
|
+
deps.sessionHandlers().handlePermissionChange(sessionId, gate, occurrenceId);
|
|
151295
152244
|
},
|
|
151296
|
-
onLiveQuestion: (sessionId, questions) => {
|
|
151297
|
-
deps.sessionHandlers().handleLiveQuestion(sessionId, questions);
|
|
152245
|
+
onLiveQuestion: (sessionId, questions, occurrenceId) => {
|
|
152246
|
+
deps.sessionHandlers().handleLiveQuestion(sessionId, questions, occurrenceId);
|
|
151298
152247
|
},
|
|
151299
152248
|
onLiveQuestionGone: (sessionId) => {
|
|
151300
152249
|
deps.pendingQuestionKey.delete(sessionId);
|
|
@@ -151375,10 +152324,11 @@ function createLiveSessionOptions(deps) {
|
|
|
151375
152324
|
if (filePath) {
|
|
151376
152325
|
deps.fileWatcher.unwatch(filePath);
|
|
151377
152326
|
deps.sessionFileMap.delete(session.id);
|
|
151378
|
-
deps.cancelPendingQuestion(session.id);
|
|
151379
152327
|
}
|
|
152328
|
+
deps.cancelPendingQuestion(session.id);
|
|
151380
152329
|
deps.pendingPermission.delete(session.id);
|
|
151381
152330
|
deps.pendingPermissionKey.delete(session.id);
|
|
152331
|
+
deps.promptRegistry.invalidateSession(session.id, "session_ended");
|
|
151382
152332
|
deps.contendedSessions.delete(session.id);
|
|
151383
152333
|
deps.rememberSelfPtyEnded(session.id);
|
|
151384
152334
|
}
|
|
@@ -151433,6 +152383,7 @@ function createApiDeps(deps) {
|
|
|
151433
152383
|
handleGetOutput: (id, res) => deps.sessionHandlers.handleGetOutput(id, res),
|
|
151434
152384
|
handleSendInput: (id, req, res) => deps.sessionHandlers.handleSendInput(id, req, res),
|
|
151435
152385
|
handleSendAnswer: (id, req, res) => deps.sessionHandlers.handleSendAnswer(id, req, res),
|
|
152386
|
+
handlePromptAnswer: (id, req, res) => deps.sessionHandlers.handlePromptAnswer(id, req, res),
|
|
151436
152387
|
handlePermissionAnswer: (id, req, res) => deps.sessionHandlers.handlePermissionAnswer(id, req, res),
|
|
151437
152388
|
handleCancel: (id, res) => deps.sessionHandlers.handleCancel(id, res),
|
|
151438
152389
|
handleStopSession: (id, res) => deps.sessionHandlers.handleStopSession(id, res),
|
|
@@ -151491,6 +152442,9 @@ function createApiDeps(deps) {
|
|
|
151491
152442
|
return;
|
|
151492
152443
|
}
|
|
151493
152444
|
deps.addSessionSubscriber(msg.sessionId, ws2);
|
|
152445
|
+
if (deps.promptRegistry) {
|
|
152446
|
+
ws2.send(JSON.stringify(deps.promptRegistry.snapshot(msg.sessionId)));
|
|
152447
|
+
}
|
|
151494
152448
|
if (deps.ptyManager.hasSession(msg.sessionId)) {
|
|
151495
152449
|
const lines = await deps.ptyManager.getOutputLines(msg.sessionId, REPLAY_MAX_LINES);
|
|
151496
152450
|
const userMessages = deps.ptyManager.getInputHistory(msg.sessionId);
|
|
@@ -153720,16 +154674,16 @@ function compareValues(a, b2) {
|
|
|
153720
154674
|
if (typeof a === "number" && typeof b2 === "number") return a - b2;
|
|
153721
154675
|
return String(a).localeCompare(String(b2));
|
|
153722
154676
|
}
|
|
153723
|
-
function makeComparator(key,
|
|
153724
|
-
const dir =
|
|
154677
|
+
function makeComparator(key, order2) {
|
|
154678
|
+
const dir = order2 === "asc" ? 1 : -1;
|
|
153725
154679
|
return (a, b2) => {
|
|
153726
154680
|
const cmp = compareValues(getSortValue(a, key), getSortValue(b2, key)) * dir;
|
|
153727
154681
|
if (cmp !== 0) return cmp;
|
|
153728
154682
|
return a.id.localeCompare(b2.id);
|
|
153729
154683
|
};
|
|
153730
154684
|
}
|
|
153731
|
-
function findCursorBoundary(sorted, cursor, key,
|
|
153732
|
-
const dir =
|
|
154685
|
+
function findCursorBoundary(sorted, cursor, key, order2) {
|
|
154686
|
+
const dir = order2 === "asc" ? 1 : -1;
|
|
153733
154687
|
for (let i = 0; i < sorted.length; i++) {
|
|
153734
154688
|
const item = sorted[i];
|
|
153735
154689
|
const cmp = compareValues(getSortValue(item, key), cursor.k) * dir;
|
|
@@ -154305,6 +155259,7 @@ var StreamerServer = class {
|
|
|
154305
155259
|
// repaint of the same gate doesn't re-broadcast on every tick. Cleared
|
|
154306
155260
|
// alongside pendingPermission.
|
|
154307
155261
|
pendingPermissionKey = /* @__PURE__ */ new Map();
|
|
155262
|
+
promptRegistry;
|
|
154308
155263
|
// Scanner lifecycle, freshness state and the cache↔disk reconcile.
|
|
154309
155264
|
scannerManager;
|
|
154310
155265
|
// Binds a live session to the JSONL/rollout its provider writes.
|
|
@@ -154557,6 +155512,20 @@ var StreamerServer = class {
|
|
|
154557
155512
|
this.browserCors = config2.browserCors ?? loadBrowserCors();
|
|
154558
155513
|
this.sessionStore = new SessionStore();
|
|
154559
155514
|
this.wsHub = new WSHub();
|
|
155515
|
+
this.promptRegistry = new PromptRegistry({
|
|
155516
|
+
emit: (event) => this.wsHub.broadcastToClients(this.sessionSubscribers.get(event.sessionId) ?? [], event),
|
|
155517
|
+
onExpire: (prompt) => clearExpiredPendingPrompt(
|
|
155518
|
+
{
|
|
155519
|
+
pendingPermission: this.pendingPermission,
|
|
155520
|
+
pendingPermissionKey: this.pendingPermissionKey,
|
|
155521
|
+
pendingQuestions: this.pendingQuestions,
|
|
155522
|
+
pendingQuestionKey: this.pendingQuestionKey,
|
|
155523
|
+
sessionSubscribers: this.sessionSubscribers,
|
|
155524
|
+
wsHub: this.wsHub
|
|
155525
|
+
},
|
|
155526
|
+
prompt
|
|
155527
|
+
)
|
|
155528
|
+
});
|
|
154560
155529
|
this.fileWatcher = new ConversationWatcher(
|
|
154561
155530
|
createConversationWatcherEvents({
|
|
154562
155531
|
sessionFileMap: this.sessionFileMap,
|
|
@@ -154600,6 +155569,7 @@ var StreamerServer = class {
|
|
|
154600
155569
|
pendingQuestionKey: this.pendingQuestionKey,
|
|
154601
155570
|
pendingPermission: this.pendingPermission,
|
|
154602
155571
|
pendingPermissionKey: this.pendingPermissionKey,
|
|
155572
|
+
promptRegistry: this.promptRegistry,
|
|
154603
155573
|
contendedSessions: this.contendedSessions,
|
|
154604
155574
|
// Thunks, not values: sessionHandlers is constructed below, the
|
|
154605
155575
|
// registry repo and the push notifiers are bound during listen(), and
|
|
@@ -154690,6 +155660,7 @@ var StreamerServer = class {
|
|
|
154690
155660
|
sessionStatusBus: this.sessionStatusBus,
|
|
154691
155661
|
sessionFileMap: this.sessionFileMap,
|
|
154692
155662
|
pendingQuestions: this.pendingQuestions,
|
|
155663
|
+
promptRegistry: this.promptRegistry,
|
|
154693
155664
|
pendingQuestionKey: this.pendingQuestionKey,
|
|
154694
155665
|
pendingPermission: this.pendingPermission,
|
|
154695
155666
|
pendingPermissionKey: this.pendingPermissionKey,
|
|
@@ -154790,6 +155761,7 @@ var StreamerServer = class {
|
|
|
154790
155761
|
terminalSeq: this.terminalSeq,
|
|
154791
155762
|
pendingPermission: this.pendingPermission,
|
|
154792
155763
|
pendingQuestions: this.pendingQuestions,
|
|
155764
|
+
promptRegistry: this.promptRegistry,
|
|
154793
155765
|
agentClient,
|
|
154794
155766
|
conversationWriter,
|
|
154795
155767
|
agentConfig
|
|
@@ -155570,6 +156542,7 @@ var StreamerServer = class {
|
|
|
155570
156542
|
if (!this.ptyManager.isRemote()) this.ptyManager.dispose();
|
|
155571
156543
|
this.fileWatcher.dispose();
|
|
155572
156544
|
this.externalTails.clear();
|
|
156545
|
+
this.promptRegistry.dispose();
|
|
155573
156546
|
this.wsHub.dispose();
|
|
155574
156547
|
this.pairTokens.dispose();
|
|
155575
156548
|
this.liveActivityRenewal?.stop();
|
|
@@ -156158,7 +157131,7 @@ var StreamerServer = class {
|
|
|
156158
157131
|
for (const p2 of pending) {
|
|
156159
157132
|
if (contended || foreignVsPty(p2.questions)) continue;
|
|
156160
157133
|
const origin = priorPtyKey !== null && questionContentKey(p2.questions) === priorPtyKey ? "pty" : "jsonl";
|
|
156161
|
-
this.
|
|
157134
|
+
this.sessionHandlers.handleJsonlQuestion(sessionId, p2.toolUseId, p2.questions, origin);
|
|
156162
157135
|
const t = setTimeout(() => {
|
|
156163
157136
|
if (this.pendingQuestions.get(sessionId)?.toolUseId === p2.toolUseId) {
|
|
156164
157137
|
this.cancelPendingQuestion(sessionId);
|
|
@@ -156176,7 +157149,7 @@ var StreamerServer = class {
|
|
|
156176
157149
|
priorToolUseId
|
|
156177
157150
|
});
|
|
156178
157151
|
this.pendingQuestionKey.set(sessionId, key);
|
|
156179
|
-
if (broadcast2) this.wsHub.
|
|
157152
|
+
if (broadcast2) this.wsHub.broadcastToClients(this.sessionSubscribers.get(sessionId) ?? [], m2);
|
|
156180
157153
|
}
|
|
156181
157154
|
}
|
|
156182
157155
|
cancelPendingQuestion(sessionId) {
|
|
@@ -156184,7 +157157,15 @@ var StreamerServer = class {
|
|
|
156184
157157
|
if (!pq) return;
|
|
156185
157158
|
this.pendingQuestions.delete(sessionId);
|
|
156186
157159
|
this.pendingQuestionKey.delete(sessionId);
|
|
156187
|
-
this.
|
|
157160
|
+
const prompt = this.promptRegistry.get(pq.promptId);
|
|
157161
|
+
if (prompt?.state === "open" || prompt?.state === "updated") {
|
|
157162
|
+
this.promptRegistry.transition(pq.promptId, "cancelled", "provider_closed");
|
|
157163
|
+
}
|
|
157164
|
+
this.wsHub.broadcastToClients(this.sessionSubscribers.get(sessionId) ?? [], {
|
|
157165
|
+
type: "question_cancelled",
|
|
157166
|
+
sessionId,
|
|
157167
|
+
toolUseId: pq.toolUseId
|
|
157168
|
+
});
|
|
156188
157169
|
}
|
|
156189
157170
|
async handleBrowse(url2, res) {
|
|
156190
157171
|
if (!this.browseRoot) {
|
|
@@ -156515,7 +157496,7 @@ function isBrewInstall(scriptPath = process.argv[1] ?? "") {
|
|
|
156515
157496
|
}
|
|
156516
157497
|
|
|
156517
157498
|
// src/updater/download.ts
|
|
156518
|
-
var
|
|
157499
|
+
var import_node_crypto6 = require("crypto");
|
|
156519
157500
|
var import_node_fs10 = require("fs");
|
|
156520
157501
|
var import_node_path11 = require("path");
|
|
156521
157502
|
var import_promises17 = require("stream/promises");
|
|
@@ -156582,7 +157563,7 @@ async function downloadAndVerify(opts) {
|
|
|
156582
157563
|
if (!res.ok || !res.body) {
|
|
156583
157564
|
throw new Error(`Failed to download ${artifact.filename}: ${res.status} ${res.statusText}`);
|
|
156584
157565
|
}
|
|
156585
|
-
const hash2 = (0,
|
|
157566
|
+
const hash2 = (0, import_node_crypto6.createHash)("sha256");
|
|
156586
157567
|
const out = (0, import_node_fs10.createWriteStream)(targetPath);
|
|
156587
157568
|
let bytes = 0;
|
|
156588
157569
|
const measured = new TransformStream({
|
|
@@ -156887,7 +157868,7 @@ var import_node_path18 = require("path");
|
|
|
156887
157868
|
var import_path38 = __toESM(require("path"), 1);
|
|
156888
157869
|
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
156889
157870
|
var import_node_assert = __toESM(require("assert"), 1);
|
|
156890
|
-
var
|
|
157871
|
+
var import_node_crypto7 = require("crypto");
|
|
156891
157872
|
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
156892
157873
|
var import_node_path19 = __toESM(require("path"), 1);
|
|
156893
157874
|
var import_fs43 = __toESM(require("fs"), 1);
|
|
@@ -159302,7 +160283,7 @@ var Te = fo === "win32";
|
|
|
159302
160283
|
var uo = 1024;
|
|
159303
160284
|
var mo = (s3, t) => {
|
|
159304
160285
|
if (!Te) return import_node_fs15.default.unlink(s3, t);
|
|
159305
|
-
let e = s3 + ".DELETE." + (0,
|
|
160286
|
+
let e = s3 + ".DELETE." + (0, import_node_crypto7.randomBytes)(16).toString("hex");
|
|
159306
160287
|
import_node_fs15.default.rename(s3, e, (i) => {
|
|
159307
160288
|
if (i) return t(i);
|
|
159308
160289
|
import_node_fs15.default.unlink(e, t);
|
|
@@ -159310,7 +160291,7 @@ var mo = (s3, t) => {
|
|
|
159310
160291
|
};
|
|
159311
160292
|
var po = (s3) => {
|
|
159312
160293
|
if (!Te) return import_node_fs15.default.unlinkSync(s3);
|
|
159313
|
-
let t = s3 + ".DELETE." + (0,
|
|
160294
|
+
let t = s3 + ".DELETE." + (0, import_node_crypto7.randomBytes)(16).toString("hex");
|
|
159314
160295
|
import_node_fs15.default.renameSync(s3, t), import_node_fs15.default.unlinkSync(t);
|
|
159315
160296
|
};
|
|
159316
160297
|
var vr = (s3, t, e) => s3 !== void 0 && s3 === s3 >>> 0 ? s3 : t !== void 0 && t === t >>> 0 ? t : e;
|